]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #8427 : brson/rust/rustc-stack, r=thestinger
authorbors <bors@rust-lang.org>
Mon, 12 Aug 2013 00:38:09 +0000 (17:38 -0700)
committerbors <bors@rust-lang.org>
Mon, 12 Aug 2013 00:38:09 +0000 (17:38 -0700)
A lot of people are hitting stack overflows in rustc. This will make it
easier to experiment with stack size.

283 files changed:
doc/rust.md
doc/tutorial.md
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/abi.rs
src/librustc/back/link.rs
src/librustc/back/passes.rs
src/librustc/back/rpath.rs
src/librustc/driver/driver.rs
src/librustc/driver/session.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/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/borrowck/check_loans.rs
src/librustc/middle/borrowck/gather_loans/gather_moves.rs
src/librustc/middle/borrowck/gather_loans/lifetime.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/borrowck/gather_loans/restrictions.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/mem_categorization.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/build.rs
src/librustc/middle/trans/builder.rs
src/librustc/middle/trans/cabi.rs
src/librustc/middle/trans/callee.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/foreign.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/type_use.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/regionck.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/coercion.rs
src/librustc/middle/typeck/mod.rs
src/librustc/rustc.rs
src/librustc/util/ppaux.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/c_str.rs [new file with mode: 0644]
src/libstd/cast.rs
src/libstd/cleanup.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/num.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/repr.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/kill.rs
src/libstd/rt/local_heap.rs
src/libstd/rt/logging.rs
src/libstd/rt/mod.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/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/intrinsics.rs
src/libstd/unstable/lang.rs
src/libstd/unstable/sync.rs
src/libstd/vec.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map.rs
src/libsyntax/ast_util.rs
src/libsyntax/attr.rs
src/libsyntax/diagnostic.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/expand.rs
src/libsyntax/ext/fmt.rs
src/libsyntax/ext/ifmt.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/trace_macros.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/ext/tt/transcribe.rs
src/libsyntax/fold.rs
src/libsyntax/opt_vec.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/comments.rs
src/libsyntax/parse/lexer.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.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_type.h
src/rt/rust_upcall.cpp
src/rt/rust_util.cpp
src/rt/rust_util.h
src/rt/rust_uv.cpp
src/rt/rustrt.def.in
src/rustllvm/RustWrapper.cpp
src/rustllvm/rustllvm.def.in
src/test/auxiliary/xc_private_method_lib.rs
src/test/bench/graph500-bfs.rs
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-borrow-mut-object-twice.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-move-out-of-vec-tail.rs
src/test/compile-fail/borrowck-object-lifetime.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-object-mutability.rs [new file with mode: 0644]
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/issue-2766-a.rs [deleted file]
src/test/compile-fail/kindck-owned-trait-contains.rs
src/test/compile-fail/macro-inner-attributes.rs [new file with mode: 0644]
src/test/compile-fail/macro-outer-attributes.rs [new file with mode: 0644]
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/object-pointer-types.rs [new file with mode: 0644]
src/test/compile-fail/selftype-traittype.rs
src/test/compile-fail/static-slice-not-null-terminated.rs [deleted file]
src/test/compile-fail/xc-private-method.rs
src/test/run-fail/borrowck-wg-fail-object.rs [new file with mode: 0644]
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/class-cast-to-trait.rs
src/test/run-pass/const-str-ptr.rs
src/test/run-pass/extern-mod-url.rs [deleted file]
src/test/run-pass/foreign-fn-linkname.rs
src/test/run-pass/issue-1251.rs
src/test/run-pass/issue-3121.rs
src/test/run-pass/issue-4446.rs
src/test/run-pass/item-attributes.rs
src/test/run-pass/objects-owned-object-borrowed-method-header.rs [new file with mode: 0644]
src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs [new file with mode: 0644]
src/test/run-pass/objects-owned-object-owned-method.rs [new file with mode: 0644]
src/test/run-pass/owned-trait-objects.rs [deleted file]
src/test/run-pass/reflect-visit-data.rs
src/test/run-pass/reflect-visit-type.rs
src/test/run-pass/trait-to-str.rs
src/test/run-pass/unique-object.rs [deleted file]
src/test/run-pass/vec-matching-autoslice.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..f4264b0d5afc36d21b4ea116f6a607a9ad933fda 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,
@@ -2195,7 +2195,7 @@ use std::float::consts::pi;
 # impl Shape for CircleStruct { fn area(&self) -> float { pi * square(self.radius) } }
 
 let concrete = @CircleStruct{center:Point{x:3f,y:4f},radius:5f};
-let mycircle: Circle = concrete as @Circle;
+let mycircle: @Circle = concrete as @Circle;
 let nonsense = mycircle.radius() * mycircle.area();
 ~~~
 
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 8e921d300b557ea53552693fa87379bf52886081..349ffc63d9701362a37ba726dfba2c1b49996ecb 100644 (file)
@@ -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 cf8ceb463b256cdc7782343d5640f909bcdea694..f79e01b6f28b296d031de972c042cb7a6a655035 100644 (file)
@@ -284,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;
 
@@ -853,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;
@@ -901,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);
@@ -922,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);
@@ -950,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);
@@ -961,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);
 
@@ -1142,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);
 
@@ -1156,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 05b6e90c682f0f6030588c444c9df4e5e59a9c8f..dae0ceed22d9dcc14b3d7045df97f2d0cbe33b9a 100644 (file)
@@ -46,7 +46,8 @@
 pub static tydesc_field_drop_glue: uint = 3u;
 pub static tydesc_field_free_glue: uint = 4u;
 pub static tydesc_field_visit_glue: uint = 5u;
-pub static n_tydesc_fields: uint = 6u;
+pub static tydesc_field_borrow_offset: uint = 6u;
+pub static n_tydesc_fields: uint = 7u;
 
 // The two halves of a closure: code and environment.
 pub static fn_field_code: uint = 0u;
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 6aac627729c39f704336038b4f3a12dd2db3d567..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,46 +119,11 @@ 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 {
@@ -208,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]
@@ -253,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,
@@ -344,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 e349502d143c0b0432104190834e75621dc25d0f..0e7dc3b2fcd914cd2da363cb745e7cef291e04b9 100644 (file)
@@ -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>()
@@ -631,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),
@@ -726,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);
@@ -737,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()
         }
@@ -785,7 +785,7 @@ pub fn build_session(sopts: @session::options,
 pub fn build_session_(sopts: @session::options,
                       cm: @codemap::CodeMap,
                       demitter: diagnostic::Emitter,
-                      span_diagnostic_handler: @diagnostic::span_handler)
+                      span_diagnostic_handler: @mut diagnostic::span_handler)
                    -> Session {
     let target_cfg = build_target_config(sopts, demitter);
     let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
@@ -946,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 d725e2db1eba109474b71b0a65eaf6d655fd8e6c..cf62e35488b1fb37959877743f7df59f64e71609 100644 (file)
@@ -192,7 +192,7 @@ pub struct Session_ {
     // For a library crate, this is always none
     entry_fn: @mut Option<(NodeId, codemap::span)>,
     entry_type: @mut Option<EntryFnType>,
-    span_diagnostic: @diagnostic::span_handler,
+    span_diagnostic: @mut diagnostic::span_handler,
     filesearch: @filesearch::FileSearch,
     building_library: @mut bool,
     working_dir: Path,
@@ -261,7 +261,7 @@ pub fn add_lint(@self,
     pub fn next_node_id(@self) -> ast::NodeId {
         return syntax::parse::next_node_id(self.parse_sess);
     }
-    pub fn diagnostic(@self) -> @diagnostic::span_handler {
+    pub fn diagnostic(@self) -> @mut diagnostic::span_handler {
         self.span_diagnostic
     }
     pub fn debugging_opt(@self, opt: uint) -> bool {
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..8a157ebc988f5ae225f84ab02c69b49e1a8c7f5a 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]
@@ -2080,6 +2082,9 @@ pub fn LLVMDIBuilderCreateUnionType(Builder: DIBuilderRef,
                                             Elements: ValueRef,
                                             RunTimeLang: c_uint)
                                             -> ValueRef;
+
+        #[fast_ffi]
+        pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool);
     }
 }
 
@@ -2099,6 +2104,12 @@ pub fn SetLinkage(Global: ValueRef, Link: Linkage) {
     }
 }
 
+pub fn SetUnnamedAddr(Global: ValueRef, Unnamed: bool) {
+    unsafe {
+        llvm::LLVMSetUnnamedAddr(Global, Unnamed as Bool);
+    }
+}
+
 pub fn ConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
     unsafe {
         llvm::LLVMConstICmp(Pred as c_ushort, V1, V2)
@@ -2259,7 +2270,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..eaf01241c8165d0b9eebc00a591edccb5d233b3e 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};
@@ -28,7 +29,7 @@
 
 // Traverses an AST, reading all the information about use'd crates and extern
 // libraries necessary for later resolving, typechecking, linking, etc.
-pub fn read_crates(diag: @span_handler,
+pub fn read_crates(diag: @mut span_handler,
                    crate: &ast::Crate,
                    cstore: @mut cstore::CStore,
                    filesearch: @FileSearch,
@@ -73,7 +74,7 @@ fn dump_crates(crate_cache: &[cache_entry]) {
 }
 
 fn warn_if_multiple_versions(e: @mut Env,
-                             diag: @span_handler,
+                             diag: @mut span_handler,
                              crate_cache: &[cache_entry]) {
     use std::either::*;
 
@@ -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)
@@ -112,7 +113,7 @@ fn warn_if_multiple_versions(e: @mut Env,
 }
 
 struct Env {
-    diag: @span_handler,
+    diag: @mut span_handler,
     filesearch: @FileSearch,
     cstore: @mut cstore::CStore,
     os: loader::os,
@@ -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 c4919e7f263213335ade8a94d45a0030f0a9ae45..9366d757dd476befc73bda2253cb9311e929aaa0 100644 (file)
@@ -55,7 +55,7 @@
                                    ii: ast::inlined_item);
 
 pub struct EncodeParams<'self> {
-    diag: @span_handler,
+    diag: @mut span_handler,
     tcx: ty::ctxt,
     reexports2: middle::resolve::ExportMap2,
     item_symbols: &'self HashMap<ast::NodeId, ~str>,
@@ -82,7 +82,7 @@ struct Stats {
 }
 
 pub struct EncodeContext<'self> {
-    diag: @span_handler,
+    diag: @mut span_handler,
     tcx: ty::ctxt,
     stats: @mut Stats,
     reexports2: middle::resolve::ExportMap2,
index e18879464e892eac378c2e59c82ac1233c39c87b..56200a221be374716e826792984f89510277b2bc 100644 (file)
 
 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,55 +142,59 @@ 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);
     }
 }
 
index 9330cfc5c88b48fc4deade90b90c0298348955fd..554cdf4b2b4feb13a9055357ec18cd10316e375f 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;
@@ -43,10 +43,10 @@ pub enum os {
 }
 
 pub struct Context {
-    diag: @span_handler,
+    diag: @mut 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,8 +152,18 @@ 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,
+                          diag: @mut span_handler,
                           attrs: ~[ast::Attribute]) {
     let r = attr::find_linkage_metas(attrs);
     for mi in r.iter() {
@@ -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 ffd79433b76930fe7186c138a71fdaaed995436a..915729d254f94a7c602421e3055a9ceda56a94e4 100644 (file)
@@ -25,7 +25,7 @@
 use syntax::print::pprust::*;
 
 pub struct ctxt {
-    diag: @span_handler,
+    diag: @mut span_handler,
     // Def -> str Callback:
     ds: @fn(def_id) -> ~str,
     // The type context.
index b909f70440a8258031011ac11d0bf8024a2d4eda..d6342c582f0525dc21e9cbd5f5d30eb4b3218bf3 100644 (file)
@@ -586,8 +586,8 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
                 }
             )
           }
-          typeck::method_trait(did, m, vstore) => {
-              typeck::method_trait(did.tr(xcx), m, vstore)
+          typeck::method_trait(did, m) => {
+              typeck::method_trait(did.tr(xcx), m)
           }
         }
     }
@@ -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 88e168db5584f7baabcd24290976f35e9a92cfb5..620a1e9efe33f8095f1f795ed6e4c67a41c92d34 100644 (file)
@@ -362,7 +362,7 @@ fn mark_variable_as_used_mut(this: &CheckLoanCtxt,
                     }
 
                     mc::cat_discr(b, _) |
-                    mc::cat_deref(b, _, mc::uniq_ptr(*)) => {
+                    mc::cat_deref(b, _, mc::uniq_ptr) => {
                         assert_eq!(cmt.mutbl, mc::McInherited);
                         cmt = b;
                     }
index 54a5c09a0e9792e38b35be8383e6e24fd4906103..24a6e5b6e0b2b230cf4c5348c24466fa3e2606a7 100644 (file)
@@ -173,7 +173,7 @@ fn check_is_legal_to_move_from(bccx: @BorrowckCtxt,
             }
         }
 
-        mc::cat_deref(b, _, mc::uniq_ptr(*)) |
+        mc::cat_deref(b, _, mc::uniq_ptr) |
         mc::cat_discr(b, _) => {
             check_is_legal_to_move_from(bccx, cmt0, b)
         }
index ddcc5fe56d04352abb18f82afa4ae0cb5c113754..b315a7a2e72908a677671cd90f6492f79cc1f295 100644 (file)
@@ -74,7 +74,7 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) {
             mc::cat_arg(*) |                           // L-Local
             mc::cat_self(*) |                          // L-Local
             mc::cat_deref(_, _, mc::region_ptr(*)) |   // L-Deref-Borrowed
-            mc::cat_deref(_, _, mc::unsafe_ptr) => {
+            mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
                 let scope = self.scope(cmt);
                 self.check_scope(scope)
             }
@@ -108,7 +108,7 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) {
             }
 
             mc::cat_downcast(base) |
-            mc::cat_deref(base, _, mc::uniq_ptr(*)) |  // L-Deref-Send
+            mc::cat_deref(base, _, mc::uniq_ptr) |     // L-Deref-Send
             mc::cat_interior(base, _) => {             // L-Field
                 self.check(base, discr_scope)
             }
@@ -347,7 +347,7 @@ fn scope(&self, cmt: mc::cmt) -> ty::Region {
                 r
             }
             mc::cat_downcast(cmt) |
-            mc::cat_deref(cmt, _, mc::uniq_ptr(*)) |
+            mc::cat_deref(cmt, _, mc::uniq_ptr) |
             mc::cat_deref(cmt, _, mc::gc_ptr(*)) |
             mc::cat_interior(cmt, _) |
             mc::cat_stack_upvar(cmt) |
index b970a6585f6cd0b09d957bc22f7af454327079bf..6ebc4b49b3779558199d300fe47e302d4534d273 100644 (file)
@@ -352,13 +352,21 @@ pub fn guarantee_adjustments(&mut self,
                                              r)
                     }
                     ty::AutoBorrowFn(r) => {
-                        let cmt_deref = mcx.cat_deref_fn(expr, cmt, 0);
+                        let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0);
                         self.guarantee_valid(expr.id,
                                              expr.span,
                                              cmt_deref,
                                              m_imm,
                                              r)
                     }
+                    ty::AutoBorrowObj(r, m) => {
+                        let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0);
+                        self.guarantee_valid(expr.id,
+                                             expr.span,
+                                             cmt_deref,
+                                             m,
+                                             r)
+                    }
                     ty::AutoUnsafe(_) => {}
                 }
             }
index ad32eb0c805e4d4369f343e734257af37da0e15d..46bb23e400ee59df4759812ca9fa233d29c40cba 100644 (file)
@@ -101,7 +101,7 @@ fn restrict(&self,
                 self.extend(result, cmt.mutbl, LpInterior(i), restrictions)
             }
 
-            mc::cat_deref(cmt_base, _, mc::uniq_ptr(*)) => {
+            mc::cat_deref(cmt_base, _, mc::uniq_ptr) => {
                 // R-Deref-Send-Pointer
                 //
                 // When we borrow the interior of an owned pointer, we
@@ -194,7 +194,7 @@ fn restrict(&self,
                 }
             }
 
-            mc::cat_deref(_, _, mc::unsafe_ptr) => {
+            mc::cat_deref(_, _, mc::unsafe_ptr(*)) => {
                 // We are very trusting when working with unsafe pointers.
                 Safe
             }
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..76532b5cd22d6c6c835c71464b8cfff089ee2e1d 100644 (file)
@@ -301,7 +301,7 @@ enum AnyVisitor {
     // recursive call can use the original visitor's method, although the
     // recursing visitor supplied to the method is the item stopping visitor.
     OldVisitor(oldvisit::vt<@mut Context>, oldvisit::vt<@mut Context>),
-    NewVisitor(@visit::Visitor<()>),
+    NewVisitor(@mut visit::Visitor<()>),
 }
 
 struct Context {
@@ -465,7 +465,7 @@ fn add_oldvisit_lint(&mut self, v: oldvisit::vt<@mut Context>) {
         self.visitors.push(OldVisitor(v, item_stopping_visitor(v)));
     }
 
-    fn add_lint(&mut self, v: @visit::Visitor<()>) {
+    fn add_lint(&mut self, v: @mut visit::Visitor<()>) {
         self.visitors.push(NewVisitor(v));
     }
 
@@ -989,12 +989,12 @@ fn visit_fn_decl(cx: &Context, fd: &ast::fn_decl) {
     })
 }
 
-fn lint_session(cx: @mut Context) -> @visit::Visitor<()> {
+fn lint_session(cx: @mut Context) -> @mut visit::Visitor<()> {
     ast_util::id_visitor(|id| {
         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 6c5209cf504a6ad977d0931134e6a35e6a43157c..283724447f831fab8fadc2b5adfca1fb0ae96cbf 100644 (file)
@@ -84,10 +84,10 @@ pub struct CopiedUpvar {
 // different kinds of pointers:
 #[deriving(Eq)]
 pub enum ptr_kind {
-    uniq_ptr(ast::mutability),
+    uniq_ptr,
     gc_ptr(ast::mutability),
     region_ptr(ast::mutability, ty::Region),
-    unsafe_ptr
+    unsafe_ptr(ast::mutability)
 }
 
 // We use the term "interior" to mean "something reachable from the
@@ -156,14 +156,12 @@ pub enum deref_kind {
 // pointer adjustment).
 pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
     match ty::get(t).sty {
-        ty::ty_uniq(mt) => {
-            Some(deref_ptr(uniq_ptr(mt.mutbl)))
-        }
-
+        ty::ty_uniq(_) |
+        ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
         ty::ty_evec(_, ty::vstore_uniq) |
         ty::ty_estr(ty::vstore_uniq) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::OwnedSigil, _}) => {
-            Some(deref_ptr(uniq_ptr(m_imm)))
+            Some(deref_ptr(uniq_ptr))
         }
 
         ty::ty_rptr(r, mt) |
@@ -171,24 +169,32 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
             Some(deref_ptr(region_ptr(mt.mutbl, r)))
         }
 
+        ty::ty_trait(_, _, ty::RegionTraitStore(r), m, _) => {
+            Some(deref_ptr(region_ptr(m, r)))
+        }
+
         ty::ty_estr(ty::vstore_slice(r)) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::BorrowedSigil,
                                       region: r, _}) => {
             Some(deref_ptr(region_ptr(ast::m_imm, r)))
         }
 
-        ty::ty_box(mt) |
-        ty::ty_evec(mt, ty::vstore_box) => {
+        ty::ty_box(ref mt) |
+        ty::ty_evec(ref mt, ty::vstore_box) => {
             Some(deref_ptr(gc_ptr(mt.mutbl)))
         }
 
+        ty::ty_trait(_, _, ty::BoxTraitStore, m, _) => {
+            Some(deref_ptr(gc_ptr(m)))
+        }
+
         ty::ty_estr(ty::vstore_box) |
         ty::ty_closure(ty::ClosureTy {sigil: ast::ManagedSigil, _}) => {
             Some(deref_ptr(gc_ptr(ast::m_imm)))
         }
 
-        ty::ty_ptr(*) => {
-            Some(deref_ptr(unsafe_ptr))
+        ty::ty_ptr(ref mt) => {
+            Some(deref_ptr(unsafe_ptr(mt.mutbl)))
         }
 
         ty::ty_enum(*) |
@@ -631,20 +637,19 @@ pub fn cat_field<N:ast_node>(&self,
         }
     }
 
-    pub fn cat_deref_fn<N:ast_node>(&self,
-                                    node: N,
-                                    base_cmt: cmt,
-                                    deref_cnt: uint)
-                                    -> cmt {
+    pub fn cat_deref_fn_or_obj<N:ast_node>(&self,
+                                           node: N,
+                                           base_cmt: cmt,
+                                           deref_cnt: uint)
+                                           -> cmt {
         // Bit of a hack: the "dereference" of a function pointer like
         // `@fn()` is a mere logical concept. We interpret it as
         // dereferencing the environment pointer; of course, we don't
         // know what type lies at the other end, so we just call it
         // `()` (the empty tuple).
 
-        let mt = ty::mt {ty: ty::mk_tup(self.tcx, ~[]),
-                         mutbl: m_imm};
-        return self.cat_deref_common(node, base_cmt, deref_cnt, mt);
+        let opaque_ty = ty::mk_tup(self.tcx, ~[]);
+        return self.cat_deref_common(node, base_cmt, deref_cnt, opaque_ty);
     }
 
     pub fn cat_deref<N:ast_node>(&self,
@@ -662,25 +667,25 @@ pub fn cat_deref<N:ast_node>(&self,
             }
         };
 
-        return self.cat_deref_common(node, base_cmt, deref_cnt, mt);
+        return self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty);
     }
 
     pub fn cat_deref_common<N:ast_node>(&self,
                                         node: N,
                                         base_cmt: cmt,
                                         deref_cnt: uint,
-                                        mt: ty::mt)
+                                        deref_ty: ty::t)
                                         -> cmt {
         match deref_kind(self.tcx, base_cmt.ty) {
             deref_ptr(ptr) => {
                 // for unique ptrs, we inherit mutability from the
                 // owning reference.
                 let m = match ptr {
-                    uniq_ptr(*) => {
-                        self.inherited_mutability(base_cmt.mutbl, mt.mutbl)
+                    uniq_ptr => {
+                        base_cmt.mutbl.inherit()
                     }
-                    gc_ptr(*) | region_ptr(_, _) | unsafe_ptr => {
-                        MutabilityCategory::from_mutbl(mt.mutbl)
+                    gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
+                        MutabilityCategory::from_mutbl(m)
                     }
                 };
 
@@ -689,18 +694,18 @@ pub fn cat_deref_common<N:ast_node>(&self,
                     span:node.span(),
                     cat:cat_deref(base_cmt, deref_cnt, ptr),
                     mutbl:m,
-                    ty:mt.ty
+                    ty:deref_ty
                 }
             }
 
             deref_interior(interior) => {
-                let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl);
+                let m = base_cmt.mutbl.inherit();
                 @cmt_ {
                     id:node.id(),
                     span:node.span(),
                     cat:cat_interior(base_cmt, interior),
                     mutbl:m,
-                    ty:mt.ty
+                    ty:deref_ty
                 }
             }
         }
@@ -742,8 +747,8 @@ pub fn cat_index<N:ast_node>(&self,
         //! - `derefs`: the deref number to be used for
         //!   the implicit index deref, if any (see above)
 
-        let mt = match ty::index(base_cmt.ty) {
-          Some(mt) => mt,
+        let element_ty = match ty::index(base_cmt.ty) {
+          Some(ref mt) => mt.ty,
           None => {
             self.tcx.sess.span_bug(
                 elt.span(),
@@ -757,11 +762,11 @@ pub fn cat_index<N:ast_node>(&self,
             // for unique ptrs, we inherit mutability from the
             // owning reference.
             let m = match ptr {
-              uniq_ptr(*) => {
-                self.inherited_mutability(base_cmt.mutbl, mt.mutbl)
+              uniq_ptr => {
+                base_cmt.mutbl.inherit()
               }
-              gc_ptr(_) | region_ptr(_, _) | unsafe_ptr => {
-                MutabilityCategory::from_mutbl(mt.mutbl)
+              gc_ptr(m) | region_ptr(m, _) | unsafe_ptr(m) => {
+                MutabilityCategory::from_mutbl(m)
               }
             };
 
@@ -771,16 +776,16 @@ pub fn cat_index<N:ast_node>(&self,
                 span:elt.span(),
                 cat:cat_deref(base_cmt, derefs, ptr),
                 mutbl:m,
-                ty:mt.ty
+                ty:element_ty
             };
 
-            interior(elt, deref_cmt, base_cmt.ty, m, mt)
+            interior(elt, deref_cmt, base_cmt.ty, m, element_ty)
           }
 
           deref_interior(_) => {
             // fixed-length vectors have no deref
-            let m = self.inherited_mutability(base_cmt.mutbl, mt.mutbl);
-            interior(elt, base_cmt, base_cmt.ty, m, mt)
+            let m = base_cmt.mutbl.inherit();
+            interior(elt, base_cmt, base_cmt.ty, m, element_ty)
           }
         };
 
@@ -788,14 +793,14 @@ fn interior<N: ast_node>(elt: N,
                                  of_cmt: cmt,
                                  vec_ty: ty::t,
                                  mutbl: MutabilityCategory,
-                                 mt: ty::mt) -> cmt
+                                 element_ty: ty::t) -> cmt
         {
             @cmt_ {
                 id:elt.id(),
                 span:elt.span(),
                 cat:cat_interior(of_cmt, InteriorElement(element_kind(vec_ty))),
                 mutbl:mutbl,
-                ty:mt.ty
+                ty:element_ty
             }
         }
     }
@@ -1130,7 +1135,7 @@ pub fn guarantor(@self) -> cmt {
             cat_stack_upvar(b) |
             cat_discr(b, _) |
             cat_interior(b, _) |
-            cat_deref(b, _, uniq_ptr(*)) => {
+            cat_deref(b, _, uniq_ptr) => {
                 b.guarantor()
             }
         }
@@ -1177,7 +1182,7 @@ pub fn freely_aliasable(&self) -> Option<AliasableReason> {
 
             cat_downcast(b) |
             cat_stack_upvar(b) |
-            cat_deref(b, _, uniq_ptr(*)) |
+            cat_deref(b, _, uniq_ptr) |
             cat_interior(b, _) |
             cat_discr(b, _) => {
                 b.freely_aliasable()
@@ -1230,10 +1235,10 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
 
 pub fn ptr_sigil(ptr: ptr_kind) -> ~str {
     match ptr {
-        uniq_ptr(_) => ~"~",
+        uniq_ptr => ~"~",
         gc_ptr(_) => ~"@",
         region_ptr(_, _) => ~"&",
-        unsafe_ptr => ~"*"
+        unsafe_ptr(_) => ~"*"
     }
 }
 
index 9ffeb99ac3559bf7bf82810e3b7abba8579173c4..aa7b2e55cdc63b423f0b3a06d4b20ba6ace48ece 100644 (file)
@@ -290,7 +290,7 @@ pub fn check_crate<'mm>(tcx: ty::ctxt,
                  method_num: method_num,
                  _
             }) |
-            method_trait(trait_id, method_num, _) => {
+            method_trait(trait_id, method_num) => {
                 if trait_id.crate == LOCAL_CRATE {
                     match tcx.items.find(&trait_id.node) {
                         Some(&node_item(item, _)) => {
@@ -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 43953a50e15c2e3d57c13e5525b215b56afff13a..4d95909404e18ef33f8bc69e7630b3724575ab04 100644 (file)
@@ -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
@@ -5365,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 327d2e698c1e181915f6bcc41a555479ca967694..c98d859337c3e4a2bf116a3c951b137030595cda 100644 (file)
  * - `store_non_ref_bindings()`
  * - `insert_lllocals()`
  *
+ *
+ * ## Notes on vector pattern matching.
+ *
+ * Vector pattern matching is surprisingly tricky. The problem is that
+ * the structure of the vector isn't fully known, and slice matches
+ * can be done on subparts of it.
+ *
+ * The way that vector pattern matches are dealt with, then, is as
+ * follows. First, we make the actual condition associated with a
+ * vector pattern simply a vector length comparison. So the pattern
+ * [1, .. x] gets the condition "vec len >= 1", and the pattern
+ * [.. x] gets the condition "vec len >= 0". The problem here is that
+ * having the condition "vec len >= 1" hold clearly does not mean that
+ * only a pattern that has exactly that condition will match. This
+ * means that it may well be the case that a condition holds, but none
+ * of the patterns matching that condition match; to deal with this,
+ * when doing vector length matches, we have match failures proceed to
+ * the next condition to check.
+ *
+ * There are a couple more subtleties to deal with. While the "actual"
+ * condition associated with vector length tests is simply a test on
+ * the vector length, the actual vec_len Opt entry contains more
+ * information used to restrict which matches are associated with it.
+ * So that all matches in a submatch are matching against the same
+ * values from inside the vector, they are split up by how many
+ * elements they match at the front and at the back of the vector. In
+ * order to make sure that arms are properly checked in order, even
+ * with the overmatching conditions, each vec_len Opt entry is
+ * associated with a range of matches.
+ * Consider the following:
+ *
+ *   match &[1, 2, 3] {
+ *       [1, 1, .. _] => 0,
+ *       [1, 2, 2, .. _] => 1,
+ *       [1, 2, 3, .. _] => 2,
+ *       [1, 2, .. _] => 3,
+ *       _ => 4
+ *   }
+ * The proper arm to match is arm 2, but arms 0 and 3 both have the
+ * condition "len >= 2". If arm 3 was lumped in with arm 0, then the
+ * wrong branch would be taken. Instead, vec_len Opts are associated
+ * with a contiguous range of matches that have the same "shape".
+ * This is sort of ugly and requires a bunch of special handling of
+ * vec_len options.
+ *
  */
 
 
@@ -189,14 +234,19 @@ enum Lit {
     ConstLit(ast::def_id),              // the def ID of the constant
 }
 
+#[deriving(Eq)]
+pub enum VecLenOpt {
+    vec_len_eq,
+    vec_len_ge(/* length of prefix */uint)
+}
+
 // An option identifying a branch (either a literal, a enum variant or a
 // range)
 enum Opt {
     lit(Lit),
     var(/* disr val */ uint, @adt::Repr),
     range(@ast::expr, @ast::expr),
-    vec_len_eq(uint),
-    vec_len_ge(uint, /* slice */uint)
+    vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
 
 fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
@@ -247,9 +297,9 @@ fn opt_eq(tcx: ty::ctxt, a: &Opt, b: &Opt) -> bool {
             }
         }
         (&var(a, _), &var(b, _)) => a == b,
-            (&vec_len_eq(a), &vec_len_eq(b)) => a == b,
-            (&vec_len_ge(a, _), &vec_len_ge(b, _)) => a == b,
-            _ => false
+        (&vec_len(a1, a2, _), &vec_len(b1, b2, _)) =>
+            a1 == b1 && a2 == b2,
+        _ => false
     }
 }
 
@@ -283,10 +333,10 @@ fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result {
             return range_result(rslt(bcx, consts::const_expr(ccx, l1)),
                                 rslt(bcx, consts::const_expr(ccx, l2)));
         }
-        vec_len_eq(n) => {
+        vec_len(n, vec_len_eq, _) => {
             return single_result(rslt(bcx, C_int(ccx, n as int)));
         }
-        vec_len_ge(n, _) => {
+        vec_len(n, vec_len_ge(_), _) => {
             return lower_bound(rslt(bcx, C_int(ccx, n as int)));
         }
     }
@@ -471,10 +521,11 @@ fn enter_match<'r>(bcx: @mut Block,
 }
 
 fn enter_default<'r>(bcx: @mut Block,
-                         dm: DefMap,
-                         m: &[Match<'r>],
-                         col: uint,
-                         val: ValueRef)
+                     dm: DefMap,
+                     m: &[Match<'r>],
+                     col: uint,
+                     val: ValueRef,
+                     chk: Option<mk_fail>)
                       -> ~[Match<'r>] {
     debug!("enter_default(bcx=%s, m=%s, col=%u, val=%s)",
            bcx.to_str(),
@@ -483,13 +534,36 @@ fn enter_default<'r>(bcx: @mut Block,
            bcx.val_to_str(val));
     let _indenter = indenter();
 
-    do enter_match(bcx, dm, m, col, val) |p| {
+    // Collect all of the matches that can match against anything.
+    let matches = do enter_match(bcx, dm, m, col, val) |p| {
         match p.node {
           ast::pat_wild | ast::pat_tup(_) => Some(~[]),
           ast::pat_ident(_, _, None) if pat_is_binding(dm, p) => Some(~[]),
           _ => None
         }
-    }
+    };
+
+    // Ok, now, this is pretty subtle. A "default" match is a match
+    // that needs to be considered if none of the actual checks on the
+    // value being considered succeed. The subtlety lies in that sometimes
+    // identifier/wildcard matches are *not* default matches. Consider:
+    // "match x { _ if something => foo, true => bar, false => baz }".
+    // There is a wildcard match, but it is *not* a default case. The boolean
+    // case on the value being considered is exhaustive. If the case is
+    // exhaustive, then there are no defaults.
+    //
+    // We detect whether the case is exhaustive in the following
+    // somewhat kludgy way: if the last wildcard/binding match has a
+    // guard, then by non-redundancy, we know that there aren't any
+    // non guarded matches, and thus by exhaustiveness, we know that
+    // we don't need any default cases. If the check *isn't* nonexhaustive
+    // (because chk is Some), then we need the defaults anyways.
+    let is_exhaustive = match matches.last_opt() {
+        Some(m) if m.data.arm.guard.is_some() && chk.is_none() => true,
+        _ => false
+    };
+
+    if is_exhaustive { ~[] } else { matches }
 }
 
 // <pcwalton> nmatsakis: what does enter_opt do?
@@ -523,17 +597,19 @@ fn enter_opt<'r>(bcx: @mut Block,
                      variant_size: uint,
                      val: ValueRef)
                   -> ~[Match<'r>] {
-    debug!("enter_opt(bcx=%s, m=%s, col=%u, val=%s)",
+    debug!("enter_opt(bcx=%s, m=%s, opt=%?, col=%u, val=%s)",
            bcx.to_str(),
            m.repr(bcx.tcx()),
+           *opt,
            col,
            bcx.val_to_str(val));
     let _indenter = indenter();
 
     let tcx = bcx.tcx();
     let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
+    let mut i = 0;
     do enter_match(bcx, tcx.def_map, m, col, val) |p| {
-        match p.node {
+        let answer = match p.node {
             ast::pat_enum(*) |
             ast::pat_ident(_, _, None) if pat_is_const(tcx.def_map, p) => {
                 let const_def = tcx.def_map.get_copy(&p.id);
@@ -588,7 +664,7 @@ 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)
                             }
@@ -599,32 +675,53 @@ fn enter_opt<'r>(bcx: @mut Block,
                 }
             }
             ast::pat_vec(ref before, slice, ref after) => {
+                let (lo, hi) = match *opt {
+                    vec_len(_, _, (lo, hi)) => (lo, hi),
+                    _ => tcx.sess.span_bug(p.span,
+                                           "vec pattern but not vec opt")
+                };
+
                 match slice {
-                    Some(slice) => {
+                    Some(slice) if i >= lo && i <= hi => {
                         let n = before.len() + after.len();
-                        let i = before.len();
-                        if opt_eq(tcx, &vec_len_ge(n, i), opt) {
+                        let this_opt = vec_len(n, vec_len_ge(before.len()),
+                                               (lo, hi));
+                        if opt_eq(tcx, &this_opt, opt) {
                             Some(vec::append_one((*before).clone(), slice) +
                                     *after)
                         } else {
                             None
                         }
                     }
-                    None => {
+                    None if i >= lo && i <= hi => {
                         let n = before.len();
-                        if opt_eq(tcx, &vec_len_eq(n), opt) {
+                        if opt_eq(tcx, &vec_len(n, vec_len_eq, (lo,hi)), opt) {
                             Some((*before).clone())
                         } else {
                             None
                         }
                     }
+                    _ => None
                 }
             }
             _ => {
                 assert_is_binding_or_wild(bcx, p);
-                Some(vec::from_elem(variant_size, dummy))
+                // In most cases, a binding/wildcard match be
+                // considered to match against any Opt. However, when
+                // doing vector pattern matching, submatches are
+                // considered even if the eventual match might be from
+                // a different submatch. Thus, when a submatch fails
+                // when doing a vector match, we proceed to the next
+                // submatch. Thus, including a default match would
+                // cause the default match to fire spuriously.
+                match *opt {
+                    vec_len(*) => None,
+                    _ => Some(vec::from_elem(variant_size, dummy))
+                }
             }
-        }
+        };
+        i += 1;
+        answer
     }
 }
 
@@ -648,7 +745,7 @@ 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)
                     }
@@ -805,9 +902,25 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
         if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;}
         set.push(val);
     }
+    // Vector comparisions are special in that since the actual
+    // conditions over-match, we need to be careful about them. This
+    // means that in order to properly handle things in order, we need
+    // to not always merge conditions.
+    fn add_veclen_to_set(set: &mut ~[Opt], i: uint,
+                         len: uint, vlo: VecLenOpt) {
+        match set.last_opt() {
+            // If the last condition in the list matches the one we want
+            // to add, then extend its range. Otherwise, make a new
+            // vec_len with a range just covering the new entry.
+            Some(&vec_len(len2, vlo2, (start, end)))
+                 if len == len2 && vlo == vlo2 =>
+                 set[set.len() - 1] = vec_len(len, vlo, (start, end+1)),
+            _ => set.push(vec_len(len, vlo, (i, i)))
+        }
+    }
 
     let mut found = ~[];
-    for br in m.iter() {
+    for (i, br) in m.iter().enumerate() {
         let cur = br.pats[col];
         match cur.node {
             ast::pat_lit(l) => {
@@ -852,12 +965,12 @@ fn add_to_set(tcx: ty::ctxt, set: &mut ~[Opt], val: Opt) {
                 add_to_set(ccx.tcx, &mut found, range(l1, l2));
             }
             ast::pat_vec(ref before, slice, ref after) => {
-                let opt = match slice {
-                    None => vec_len_eq(before.len()),
-                    Some(_) => vec_len_ge(before.len() + after.len(),
-                                          before.len())
+                let (len, vec_opt) = match slice {
+                    None => (before.len(), vec_len_eq),
+                    Some(_) => (before.len() + after.len(),
+                                vec_len_ge(before.len()))
                 };
-                add_to_set(ccx.tcx, &mut found, opt);
+                add_veclen_to_set(&mut found, i, len, vec_opt);
             }
             _ => {}
         }
@@ -1075,13 +1188,13 @@ fn score(p: &ast::pat) -> uint {
     }
     let mut scores = vec::from_elem(m[0].pats.len(), 0u);
     for br in m.iter() {
-        let mut i = 0u;
-        for p in br.pats.iter() { scores[i] += score(*p); i += 1u; }
+        for (i, p) in br.pats.iter().enumerate() {
+            scores[i] += score(*p);
+        }
     }
     let mut max_score = 0u;
     let mut best_col = 0u;
-    let mut i = 0u;
-    for score in scores.iter() {
+    for (i, score) in scores.iter().enumerate() {
         let score = *score;
 
         // Irrefutable columns always go first, they'd only be duplicated in
@@ -1090,7 +1203,6 @@ fn score(p: &ast::pat) -> uint {
         // If no irrefutable ones are found, we pick the one with the biggest
         // branching factor.
         if score > max_score { max_score = score; best_col = i; }
-        i += 1u;
     }
     return best_col;
 }
@@ -1460,7 +1572,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
                 test_val = Load(bcx, val);
                 kind = compare;
             },
-            vec_len_eq(*) | vec_len_ge(*) => {
+            vec_len(*) => {
                 let vt = tvec::vec_types(bcx, node_id_type(bcx, pat_id));
                 let unboxed = load_if_immediate(bcx, val, vt.vec_ty);
                 let (_, len) = tvec::get_base_and_len(
@@ -1487,16 +1599,19 @@ fn compile_submatch_continue(mut bcx: @mut Block,
         C_int(ccx, 0) // Placeholder for when not using a switch
     };
 
-    let defaults = enter_default(else_cx, dm, m, col, val);
+    let defaults = enter_default(else_cx, dm, m, col, val, chk);
     let exhaustive = chk.is_none() && defaults.len() == 0u;
     let len = opts.len();
-    let mut i = 0u;
 
     // Compile subtrees for each option
-    for opt in opts.iter() {
-        i += 1u;
+    for (i, opt) in opts.iter().enumerate() {
+        // In some cases in vector pattern matching, we need to override
+        // the failure case so that instead of failing, it proceeds to
+        // try more matching. branch_chk, then, is the proper failure case
+        // for the current conditional branch.
+        let mut branch_chk = chk;
         let mut opt_cx = else_cx;
-        if !exhaustive || i < len {
+        if !exhaustive || i+1 < len {
             opt_cx = sub_block(bcx, "match_case");
             match kind {
               single => Br(bcx, opt_cx.llbb),
@@ -1586,6 +1701,10 @@ fn compile_submatch_continue(mut bcx: @mut Block,
                       }
                   };
                   bcx = sub_block(after_cx, "compare_vec_len_next");
+
+                  // If none of these subcases match, move on to the
+                  // next condition.
+                  branch_chk = Some::<mk_fail>(|| bcx.llbb);
                   CondBr(after_cx, matches, opt_cx.llbb, bcx.llbb);
               }
               _ => ()
@@ -1604,17 +1723,13 @@ fn compile_submatch_continue(mut bcx: @mut Block,
                 unpacked = argvals;
                 opt_cx = new_bcx;
             }
-            vec_len_eq(n) | vec_len_ge(n, _) => {
-                let n = match *opt {
-                    vec_len_ge(*) => n + 1u,
-                    _ => n
-                };
-                let slice = match *opt {
-                    vec_len_ge(_, i) => Some(i),
-                    _ => None
+            vec_len(n, vt, _) => {
+                let (n, slice) = match vt {
+                    vec_len_ge(i) => (n + 1u, Some(i)),
+                    vec_len_eq => (n, None)
                 };
-                let args = extract_vec_elems(opt_cx, pat_span, pat_id, n, slice,
-                                             val, test_val);
+                let args = extract_vec_elems(opt_cx, pat_span, pat_id, n,
+                                             slice, val, test_val);
                 size = args.vals.len();
                 unpacked = args.vals.clone();
                 opt_cx = args.bcx;
@@ -1623,7 +1738,7 @@ fn compile_submatch_continue(mut bcx: @mut Block,
         }
         let opt_ms = enter_opt(opt_cx, m, opt, col, size, val);
         let opt_vals = vec::append(unpacked, vals_left);
-        compile_submatch(opt_cx, opt_ms, opt_vals, chk);
+        compile_submatch(opt_cx, opt_ms, opt_vals, branch_chk);
     }
 
     // Compile the fall-through case, if any
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..1291a586682abc7438d35cc48b0223fb7b6041f7 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, }
@@ -2159,19 +2180,18 @@ pub fn trans_item(ccx: @mut CrateContext, item: &ast::item) {
       }
       ast::item_static(_, m, expr) => {
           consts::trans_const(ccx, m, item.id);
-          // Do static_assert checking. It can't really be done much earlier because we need to get
-          // the value of the bool out of LLVM
-          for attr in item.attrs.iter() {
-              if "static_assert" == attr.name() {
-                  if m == ast::m_mutbl {
-                      ccx.sess.span_fatal(expr.span,
-                                          "cannot have static_assert on a mutable static");
-                  }
-                  let v = ccx.const_values.get_copy(&item.id);
-                  unsafe {
-                      if !(llvm::LLVMConstIntGetZExtValue(v) as bool) {
-                          ccx.sess.span_fatal(expr.span, "static assertion failed");
-                      }
+          // Do static_assert checking. It can't really be done much earlier
+          // because we need to get the value of the bool out of LLVM
+          if attr::contains_name(item.attrs, "static_assert") {
+              if m == ast::m_mutbl {
+                  ccx.sess.span_fatal(expr.span,
+                                      "cannot have static_assert on a mutable \
+                                       static");
+              }
+              let v = ccx.const_values.get_copy(&item.id);
+              unsafe {
+                  if !(llvm::LLVMConstIntGetZExtValue(v) as bool) {
+                      ccx.sess.span_fatal(expr.span, "static assertion failed");
                   }
               }
           }
@@ -2312,7 +2332,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 +2342,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 +2360,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 +2385,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);
         }
     }
@@ -2386,12 +2405,7 @@ pub fn fill_fn_pair(bcx: @mut Block, pair: ValueRef, llfn: ValueRef,
 }
 
 pub fn item_path(ccx: &CrateContext, id: &ast::NodeId) -> path {
-    match ccx.tcx.items.get_copy(id) {
-        ast_map::node_item(i, p) =>
-            vec::append((*p).clone(), [path_name(i.ident)]),
-        // separate map for paths?
-        _ => fail!("item_path")
-    }
+    ty::item_path(ccx.tcx, ast_util::local_def(*id))
 }
 
 fn exported_name(ccx: @mut CrateContext, path: path, ty: ty::t, attrs: &[ast::Attribute]) -> ~str {
@@ -2428,10 +2442,19 @@ 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)
                                 };
 
+                                // Apply the `unnamed_addr` attribute if
+                                // requested
+                                if attr::contains_name(i.attrs,
+                                                       "address_insignificant"){
+                                    lib::llvm::SetUnnamedAddr(g, true);
+                                    lib::llvm::SetLinkage(g,
+                                        lib::llvm::InternalLinkage);
+                                }
+
                                 ccx.item_symbols.insert(i.id, sym);
                                 g
                             }
@@ -2452,7 +2475,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 +2516,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 +2623,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)
                 }
@@ -2720,6 +2743,60 @@ pub fn declare_intrinsics(llmod: ModuleRef) -> HashMap<&'static str, ValueRef> {
     ifn!("llvm.bswap.i32",[Type::i32()], Type::i32());
     ifn!("llvm.bswap.i64",[Type::i64()], Type::i64());
 
+    ifn!("llvm.sadd.with.overflow.i8",
+        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
+    ifn!("llvm.sadd.with.overflow.i16",
+        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
+    ifn!("llvm.sadd.with.overflow.i32",
+        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
+    ifn!("llvm.sadd.with.overflow.i64",
+        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
+
+    ifn!("llvm.uadd.with.overflow.i8",
+        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
+    ifn!("llvm.uadd.with.overflow.i16",
+        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
+    ifn!("llvm.uadd.with.overflow.i32",
+        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
+    ifn!("llvm.uadd.with.overflow.i64",
+        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
+
+    ifn!("llvm.ssub.with.overflow.i8",
+        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
+    ifn!("llvm.ssub.with.overflow.i16",
+        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
+    ifn!("llvm.ssub.with.overflow.i32",
+        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
+    ifn!("llvm.ssub.with.overflow.i64",
+        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
+
+    ifn!("llvm.usub.with.overflow.i8",
+        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
+    ifn!("llvm.usub.with.overflow.i16",
+        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
+    ifn!("llvm.usub.with.overflow.i32",
+        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
+    ifn!("llvm.usub.with.overflow.i64",
+        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
+
+    ifn!("llvm.smul.with.overflow.i8",
+        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
+    ifn!("llvm.smul.with.overflow.i16",
+        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
+    ifn!("llvm.smul.with.overflow.i32",
+        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
+    ifn!("llvm.smul.with.overflow.i64",
+        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
+
+    ifn!("llvm.umul.with.overflow.i8",
+        [Type::i8(), Type::i8()], Type::struct_([Type::i8(), Type::i1()], false));
+    ifn!("llvm.umul.with.overflow.i16",
+        [Type::i16(), Type::i16()], Type::struct_([Type::i16(), Type::i1()], false));
+    ifn!("llvm.umul.with.overflow.i32",
+        [Type::i32(), Type::i32()], Type::struct_([Type::i32(), Type::i1()], false));
+    ifn!("llvm.umul.with.overflow.i64",
+        [Type::i64(), Type::i64()], Type::struct_([Type::i64(), Type::i1()], false));
+
     return intrinsics;
 }
 
@@ -2741,7 +2818,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 +2833,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 +2881,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 +2900,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 +2963,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 +2991,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 c8e2a17c3b5f1bd93bc81448101c31e08a0404fb..dab970569212e8568e0e336cb05659c122f7cc24 100644 (file)
@@ -714,9 +714,11 @@ pub fn ExtractValue(cx: @mut Block, AggVal: ValueRef, Index: uint) -> ValueRef {
     }
 }
 
-pub fn InsertValue(cx: @mut Block, AggVal: ValueRef, EltVal: ValueRef, Index: uint) {
-    if cx.unreachable { return; }
-    B(cx).insert_value(AggVal, EltVal, Index)
+pub fn InsertValue(cx: @mut Block, AggVal: ValueRef, EltVal: ValueRef, Index: uint) -> ValueRef {
+    unsafe {
+        if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
+        B(cx).insert_value(AggVal, EltVal, Index)
+    }
 }
 
 pub fn IsNull(cx: @mut Block, Val: ValueRef) -> ValueRef {
index 1d821e5af94bd3769c8477a846978c66564209e9..5c216b2e14346684620185f0213be2666003b9b0 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)
@@ -861,11 +861,11 @@ pub fn extract_value(&self, agg_val: ValueRef, idx: uint) -> ValueRef {
     }
 
     pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef,
-                       idx: uint) {
+                       idx: uint) -> ValueRef {
         self.count_insn("insertvalue");
         unsafe {
             llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
-                                       noname());
+                                       noname())
         }
     }
 
@@ -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 a0e71bc22727969692c1acb775a07c4eda982f43..4caaf384873511c1dc8865f2bdcd895e7338781e 100644 (file)
@@ -60,7 +60,6 @@ pub struct MethodData {
     llfn: ValueRef,
     llself: ValueRef,
     temp_cleanup: Option<ValueRef>,
-    self_ty: ty::t,
     self_mode: ty::SelfMode,
 }
 
index 240696ec1908b5a706b5b1da79ef34308b87bf8f..3253e24ae8898a6045131d8c7e98727c960da635 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};
@@ -53,6 +54,7 @@ pub struct tydesc_info {
     tydesc: ValueRef,
     size: ValueRef,
     align: ValueRef,
+    borrow_offset: ValueRef,
     take_glue: Option<ValueRef>,
     drop_glue: Option<ValueRef>,
     free_glue: Option<ValueRef>,
@@ -237,7 +239,7 @@ pub fn arg_pos(&self, arg: uint) -> uint {
     }
 
     pub fn out_arg_pos(&self) -> uint {
-        assert!(self.has_immediate_return_value);
+        assert!(!self.has_immediate_return_value);
         0u
     }
 
@@ -315,7 +317,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) {
@@ -685,7 +687,6 @@ pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
                          t]);
 }
 
-
 // LLVM constant constructors.
 pub fn C_null(t: Type) -> ValueRef {
     unsafe {
@@ -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..187c121bbd33799b642c70304244213272a7f5f0 100644 (file)
@@ -13,7 +13,7 @@
 use driver::session;
 use lib::llvm::{ContextRef, ModuleRef, ValueRef};
 use lib::llvm::{llvm, TargetData, TypeNames};
-use lib::llvm::{mk_target_data};
+use lib::llvm::{mk_target_data, False};
 use metadata::common::LinkMeta;
 use middle::astencode;
 use middle::resolve;
 use middle::trans::builder::Builder;
 use middle::trans::debuginfo;
 use middle::trans::type_use;
+use middle::trans::common::{C_i32, C_null};
 use middle::ty;
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::hash;
 use std::hashmap::{HashMap, HashSet};
 use std::local_data;
+use std::vec;
+use std::libc::c_uint;
 use syntax::ast;
 
 use middle::trans::common::{mono_id,ExternMap,tydesc_info,BuilderRef_res,Stats};
@@ -124,11 +128,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);
@@ -229,6 +239,36 @@ pub fn new(sess: session::Session,
     pub fn builder(@mut self) -> Builder {
         Builder::new(self)
     }
+
+    pub fn const_inbounds_gepi(&self,
+                               pointer: ValueRef,
+                               indices: &[uint]) -> ValueRef {
+        debug!("const_inbounds_gepi: pointer=%s indices=%?",
+               self.tn.val_to_str(pointer), indices);
+        let v: ~[ValueRef] =
+            indices.iter().map(|i| C_i32(*i as i32)).collect();
+        unsafe {
+            llvm::LLVMConstInBoundsGEP(pointer,
+                                       vec::raw::to_ptr(v),
+                                       indices.len() as c_uint)
+        }
+    }
+
+    pub fn offsetof_gep(&self,
+                        llptr_ty: Type,
+                        indices: &[uint]) -> ValueRef {
+        /*!
+         * Returns the offset of applying the given GEP indices
+         * to an instance of `llptr_ty`. Similar to `offsetof` in C,
+         * except that `llptr_ty` must be a pointer type.
+         */
+
+        unsafe {
+            let null = C_null(llptr_ty);
+            llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
+                                    self.int_type.to_ref())
+        }
+    }
 }
 
 #[unsafe_destructor]
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..cb4a7f364dac6c39c11a21cb704161abaea696ea 100644 (file)
 use middle::trans::tvec;
 use middle::trans::type_of;
 use middle::ty::struct_fields;
-use middle::ty::{AutoDerefRef, AutoAddEnv};
-use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn,
-                 AutoUnsafe};
+use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoUnsafe};
+use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef, AutoBorrowFn};
 use middle::ty;
 use util::common::indenter;
 use util::ppaux::Repr;
@@ -223,6 +222,10 @@ pub fn trans_to_datum(bcx: @mut Block, expr: @ast::expr) -> DatumBlock {
                                                     datum.ty, Some(adjustment));
                     unpack_datum!(bcx, auto_borrow_fn(bcx, adjusted_ty, datum))
                 }
+                Some(AutoBorrowObj(*)) => {
+                    unpack_datum!(bcx, auto_borrow_obj(
+                        bcx, adj.autoderefs, expr, datum))
+                }
             };
         }
     }
@@ -298,6 +301,98 @@ fn auto_slice_and_ref(bcx: @mut Block,
         let DatumBlock { bcx, datum } = auto_slice(bcx, autoderefs, expr, datum);
         auto_ref(bcx, datum)
     }
+
+    fn auto_borrow_obj(mut bcx: @mut Block,
+                       autoderefs: uint,
+                       expr: @ast::expr,
+                       source_datum: Datum) -> DatumBlock {
+        let tcx = bcx.tcx();
+        let target_obj_ty = expr_ty_adjusted(bcx, expr);
+        debug!("auto_borrow_obj(target=%s)",
+               target_obj_ty.repr(tcx));
+        let scratch = scratch_datum(bcx, target_obj_ty,
+                                    "__auto_borrow_obj", false);
+
+        // Convert a @Object, ~Object, or &Object pair into an &Object pair.
+
+        // Get a pointer to the source object, which is represented as
+        // a (vtable, data) pair.
+        let source_llval = source_datum.to_ref_llval(bcx);
+
+        // Set the vtable field of the new pair
+        let vtable_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_vtable]);
+        let vtable = Load(bcx, vtable_ptr);
+        Store(bcx, vtable, GEPi(bcx, scratch.val, [0u, abi::trt_field_vtable]));
+
+        // Load the data for the source, which is either an @T,
+        // ~T, or &T, depending on source_obj_ty.
+        let source_data_ptr = GEPi(bcx, source_llval, [0u, abi::trt_field_box]);
+        let source_data = Load(bcx, source_data_ptr); // always a ptr
+        let (source_store, source_mutbl) = match ty::get(source_datum.ty).sty {
+            ty::ty_trait(_, _, s, m, _) => (s, m),
+            _ => {
+                bcx.sess().span_bug(
+                    expr.span,
+                    fmt!("auto_borrow_trait_obj expected a trait, found %s",
+                         source_datum.ty.repr(bcx.tcx())));
+            }
+        };
+        let target_data = match source_store {
+            ty::BoxTraitStore(*) => {
+                // For deref of @T or @mut T, create a dummy datum and
+                // use the datum's deref method. This is more work
+                // than just calling GEPi ourselves, but it ensures
+                // that any write guards will be appropriate
+                // processed.  Note that we don't know the type T, so
+                // just substitute `i8`-- it doesn't really matter for
+                // our purposes right now.
+                let source_ty =
+                    ty::mk_box(tcx,
+                               ty::mt {
+                                   ty: ty::mk_i8(),
+                                   mutbl: source_mutbl});
+                let source_datum =
+                    Datum {val: source_data,
+                           ty: source_ty,
+                           mode: ByValue};
+                let derefd_datum =
+                    unpack_datum!(bcx,
+                                  source_datum.deref(bcx,
+                                                     expr,
+                                                     autoderefs));
+                derefd_datum.to_rptr(bcx).to_value_llval(bcx)
+            }
+            ty::UniqTraitStore(*) => {
+                // For a ~T box, there may or may not be a header,
+                // depending on whether the type T references managed
+                // boxes. However, since we do not *know* the type T
+                // for objects, this presents a hurdle. Our solution is
+                // to load the "borrow offset" from the type descriptor;
+                // this value will either be 0 or sizeof(BoxHeader), depending
+                // on the type T.
+                let llopaque =
+                    PointerCast(bcx, source_data, Type::opaque().ptr_to());
+                let lltydesc_ptr_ptr =
+                    PointerCast(bcx, vtable,
+                                bcx.ccx().tydesc_type.ptr_to().ptr_to());
+                let lltydesc_ptr =
+                    Load(bcx, lltydesc_ptr_ptr);
+                let borrow_offset_ptr =
+                    GEPi(bcx, lltydesc_ptr,
+                         [0, abi::tydesc_field_borrow_offset]);
+                let borrow_offset =
+                    Load(bcx, borrow_offset_ptr);
+                InBoundsGEP(bcx, llopaque, [borrow_offset])
+            }
+            ty::RegionTraitStore(*) => {
+                source_data
+            }
+        };
+        Store(bcx, target_data,
+              GEPi(bcx, scratch.val, [0u, abi::trt_field_box]));
+
+        DatumBlock { bcx: bcx, datum: scratch }
+    }
 }
 
 pub fn trans_into(bcx: @mut Block, expr: @ast::expr, dest: Dest) -> @mut Block {
@@ -582,7 +677,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 +944,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 +973,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 +1031,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 b1e600b9d7376f5466d53ba06a500a948fe8e90d..7694f690286b77c7c83edb15f3c56fbcc9144b0b 100644 (file)
@@ -550,6 +550,24 @@ fn simple_llvm_intrinsic(bcx: @mut Block, name: &'static str, num_args: uint) {
         Ret(bcx, Call(bcx, llfn, args.slice(0, num_args)));
     }
 
+    fn with_overflow_instrinsic(bcx: @mut Block, name: &'static str) {
+        let first_real_arg = bcx.fcx.arg_pos(0u);
+        let a = get_param(bcx.fcx.llfn, first_real_arg);
+        let b = get_param(bcx.fcx.llfn, first_real_arg + 1);
+        let llfn = bcx.ccx().intrinsics.get_copy(&name);
+
+        // convert `i1` to a `bool`, and write to the out parameter
+        let val = Call(bcx, llfn, [a, b]);
+        let result = ExtractValue(bcx, val, 0);
+        let overflow = ZExt(bcx, ExtractValue(bcx, val, 1), Type::bool());
+        let retptr = get_param(bcx.fcx.llfn, bcx.fcx.out_arg_pos());
+        let ret = Load(bcx, retptr);
+        let ret = InsertValue(bcx, ret, result, 0);
+        let ret = InsertValue(bcx, ret, overflow, 1);
+        Store(bcx, ret, retptr);
+        RetVoid(bcx)
+    }
+
     fn memcpy_intrinsic(bcx: @mut Block, name: &'static str, tp_ty: ty::t, sizebits: u8) {
         let ccx = bcx.ccx();
         let lltp_ty = type_of::type_of(ccx, tp_ty);
@@ -839,8 +857,6 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
         "visit_tydesc" => {
             let td = get_param(decl, first_real_arg);
             let visitor = get_param(decl, first_real_arg + 1u);
-            //let llvisitorptr = alloca(bcx, val_ty(visitor));
-            //Store(bcx, visitor, llvisitorptr);
             let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to());
             glue::call_tydesc_glue_full(bcx, visitor, td,
                                         abi::tydesc_field_visit_glue, None);
@@ -944,6 +960,37 @@ fn count_zeros_intrinsic(bcx: @mut Block, name: &'static str) {
         "bswap16" => simple_llvm_intrinsic(bcx, "llvm.bswap.i16", 1),
         "bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1),
         "bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1),
+
+        "i8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i8"),
+        "i16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i16"),
+        "i32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i32"),
+        "i64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.sadd.with.overflow.i64"),
+
+        "u8_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i8"),
+        "u16_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i16"),
+        "u32_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i32"),
+        "u64_add_with_overflow" => with_overflow_instrinsic(bcx, "llvm.uadd.with.overflow.i64"),
+
+        "i8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i8"),
+        "i16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i16"),
+        "i32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i32"),
+        "i64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.ssub.with.overflow.i64"),
+
+        "u8_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i8"),
+        "u16_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i16"),
+        "u32_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i32"),
+        "u64_sub_with_overflow" => with_overflow_instrinsic(bcx, "llvm.usub.with.overflow.i64"),
+
+        "i8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i8"),
+        "i16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i16"),
+        "i32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i32"),
+        "i64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.smul.with.overflow.i64"),
+
+        "u8_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i8"),
+        "u16_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i16"),
+        "u32_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i32"),
+        "u64_mul_with_overflow" => with_overflow_instrinsic(bcx, "llvm.umul.with.overflow.i64"),
+
         _ => {
             // Could we make this an enum rather than a string? does it get
             // checked earlier?
index 948c9ceef8e6182da8188e5f6eb048ef556647cc..4f894deb1a1c19eed3d692569ea876997395a246 100644 (file)
@@ -37,6 +37,7 @@
 
 use middle::trans::type_::Type;
 
+use std::c_str::ToCStr;
 use std::libc::c_uint;
 use syntax::ast;
 
@@ -347,7 +348,8 @@ pub fn make_visit_glue(bcx: @mut Block, v: ValueRef, t: ty::t) -> @mut Block {
     let _icx = push_ctxt("make_visit_glue");
     do with_scope(bcx, None, "visitor cleanup") |bcx| {
         let mut bcx = bcx;
-        let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx()){
+        let (visitor_trait, object_ty) = match ty::visitor_object_ty(bcx.tcx(),
+                                                                     ty::re_static) {
             Ok(pair) => pair,
             Err(s) => {
                 bcx.tcx().sess.fatal(s);
@@ -654,12 +656,24 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
                   ppaux::ty_to_str(ccx.tcx, t));
     }
 
+    let has_header = match ty::get(t).sty {
+        ty::ty_box(*) => true,
+        ty::ty_uniq(*) => ty::type_contents(ccx.tcx, t).contains_managed(),
+        _ => false
+    };
+
+    let borrow_offset = if has_header {
+        ccx.offsetof_gep(llty, [0u, abi::box_field_body])
+    } else {
+        C_uint(ccx, 0)
+    };
+
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
     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)
         }
@@ -669,6 +683,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
         tydesc: gvar,
         size: llsize,
         align: llalign,
+        borrow_offset: borrow_offset,
         take_glue: None,
         drop_glue: None,
         free_glue: None,
@@ -784,13 +799,17 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               }
             };
 
+        debug!("ti.borrow_offset: %s",
+               ccx.tn.val_to_str(ti.borrow_offset));
+
         let tydesc = C_named_struct(ccx.tydesc_type,
                                     [ti.size, // size
-                                    ti.align, // align
-                                    take_glue, // take_glue
-                                    drop_glue, // drop_glue
-                                    free_glue, // free_glue
-                                    visit_glue]); // visit_glue
+                                     ti.align, // align
+                                     take_glue, // take_glue
+                                     drop_glue, // drop_glue
+                                     free_glue, // free_glue
+                                     visit_glue, // visit_glue
+                                     ti.borrow_offset]); // borrow_offset
 
         unsafe {
             let gvar = ti.tydesc;
index 9be01ef1db94f639da751f44bb3ed3ef253e31bd..f5b2ff755966e6cf3f29ff2f7b2cb2fe26202d19 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;
@@ -163,7 +164,6 @@ pub fn trans_method_callee(bcx: @mut Block,
                     llfn: callee_fn.llfn,
                     llself: val,
                     temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v),
-                    self_ty: node_id_type(bcx, this.id),
                     self_mode: mentry.self_mode,
                 })
             }
@@ -186,13 +186,11 @@ pub fn trans_method_callee(bcx: @mut Block,
             }
         }
 
-        typeck::method_trait(_, off, store) => {
+        typeck::method_trait(_, off) => {
             trans_trait_callee(bcx,
                                callee_id,
                                off,
-                               this,
-                               store,
-                               mentry.explicit_self)
+                               this)
         }
     }
 }
@@ -287,7 +285,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);
@@ -340,7 +338,6 @@ pub fn trans_monomorphized_callee(bcx: @mut Block,
                   llfn: llfn_val,
                   llself: llself_val,
                   temp_cleanup: temp_cleanups.head_opt().map_move(|v| *v),
-                  self_ty: node_id_type(bcx, base.id),
                   self_mode: mentry.self_mode,
               })
           }
@@ -405,142 +402,78 @@ pub fn combine_impl_and_methods_tps(bcx: @mut Block,
 pub fn trans_trait_callee(bcx: @mut Block,
                           callee_id: ast::NodeId,
                           n_method: uint,
-                          self_expr: @ast::expr,
-                          store: ty::TraitStore,
-                          explicit_self: ast::explicit_self_)
+                          self_expr: @ast::expr)
                           -> Callee {
-    //!
-    //
-    // Create a method callee where the method is coming from a trait
-    // instance (e.g., @Trait type).  In this case, we must pull the
-    // fn pointer out of the vtable that is packaged up with the
-    // @/~/&Trait instance.  @/~/&Traits are represented as a pair, so we
-    // first evaluate the self expression (expected a by-ref result) and then
-    // extract the self data and vtable out of the pair.
+    /*!
+     * Create a method callee where the method is coming from a trait
+     * object (e.g., @Trait type).  In this case, we must pull the fn
+     * pointer out of the vtable that is packaged up with the object.
+     * Objects are represented as a pair, so we first evaluate the self
+     * expression and then extract the self data and vtable out of the
+     * pair.
+     */
 
     let _icx = push_ctxt("impl::trans_trait_callee");
     let mut bcx = bcx;
-    let self_datum = unpack_datum!(bcx,
-        expr::trans_to_datum(bcx, self_expr));
-    let llpair = self_datum.to_ref_llval(bcx);
-
-    let llpair = match explicit_self {
-        ast::sty_region(*) => Load(bcx, llpair),
-        ast::sty_static | ast::sty_value |
-        ast::sty_box(_) | ast::sty_uniq => llpair
-    };
+
+    let self_ty = expr_ty_adjusted(bcx, self_expr);
+    let self_scratch = scratch_datum(bcx, self_ty, "__trait_callee", false);
+    bcx = expr::trans_into(bcx, self_expr, expr::SaveIn(self_scratch.val));
+
+    // Arrange a temporary cleanup for the object in case something
+    // should go wrong before the method is actually *invoked*.
+    self_scratch.add_clean(bcx);
 
     let callee_ty = node_id_type(bcx, callee_id);
     trans_trait_callee_from_llval(bcx,
                                   callee_ty,
                                   n_method,
-                                  llpair,
-                                  store,
-                                  explicit_self)
+                                  self_scratch.val,
+                                  Some(self_scratch.val))
 }
 
 pub fn trans_trait_callee_from_llval(bcx: @mut Block,
                                      callee_ty: ty::t,
                                      n_method: uint,
                                      llpair: ValueRef,
-                                     store: ty::TraitStore,
-                                     explicit_self: ast::explicit_self_)
+                                     temp_cleanup: Option<ValueRef>)
                                   -> Callee {
-    //!
-    //
-    // Same as `trans_trait_callee()` above, except that it is given
-    // a by-ref pointer to the @Trait pair.
+    /*!
+     * Same as `trans_trait_callee()` above, except that it is given
+     * a by-ref pointer to the object pair.
+     */
 
     let _icx = push_ctxt("impl::trans_trait_callee");
     let ccx = bcx.ccx();
 
-    // Load the vtable from the @Trait pair
-    debug!("(translating trait callee) loading vtable from pair %s",
-           bcx.val_to_str(llpair));
-    let llvtable = Load(bcx,
-                      PointerCast(bcx,
-                                  GEPi(bcx, llpair,
-                                       [0u, abi::trt_field_vtable]),
-                                  Type::vtable().ptr_to().ptr_to()));
-
-    // Load the box from the @Trait pair and GEP over the box header if
-    // necessary:
-    let mut llself;
+    // Load the data pointer from the object.
     debug!("(translating trait callee) loading second index from pair");
     let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]);
     let llbox = Load(bcx, llboxptr);
-
-    // Munge `llself` appropriately for the type of `self` in the method.
-    match explicit_self {
-        ast::sty_static => {
-            bcx.tcx().sess.bug("shouldn't see static method here");
-        }
-        ast::sty_value => {
-            bcx.tcx().sess.bug("methods with by-value self should not be \
-                                called on objects");
-        }
-        ast::sty_region(*) => {
-            match store {
-                ty::UniqTraitStore
-                    if !ty::type_contents(bcx.tcx(), callee_ty).contains_managed() => {
-                    llself = llbox;
-                }
-                ty::BoxTraitStore |
-                ty::UniqTraitStore => {
-                    llself = GEPi(bcx, llbox, [0u, abi::box_field_body]);
-                }
-                ty::RegionTraitStore(_) => {
-                    llself = llbox;
-                }
-            }
-        }
-        ast::sty_box(_) => {
-            // Bump the reference count on the box.
-            debug!("(translating trait callee) callee type is `%s`",
-                   bcx.ty_to_str(callee_ty));
-            glue::incr_refcnt_of_boxed(bcx, llbox);
-
-            // Pass a pointer to the box.
-            match store {
-                ty::BoxTraitStore => llself = llbox,
-                _ => bcx.tcx().sess.bug("@self receiver with non-@Trait")
-            }
-        }
-        ast::sty_uniq => {
-            // Pass the unique pointer.
-            match store {
-                ty::UniqTraitStore => llself = llbox,
-                _ => bcx.tcx().sess.bug("~self receiver with non-~Trait")
-            }
-
-            zero_mem(bcx, llboxptr, ty::mk_opaque_box(bcx.tcx()));
-        }
-    }
-
-    llself = PointerCast(bcx, llself, Type::opaque_box(ccx).ptr_to());
-    let scratch = scratch_datum(bcx, ty::mk_opaque_box(bcx.tcx()),
-                                "__trait_callee", false);
-    Store(bcx, llself, scratch.val);
-    scratch.add_clean(bcx);
+    let llself = PointerCast(bcx, llbox, Type::opaque_box(ccx).ptr_to());
 
     // Load the function from the vtable and cast it to the expected type.
     debug!("(translating trait callee) loading method");
     let llcallee_ty = type_of_fn_from_ty(ccx, callee_ty);
-
-    // Plus one in order to skip past the type descriptor.
+    let llvtable = Load(bcx,
+                        PointerCast(bcx,
+                                    GEPi(bcx, llpair,
+                                         [0u, abi::trt_field_vtable]),
+                                    Type::vtable().ptr_to().ptr_to()));
     let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
-
     let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
 
     return Callee {
         bcx: bcx,
         data: Method(MethodData {
             llfn: mptr,
-            llself: scratch.to_value_llval(bcx),
-            temp_cleanup: Some(scratch.val),
-            self_ty: scratch.ty,
+            llself: llself,
+            temp_cleanup: temp_cleanup,
+
+                // We know that the func declaration is &self, ~self,
+                // or @self, and such functions are always by-copy
+                // (right now, at least).
             self_mode: ty::ByCopy,
-            /* XXX: Some(llbox) */
         })
     };
 }
@@ -604,7 +537,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..fe5f8cd70ef19ba1d7f366c9373067b183634024 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 ]));
@@ -100,17 +100,13 @@ pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
             debug!("arg %u: %s", i, bcx.val_to_str(*a));
         }
         let bool_ty = ty::mk_bool();
-        // XXX: Should not be BoxTraitStore!
         let result = unpack_result!(bcx, callee::trans_call_inner(
             self.bcx, None, mth_ty, bool_ty,
             |bcx| meth::trans_trait_callee_from_llval(bcx,
                                                       mth_ty,
                                                       mth_idx,
                                                       v,
-                                                      ty::BoxTraitStore,
-                                                      ast::sty_region(
-                                                        None,
-                                                        ast::m_imm)),
+                                                      None),
             ArgVals(args), None, DontAutorefArg));
         let result = bool_to_i1(bcx, result);
         let next_bcx = sub_block(bcx, "next");
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..8d94a0d10d6fae3c71e2b5754b157886cd3fb334 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 {
@@ -204,10 +205,18 @@ pub fn tydesc(arch: Architecture) -> Type {
 
         let int_ty = Type::int(arch);
 
-        let elems = [
-            int_ty, int_ty,
-            glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
-        ];
+        // Must mirror:
+        //
+        // std::unstable::intrinsics::TyDesc
+        // type_desc in rt
+
+        let elems = [int_ty,     // size
+                     int_ty,     // align
+                     glue_fn_ty, // take
+                     glue_fn_ty, // drop
+                     glue_fn_ty, // free
+                     glue_fn_ty, // visit
+                     int_ty];    // borrow_offset
 
         tydesc.set_struct_body(elems, false);
 
@@ -248,8 +257,12 @@ pub fn box(ctx: &CrateContext, ty: &Type) -> Type {
         Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
     }
 
+    pub fn opaque() -> Type {
+        Type::i8()
+    }
+
     pub fn opaque_box(ctx: &CrateContext) -> Type {
-        Type::box(ctx, &Type::i8())
+        Type::box(ctx, &Type::opaque())
     }
 
     pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
index f25bf011f5d062f56c2130bb570bc725dc40e3d8..74661098348e671245ade9ace4f121a2503ed334 100644 (file)
@@ -168,6 +168,22 @@ fn store_type_uses(cx: Context, fn_id: def_id) -> @~[type_uses] {
 
                     "bswap16" | "bswap32" | "bswap64" => 0,
 
+
+                    "i8_add_with_overflow"  | "u8_add_with_overflow" |
+                    "i16_add_with_overflow" | "u16_add_with_overflow" |
+                    "i32_add_with_overflow" | "u32_add_with_overflow" |
+                    "i64_add_with_overflow" | "u64_add_with_overflow" => 0,
+
+                    "i8_sub_with_overflow"  | "u8_sub_with_overflow" |
+                    "i16_sub_with_overflow" | "u16_sub_with_overflow" |
+                    "i32_sub_with_overflow" | "u32_sub_with_overflow" |
+                    "i64_sub_with_overflow" | "u64_sub_with_overflow" => 0,
+
+                    "i8_mul_with_overflow"  | "u8_mul_with_overflow" |
+                    "i16_mul_with_overflow" | "u16_mul_with_overflow" |
+                    "i32_mul_with_overflow" | "u32_mul_with_overflow" |
+                    "i64_mul_with_overflow" | "u64_mul_with_overflow" => 0,
+
                     // would be cool to make these an enum instead of
                     // strings!
                     _ => fail!("unknown intrinsic in type_use")
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..2ba6930d9c5ea5193cd41e6071703708fc47984c 100644 (file)
@@ -226,13 +226,16 @@ pub enum AutoRef {
     AutoBorrowFn(Region),
 
     /// Convert from T to *T
-    AutoUnsafe(ast::mutability)
+    AutoUnsafe(ast::mutability),
+
+    /// Convert from @Trait/~Trait/&Trait to &Trait
+    AutoBorrowObj(Region, ast::mutability),
 }
 
 pub type ctxt = @ctxt_;
 
 struct ctxt_ {
-    diag: @syntax::diagnostic::span_handler,
+    diag: @mut syntax::diagnostic::span_handler,
     interner: @mut HashMap<intern_key, ~t_box_>,
     next_id: @mut uint,
     cstore: @mut metadata::cstore::CStore,
@@ -1004,7 +1007,13 @@ fn sflags(substs: &substs) -> uint {
       &ty_self(_) => flags |= has_self as uint,
       &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
       &ty_trait(_, ref substs, _, _, _) => {
-        flags |= sflags(substs);
+          flags |= sflags(substs);
+          match st {
+              ty_trait(_, _, RegionTraitStore(r), _, _) => {
+                    flags |= rflags(r);
+                }
+              _ => {}
+          }
       }
       &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
       &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
@@ -3009,6 +3018,10 @@ pub fn adjust_ty(cx: ctxt,
                         AutoUnsafe(m) => {
                             mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
                         }
+
+                        AutoBorrowObj(r, m) => {
+                            borrow_obj(cx, span, r, m, adjusted_ty)
+                        }
                     }
                 }
             }
@@ -3054,6 +3067,22 @@ fn borrow_fn(cx: ctxt, span: span, r: Region, ty: ty::t) -> ty::t {
             }
         }
     }
+
+    fn borrow_obj(cx: ctxt, span: span, r: Region,
+                  m: ast::mutability, ty: ty::t) -> ty::t {
+        match get(ty).sty {
+            ty_trait(trt_did, ref trt_substs, _, _, b) => {
+                ty::mk_trait(cx, trt_did, trt_substs.clone(),
+                             RegionTraitStore(r), m, b)
+            }
+            ref s => {
+                cx.sess.span_bug(
+                    span,
+                    fmt!("borrow-trait-obj associated with bad sty: %?",
+                         s));
+            }
+        }
+    }
 }
 
 impl AutoRef {
@@ -3064,6 +3093,7 @@ pub fn map_region(&self, f: &fn(Region) -> Region) -> AutoRef {
             ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m),
             ty::AutoBorrowFn(r) => ty::AutoBorrowFn(f(r)),
             ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
+            ty::AutoBorrowObj(r, m) => ty::AutoBorrowObj(f(r), m),
         }
     }
 }
@@ -3101,7 +3131,7 @@ pub fn method_call_type_param_defs(tcx: ctxt,
           typeck::method_param(typeck::method_param {
               trait_id: trt_id,
               method_num: n_mth, _}) |
-          typeck::method_trait(trt_id, n_mth, _) => {
+          typeck::method_trait(trt_id, n_mth) => {
             // ...trait methods bounds, in contrast, include only the
             // method bounds, so we must preprend the tps from the
             // trait itself.  This ought to be harmonized.
@@ -3791,9 +3821,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 +3965,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 +4147,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")
@@ -4457,7 +4487,8 @@ pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
     }
 }
 
-pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
+pub fn visitor_object_ty(tcx: ctxt,
+                         region: ty::Region) -> Result<(@TraitRef, t), ~str> {
     let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
         Ok(id) => id,
         Err(s) => { return Err(s); }
@@ -4468,13 +4499,11 @@ pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
         tps: ~[]
     };
     let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
-    let mut static_trait_bound = EmptyBuiltinBounds();
-    static_trait_bound.add(BoundStatic);
     Ok((trait_ref,
         mk_trait(tcx,
                  trait_ref.def_id,
                  trait_ref.substs.clone(),
-                 BoxTraitStore,
+                 RegionTraitStore(region),
                  ast::m_imm,
-                 static_trait_bound)))
+                 EmptyBuiltinBounds())))
 }
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..352836d81e45926e4d2a4e1bcbc5672cc6ae8135 100644 (file)
@@ -94,6 +94,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
 use middle::typeck::{param_numbered, param_self, param_index};
 use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
 use util::common::indenter;
+use util::ppaux::Repr;
 
 use std::hashmap::HashSet;
 use std::result;
@@ -147,9 +148,24 @@ pub fn lookup(
         check_traits: check_traits,
         autoderef_receiver: autoderef_receiver,
     };
-    let mme = lcx.do_lookup(self_ty);
-    debug!("method lookup for %s yielded %?", expr.repr(fcx.tcx()), mme);
-    return mme;
+
+    let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty);
+    debug!("method lookup(self_ty=%s, expr=%s, self_expr=%s)",
+           self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
+           self_expr.repr(fcx.tcx()));
+
+    debug!("searching inherent candidates");
+    lcx.push_inherent_candidates(self_ty);
+    let mme = lcx.search(self_ty);
+    if mme.is_some() {
+        return mme;
+    }
+
+    debug!("searching extension candidates");
+    lcx.reset_candidates();
+    lcx.push_bound_candidates(self_ty);
+    lcx.push_extension_candidates();
+    return lcx.search(self_ty);
 }
 
 pub struct LookupContext<'self> {
@@ -173,27 +189,28 @@ pub struct LookupContext<'self> {
  */
 #[deriving(Clone)]
 pub struct Candidate {
-    rcvr_ty: ty::t,
+    rcvr_match_condition: RcvrMatchCondition,
     rcvr_substs: ty::substs,
     method_ty: @ty::Method,
     origin: method_origin,
 }
 
-impl<'self> LookupContext<'self> {
-    pub fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
-        let self_ty = structurally_resolved_type(self.fcx,
-                                                     self.self_expr.span,
-                                                     self_ty);
-
-        debug!("do_lookup(self_ty=%s, expr=%s, self_expr=%s)",
-               self.ty_to_str(self_ty),
-               self.expr.repr(self.tcx()),
-               self.self_expr.repr(self.tcx()));
-
-        // Prepare the list of candidates
-        self.push_inherent_candidates(self_ty);
-        self.push_extension_candidates();
+/// This type represents the conditions under which the receiver is
+/// considered to "match" a given method candidate. Typically the test
+/// is whether the receiver is of a particular type. However, this
+/// type is the type of the receiver *after accounting for the
+/// method's self type* (e.g., if the method is an `@self` method, we
+/// have *already verified* that the receiver is of some type `@T` and
+/// now we must check that the type `T` is correct).  Unfortunately,
+/// because traits are not types, this is a pain to do.
+#[deriving(Clone)]
+enum RcvrMatchCondition {
+    RcvrMatchesIfObject(ast::def_id),
+    RcvrMatchesIfSubtype(ty::t)
+}
 
+impl<'self> LookupContext<'self> {
+    fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
         let mut self_ty = self_ty;
         let mut autoderefs = 0;
         loop {
@@ -247,7 +264,7 @@ pub fn do_lookup(&self, self_ty: ty::t) -> Option<method_map_entry> {
         self.search_for_autosliced_method(self_ty, autoderefs)
     }
 
-    pub fn deref(&self, ty: ty::t)
+    fn deref(&self, ty: ty::t)
                  -> Option<ty::t> {
         match ty::deref(self.tcx(), ty, false) {
             None => None,
@@ -262,7 +279,12 @@ pub fn deref(&self, ty: ty::t)
     // ______________________________________________________________________
     // Candidate collection (see comment at start of file)
 
-    pub fn push_inherent_candidates(&self, self_ty: ty::t) {
+    fn reset_candidates(&self) {
+        *self.inherent_candidates = ~[];
+        *self.extension_candidates = ~[];
+    }
+
+    fn push_inherent_candidates(&self, self_ty: ty::t) {
         /*!
          * Collect all inherent candidates into
          * `self.inherent_candidates`.  See comment at the start of
@@ -275,20 +297,10 @@ pub fn push_inherent_candidates(&self, self_ty: ty::t) {
         let mut self_ty = self_ty;
         loop {
             match get(self_ty).sty {
-                ty_param(p) => {
-                    self.push_inherent_candidates_from_param(self_ty, p);
-                }
-                ty_trait(did, ref substs, store, _, _) => {
-                    self.push_inherent_candidates_from_trait(
-                        self_ty, did, substs, store);
+                ty_trait(did, ref substs, _, _, _) => {
+                    self.push_inherent_candidates_from_trait(did, substs);
                     self.push_inherent_impl_candidates_for_type(did);
                 }
-                ty_self(self_did) => {
-                    // Call is of the form "self.foo()" and appears in one
-                    // of a trait's default method implementations.
-                    self.push_inherent_candidates_from_self(
-                        self_ty, self_did);
-                }
                 ty_enum(did, _) | ty_struct(did, _) => {
                     if self.check_traits == CheckTraitsAndInherentMethods {
                         self.push_inherent_impl_candidates_for_type(did);
@@ -307,7 +319,30 @@ pub fn push_inherent_candidates(&self, self_ty: ty::t) {
         }
     }
 
-    pub fn push_extension_candidates(&self) {
+    fn push_bound_candidates(&self, self_ty: ty::t) {
+        let mut self_ty = self_ty;
+        loop {
+            match get(self_ty).sty {
+                ty_param(p) => {
+                    self.push_inherent_candidates_from_param(self_ty, p);
+                }
+                ty_self(self_did) => {
+                    // Call is of the form "self.foo()" and appears in one
+                    // of a trait's default method implementations.
+                    self.push_inherent_candidates_from_self(
+                        self_ty, self_did);
+                }
+                _ => { /* No bound methods in these types */ }
+            }
+
+            self_ty = match self.deref(self_ty) {
+                None => { return; }
+                Some(ty) => { ty }
+            }
+        }
+    }
+
+    fn push_extension_candidates(&self) {
         // If the method being called is associated with a trait, then
         // find all the impls of that trait.  Each of those are
         // candidates.
@@ -328,11 +363,9 @@ pub fn push_extension_candidates(&self) {
         }
     }
 
-    pub fn push_inherent_candidates_from_trait(&self,
-                                               self_ty: ty::t,
+    fn push_inherent_candidates_from_trait(&self,
                                                did: def_id,
-                                               substs: &ty::substs,
-                                               store: ty::TraitStore) {
+                                               substs: &ty::substs) {
         debug!("push_inherent_candidates_from_trait(did=%s, substs=%s)",
                self.did_to_str(did),
                substs_to_str(self.tcx(), substs));
@@ -346,41 +379,35 @@ pub fn push_inherent_candidates_from_trait(&self,
         };
         let method = ms[index];
 
-        /* FIXME(#5762) we should transform the vstore in accordance
-           with the self type
-
-        match method.self_type {
-            ast::sty_region(_) => {
-                return; // inapplicable
+        match method.explicit_self {
+            ast::sty_static => {
+                return; // not a method we can call with dot notation
             }
-            ast::sty_region(_) => vstore_slice(r)
-            ast::sty_box(_) => vstore_box, // NDM mutability, as per #5762
-            ast::sty_uniq(_) => vstore_uniq
+            _ => {}
         }
-        */
 
         // It is illegal to invoke a method on a trait instance that
-        // refers to the `self` type.  Nonetheless, we substitute
-        // `trait_ty` for `self` here, because it allows the compiler
-        // to soldier on.  An error will be reported should this
-        // candidate be selected if the method refers to `self`.
+        // refers to the `self` type. An error will be reported by
+        // `enforce_object_limitations()` if the method refers
+        // to the `Self` type. Substituting ty_err here allows
+        // compiler to soldier on.
         //
-        // NB: `confirm_candidate()` also relies upon this substitution
-        // for Self.
+        // NOTE: `confirm_candidate()` also relies upon this substitution
+        // for Self. (fix)
         let rcvr_substs = substs {
-            self_ty: Some(self_ty),
+            self_ty: Some(ty::mk_err()),
             ..(*substs).clone()
         };
 
         self.inherent_candidates.push(Candidate {
-            rcvr_ty: self_ty,
+            rcvr_match_condition: RcvrMatchesIfObject(did),
             rcvr_substs: rcvr_substs,
             method_ty: method,
-            origin: method_trait(did, index, store)
+            origin: method_trait(did, index)
         });
     }
 
-    pub fn push_inherent_candidates_from_param(&self,
+    fn push_inherent_candidates_from_param(&self,
                                                rcvr_ty: ty::t,
                                                param_ty: param_ty) {
         debug!("push_inherent_candidates_from_param(param_ty=%?)",
@@ -403,7 +430,7 @@ pub fn push_inherent_candidates_from_param(&self,
     }
 
 
-    pub fn push_inherent_candidates_from_self(&self,
+    fn push_inherent_candidates_from_self(&self,
                                               self_ty: ty::t,
                                               did: def_id) {
         let tcx = self.tcx();
@@ -413,7 +440,7 @@ pub fn push_inherent_candidates_from_self(&self,
             self_ty, &[trait_ref], param_self);
     }
 
-    pub fn push_inherent_candidates_from_bounds(&self,
+    fn push_inherent_candidates_from_bounds(&self,
                                                 self_ty: ty::t,
                                                 bounds: &[@TraitRef],
                                                 param: param_index) {
@@ -433,11 +460,11 @@ pub fn push_inherent_candidates_from_bounds(&self,
                     let method = trait_methods[pos];
 
                     let cand = Candidate {
-                        rcvr_ty: self_ty,
+                        rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
                         rcvr_substs: bound_trait_ref.substs.clone(),
                         method_ty: method,
                         origin: method_param(
-                            method_param {
+                                             method_param {
                                 trait_id: bound_trait_ref.def_id,
                                 method_num: pos,
                                 param_num: param,
@@ -459,7 +486,7 @@ pub fn push_inherent_candidates_from_bounds(&self,
     }
 
 
-    pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
+    fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
         let opt_impl_infos = self.tcx().inherent_impls.find(&did);
         for impl_infos in opt_impl_infos.iter() {
             for impl_info in impl_infos.iter() {
@@ -469,7 +496,7 @@ pub fn push_inherent_impl_candidates_for_type(&self, did: def_id) {
         }
     }
 
-    pub fn push_candidates_from_impl(&self,
+    fn push_candidates_from_impl(&self,
                                      candidates: &mut ~[Candidate],
                                      impl_info: &ty::Impl) {
         if !self.impl_dups.insert(impl_info.did) {
@@ -502,7 +529,7 @@ pub fn push_candidates_from_impl(&self,
         } = impl_self_ty(&vcx, location_info, impl_info.did);
 
         candidates.push(Candidate {
-            rcvr_ty: impl_ty,
+            rcvr_match_condition: RcvrMatchesIfSubtype(impl_ty),
             rcvr_substs: impl_substs,
             method_ty: method,
             origin: method_static(method.def_id)
@@ -512,7 +539,7 @@ pub fn push_candidates_from_impl(&self,
     // ______________________________________________________________________
     // Candidate selection (see comment at start of file)
 
-    pub fn search_for_autoderefd_method(&self,
+    fn search_for_autoderefd_method(&self,
                                         self_ty: ty::t,
                                         autoderefs: uint)
                                         -> Option<method_map_entry> {
@@ -531,12 +558,11 @@ pub fn search_for_autoderefd_method(&self,
         }
     }
 
-    pub fn consider_reborrow(&self,
+    fn consider_reborrow(&self,
                              self_ty: ty::t,
                              autoderefs: uint)
                              -> (ty::t, ty::AutoAdjustment) {
         /*!
-         *
          * In the event that we are invoking a method with a receiver
          * of a borrowed type like `&T`, `&mut T`, or `&mut [T]`,
          * we will "reborrow" the receiver implicitly.  For example, if
@@ -579,6 +605,17 @@ pub fn consider_reborrow(&self,
                      autoderefs: autoderefs,
                      autoref: Some(ty::AutoBorrowVec(region, self_mt.mutbl))}))
             }
+            ty_trait(did, ref substs, ty::RegionTraitStore(_), mutbl, bounds) => {
+                let region =
+                    self.infcx().next_region_var(
+                        infer::Autoref(self.expr.span));
+                (ty::mk_trait(tcx, did, substs.clone(),
+                              ty::RegionTraitStore(region),
+                              mutbl, bounds),
+                 ty::AutoDerefRef(ty::AutoDerefRef {
+                     autoderefs: autoderefs,
+                     autoref: Some(ty::AutoBorrowObj(region, mutbl))}))
+            }
             _ => {
                 (self_ty,
                  ty::AutoDerefRef(ty::AutoDerefRef {
@@ -598,7 +635,7 @@ fn default_method_hack(self_mt: ty::mt) -> bool {
         }
     }
 
-    pub fn search_for_autosliced_method(&self,
+    fn search_for_autosliced_method(&self,
                                         self_ty: ty::t,
                                         autoderefs: uint)
                                         -> Option<method_map_entry> {
@@ -608,7 +645,8 @@ pub fn search_for_autosliced_method(&self,
          * `~[]` to `&[]`. */
 
         let tcx = self.tcx();
-        match ty::get(self_ty).sty {
+        let sty = ty::get(self_ty).sty.clone();
+        match sty {
             ty_evec(mt, vstore_box) |
             ty_evec(mt, vstore_uniq) |
             ty_evec(mt, vstore_slice(_)) | // NDM(#3148)
@@ -655,8 +693,20 @@ pub fn search_for_autosliced_method(&self,
                     })
             }
 
-            ty_trait(*) | ty_closure(*) => {
-                // NDM---eventually these should be some variant of autoref
+            ty_trait(trt_did, trt_substs, _, _, b) => {
+                // Coerce ~/@/&Trait instances to &Trait.
+
+                self.search_for_some_kind_of_autorefd_method(
+                    AutoBorrowObj, autoderefs, [m_const, m_imm, m_mutbl],
+                    |trt_mut, reg| {
+                        ty::mk_trait(tcx, trt_did, trt_substs.clone(),
+                                     RegionTraitStore(reg), trt_mut, b)
+                    })
+            }
+
+            ty_closure(*) => {
+                // This case should probably be handled similarly to
+                // Trait instances.
                 None
             }
 
@@ -664,7 +714,7 @@ pub fn search_for_autosliced_method(&self,
         }
     }
 
-    pub fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
+    fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
                                       -> Option<method_map_entry> {
         /*!
          *
@@ -696,7 +746,7 @@ pub fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
         }
     }
 
-    pub fn search_for_some_kind_of_autorefd_method(
+    fn search_for_some_kind_of_autorefd_method(
         &self,
         kind: &fn(Region, ast::mutability) -> ty::AutoRef,
         autoderefs: uint,
@@ -725,7 +775,7 @@ pub fn search_for_some_kind_of_autorefd_method(
         return None;
     }
 
-    pub fn search_for_method(&self, rcvr_ty: ty::t)
+    fn search_for_method(&self, rcvr_ty: ty::t)
                              -> Option<method_map_entry> {
         debug!("search_for_method(rcvr_ty=%s)", self.ty_to_str(rcvr_ty));
         let _indenter = indenter();
@@ -753,13 +803,13 @@ pub fn search_for_method(&self, rcvr_ty: ty::t)
         }
     }
 
-    pub fn consider_candidates(&self,
+    fn consider_candidates(&self,
                                rcvr_ty: ty::t,
                                candidates: &mut ~[Candidate])
                                -> 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);
@@ -780,7 +830,7 @@ pub fn consider_candidates(&self,
         Some(self.confirm_candidate(rcvr_ty, &relevant_candidates[0]))
     }
 
-    pub fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
+    fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
         let mut merged = ~[];
         let mut i = 0;
         while i < candidates.len() {
@@ -826,7 +876,7 @@ pub fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
         return merged;
     }
 
-    pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
+    fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
                              -> method_map_entry {
         let tcx = self.tcx();
         let fty = self.fn_ty_from_origin(&candidate.origin);
@@ -836,31 +886,16 @@ pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
                self.cand_to_str(candidate),
                self.ty_to_str(fty));
 
-        self.enforce_trait_instance_limitations(fty, candidate);
+        self.enforce_object_limitations(fty, candidate);
         self.enforce_drop_trait_limitations(candidate);
 
         // static methods should never have gotten this far:
         assert!(candidate.method_ty.explicit_self != sty_static);
 
         let transformed_self_ty = match candidate.origin {
-            method_trait(*) => {
-                match candidate.method_ty.explicit_self {
-                    sty_region(*) => {
-                        // FIXME(#5762) again, preserving existing
-                        // behavior here which (for &self) desires
-                        // &@Trait where @Trait is the type of the
-                        // receiver.  Here we fetch the method's
-                        // transformed_self_ty which will be something
-                        // like &'a Self.  We then perform a
-                        // substitution which will replace Self with
-                        // @Trait.
-                        let t = candidate.method_ty.transformed_self_ty.unwrap();
-                        ty::subst(tcx, &candidate.rcvr_substs, t)
-                    }
-                    _ => {
-                        candidate.rcvr_ty
-                    }
-                }
+            method_trait(trait_def_id, _) => {
+                self.construct_transformed_self_ty_for_object(
+                    trait_def_id, candidate)
             }
             _ => {
                 let t = candidate.method_ty.transformed_self_ty.unwrap();
@@ -950,23 +985,88 @@ pub fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
         self.fcx.write_ty(self.callee_id, fty);
         self.fcx.write_substs(self.callee_id, all_substs);
         method_map_entry {
-            self_ty: rcvr_ty,
+            self_ty: transformed_self_ty,
             self_mode: self_mode,
             explicit_self: candidate.method_ty.explicit_self,
             origin: candidate.origin,
         }
     }
 
-    pub fn enforce_trait_instance_limitations(&self,
-                                              method_fty: ty::t,
-                                              candidate: &Candidate) {
+    fn construct_transformed_self_ty_for_object(&self,
+                                                trait_def_id: ast::def_id,
+                                                candidate: &Candidate) -> ty::t
+    {
         /*!
+         * This is a bit tricky. We have a match against a trait method
+         * being invoked on an object, and we want to generate the
+         * self-type. As an example, consider a trait
+         *
+         *     trait Foo {
+         *         fn r_method<'a>(&'a self);
+         *         fn m_method(@mut self);
+         *     }
          *
-         * There are some limitations to calling functions through a
-         * trait instance, because (a) the self type is not known
+         * Now, assuming that `r_method` is being called, we want the
+         * result to be `&'a Foo`. Assuming that `m_method` is being
+         * called, we want the result to be `@mut Foo`. Of course,
+         * this transformation has already been done as part of
+         * `candidate.method_ty.transformed_self_ty`, but there the
+         * type is expressed in terms of `Self` (i.e., `&'a Self`, `@mut Self`).
+         * Because objects are not standalone types, we can't just substitute
+         * `s/Self/Foo/`, so we must instead perform this kind of hokey
+         * match below.
+         */
+
+        let substs = ty::substs {regions: candidate.rcvr_substs.regions.clone(),
+                                 self_ty: None,
+                                 tps: candidate.rcvr_substs.tps.clone()};
+        match candidate.method_ty.explicit_self {
+            ast::sty_static => {
+                self.bug(~"static method for object type receiver");
+            }
+            ast::sty_value => {
+                ty::mk_err() // error reported in `enforce_object_limitations()`
+            }
+            ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {
+                let transformed_self_ty =
+                    candidate.method_ty.transformed_self_ty.clone().unwrap();
+                match ty::get(transformed_self_ty).sty {
+                    ty::ty_rptr(r, mt) => { // must be sty_region
+                        ty::mk_trait(self.tcx(), trait_def_id,
+                                     substs, RegionTraitStore(r), mt.mutbl,
+                                     ty::EmptyBuiltinBounds())
+                    }
+                    ty::ty_box(mt) => { // must be sty_box
+                        ty::mk_trait(self.tcx(), trait_def_id,
+                                     substs, BoxTraitStore, mt.mutbl,
+                                     ty::EmptyBuiltinBounds())
+                    }
+                    ty::ty_uniq(mt) => { // must be sty_uniq
+                        ty::mk_trait(self.tcx(), trait_def_id,
+                                     substs, UniqTraitStore, mt.mutbl,
+                                     ty::EmptyBuiltinBounds())
+                    }
+                    _ => {
+                        self.bug(
+                            fmt!("'impossible' transformed_self_ty: %s",
+                                 transformed_self_ty.repr(self.tcx())));
+                    }
+                }
+            }
+        }
+    }
+
+    fn enforce_object_limitations(&self,
+                                  method_fty: ty::t,
+                                  candidate: &Candidate)
+    {
+        /*!
+         * There are some limitations to calling functions through an
+         * object, because (a) the self type is not known
          * (that's the whole point of a trait instance, after all, to
          * obscure the self type) and (b) the call must go through a
-         * vtable and hence cannot be monomorphized. */
+         * vtable and hence cannot be monomorphized.
+         */
 
         match candidate.origin {
             method_static(*) | method_param(*) => {
@@ -975,21 +1075,39 @@ pub fn enforce_trait_instance_limitations(&self,
             method_trait(*) => {}
         }
 
-        if ty::type_has_self(method_fty) {
+        match candidate.method_ty.explicit_self {
+            ast::sty_static => { // reason (a) above
+                self.tcx().sess.span_err(
+                    self.expr.span,
+                    "cannot call a method without a receiver \
+                     through an object");
+            }
+
+            ast::sty_value => { // reason (a) above
+                self.tcx().sess.span_err(
+                    self.expr.span,
+                    "cannot call a method with a by-value receiver \
+                     through an object");
+            }
+
+            ast::sty_region(*) | ast::sty_box(*) | ast::sty_uniq(*) => {}
+        }
+
+        if ty::type_has_self(method_fty) { // reason (a) above
             self.tcx().sess.span_err(
                 self.expr.span,
                 "cannot call a method whose type contains a \
-                 self-type through a boxed trait");
+                 self-type through an object");
         }
 
-        if candidate.method_ty.generics.has_type_params() {
+        if candidate.method_ty.generics.has_type_params() { // reason (b) above
             self.tcx().sess.span_err(
                 self.expr.span,
-                "cannot call a generic method through a boxed trait");
+                "cannot call a generic method through an object");
         }
     }
 
-    pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
+    fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
         // No code can call the finalize method explicitly.
         let bad;
         match candidate.origin {
@@ -999,7 +1117,7 @@ pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
             // XXX: does this properly enforce this on everything now
             // that self has been merged in? -sully
             method_param(method_param { trait_id: trait_id, _ }) |
-            method_trait(trait_id, _, _) => {
+            method_trait(trait_id, _) => {
                 bad = self.tcx().destructor_for_type.contains_key(&trait_id);
             }
         }
@@ -1012,43 +1130,18 @@ pub fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
 
     // `rcvr_ty` is the type of the expression. It may be a subtype of a
     // candidate method's `self_ty`.
-    pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
+    fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
         debug!("is_relevant(rcvr_ty=%s, candidate=%s)",
                self.ty_to_str(rcvr_ty), self.cand_to_str(candidate));
 
-        // Check for calls to object methods.  We resolve these differently.
-        //
-        // FIXME(#5762)---we don't check that an @self method is only called
-        // on an @Trait object here and so forth
-        match candidate.origin {
-            method_trait(*) => {
-                match candidate.method_ty.explicit_self {
-                    sty_static | sty_value => {
-                        return false;
-                    }
-                    sty_region(*) => {
-                        // just echoing current behavior here, which treats
-                        // an &self method on an @Trait object as requiring
-                        // an &@Trait receiver (wacky)
-                    }
-                    sty_box(*) | sty_uniq(*) => {
-                        return self.fcx.can_mk_subty(rcvr_ty,
-                                                     candidate.rcvr_ty).is_ok();
-                    }
-                };
-            }
-            _ => {}
-        }
-
-        let result = match candidate.method_ty.explicit_self {
+        return match candidate.method_ty.explicit_self {
             sty_static => {
                 debug!("(is relevant?) explicit self is static");
                 false
             }
 
             sty_value => {
-                debug!("(is relevant?) explicit self is by-value");
-                self.fcx.can_mk_subty(rcvr_ty, candidate.rcvr_ty).is_ok()
+                rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
             }
 
             sty_region(_, m) => {
@@ -1056,7 +1149,12 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
                 match ty::get(rcvr_ty).sty {
                     ty::ty_rptr(_, mt) => {
                         mutability_matches(mt.mutbl, m) &&
-                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
+                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    }
+
+                    ty::ty_trait(self_did, _, RegionTraitStore(_), self_m, _) => {
+                        mutability_matches(self_m, m) &&
+                        rcvr_matches_object(self_did, candidate)
                     }
 
                     _ => false
@@ -1068,7 +1166,12 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
                 match ty::get(rcvr_ty).sty {
                     ty::ty_box(mt) => {
                         mutability_matches(mt.mutbl, m) &&
-                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
+                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    }
+
+                    ty::ty_trait(self_did, _, BoxTraitStore, self_m, _) => {
+                        mutability_matches(self_m, m) &&
+                        rcvr_matches_object(self_did, candidate)
                     }
 
                     _ => false
@@ -1079,8 +1182,11 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
                 debug!("(is relevant?) explicit self is a unique pointer");
                 match ty::get(rcvr_ty).sty {
                     ty::ty_uniq(mt) => {
-                        mutability_matches(mt.mutbl, ast::m_imm) &&
-                        self.fcx.can_mk_subty(mt.ty, candidate.rcvr_ty).is_ok()
+                        rcvr_matches_ty(self.fcx, mt.ty, candidate)
+                    }
+
+                    ty::ty_trait(self_did, _, UniqTraitStore, _, _) => {
+                        rcvr_matches_object(self_did, candidate)
                     }
 
                     _ => false
@@ -1088,9 +1194,30 @@ pub fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
             }
         };
 
-        debug!("(is relevant?) %s", if result { "yes" } else { "no" });
+        fn rcvr_matches_object(self_did: ast::def_id,
+                               candidate: &Candidate) -> bool {
+            match candidate.rcvr_match_condition {
+                RcvrMatchesIfObject(desired_did) => {
+                    self_did == desired_did
+                }
+                RcvrMatchesIfSubtype(_) => {
+                    false
+                }
+            }
+        }
 
-        return result;
+        fn rcvr_matches_ty(fcx: @mut FnCtxt,
+                           rcvr_ty: ty::t,
+                           candidate: &Candidate) -> bool {
+            match candidate.rcvr_match_condition {
+                RcvrMatchesIfObject(_) => {
+                    false
+                }
+                RcvrMatchesIfSubtype(of_type) => {
+                    fcx.can_mk_subty(rcvr_ty, of_type).is_ok()
+                }
+            }
+        }
 
         fn mutability_matches(self_mutbl: ast::mutability,
                               candidate_mutbl: ast::mutability) -> bool {
@@ -1108,7 +1235,7 @@ fn mutability_matches(self_mutbl: ast::mutability,
         }
     }
 
-    pub fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
+    fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
         return match *origin {
             method_static(did) => {
                 ty::lookup_item_type(self.tcx(), did).ty
@@ -1116,7 +1243,7 @@ pub fn fn_ty_from_origin(&self, origin: &method_origin) -> ty::t {
             method_param(ref mp) => {
                 type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num)
             }
-            method_trait(did, idx, _) => {
+            method_trait(did, idx) => {
                 type_of_trait_method(self.tcx(), did, idx)
             }
         };
@@ -1129,7 +1256,7 @@ fn type_of_trait_method(tcx: ty::ctxt,
         }
     }
 
-    pub fn report_candidate(&self, idx: uint, origin: &method_origin) {
+    fn report_candidate(&self, idx: uint, origin: &method_origin) {
         match *origin {
             method_static(impl_did) => {
                 self.report_static_candidate(idx, impl_did)
@@ -1137,13 +1264,13 @@ pub fn report_candidate(&self, idx: uint, origin: &method_origin) {
             method_param(ref mp) => {
                 self.report_param_candidate(idx, (*mp).trait_id)
             }
-            method_trait(trait_did, _, _) => {
+            method_trait(trait_did, _) => {
                 self.report_trait_candidate(idx, trait_did)
             }
         }
     }
 
-    pub fn report_static_candidate(&self, idx: uint, did: def_id) {
+    fn report_static_candidate(&self, idx: uint, did: def_id) {
         let span = if did.crate == ast::LOCAL_CRATE {
             match self.tcx().items.find(&did.node) {
               Some(&ast_map::node_method(m, _, _)) => m.span,
@@ -1159,7 +1286,7 @@ pub fn report_static_candidate(&self, idx: uint, did: def_id) {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    pub fn report_param_candidate(&self, idx: uint, did: def_id) {
+    fn report_param_candidate(&self, idx: uint, did: def_id) {
         self.tcx().sess.span_note(
             self.expr.span,
             fmt!("candidate #%u derives from the bound `%s`",
@@ -1167,7 +1294,7 @@ pub fn report_param_candidate(&self, idx: uint, did: def_id) {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    pub fn report_trait_candidate(&self, idx: uint, did: def_id) {
+    fn report_trait_candidate(&self, idx: uint, did: def_id) {
         self.tcx().sess.span_note(
             self.expr.span,
             fmt!("candidate #%u derives from the type of the receiver, \
@@ -1176,31 +1303,31 @@ pub fn report_trait_candidate(&self, idx: uint, did: def_id) {
                  ty::item_path_str(self.tcx(), did)));
     }
 
-    pub fn infcx(&self) -> @mut infer::InferCtxt {
+    fn infcx(&self) -> @mut infer::InferCtxt {
         self.fcx.inh.infcx
     }
 
-    pub fn tcx(&self) -> ty::ctxt {
+    fn tcx(&self) -> ty::ctxt {
         self.fcx.tcx()
     }
 
-    pub fn ty_to_str(&self, t: ty::t) -> ~str {
+    fn ty_to_str(&self, t: ty::t) -> ~str {
         self.fcx.infcx().ty_to_str(t)
     }
 
-    pub fn cand_to_str(&self, cand: &Candidate) -> ~str {
+    fn cand_to_str(&self, cand: &Candidate) -> ~str {
         fmt!("Candidate(rcvr_ty=%s, rcvr_substs=%s, origin=%?)",
-             self.ty_to_str(cand.rcvr_ty),
+             cand.rcvr_match_condition.repr(self.tcx()),
              ty::substs_to_str(self.tcx(), &cand.rcvr_substs),
              cand.origin)
     }
 
-    pub fn did_to_str(&self, did: def_id) -> ~str {
+    fn did_to_str(&self, did: def_id) -> ~str {
         ty::item_path_str(self.tcx(), did)
     }
 
-    pub fn bug(&self, s: ~str) -> ! {
-        self.tcx().sess.bug(s)
+    fn bug(&self, s: ~str) -> ! {
+        self.tcx().sess.span_bug(self.self_expr.span, s)
     }
 }
 
@@ -1210,3 +1337,16 @@ pub fn get_mode_from_explicit_self(explicit_self: ast::explicit_self_) -> SelfMo
         _ => ty::ByCopy,
     }
 }
+
+impl Repr for RcvrMatchCondition {
+    fn repr(&self, tcx: ty::ctxt) -> ~str {
+        match *self {
+            RcvrMatchesIfObject(d) => {
+                fmt!("RcvrMatchesIfObject(%s)", d.repr(tcx))
+            }
+            RcvrMatchesIfSubtype(t) => {
+                fmt!("RcvrMatchesIfSubtype(%s)", t.repr(tcx))
+            }
+        }
+    }
+}
index da0e219310fde2b64b3f325b892d7cd5d028acc5..e7ef30c4576c4868803cd7bfbcbf7ed2ce37de70 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
@@ -3437,7 +3437,8 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
                   Ok(t) => t,
                   Err(s) => { tcx.sess.span_fatal(it.span, s); }
               };
-              let visitor_object_ty = match ty::visitor_object_ty(tcx) {
+              let region = ty::re_bound(ty::br_anon(0));
+              let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
                   Ok((_, vot)) => vot,
                   Err(s) => { tcx.sess.span_fatal(it.span, s); }
               };
@@ -3647,6 +3648,39 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
             "bswap16"  => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
             "bswap32"  => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
             "bswap64"  => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
+
+            "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
+                (0, ~[ty::mk_i8(), ty::mk_i8()],
+                ty::mk_tup(tcx, ~[ty::mk_i8(), ty::mk_bool()])),
+
+            "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
+                (0, ~[ty::mk_i16(), ty::mk_i16()],
+                ty::mk_tup(tcx, ~[ty::mk_i16(), ty::mk_bool()])),
+
+            "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
+                (0, ~[ty::mk_i32(), ty::mk_i32()],
+                ty::mk_tup(tcx, ~[ty::mk_i32(), ty::mk_bool()])),
+
+            "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
+                (0, ~[ty::mk_i64(), ty::mk_i64()],
+                ty::mk_tup(tcx, ~[ty::mk_i64(), ty::mk_bool()])),
+
+            "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
+                (0, ~[ty::mk_u8(), ty::mk_u8()],
+                ty::mk_tup(tcx, ~[ty::mk_u8(), ty::mk_bool()])),
+
+            "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
+                (0, ~[ty::mk_u16(), ty::mk_u16()],
+                ty::mk_tup(tcx, ~[ty::mk_u16(), ty::mk_bool()])),
+
+            "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
+                (0, ~[ty::mk_u32(), ty::mk_u32()],
+                ty::mk_tup(tcx, ~[ty::mk_u32(), ty::mk_bool()])),
+
+            "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
+                (0, ~[ty::mk_u64(), ty::mk_u64()],
+                ty::mk_tup(tcx, ~[ty::mk_u64(), ty::mk_bool()])),
+
             ref other => {
                 tcx.sess.span_err(it.span,
                                   fmt!("unrecognized intrinsic function: `%s`",
index 18e7295d61a0528f1cf86fe6f4b543a5a19a55ae..d034277d44af82526360f62b0b392d739f105d3c 100644 (file)
@@ -863,7 +863,8 @@ pub fn for_autoref(rcx: @mut Rcx,
 
             ty::AutoBorrowVec(r, _) |
             ty::AutoBorrowVecRef(r, _) |
-            ty::AutoBorrowFn(r) => {
+            ty::AutoBorrowFn(r) |
+            ty::AutoBorrowObj(r, _) => {
                 // In each of these cases, what is being borrowed is
                 // not the (autoderef'd) expr itself but rather the
                 // contents of the autoderef'd expression (i.e., what
@@ -1072,7 +1073,8 @@ fn categorize(rcx: @mut Rcx, expr: @ast::expr) -> ExprCategorization {
                     Some(ty::AutoPtr(r, _)) |
                     Some(ty::AutoBorrowVec(r, _)) |
                     Some(ty::AutoBorrowVecRef(r, _)) |
-                    Some(ty::AutoBorrowFn(r)) => {
+                    Some(ty::AutoBorrowFn(r)) |
+                    Some(ty::AutoBorrowObj(r, _)) => {
                         // If there is an autoref, then the result of this
                         // expression will be some sort of borrowed pointer.
                         expr_ct.cat.guarantor = 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 a6899d7150e08d16b7d9e19c389f64616cc6a319..f2bde146ea79cf338f7660b06cce266470982131 100644 (file)
@@ -65,7 +65,7 @@ fn foo<A>(a: A, b: A) { ... }
 */
 
 
-use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn};
+use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowFn, AutoBorrowObj};
 use middle::ty::{AutoDerefRef};
 use middle::ty::{vstore_slice, vstore_box, vstore_uniq};
 use middle::ty::{mt};
@@ -121,6 +121,12 @@ pub fn tys(&self, a: ty::t, b: ty::t) -> CoerceResult {
                 };
             }
 
+            ty::ty_trait(_, _, ty::RegionTraitStore(*), _, _) => {
+                return do self.unpack_actual_value(a) |sty_a| {
+                    self.coerce_borrowed_object(a, sty_a, b)
+                };
+            }
+
             ty::ty_ptr(mt_b) => {
                 return do self.unpack_actual_value(a) |sty_a| {
                     self.coerce_unsafe_ptr(a, sty_a, b, mt_b)
@@ -265,6 +271,40 @@ pub fn coerce_borrowed_vector(&self,
         })))
     }
 
+    fn coerce_borrowed_object(&self,
+                              a: ty::t,
+                              sty_a: &ty::sty,
+                              b: ty::t) -> CoerceResult
+    {
+        debug!("coerce_borrowed_object(a=%s, sty_a=%?, b=%s)",
+               a.inf_str(self.infcx), sty_a,
+               b.inf_str(self.infcx));
+
+        let tcx = self.infcx.tcx;
+        let r_a = self.infcx.next_region_var(Coercion(self.trace));
+        let trt_mut;
+
+        let a_borrowed = match *sty_a {
+            ty::ty_trait(_, _, ty::RegionTraitStore(_), _, _) => {
+                return self.subtype(a, b);
+            }
+            ty::ty_trait(did, ref substs, _, m, b) => {
+                trt_mut = m;
+                ty::mk_trait(tcx, did, substs.clone(),
+                             ty::RegionTraitStore(r_a), m, b)
+            }
+            _ => {
+                return self.subtype(a, b);
+            }
+        };
+
+        if_ok!(self.tys(a_borrowed, b));
+        Ok(Some(@AutoDerefRef(AutoDerefRef {
+            autoderefs: 0,
+            autoref: Some(AutoBorrowObj(r_a, trt_mut))
+        })))
+    }
+
     pub fn coerce_borrowed_fn(&self,
                               a: ty::t,
                               sty_a: &ty::sty,
index b1356ffb2d5e943632dd9d6a47f0b9966bb9ba52..53ae80f19facc3354325fcdd3c873c24724162bd 100644 (file)
@@ -88,7 +88,7 @@ pub enum method_origin {
     method_param(method_param),
 
     // method invoked on a trait instance
-    method_trait(ast::def_id, uint, ty::TraitStore),
+    method_trait(ast::def_id, uint),
 
 }
 
index 625a4aec544dab9a64e344a3a302e3f671d1ff7a..ec80d1a44ead9ccf9a6089700119f1073ee63799 100644 (file)
@@ -156,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();
 
@@ -173,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),
@@ -312,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 1bea3003c63d292402bec46afef8cd578739a293..3bc0a7167e9bdd8a2ce7f59c3e466f59293c5ab0 100644 (file)
@@ -747,9 +747,8 @@ fn repr(&self, tcx: ctxt) -> ~str {
             &typeck::method_param(ref p) => {
                 p.repr(tcx)
             }
-            &typeck::method_trait(def_id, n, st) => {
-                fmt!("method_trait(%s, %?, %s)", def_id.repr(tcx), n,
-                     st.repr(tcx))
+            &typeck::method_trait(def_id, n) => {
+                fmt!("method_trait(%s, %?)", def_id.repr(tcx), n)
             }
         }
     }
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]
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 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 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 3507dc9d2b233543bdf76c6f2cb31f43d2cfd548..d2e9cf9ae7e96828d2a82d32b75b2aab69106e7b 100644 (file)
@@ -49,7 +49,9 @@ fn equals(&self, _other: &()) -> bool { true }
 
 #[cfg(not(test))]
 impl Zero for () {
+    #[inline]
     fn zero() -> () { () }
+    #[inline]
     fn is_zero(&self) -> bool { true }
 }
 
index bbadf1caca2413c4570460ac9040d28cc1940554..62452a4edff552b128e7a439f9dc242f7dff66dd 100644 (file)
@@ -18,7 +18,9 @@
 use cmp::{Eq, ApproxEq, Ord};
 use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
-use option::Option;
+use option::{Option, Some, None};
+#[cfg(not(stage0))]
+use unstable::intrinsics;
 
 pub mod strconv;
 
@@ -516,6 +518,416 @@ impl Saturating for u16 {}
 impl Saturating for u32 {}
 impl Saturating for u64 {}
 
+pub trait CheckedAdd: Add<Self, Self> {
+    fn checked_add(&self, v: &Self) -> Option<Self>;
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for i8 {
+    #[inline]
+    fn checked_add(&self, v: &i8) -> Option<i8> {
+        unsafe {
+            let (x, y) = intrinsics::i8_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for i16 {
+    #[inline]
+    fn checked_add(&self, v: &i16) -> Option<i16> {
+        unsafe {
+            let (x, y) = intrinsics::i16_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for i32 {
+    #[inline]
+    fn checked_add(&self, v: &i32) -> Option<i32> {
+        unsafe {
+            let (x, y) = intrinsics::i32_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for i64 {
+    #[inline]
+    fn checked_add(&self, v: &i64) -> Option<i64> {
+        unsafe {
+            let (x, y) = intrinsics::i64_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "32")]
+impl CheckedAdd for int {
+    #[inline]
+    fn checked_add(&self, v: &int) -> Option<int> {
+        unsafe {
+            let (x, y) = intrinsics::i32_add_with_overflow(*self as i32, *v as i32);
+            if y { None } else { Some(x as int) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedAdd for int {
+    #[inline]
+    fn checked_add(&self, v: &int) -> Option<int> {
+        unsafe {
+            let (x, y) = intrinsics::i64_add_with_overflow(*self as i64, *v as i64);
+            if y { None } else { Some(x as int) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for u8 {
+    #[inline]
+    fn checked_add(&self, v: &u8) -> Option<u8> {
+        unsafe {
+            let (x, y) = intrinsics::u8_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for u16 {
+    #[inline]
+    fn checked_add(&self, v: &u16) -> Option<u16> {
+        unsafe {
+            let (x, y) = intrinsics::u16_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for u32 {
+    #[inline]
+    fn checked_add(&self, v: &u32) -> Option<u32> {
+        unsafe {
+            let (x, y) = intrinsics::u32_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedAdd for u64 {
+    #[inline]
+    fn checked_add(&self, v: &u64) -> Option<u64> {
+        unsafe {
+            let (x, y) = intrinsics::u64_add_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "32")]
+impl CheckedAdd for uint {
+    #[inline]
+    fn checked_add(&self, v: &uint) -> Option<uint> {
+        unsafe {
+            let (x, y) = intrinsics::u32_add_with_overflow(*self as u32, *v as u32);
+            if y { None } else { Some(x as uint) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedAdd for uint {
+    #[inline]
+    fn checked_add(&self, v: &uint) -> Option<uint> {
+        unsafe {
+            let (x, y) = intrinsics::u64_add_with_overflow(*self as u64, *v as u64);
+            if y { None } else { Some(x as uint) }
+        }
+    }
+}
+
+pub trait CheckedSub: Sub<Self, Self> {
+    fn checked_sub(&self, v: &Self) -> Option<Self>;
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for i8 {
+    #[inline]
+    fn checked_sub(&self, v: &i8) -> Option<i8> {
+        unsafe {
+            let (x, y) = intrinsics::i8_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for i16 {
+    #[inline]
+    fn checked_sub(&self, v: &i16) -> Option<i16> {
+        unsafe {
+            let (x, y) = intrinsics::i16_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for i32 {
+    #[inline]
+    fn checked_sub(&self, v: &i32) -> Option<i32> {
+        unsafe {
+            let (x, y) = intrinsics::i32_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for i64 {
+    #[inline]
+    fn checked_sub(&self, v: &i64) -> Option<i64> {
+        unsafe {
+            let (x, y) = intrinsics::i64_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "32")]
+impl CheckedSub for int {
+    #[inline]
+    fn checked_sub(&self, v: &int) -> Option<int> {
+        unsafe {
+            let (x, y) = intrinsics::i32_sub_with_overflow(*self as i32, *v as i32);
+            if y { None } else { Some(x as int) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedSub for int {
+    #[inline]
+    fn checked_sub(&self, v: &int) -> Option<int> {
+        unsafe {
+            let (x, y) = intrinsics::i64_sub_with_overflow(*self as i64, *v as i64);
+            if y { None } else { Some(x as int) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for u8 {
+    #[inline]
+    fn checked_sub(&self, v: &u8) -> Option<u8> {
+        unsafe {
+            let (x, y) = intrinsics::u8_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for u16 {
+    #[inline]
+    fn checked_sub(&self, v: &u16) -> Option<u16> {
+        unsafe {
+            let (x, y) = intrinsics::u16_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for u32 {
+    #[inline]
+    fn checked_sub(&self, v: &u32) -> Option<u32> {
+        unsafe {
+            let (x, y) = intrinsics::u32_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedSub for u64 {
+    #[inline]
+    fn checked_sub(&self, v: &u64) -> Option<u64> {
+        unsafe {
+            let (x, y) = intrinsics::u64_sub_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "32")]
+impl CheckedSub for uint {
+    #[inline]
+    fn checked_sub(&self, v: &uint) -> Option<uint> {
+        unsafe {
+            let (x, y) = intrinsics::u32_sub_with_overflow(*self as u32, *v as u32);
+            if y { None } else { Some(x as uint) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedSub for uint {
+    #[inline]
+    fn checked_sub(&self, v: &uint) -> Option<uint> {
+        unsafe {
+            let (x, y) = intrinsics::u64_sub_with_overflow(*self as u64, *v as u64);
+            if y { None } else { Some(x as uint) }
+        }
+    }
+}
+
+pub trait CheckedMul: Mul<Self, Self> {
+    fn checked_mul(&self, v: &Self) -> Option<Self>;
+}
+
+#[cfg(not(stage0))]
+impl CheckedMul for i8 {
+    #[inline]
+    fn checked_mul(&self, v: &i8) -> Option<i8> {
+        unsafe {
+            let (x, y) = intrinsics::i8_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedMul for i16 {
+    #[inline]
+    fn checked_mul(&self, v: &i16) -> Option<i16> {
+        unsafe {
+            let (x, y) = intrinsics::i16_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedMul for i32 {
+    #[inline]
+    fn checked_mul(&self, v: &i32) -> Option<i32> {
+        unsafe {
+            let (x, y) = intrinsics::i32_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+// FIXME: #8449: should not be disabled on 32-bit
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedMul for i64 {
+    #[inline]
+    fn checked_mul(&self, v: &i64) -> Option<i64> {
+        unsafe {
+            let (x, y) = intrinsics::i64_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "32")]
+impl CheckedMul for int {
+    #[inline]
+    fn checked_mul(&self, v: &int) -> Option<int> {
+        unsafe {
+            let (x, y) = intrinsics::i32_mul_with_overflow(*self as i32, *v as i32);
+            if y { None } else { Some(x as int) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedMul for int {
+    #[inline]
+    fn checked_mul(&self, v: &int) -> Option<int> {
+        unsafe {
+            let (x, y) = intrinsics::i64_mul_with_overflow(*self as i64, *v as i64);
+            if y { None } else { Some(x as int) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedMul for u8 {
+    #[inline]
+    fn checked_mul(&self, v: &u8) -> Option<u8> {
+        unsafe {
+            let (x, y) = intrinsics::u8_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedMul for u16 {
+    #[inline]
+    fn checked_mul(&self, v: &u16) -> Option<u16> {
+        unsafe {
+            let (x, y) = intrinsics::u16_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0))]
+impl CheckedMul for u32 {
+    #[inline]
+    fn checked_mul(&self, v: &u32) -> Option<u32> {
+        unsafe {
+            let (x, y) = intrinsics::u32_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+// FIXME: #8449: should not be disabled on 32-bit
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedMul for u64 {
+    #[inline]
+    fn checked_mul(&self, v: &u64) -> Option<u64> {
+        unsafe {
+            let (x, y) = intrinsics::u64_mul_with_overflow(*self, *v);
+            if y { None } else { Some(x) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "32")]
+impl CheckedMul for uint {
+    #[inline]
+    fn checked_mul(&self, v: &uint) -> Option<uint> {
+        unsafe {
+            let (x, y) = intrinsics::u32_mul_with_overflow(*self as u32, *v as u32);
+            if y { None } else { Some(x as uint) }
+        }
+    }
+}
+
+#[cfg(not(stage0), target_word_size = "64")]
+impl CheckedMul for uint {
+    #[inline]
+    fn checked_mul(&self, v: &uint) -> Option<uint> {
+        unsafe {
+            let (x, y) = intrinsics::u64_mul_with_overflow(*self as u64, *v as u64);
+            if y { None } else { Some(x as uint) }
+        }
+    }
+}
+
 /// Helper function for testing numeric operations
 #[cfg(test)]
 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
@@ -534,6 +946,8 @@ pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
 
 #[cfg(test)]
 mod tests {
+    use prelude::*;
+    use uint;
     use super::*;
 
     macro_rules! test_cast_20(
@@ -639,4 +1053,39 @@ fn test_saturating_sub_int() {
         assert_eq!(max_value.saturating_sub(-max_value), max_value);
         assert_eq!((max_value-2).saturating_sub(-1), max_value-1);
     }
+
+    #[test]
+    fn test_checked_add() {
+        let five_less = uint::max_value - 5;
+        assert_eq!(five_less.checked_add(&0), Some(uint::max_value - 5));
+        assert_eq!(five_less.checked_add(&1), Some(uint::max_value - 4));
+        assert_eq!(five_less.checked_add(&2), Some(uint::max_value - 3));
+        assert_eq!(five_less.checked_add(&3), Some(uint::max_value - 2));
+        assert_eq!(five_less.checked_add(&4), Some(uint::max_value - 1));
+        assert_eq!(five_less.checked_add(&5), Some(uint::max_value));
+        assert_eq!(five_less.checked_add(&6), None);
+        assert_eq!(five_less.checked_add(&7), None);
+    }
+
+    #[test]
+    fn test_checked_sub() {
+        assert_eq!(5u.checked_sub(&0), Some(5));
+        assert_eq!(5u.checked_sub(&1), Some(4));
+        assert_eq!(5u.checked_sub(&2), Some(3));
+        assert_eq!(5u.checked_sub(&3), Some(2));
+        assert_eq!(5u.checked_sub(&4), Some(1));
+        assert_eq!(5u.checked_sub(&5), Some(0));
+        assert_eq!(5u.checked_sub(&6), None);
+        assert_eq!(5u.checked_sub(&7), None);
+    }
+
+    #[test]
+    fn test_checked_mul() {
+        let third = uint::max_value / 3;
+        assert_eq!(third.checked_mul(&0), Some(0));
+        assert_eq!(third.checked_mul(&1), Some(third));
+        assert_eq!(third.checked_mul(&2), Some(third * 2));
+        assert_eq!(third.checked_mul(&3), Some(third * 3));
+        assert_eq!(third.checked_mul(&4), None);
+    }
 }
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..93e14be582b603147f489c2f319019fc37fd872b 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,9 +51,9 @@
 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::{Num, NumCast, CheckedAdd, CheckedSub, CheckedMul};
 pub use num::{Orderable, Signed, Unsigned, Round};
 pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
 pub use num::{Integer, Fractional, Real, RealExt};
@@ -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 a53e3e796a790db7090bd0cc930c0223bcea53f4..d0970f1b6b7ad038a65db944f11417a8e9ccf5b1 100644 (file)
@@ -158,6 +158,7 @@ pub fn visit_inner(&self, inner: *TyDesc) -> bool {
     }
 
     #[inline]
+    #[cfg(stage0)]
     pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
         unsafe {
             let u = ReprVisitor(ptr, self.writer);
@@ -167,6 +168,17 @@ pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
         }
     }
 
+    #[inline]
+    #[cfg(not(stage0))]
+    pub fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
+        unsafe {
+            let u = ReprVisitor(ptr, self.writer);
+            let v = reflect::MovePtrAdaptor(u);
+            visit_tydesc(inner, &v as &TyVisitor);
+            true
+        }
+    }
+
     #[inline]
     pub fn write<T:Repr>(&self) -> bool {
         do self.get |v:&T| {
@@ -556,6 +568,7 @@ fn visit_opaque_box(&self) -> bool {
     fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
 }
 
+#[cfg(stage0)]
 pub fn write_repr<T>(writer: @Writer, object: &T) {
     unsafe {
         let ptr = ptr::to_unsafe_ptr(object) as *c_void;
@@ -566,6 +579,17 @@ pub fn write_repr<T>(writer: @Writer, object: &T) {
     }
 }
 
+#[cfg(not(stage0))]
+pub fn write_repr<T>(writer: @Writer, object: &T) {
+    unsafe {
+        let ptr = ptr::to_unsafe_ptr(object) as *c_void;
+        let tydesc = get_tydesc::<T>();
+        let u = ReprVisitor(ptr, writer);
+        let v = reflect::MovePtrAdaptor(u);
+        visit_tydesc(tydesc, &v as &TyVisitor)
+    }
+}
+
 #[cfg(test)]
 struct P {a: int, b: float}
 
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 936a6526508a93f4c47cf5fdf2d69f4b15c4586f..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;
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 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 01a52892f633b95eb71484d218fbf18f43dab314..1b9f28b95fb3fc27b5042e067f933922b41d78ee 100644 (file)
@@ -63,7 +63,7 @@
 use cell::Cell;
 use clone::Clone;
 use container::Container;
-use iterator::{Iterator, IteratorUtil, range};
+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
@@ -391,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();
     }
 
@@ -401,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 0e8d26e9482bac99761e536d5a16da8c5867195c..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 {
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 92366d5187fe23cae6bc7aa3126d2bda464af8e5..ca94468e1adaedbb670c421840a46fd9c2d6d108 100644 (file)
@@ -232,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 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 2d81a981074888e087e98ece4ffc8be8191c7769..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())
     }
 }
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 430eb8544f6306f73245f885ff4110796a487f96..0b270edc5342ae241b57d5b4792c18cd1214ea42 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"]
@@ -690,6 +807,7 @@ pub fn from_utf16(v: &[u16]) -> ~str {
 
 /// Allocates a new string with the specified capacity. The string returned is
 /// the empty string, but has capacity for much more.
+#[cfg(stage0)]
 #[inline]
 pub fn with_capacity(capacity: uint) -> ~str {
     let mut buf = ~"";
@@ -697,6 +815,16 @@ pub fn with_capacity(capacity: uint) -> ~str {
     buf
 }
 
+/// Allocates a new string with the specified capacity. The string returned is
+/// the empty string, but has capacity for much more.
+#[cfg(not(stage0))]
+#[inline]
+pub fn with_capacity(capacity: uint) -> ~str {
+    unsafe {
+        cast::transmute(vec::with_capacity::<~[u8]>(capacity))
+    }
+}
+
 /// As char_len but for a slice of a string
 ///
 /// # Arguments
@@ -800,20 +928,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 +943,39 @@ 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)
+    }
+
+    #[lang="strdup_uniq"]
+    #[cfg(not(test))]
+    #[allow(missing_doc)]
+    #[inline]
+    pub unsafe fn strdup_uniq(ptr: *u8, len: uint) -> ~str {
+        from_buf_len(ptr, len)
     }
 
-    /// 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 +987,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 +1007,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 +1021,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 +1046,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 +1060,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 +1127,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 +1137,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 {
@@ -1119,10 +1331,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 {
@@ -1210,7 +1429,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
@@ -1246,7 +1464,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.
@@ -1258,7 +1476,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
@@ -1366,7 +1584,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 }
@@ -1394,7 +1612,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`)
@@ -1597,6 +1815,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| {
@@ -1614,6 +1833,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| {
@@ -1622,6 +1859,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 = ~[];
@@ -1762,6 +2008,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();
@@ -1770,6 +2017,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
@@ -1836,6 +2091,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
@@ -1857,6 +2113,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
@@ -1959,61 +2236,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)]
@@ -2028,6 +2250,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.
@@ -2174,6 +2397,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 {
@@ -2182,6 +2406,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.
     ///
@@ -2200,13 +2447,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();
@@ -2214,8 +2486,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) }
@@ -2282,7 +2565,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;
@@ -2904,71 +3186,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");
         }
     }
@@ -2986,30 +3208,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";
@@ -3031,50 +3254,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);
             }
         }
     }
@@ -3508,7 +3705,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";
@@ -3522,7 +3719,7 @@ fn sum_len<S: Container>(v: &[S]) -> uint {
 #[cfg(test)]
 mod bench {
     use extra::test::BenchHarness;
-    use str;
+    use super::*;
 
     #[bench]
     fn is_utf8_100_ascii(bh: &mut BenchHarness) {
@@ -3532,7 +3729,7 @@ fn is_utf8_100_ascii(bh: &mut BenchHarness) {
 
         assert_eq!(100, s.len());
         do bh.iter {
-            str::is_utf8(s);
+            is_utf8(s);
         }
     }
 
@@ -3541,7 +3738,7 @@ fn is_utf8_100_multibyte(bh: &mut BenchHarness) {
         let s = bytes!("𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰");
         assert_eq!(100, s.len());
         do bh.iter {
-            str::is_utf8(s);
+            is_utf8(s);
         }
     }
 
@@ -3564,4 +3761,11 @@ fn map_chars_100_multibytes(bh: &mut BenchHarness) {
             s.map_chars(|c| ((c as uint) + 1) as char);
         }
     }
+
+    #[bench]
+    fn bench_with_capacity(bh: &mut BenchHarness) {
+        do bh.iter {
+            with_capacity(100);
+        }
+    }
 }
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 05a17f8539c216b93dce541651ceffa47b62cbb8..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;
@@ -91,7 +88,7 @@
 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;
 // 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()),
         }
     }
@@ -123,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),
         }
     }
@@ -147,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()
     }
 }
 
@@ -466,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);
             }
@@ -498,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| {
@@ -513,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"),
@@ -521,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>();
@@ -534,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>();
@@ -587,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")
         }
     }
 }
@@ -598,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| {
@@ -665,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")
     }
 }
 
@@ -811,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 c60edad3dbd5683e6ec69cae281376a950089a6c..92725fda70598c8f13a3d5d1871e4554d49fc48d 100644 (file)
 
 pub type GlueFn = extern "Rust" fn(*i8);
 
-// NB: this has to be kept in sync with the Rust ABI.
+// NB: this has to be kept in sync with `type_desc` in `rt`
 #[lang="ty_desc"]
 #[cfg(not(test))]
 pub struct TyDesc {
+    // sizeof(T)
     size: uint,
+
+    // alignof(T)
     align: uint,
+
+    // Called on a copy of a value of type `T` *after* memcpy
     take_glue: GlueFn,
+
+    // Called when a value of type `T` is no longer needed
     drop_glue: GlueFn,
+
+    // Called by drop glue when a value of type `T` can be freed
     free_glue: GlueFn,
+
+    // Called by reflection visitor to visit a value of type `T`
     visit_glue: GlueFn,
+
+    // If T represents a box pointer (`@U` or `~U`), then
+    // `borrow_offset` is the amount that the pointer must be adjusted
+    // to find the payload.  This is always derivable from the type
+    // `U`, but in the case of `@Trait` or `~Trait` objects, the type
+    // `U` is unknown.
+    borrow_offset: uint,
 }
 
 #[lang="opaque"]
@@ -310,8 +328,12 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
     /// Returns `true` if a type is managed (will be allocated on the local heap)
     pub fn contains_managed<T>() -> bool;
 
+    #[cfg(stage0)]
     pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor);
 
+    #[cfg(not(stage0))]
+    pub fn visit_tydesc(td: *TyDesc, tv: &TyVisitor);
+
     pub fn frame_address(f: &once fn(*u8));
 
     /// Get the address of the `__morestack` stack growth function.
@@ -428,6 +450,60 @@ fn visit_leave_fn(&self, purity: uint, proto: uint,
     pub fn bswap16(x: i16) -> i16;
     pub fn bswap32(x: i32) -> i32;
     pub fn bswap64(x: i64) -> i64;
+
+    #[cfg(not(stage0))]
+    pub fn i8_add_with_overflow(x: i8, y: i8) -> (i8, bool);
+    #[cfg(not(stage0))]
+    pub fn i16_add_with_overflow(x: i16, y: i16) -> (i16, bool);
+    #[cfg(not(stage0))]
+    pub fn i32_add_with_overflow(x: i32, y: i32) -> (i32, bool);
+    #[cfg(not(stage0))]
+    pub fn i64_add_with_overflow(x: i64, y: i64) -> (i64, bool);
+
+    #[cfg(not(stage0))]
+    pub fn u8_add_with_overflow(x: u8, y: u8) -> (u8, bool);
+    #[cfg(not(stage0))]
+    pub fn u16_add_with_overflow(x: u16, y: u16) -> (u16, bool);
+    #[cfg(not(stage0))]
+    pub fn u32_add_with_overflow(x: u32, y: u32) -> (u32, bool);
+    #[cfg(not(stage0))]
+    pub fn u64_add_with_overflow(x: u64, y: u64) -> (u64, bool);
+
+    #[cfg(not(stage0))]
+    pub fn i8_sub_with_overflow(x: i8, y: i8) -> (i8, bool);
+    #[cfg(not(stage0))]
+    pub fn i16_sub_with_overflow(x: i16, y: i16) -> (i16, bool);
+    #[cfg(not(stage0))]
+    pub fn i32_sub_with_overflow(x: i32, y: i32) -> (i32, bool);
+    #[cfg(not(stage0))]
+    pub fn i64_sub_with_overflow(x: i64, y: i64) -> (i64, bool);
+
+    #[cfg(not(stage0))]
+    pub fn u8_sub_with_overflow(x: u8, y: u8) -> (u8, bool);
+    #[cfg(not(stage0))]
+    pub fn u16_sub_with_overflow(x: u16, y: u16) -> (u16, bool);
+    #[cfg(not(stage0))]
+    pub fn u32_sub_with_overflow(x: u32, y: u32) -> (u32, bool);
+    #[cfg(not(stage0))]
+    pub fn u64_sub_with_overflow(x: u64, y: u64) -> (u64, bool);
+
+    #[cfg(not(stage0))]
+    pub fn i8_mul_with_overflow(x: i8, y: i8) -> (i8, bool);
+    #[cfg(not(stage0))]
+    pub fn i16_mul_with_overflow(x: i16, y: i16) -> (i16, bool);
+    #[cfg(not(stage0))]
+    pub fn i32_mul_with_overflow(x: i32, y: i32) -> (i32, bool);
+    #[cfg(not(stage0))]
+    pub fn i64_mul_with_overflow(x: i64, y: i64) -> (i64, bool);
+
+    #[cfg(not(stage0))]
+    pub fn u8_mul_with_overflow(x: u8, y: u8) -> (u8, bool);
+    #[cfg(not(stage0))]
+    pub fn u16_mul_with_overflow(x: u16, y: u16) -> (u16, bool);
+    #[cfg(not(stage0))]
+    pub fn u32_mul_with_overflow(x: u32, y: u32) -> (u32, bool);
+    #[cfg(not(stage0))]
+    pub fn u64_mul_with_overflow(x: u64, y: u64) -> (u64, bool);
 }
 
 #[cfg(target_endian = "little")] pub fn to_le16(x: i16) -> i16 { x }
index 98c0fe254b697643325efbe9dff7fb6a9f514991..d8df967a45ca2233cc2fa1d2c8076a34f3178844 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 str;
+use libc::{c_char, c_void, size_t, uintptr_t};
 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 +28,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
@@ -117,12 +92,6 @@ pub unsafe fn check_not_borrowed(a: *u8,
     borrowck::check_not_borrowed(a, file, line)
 }
 
-#[lang="strdup_uniq"]
-#[inline]
-pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
-    str::raw::from_buf_len(ptr, len)
-}
-
 #[lang="annihilate"]
 pub unsafe fn annihilate() {
     ::cleanup::annihilate()
@@ -132,23 +101,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..d626b8604db87ed065ee36ff93d632514edbc7a8 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);
@@ -561,7 +561,7 @@ fn idx(&self, index: uint) -> Option<&'self [T]> {
 
 #[cfg(not(test))]
 pub mod traits {
-    use super::Vector;
+    use super::*;
 
     use clone::Clone;
     use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Equal, Equiv};
@@ -686,17 +686,17 @@ fn gt(&self, other: &@[T]) -> bool { self.as_slice() > other.as_slice() }
     impl<'self,T:Clone, V: Vector<T>> Add<V, ~[T]> for &'self [T] {
         #[inline]
         fn add(&self, rhs: &V) -> ~[T] {
-            let mut res = self.to_owned();
+            let mut res = with_capacity(self.len() + rhs.as_slice().len());
+            res.push_all(*self);
             res.push_all(rhs.as_slice());
             res
         }
     }
+
     impl<T:Clone, V: Vector<T>> Add<V, ~[T]> for ~[T] {
         #[inline]
         fn add(&self, rhs: &V) -> ~[T] {
-            let mut res = self.to_owned();
-            res.push_all(rhs.as_slice());
-            res
+            self.as_slice() + rhs.as_slice()
         }
     }
 }
@@ -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;
         }
@@ -3662,4 +3662,13 @@ fn mut_iterator(bh: &mut BenchHarness) {
             }
         }
     }
+
+    #[bench]
+    fn add(b: &mut BenchHarness) {
+        let xs: &[int] = [5, ..10];
+        let ys: &[int] = [5, ..10];
+        do b.iter() {
+            xs + ys;
+        }
+    }
 }
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 6b4da9671a9636a02641804fc2a0cb3e23672125..1fea0c2e6f92db4a1e099ede69a4df1863c8f7ad 100644 (file)
@@ -85,7 +85,7 @@ pub enum ast_node {
 pub struct Ctx {
     map: map,
     path: path,
-    diag: @span_handler,
+    diag: @mut span_handler,
 }
 
 impl Ctx {
@@ -141,7 +141,7 @@ fn map_expr(@mut self, ex: @expr) {
             }
         }
 
-        visit::visit_expr(self as @Visitor<()>, ex, ());
+        visit::visit_expr(self as @mut Visitor<()>, ex, ());
     }
 
     fn map_fn(@mut self,
@@ -153,18 +153,18 @@ fn map_fn(@mut self,
         for a in decl.inputs.iter() {
             self.map.insert(a.id, node_arg);
         }
-        visit::visit_fn(self as @Visitor<()>, fk, decl, body, sp, id, ());
+        visit::visit_fn(self as @mut Visitor<()>, fk, decl, body, sp, id, ());
     }
 
     fn map_stmt(@mut self, stmt: @stmt) {
         self.map.insert(stmt_id(stmt), node_stmt(stmt));
-        visit::visit_stmt(self as @Visitor<()>, stmt, ());
+        visit::visit_stmt(self as @mut Visitor<()>, stmt, ());
     }
 
     fn map_block(@mut self, b: &Block) {
         // clone is FIXME #2543
         self.map.insert(b.id, node_block((*b).clone()));
-        visit::visit_block(self as @Visitor<()>, b, ());
+        visit::visit_block(self as @mut Visitor<()>, b, ());
     }
 
     fn map_pat(@mut self, pat: @pat) {
@@ -177,7 +177,7 @@ fn map_pat(@mut self, pat: @pat) {
             _ => ()
         }
 
-        visit::visit_pat(self as @Visitor<()>, pat, ());
+        visit::visit_pat(self as @mut Visitor<()>, pat, ());
     }
 }
 
@@ -254,13 +254,13 @@ fn visit_item(@mut self, i: @item, _: ()) {
             }
             _ => self.path.push(path_name(i.ident))
         }
-        visit::visit_item(self as @Visitor<()>, i, ());
+        visit::visit_item(self as @mut Visitor<()>, i, ());
         self.path.pop();
     }
 
     fn visit_pat(@mut self, pat: @pat, _: ()) {
         self.map_pat(pat);
-        visit::visit_pat(self as @Visitor<()>, pat, ())
+        visit::visit_pat(self as @mut Visitor<()>, pat, ())
     }
 
     fn visit_expr(@mut self, expr: @expr, _: ()) {
@@ -288,27 +288,27 @@ fn visit_block(@mut self, block: &Block, _: ()) {
     // XXX: Methods below can become default methods.
 
     fn visit_mod(@mut self, module: &_mod, _: span, _: NodeId, _: ()) {
-        visit::visit_mod(self as @Visitor<()>, module, ())
+        visit::visit_mod(self as @mut Visitor<()>, module, ())
     }
 
     fn visit_view_item(@mut self, view_item: &view_item, _: ()) {
-        visit::visit_view_item(self as @Visitor<()>, view_item, ())
+        visit::visit_view_item(self as @mut Visitor<()>, view_item, ())
     }
 
     fn visit_foreign_item(@mut self, foreign_item: @foreign_item, _: ()) {
-        visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ())
+        visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, ())
     }
 
     fn visit_local(@mut self, local: @Local, _: ()) {
-        visit::visit_local(self as @Visitor<()>, local, ())
+        visit::visit_local(self as @mut Visitor<()>, local, ())
     }
 
     fn visit_arm(@mut self, arm: &arm, _: ()) {
-        visit::visit_arm(self as @Visitor<()>, arm, ())
+        visit::visit_arm(self as @mut Visitor<()>, arm, ())
     }
 
     fn visit_decl(@mut self, decl: @decl, _: ()) {
-        visit::visit_decl(self as @Visitor<()>, decl, ())
+        visit::visit_decl(self as @mut Visitor<()>, decl, ())
     }
 
     fn visit_expr_post(@mut self, _: @expr, _: ()) {
@@ -316,11 +316,11 @@ fn visit_expr_post(@mut self, _: @expr, _: ()) {
     }
 
     fn visit_ty(@mut self, typ: &Ty, _: ()) {
-        visit::visit_ty(self as @Visitor<()>, typ, ())
+        visit::visit_ty(self as @mut Visitor<()>, typ, ())
     }
 
     fn visit_generics(@mut self, generics: &Generics, _: ()) {
-        visit::visit_generics(self as @Visitor<()>, generics, ())
+        visit::visit_generics(self as @mut Visitor<()>, generics, ())
     }
 
     fn visit_fn(@mut self,
@@ -330,7 +330,7 @@ fn visit_fn(@mut self,
                 span: span,
                 node_id: NodeId,
                 _: ()) {
-        visit::visit_fn(self as @Visitor<()>,
+        visit::visit_fn(self as @mut Visitor<()>,
                         function_kind,
                         function_declaration,
                         block,
@@ -340,11 +340,11 @@ fn visit_fn(@mut self,
     }
 
     fn visit_ty_method(@mut self, ty_method: &TypeMethod, _: ()) {
-        visit::visit_ty_method(self as @Visitor<()>, ty_method, ())
+        visit::visit_ty_method(self as @mut Visitor<()>, ty_method, ())
     }
 
     fn visit_trait_method(@mut self, trait_method: &trait_method, _: ()) {
-        visit::visit_trait_method(self as @Visitor<()>, trait_method, ())
+        visit::visit_trait_method(self as @mut Visitor<()>, trait_method, ())
     }
 
     fn visit_struct_def(@mut self,
@@ -353,7 +353,7 @@ fn visit_struct_def(@mut self,
                         generics: &Generics,
                         node_id: NodeId,
                         _: ()) {
-        visit::visit_struct_def(self as @Visitor<()>,
+        visit::visit_struct_def(self as @mut Visitor<()>,
                                 struct_def,
                                 ident,
                                 generics,
@@ -362,24 +362,24 @@ fn visit_struct_def(@mut self,
     }
 
     fn visit_struct_field(@mut self, struct_field: @struct_field, _: ()) {
-        visit::visit_struct_field(self as @Visitor<()>, struct_field, ())
+        visit::visit_struct_field(self as @mut Visitor<()>, struct_field, ())
     }
 }
 
-pub fn map_crate(diag: @span_handler, c: &Crate) -> map {
+pub fn map_crate(diag: @mut span_handler, c: &Crate) -> map {
     let cx = @mut Ctx {
         map: @mut HashMap::new(),
         path: ~[],
         diag: diag,
     };
-    visit::visit_crate(cx as @Visitor<()>, c, ());
+    visit::visit_crate(cx as @mut Visitor<()>, c, ());
     cx.map
 }
 
 // Used for items loaded from external crate that are being inlined into this
 // crate.  The `path` should be the path to the item but should not include
 // the item itself.
-pub fn map_decoded_item(diag: @span_handler,
+pub fn map_decoded_item(diag: @mut span_handler,
                         map: map,
                         path: path,
                         ii: &inlined_item) {
@@ -409,7 +409,7 @@ pub fn map_decoded_item(diag: @span_handler,
     }
 
     // visit the item / method contents and add those to the map:
-    ii.accept((), cx as @Visitor<()>);
+    ii.accept((), cx as @mut Visitor<()>);
 }
 
 pub fn node_id_to_str(map: map, id: NodeId, itr: @ident_interner) -> ~str {
index ba167fe67148ef5df984fbdf00e50495fb7f6f39..d99f8cab4937fad51167888fa80d1660e84e4bc8 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
@@ -298,7 +298,7 @@ pub fn struct_field_visibility(field: ast::struct_field) -> visibility {
 pub trait inlined_item_utils {
     fn ident(&self) -> ident;
     fn id(&self) -> ast::NodeId;
-    fn accept<E: Clone>(&self, e: E, v: @Visitor<E>);
+    fn accept<E: Clone>(&self, e: E, v: @mut Visitor<E>);
 }
 
 impl inlined_item_utils for inlined_item {
@@ -318,7 +318,7 @@ fn id(&self) -> ast::NodeId {
         }
     }
 
-    fn accept<E: Clone>(&self, e: E, v: @Visitor<E>) {
+    fn accept<E: Clone>(&self, e: E, v: @mut Visitor<E>) {
         match *self {
             ii_item(i) => v.visit_item(i, e),
             ii_foreign(i) => v.visit_foreign_item(i, e),
@@ -414,12 +414,12 @@ fn visit_mod(@mut self,
                  node_id: NodeId,
                  env: ()) {
         (self.visit_callback)(node_id);
-        visit::visit_mod(self as @Visitor<()>, module, env)
+        visit::visit_mod(self as @mut Visitor<()>, module, env)
     }
 
     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) => {
@@ -439,12 +439,12 @@ fn visit_view_item(@mut self, view_item: &view_item, env: ()) {
                 }
             }
         }
-        visit::visit_view_item(self as @Visitor<()>, view_item, env)
+        visit::visit_view_item(self as @mut Visitor<()>, view_item, env)
     }
 
     fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) {
         (self.visit_callback)(foreign_item.id);
-        visit::visit_foreign_item(self as @Visitor<()>, foreign_item, env)
+        visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, env)
     }
 
     fn visit_item(@mut self, item: @item, env: ()) {
@@ -466,39 +466,39 @@ fn visit_item(@mut self, item: @item, env: ()) {
             _ => {}
         }
 
-        visit::visit_item(self as @Visitor<()>, item, env);
+        visit::visit_item(self as @mut Visitor<()>, item, env);
 
         self.visited_outermost = false
     }
 
     fn visit_local(@mut self, local: @Local, env: ()) {
         (self.visit_callback)(local.id);
-        visit::visit_local(self as @Visitor<()>, local, env)
+        visit::visit_local(self as @mut Visitor<()>, local, env)
     }
 
     fn visit_block(@mut self, block: &Block, env: ()) {
         (self.visit_callback)(block.id);
-        visit::visit_block(self as @Visitor<()>, block, env)
+        visit::visit_block(self as @mut Visitor<()>, block, env)
     }
 
     fn visit_stmt(@mut self, statement: @stmt, env: ()) {
         (self.visit_callback)(ast_util::stmt_id(statement));
-        visit::visit_stmt(self as @Visitor<()>, statement, env)
+        visit::visit_stmt(self as @mut Visitor<()>, statement, env)
     }
 
     // XXX: Default
     fn visit_arm(@mut self, arm: &arm, env: ()) {
-        visit::visit_arm(self as @Visitor<()>, arm, env)
+        visit::visit_arm(self as @mut Visitor<()>, arm, env)
     }
 
     fn visit_pat(@mut self, pattern: @pat, env: ()) {
         (self.visit_callback)(pattern.id);
-        visit::visit_pat(self as @Visitor<()>, pattern, env)
+        visit::visit_pat(self as @mut Visitor<()>, pattern, env)
     }
 
     // XXX: Default
     fn visit_decl(@mut self, declaration: @decl, env: ()) {
-        visit::visit_decl(self as @Visitor<()>, declaration, env)
+        visit::visit_decl(self as @mut Visitor<()>, declaration, env)
     }
 
     fn visit_expr(@mut self, expression: @expr, env: ()) {
@@ -509,7 +509,7 @@ fn visit_expr(@mut self, expression: @expr, env: ()) {
             }
         }
         (self.visit_callback)(expression.id);
-        visit::visit_expr(self as @Visitor<()>, expression, env)
+        visit::visit_expr(self as @mut Visitor<()>, expression, env)
     }
 
     // XXX: Default
@@ -523,12 +523,12 @@ fn visit_ty(@mut self, typ: &Ty, env: ()) {
             ty_path(_, _, id) => (self.visit_callback)(id),
             _ => {}
         }
-        visit::visit_ty(self as @Visitor<()>, typ, env)
+        visit::visit_ty(self as @mut Visitor<()>, typ, env)
     }
 
     fn visit_generics(@mut self, generics: &Generics, env: ()) {
         self.visit_generics_helper(generics);
-        visit::visit_generics(self as @Visitor<()>, generics, env)
+        visit::visit_generics(self as @mut Visitor<()>, generics, env)
     }
 
     fn visit_fn(@mut self,
@@ -563,7 +563,7 @@ fn visit_fn(@mut self,
             (self.visit_callback)(argument.id)
         }
 
-        visit::visit_fn(self as @Visitor<()>,
+        visit::visit_fn(self as @mut Visitor<()>,
                         function_kind,
                         function_declaration,
                         block,
@@ -581,12 +581,12 @@ fn visit_fn(@mut self,
 
     // XXX: Default
     fn visit_ty_method(@mut self, type_method: &TypeMethod, env: ()) {
-        visit::visit_ty_method(self as @Visitor<()>, type_method, env)
+        visit::visit_ty_method(self as @mut Visitor<()>, type_method, env)
     }
 
     // XXX: Default
     fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) {
-        visit::visit_trait_method(self as @Visitor<()>, trait_method, env)
+        visit::visit_trait_method(self as @mut Visitor<()>, trait_method, env)
     }
 
     // XXX: Default
@@ -596,7 +596,7 @@ fn visit_struct_def(@mut self,
                         generics: &Generics,
                         node_id: NodeId,
                         env: ()) {
-        visit::visit_struct_def(self as @Visitor<()>,
+        visit::visit_struct_def(self as @mut Visitor<()>,
                                 struct_definition,
                                 identifier,
                                 generics,
@@ -606,18 +606,18 @@ fn visit_struct_def(@mut self,
 
     fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) {
         (self.visit_callback)(struct_field.node.id);
-        visit::visit_struct_field(self as @Visitor<()>, struct_field, env)
+        visit::visit_struct_field(self as @mut Visitor<()>, struct_field, env)
     }
 }
 
 pub fn id_visitor(vfn: @fn(NodeId), pass_through_items: bool)
-                  -> @Visitor<()> {
-    let visitor = @IdVisitor {
+                  -> @mut Visitor<()> {
+    let visitor = @mut IdVisitor {
         visit_callback: vfn,
         pass_through_items: pass_through_items,
         visited_outermost: false,
     };
-    visitor as @Visitor<()>
+    visitor as @mut Visitor<()>
 }
 
 pub fn visit_ids_for_inlined_item(item: &inlined_item, vfn: @fn(NodeId)) {
@@ -757,9 +757,9 @@ fn each_view_item(&self, f: @fn(&ast::view_item) -> bool) -> bool {
             callback: f,
         };
         let visitor = @mut SimpleVisitorVisitor {
-            simple_visitor: data as @SimpleVisitor,
+            simple_visitor: data as @mut SimpleVisitor,
         };
-        visit::visit_crate(visitor as @Visitor<()>, self, ());
+        visit::visit_crate(visitor as @mut Visitor<()>, self, ());
         true
     }
 }
index 9edd41152f7f288ef090b2b94f555fabf4edf0b7..47d8ebecca06a313fb68f3c49b07d6c7c116bbc6 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 {
@@ -313,7 +313,7 @@ pub fn test_cfg<AM: AttrMetaMethods, It: Iterator<AM>>
     no_cfgs || some_cfg_matches
 }
 
-pub fn require_unique_names(diagnostic: @span_handler,
+pub fn require_unique_names(diagnostic: @mut span_handler,
                             metas: &[@MetaItem]) {
     let mut set = HashSet::new();
     for meta in metas.iter() {
index 2b6cb91a5df1759771fb7e4567c270f8806a0535..5cdfe8e0f110b5298879198d58fe7d2d8d11a63d 100644 (file)
@@ -50,7 +50,7 @@ pub trait span_handler {
     fn span_note(@mut self, sp: span, msg: &str);
     fn span_bug(@mut self, sp: span, msg: &str) -> !;
     fn span_unimpl(@mut self, sp: span, msg: &str) -> !;
-    fn handler(@mut self) -> @handler;
+    fn handler(@mut self) -> @mut handler;
 }
 
 struct HandlerT {
@@ -59,7 +59,7 @@ struct HandlerT {
 }
 
 struct CodemapT {
-    handler: @handler,
+    handler: @mut handler,
     cm: @codemap::CodeMap,
 }
 
@@ -84,7 +84,7 @@ fn span_bug(@mut self, sp: span, msg: &str) -> ! {
     fn span_unimpl(@mut self, sp: span, msg: &str) -> ! {
         self.span_bug(sp, ~"unimplemented " + msg);
     }
-    fn handler(@mut self) -> @handler {
+    fn handler(@mut self) -> @mut handler {
         self.handler
     }
 }
@@ -143,12 +143,12 @@ pub fn ice_msg(msg: &str) -> ~str {
     fmt!("internal compiler error: %s", msg)
 }
 
-pub fn mk_span_handler(handler: @handler, cm: @codemap::CodeMap)
-                    -> @span_handler {
-    @mut CodemapT { handler: handler, cm: cm } as @span_handler
+pub fn mk_span_handler(handler: @mut handler, cm: @codemap::CodeMap)
+                    -> @mut span_handler {
+    @mut CodemapT { handler: handler, cm: cm } as @mut span_handler
 }
 
-pub fn mk_handler(emitter: Option<Emitter>) -> @handler {
+pub fn mk_handler(emitter: Option<Emitter>) -> @mut handler {
     let emit: Emitter = match emitter {
         Some(e) => e,
         None => {
@@ -157,7 +157,7 @@ pub fn mk_handler(emitter: Option<Emitter>) -> @handler {
         }
     };
 
-    @mut HandlerT { err_count: 0, emit: emit } as @handler
+    @mut HandlerT { err_count: 0, emit: emit } as @mut handler
 }
 
 #[deriving(Eq)]
@@ -341,7 +341,7 @@ fn print_macro_backtrace(cm: @codemap::CodeMap, sp: span) {
     }
 }
 
-pub fn expect<T:Clone>(diag: @span_handler,
+pub fn expect<T:Clone>(diag: @mut span_handler,
                        opt: Option<T>,
                        msg: &fn() -> ~str) -> T {
     match opt {
index 1e696451701726593cfccd1b6deda0ebf1fcd72e..dfaffa0c2759dd3fc2e52329f1c5b4dfe61a45f3 100644 (file)
@@ -421,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)
     }
 
@@ -436,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
@@ -446,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) =>
@@ -457,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 {
@@ -477,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
@@ -487,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),
@@ -499,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) {
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 a928680e093929f041c275f12dc8951e77801261..1547446957ed4a194da272b0d5c1a30ded60f57b 100644 (file)
@@ -548,52 +548,52 @@ fn visit_pat(@mut self, pattern: @ast::pat, _: ()) {
                 }
             }
             // use the default traversal for non-pat_idents
-            _ => visit::visit_pat(self as @Visitor<()>, pattern, ())
+            _ => visit::visit_pat(self as @mut Visitor<()>, pattern, ())
         }
     }
 
     // XXX: Methods below can become default methods.
 
     fn visit_mod(@mut self, module: &ast::_mod, _: span, _: NodeId, _: ()) {
-        visit::visit_mod(self as @Visitor<()>, module, ())
+        visit::visit_mod(self as @mut Visitor<()>, module, ())
     }
 
     fn visit_view_item(@mut self, view_item: &ast::view_item, _: ()) {
-        visit::visit_view_item(self as @Visitor<()>, view_item, ())
+        visit::visit_view_item(self as @mut Visitor<()>, view_item, ())
     }
 
     fn visit_item(@mut self, item: @ast::item, _: ()) {
-        visit::visit_item(self as @Visitor<()>, item, ())
+        visit::visit_item(self as @mut Visitor<()>, item, ())
     }
 
     fn visit_foreign_item(@mut self,
                           foreign_item: @ast::foreign_item,
                           _: ()) {
-        visit::visit_foreign_item(self as @Visitor<()>, foreign_item, ())
+        visit::visit_foreign_item(self as @mut Visitor<()>, foreign_item, ())
     }
 
     fn visit_local(@mut self, local: @ast::Local, _: ()) {
-        visit::visit_local(self as @Visitor<()>, local, ())
+        visit::visit_local(self as @mut Visitor<()>, local, ())
     }
 
     fn visit_block(@mut self, block: &ast::Block, _: ()) {
-        visit::visit_block(self as @Visitor<()>, block, ())
+        visit::visit_block(self as @mut Visitor<()>, block, ())
     }
 
     fn visit_stmt(@mut self, stmt: @ast::stmt, _: ()) {
-        visit::visit_stmt(self as @Visitor<()>, stmt, ())
+        visit::visit_stmt(self as @mut Visitor<()>, stmt, ())
     }
 
     fn visit_arm(@mut self, arm: &ast::arm, _: ()) {
-        visit::visit_arm(self as @Visitor<()>, arm, ())
+        visit::visit_arm(self as @mut Visitor<()>, arm, ())
     }
 
     fn visit_decl(@mut self, decl: @ast::decl, _: ()) {
-        visit::visit_decl(self as @Visitor<()>, decl, ())
+        visit::visit_decl(self as @mut Visitor<()>, decl, ())
     }
 
     fn visit_expr(@mut self, expr: @ast::expr, _: ()) {
-        visit::visit_expr(self as @Visitor<()>, expr, ())
+        visit::visit_expr(self as @mut Visitor<()>, expr, ())
     }
 
     fn visit_expr_post(@mut self, _: @ast::expr, _: ()) {
@@ -601,11 +601,11 @@ fn visit_expr_post(@mut self, _: @ast::expr, _: ()) {
     }
 
     fn visit_ty(@mut self, typ: &ast::Ty, _: ()) {
-        visit::visit_ty(self as @Visitor<()>, typ, ())
+        visit::visit_ty(self as @mut Visitor<()>, typ, ())
     }
 
     fn visit_generics(@mut self, generics: &ast::Generics, _: ()) {
-        visit::visit_generics(self as @Visitor<()>, generics, ())
+        visit::visit_generics(self as @mut Visitor<()>, generics, ())
     }
 
     fn visit_fn(@mut self,
@@ -615,7 +615,7 @@ fn visit_fn(@mut self,
                 span: span,
                 node_id: NodeId,
                 _: ()) {
-        visit::visit_fn(self as @Visitor<()>,
+        visit::visit_fn(self as @mut Visitor<()>,
                         function_kind,
                         function_declaration,
                         block,
@@ -625,13 +625,13 @@ fn visit_fn(@mut self,
     }
 
     fn visit_ty_method(@mut self, ty_method: &ast::TypeMethod, _: ()) {
-        visit::visit_ty_method(self as @Visitor<()>, ty_method, ())
+        visit::visit_ty_method(self as @mut Visitor<()>, ty_method, ())
     }
 
     fn visit_trait_method(@mut self,
                           trait_method: &ast::trait_method,
                           _: ()) {
-        visit::visit_trait_method(self as @Visitor<()>, trait_method, ())
+        visit::visit_trait_method(self as @mut Visitor<()>, trait_method, ())
     }
 
     fn visit_struct_def(@mut self,
@@ -640,7 +640,7 @@ fn visit_struct_def(@mut self,
                         generics: &ast::Generics,
                         node_id: NodeId,
                         _: ()) {
-        visit::visit_struct_def(self as @Visitor<()>,
+        visit::visit_struct_def(self as @mut Visitor<()>,
                                 struct_def,
                                 ident,
                                 generics,
@@ -651,18 +651,18 @@ fn visit_struct_def(@mut self,
     fn visit_struct_field(@mut self,
                           struct_field: @ast::struct_field,
                           _: ()) {
-        visit::visit_struct_field(self as @Visitor<()>, struct_field, ())
+        visit::visit_struct_field(self as @mut Visitor<()>, struct_field, ())
     }
 }
 
 // return a visitor that extracts the pat_ident paths
 // from a given pattern and puts them in a mutable
 // array (passed in to the traversal)
-pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @Visitor<()> {
+pub fn new_name_finder(idents: @mut ~[ast::ident]) -> @mut Visitor<()> {
     let context = @mut NewNameFinderContext {
         ident_accumulator: idents,
     };
-    context as @Visitor<()>
+    context as @mut Visitor<()>
 }
 
 pub fn expand_block(extsbox: @mut SyntaxEnv,
@@ -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 008545c9729b15390d367b7951af3a19c7f00b68..10f2055b5fbbae4328b239f346392439dad2353f 100644 (file)
@@ -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..65d2f798f31dfe853fc58bc52501322a987a8819 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"), ~[
@@ -429,7 +429,12 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::expr {
             let st = ast::item_static(ty, ast::m_imm, method);
             let static_name = self.ecx.ident_of(fmt!("__static_method_%u",
                                                      self.method_statics.len()));
-            let item = self.ecx.item(sp, static_name, ~[], st);
+            // Flag these statics as `address_insignificant` so LLVM can
+            // merge duplicate globals as much as possible (which we're
+            // generating a whole lot of).
+            let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant");
+            let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
+            let item = self.ecx.item(sp, static_name, ~[unnamed], st);
             self.method_statics.push(item);
             self.ecx.expr_ident(sp, static_name)
         };
@@ -550,7 +555,10 @@ fn to_expr(&self) -> @ast::expr {
         let ty = self.ecx.ty(self.fmtsp, ty);
         let st = ast::item_static(ty, ast::m_imm, fmt);
         let static_name = self.ecx.ident_of("__static_fmtstr");
-        let item = self.ecx.item(self.fmtsp, static_name, ~[], st);
+        // see above comment for `address_insignificant` and why we do it
+        let unnamed = self.ecx.meta_word(self.fmtsp, @"address_insignificant");
+        let unnamed = self.ecx.attribute(self.fmtsp, unnamed);
+        let item = self.ecx.item(self.fmtsp, static_name, ~[unnamed], st);
         let decl = respan(self.fmtsp, ast::decl_item(item));
         lets.push(@respan(self.fmtsp, ast::stmt_decl(@decl, self.ecx.next_id())));
 
@@ -575,8 +583,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, ~[
@@ -613,6 +621,7 @@ fn format_arg(&self, sp: span, arg: Either<uint, @str>,
         if ty == Unknown {
             ty = Known(@"?");
         }
+
         let argptr = self.ecx.expr_addr_of(sp, self.ecx.expr_ident(sp, ident));
         match ty {
             Known(tyname) => {
@@ -685,7 +694,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 f7f17d3ba64ac33ed235f87f3104e305caec3f00..f3e7613d96a34547605a0624032e089e515fbfe4 100644 (file)
@@ -25,7 +25,7 @@ pub fn expand_trace_macros(cx: @ExtCtxt,
     let tt_rdr = new_tt_reader(cx.parse_sess().span_diagnostic,
                                None,
                                tt.to_owned());
-    let rdr = tt_rdr as @reader;
+    let rdr = tt_rdr as @mut reader;
     let rust_parser = Parser(sess, cfg.clone(), rdr.dup());
 
     if rust_parser.is_keyword(keywords::True) {
index 5a1317034b2211aba47e95ea2f1d5df984392bb2..c208a7f7e3e403b77ab9fa6144027158527fe32d 100644 (file)
@@ -17,6 +17,7 @@
 use parse::lexer::*; //resolve bug?
 use parse::ParseSess;
 use parse::parser::Parser;
+use parse::attr::parser_attr;
 use parse::token::{Token, EOF, to_str, nonterminal, get_ident_interner, ident_to_str};
 use parse::token;
 
@@ -223,7 +224,7 @@ pub enum parse_result {
 pub fn parse_or_else(
     sess: @mut ParseSess,
     cfg: ast::CrateConfig,
-    rdr: @reader,
+    rdr: @mut reader,
     ms: ~[matcher]
 ) -> HashMap<ident, @named_match> {
     match parse(sess, cfg, rdr, ms) {
@@ -236,7 +237,7 @@ pub fn parse_or_else(
 pub fn parse(
     sess: @mut ParseSess,
     cfg: ast::CrateConfig,
-    rdr: @reader,
+    rdr: @mut reader,
     ms: &[matcher]
 ) -> parse_result {
     let mut cur_eis = ~[];
@@ -418,18 +419,19 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal {
         Some(i) => token::nt_item(i),
         None => p.fatal("expected an item keyword")
       },
-      "block" => token::nt_block(p.parse_block()),
+      "block" => token::nt_block(~p.parse_block()),
       "stmt" => token::nt_stmt(p.parse_stmt(~[])),
       "pat" => token::nt_pat(p.parse_pat()),
       "expr" => token::nt_expr(p.parse_expr()),
-      "ty" => token::nt_ty(p.parse_ty(false /* no need to disambiguate*/)),
+      "ty" => token::nt_ty(~p.parse_ty(false /* no need to disambiguate*/)),
       // this could be handled like a token, since it is one
       "ident" => match *p.token {
-        token::IDENT(sn,b) => { p.bump(); token::nt_ident(sn,b) }
+        token::IDENT(sn,b) => { p.bump(); token::nt_ident(~sn,b) }
         _ => p.fatal(~"expected ident, found "
                      + token::to_str(get_ident_interner(), p.token))
       },
-      "path" => token::nt_path(p.parse_path_with_tps(false)),
+      "path" => token::nt_path(~p.parse_path_with_tps(false)),
+      "attr" => token::nt_attr(@p.parse_attribute(false)),
       "tt" => {
         *p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
         let res = token::nt_tt(@p.parse_token_tree());
index 10735dad32f00e9b93b46d37e9dbf6df7dbefd43..54ac1f1e48f44a698a6510a021cc7b5cbfb2b4d6 100644 (file)
@@ -59,7 +59,7 @@ fn ms(m: matcher_) -> matcher {
                                    arg.clone());
     let argument_map = parse_or_else(cx.parse_sess(),
                                      cx.cfg(),
-                                     arg_reader as @reader,
+                                     arg_reader as @mut reader,
                                      argument_gram);
 
     // Extract the arguments:
@@ -101,7 +101,7 @@ fn generic_extension(cx: @ExtCtxt, sp: span, name: ident,
                     s_d,
                     None,
                     arg.to_owned()
-                ) as @reader;
+                ) as @mut reader;
                 match parse(cx.parse_sess(), cx.cfg(), arg_rdr, *mtcs) {
                   success(named_matches) => {
                     let rhs = match rhses[i] {
@@ -123,7 +123,7 @@ fn generic_extension(cx: @ExtCtxt, sp: span, name: ident,
                                                rhs);
                     let p = @Parser(cx.parse_sess(),
                                     cx.cfg(),
-                                    trncbr as @reader);
+                                    trncbr as @mut reader);
 
                     // Let the context choose how to interpret the result.
                     // Weird, but useful for X-macros.
index 16019b2144833fc3221280bd8d1a31afa99bcfe0..13bad252243090552db2549b7189d654242d5a57 100644 (file)
@@ -30,7 +30,7 @@ struct TtFrame {
 }
 
 pub struct TtReader {
-    sp_diag: @span_handler,
+    sp_diag: @mut span_handler,
     // the unzipped tree:
     stack: @mut TtFrame,
     /* for MBE-style macro transcription */
@@ -45,7 +45,7 @@ pub struct TtReader {
 /** This can do Macro-By-Example transcription. On the other hand, if
  *  `src` contains no `tt_seq`s and `tt_nonterminal`s, `interp` can (and
  *  should) be none. */
-pub fn new_tt_reader(sp_diag: @span_handler,
+pub fn new_tt_reader(sp_diag: @mut span_handler,
                      interp: Option<HashMap<ident,@named_match>>,
                      src: ~[ast::token_tree])
                   -> @mut TtReader {
@@ -279,7 +279,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan {
               /* sidestep the interpolation tricks for ident because
               (a) idents can be in lots of places, so it'd be a pain
               (b) we actually can, since it's a token. */
-              matched_nonterminal(nt_ident(sn,b)) => {
+              matched_nonterminal(nt_ident(~sn,b)) => {
                 r.cur_span = sp; r.cur_tok = IDENT(sn,b);
                 r.stack.idx += 1u;
                 return ret_val;
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 8cce5f15e67a84f0ec008f0d247003d5b5d52798..f2489d80e1e69fe83681f1ea2be16c8af8a450a8 100644 (file)
@@ -9,21 +9,17 @@
 // except according to those terms.
 
 use ast;
-use codemap::spanned;
+use codemap::{spanned, mk_sp};
 use codemap::BytePos;
 use parse::common::*; //resolve bug?
 use parse::token;
 use parse::parser::Parser;
+use parse::token::INTERPOLATED;
 
 // a parser that can parse attributes.
 pub trait parser_attr {
     fn parse_outer_attributes(&self) -> ~[ast::Attribute];
-    fn parse_attribute(&self, style: ast::AttrStyle) -> ast::Attribute;
-    fn parse_attribute_naked(
-        &self,
-        style: ast::AttrStyle,
-        lo: BytePos
-    ) -> ast::Attribute;
+    fn parse_attribute(&self, permit_inner: bool) -> ast::Attribute;
     fn parse_inner_attrs_and_next(&self) ->
         (~[ast::Attribute], ~[ast::Attribute]);
     fn parse_meta_item(&self) -> @ast::MetaItem;
@@ -37,12 +33,17 @@ impl parser_attr for Parser {
     fn parse_outer_attributes(&self) -> ~[ast::Attribute] {
         let mut attrs: ~[ast::Attribute] = ~[];
         loop {
+            debug!("parse_outer_attributes: self.token=%?",
+                   self.token);
             match *self.token {
+              token::INTERPOLATED(token::nt_attr(*)) => {
+                attrs.push(self.parse_attribute(false));
+              }
               token::POUND => {
                 if self.look_ahead(1, |t| *t != token::LBRACKET) {
                     break;
                 }
-                attrs.push(self.parse_attribute(ast::AttrOuter));
+                attrs.push(self.parse_attribute(false));
               }
               token::DOC_COMMENT(s) => {
                 let attr = ::attr::mk_sugared_doc_attr(
@@ -62,23 +63,49 @@ fn parse_outer_attributes(&self) -> ~[ast::Attribute] {
         return attrs;
     }
 
-    // matches attribute = # attribute_naked
-    fn parse_attribute(&self, style: ast::AttrStyle) -> ast::Attribute {
-        let lo = self.span.lo;
-        self.expect(&token::POUND);
-        return self.parse_attribute_naked(style, lo);
+    // matches attribute = # [ meta_item ]
+    //
+    // if permit_inner is true, then a trailing `;` indicates an inner
+    // attribute
+    fn parse_attribute(&self, permit_inner: bool) -> ast::Attribute {
+        debug!("parse_attributes: permit_inner=%? self.token=%?",
+               permit_inner, self.token);
+        let (span, value) = match *self.token {
+            INTERPOLATED(token::nt_attr(attr)) => {
+                assert!(attr.node.style == ast::AttrOuter);
+                self.bump();
+                (attr.span, attr.node.value)
+            }
+            token::POUND => {
+                let lo = self.span.lo;
+                self.bump();
+                self.expect(&token::LBRACKET);
+                let meta_item = self.parse_meta_item();
+                self.expect(&token::RBRACKET);
+                let hi = self.span.hi;
+                (mk_sp(lo, hi), meta_item)
+            }
+            _ => {
+                self.fatal(fmt!("expected `#` but found `%s`",
+                                self.this_token_to_str()));
+            }
+        };
+        let style = if permit_inner && *self.token == token::SEMI {
+            self.bump();
+            ast::AttrInner
+        } else {
+            ast::AttrOuter
+        };
+        return spanned {
+            span: span,
+            node: ast::Attribute_ {
+                style: style,
+                value: value,
+                is_sugared_doc: false
+            }
+        };
     }
 
-    // matches attribute_naked = [ meta_item ]
-    fn parse_attribute_naked(&self, style: ast::AttrStyle, lo: BytePos) ->
-        ast::Attribute {
-        self.expect(&token::LBRACKET);
-        let meta_item = self.parse_meta_item();
-        self.expect(&token::RBRACKET);
-        let hi = self.span.hi;
-        return spanned(lo, hi, ast::Attribute_ { style: style,
-                                                 value: meta_item, is_sugared_doc: false }); }
-
     // Parse attributes that appear after the opening of an item, each
     // terminated by a semicolon. In addition to a vector of inner attributes,
     // this function also returns a vector that may contain the first outer
@@ -89,47 +116,37 @@ fn parse_attribute_naked(&self, style: ast::AttrStyle, lo: BytePos) ->
     // matches inner_attrs* outer_attr?
     // you can make the 'next' field an Option, but the result is going to be
     // more useful as a vector.
-    fn parse_inner_attrs_and_next(&self) ->
-        (~[ast::Attribute], ~[ast::Attribute]) {
+    fn parse_inner_attrs_and_next(&self)
+                                  -> (~[ast::Attribute], ~[ast::Attribute]) {
         let mut inner_attrs: ~[ast::Attribute] = ~[];
         let mut next_outer_attrs: ~[ast::Attribute] = ~[];
         loop {
-            match *self.token {
-              token::POUND => {
-                if self.look_ahead(1, |t| *t != token::LBRACKET) {
-                    // This is an extension
-                    break;
+            let attr = match *self.token {
+                token::INTERPOLATED(token::nt_attr(*)) => {
+                    self.parse_attribute(true)
+                }
+                token::POUND => {
+                    if self.look_ahead(1, |t| *t != token::LBRACKET) {
+                        // This is an extension
+                        break;
+                    }
+                    self.parse_attribute(true)
                 }
-                let attr = self.parse_attribute(ast::AttrInner);
-                if *self.token == token::SEMI {
+                token::DOC_COMMENT(s) => {
                     self.bump();
-                    inner_attrs.push(attr);
-                } else {
-                    // It's not really an inner attribute
-                    let outer_attr =
-                        spanned(attr.span.lo, attr.span.hi,
-                            ast::Attribute_ { style: ast::AttrOuter,
-                                              value: attr.node.value,
-                                              is_sugared_doc: false });
-                    next_outer_attrs.push(outer_attr);
-                    break;
+                    ::attr::mk_sugared_doc_attr(self.id_to_str(s),
+                                                self.span.lo,
+                                                self.span.hi)
                 }
-              }
-              token::DOC_COMMENT(s) => {
-                let attr = ::attr::mk_sugared_doc_attr(
-                    self.id_to_str(s),
-                    self.span.lo,
-                    self.span.hi
-                );
-                self.bump();
-                if attr.node.style == ast::AttrInner {
-                  inner_attrs.push(attr);
-                } else {
-                  next_outer_attrs.push(attr);
-                  break;
+                _ => {
+                    break;
                 }
-              }
-              _ => break
+            };
+            if attr.node.style == ast::AttrInner {
+                inner_attrs.push(attr);
+            } else {
+                next_outer_attrs.push(attr);
+                break;
             }
         }
         (inner_attrs, next_outer_attrs)
index 41379e6599c6e8b47e3835f9d5c9b4aa5c31379e..9a9164f510210376cc2a9fcfe0497e213e49c41a 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);
@@ -267,7 +267,7 @@ fn read_block_comment(rdr: @mut StringReader,
         while level > 0 {
             debug!("=== block comment level %d", level);
             if is_eof(rdr) {
-                (rdr as @reader).fatal(~"unterminated block comment");
+                (rdr as @mut reader).fatal(~"unterminated block comment");
             }
             if rdr.curr == '\n' {
                 trim_whitespace_prefix_and_push_line(&mut lines, curr_line,
@@ -334,7 +334,7 @@ pub struct lit {
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
 pub fn gather_comments_and_literals(span_diagnostic:
-                                    @diagnostic::span_handler,
+                                    @mut diagnostic::span_handler,
                                     path: @str,
                                     srdr: @io::Reader)
                                  -> (~[cmnt], ~[lit]) {
index 49deafeda40bb55c2a38f8a2e8f42fb7506d0e9e..d0041021f7cc77158a8e1fa130a1c8bf4a361e75 100644 (file)
@@ -28,9 +28,9 @@ pub trait reader {
     fn is_eof(@mut self) -> bool;
     fn next_token(@mut self) -> TokenAndSpan;
     fn fatal(@mut self, ~str) -> !;
-    fn span_diag(@mut self) -> @span_handler;
+    fn span_diag(@mut self) -> @mut span_handler;
     fn peek(@mut self) -> TokenAndSpan;
-    fn dup(@mut self) -> @reader;
+    fn dup(@mut self) -> @mut reader;
 }
 
 #[deriving(Clone, Eq)]
@@ -40,7 +40,7 @@ pub struct TokenAndSpan {
 }
 
 pub struct StringReader {
-    span_diagnostic: @span_handler,
+    span_diagnostic: @mut span_handler,
     src: @str,
     // The absolute offset within the codemap of the next character to read
     pos: BytePos,
@@ -56,7 +56,7 @@ pub struct StringReader {
     peek_span: span
 }
 
-pub fn new_string_reader(span_diagnostic: @span_handler,
+pub fn new_string_reader(span_diagnostic: @mut span_handler,
                          filemap: @codemap::FileMap)
                       -> @mut StringReader {
     let r = new_low_level_string_reader(span_diagnostic, filemap);
@@ -65,13 +65,14 @@ pub fn new_string_reader(span_diagnostic: @span_handler,
 }
 
 /* For comments.rs, which hackily pokes into 'pos' and 'curr' */
-pub fn new_low_level_string_reader(span_diagnostic: @span_handler,
+pub fn new_low_level_string_reader(span_diagnostic: @mut span_handler,
                                    filemap: @codemap::FileMap)
                                 -> @mut StringReader {
     // Force the initial reader bump to start on a fresh line
     let initial_char = '\n';
     let r = @mut StringReader {
-        span_diagnostic: span_diagnostic, src: filemap.src,
+        span_diagnostic: span_diagnostic,
+        src: filemap.src,
         pos: filemap.start_pos,
         last_pos: filemap.start_pos,
         col: CharPos(0),
@@ -116,7 +117,7 @@ fn next_token(@mut self) -> TokenAndSpan {
     fn fatal(@mut self, m: ~str) -> ! {
         self.span_diagnostic.span_fatal(self.peek_span, m)
     }
-    fn span_diag(@mut self) -> @span_handler { self.span_diagnostic }
+    fn span_diag(@mut self) -> @mut span_handler { self.span_diagnostic }
     fn peek(@mut self) -> TokenAndSpan {
         // XXX(pcwalton): Bad copy!
         TokenAndSpan {
@@ -124,23 +125,27 @@ fn peek(@mut self) -> TokenAndSpan {
             sp: self.peek_span,
         }
     }
-    fn dup(@mut self) -> @reader { dup_string_reader(self) as @reader }
+    fn dup(@mut self) -> @mut reader { dup_string_reader(self) as @mut reader }
 }
 
 impl reader for TtReader {
     fn is_eof(@mut self) -> bool { self.cur_tok == token::EOF }
-    fn next_token(@mut self) -> TokenAndSpan { tt_next_token(self) }
+    fn next_token(@mut self) -> TokenAndSpan {
+        let r = tt_next_token(self);
+        debug!("TtReader: r=%?", r);
+        return r;
+    }
     fn fatal(@mut self, m: ~str) -> ! {
         self.sp_diag.span_fatal(self.cur_span, m);
     }
-    fn span_diag(@mut self) -> @span_handler { self.sp_diag }
+    fn span_diag(@mut self) -> @mut span_handler { self.sp_diag }
     fn peek(@mut self) -> TokenAndSpan {
         TokenAndSpan {
             tok: self.cur_tok.clone(),
             sp: self.cur_span,
         }
     }
-    fn dup(@mut self) -> @reader { dup_tt_reader(self) as @reader }
+    fn dup(@mut self) -> @mut reader { dup_tt_reader(self) as @mut reader }
 }
 
 // EFFECT: advance peek_tok and peek_span to refer to the next token.
index 1731a587a8efa3c3c75c091aaf71cf7d0db58db4..23c6a8b97208b014aa3f782fa96d2a7ec61a6980 100644 (file)
@@ -43,7 +43,7 @@
 pub struct ParseSess {
     cm: @codemap::CodeMap, // better be the same as the one in the reader!
     next_id: NodeId,
-    span_diagnostic: @span_handler, // better be the same as the one in the reader!
+    span_diagnostic: @mut span_handler, // better be the same as the one in the reader!
     /// Used to determine and report recursive mod inclusions
     included_mod_stack: ~[Path],
 }
@@ -58,7 +58,7 @@ pub fn new_parse_sess(demitter: Option<Emitter>) -> @mut ParseSess {
     }
 }
 
-pub fn new_parse_sess_special_handler(sh: @span_handler,
+pub fn new_parse_sess_special_handler(sh: @mut span_handler,
                                       cm: @codemap::CodeMap)
                                    -> @mut ParseSess {
     @mut ParseSess {
@@ -306,7 +306,7 @@ pub fn filemap_to_tts(sess: @mut ParseSess, filemap: @FileMap)
     // parsing tt's probably shouldn't require a parser at all.
     let cfg = ~[];
     let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap);
-    let p1 = Parser(sess, cfg, srdr as @reader);
+    let p1 = Parser(sess, cfg, srdr as @mut reader);
     p1.parse_all_token_trees()
 }
 
@@ -315,7 +315,7 @@ pub fn tts_to_parser(sess: @mut ParseSess,
                      tts: ~[ast::token_tree],
                      cfg: ast::CrateConfig) -> Parser {
     let trdr = lexer::new_tt_reader(sess.span_diagnostic, None, tts);
-    Parser(sess, cfg, trdr as @reader)
+    Parser(sess, cfg, trdr as @mut reader)
 }
 
 // abort if necessary
index 7d6dce22fb7b423553d034f8f718c373860d68c8..27e339f000c297ac1002bd472e0c98afa0182199 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[macro_escape];
+
 use abi;
 use abi::AbiSet;
 use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil};
@@ -144,7 +146,7 @@ macro_rules! maybe_whole_expr (
                     Some($p.mk_expr(
                         ($p).span.lo,
                         ($p).span.hi,
-                        expr_path(/* bad */ (*pt).clone())))
+                        expr_path(/* bad */ (**pt).clone())))
                 }
                 _ => None
             };
@@ -233,8 +235,8 @@ macro_rules! maybe_whole (
                 _ => None
             };
             match __found__ {
-                Some(INTERPOLATED(token::$constructor(x))) => {
-                    return (~[], x.clone())
+                Some(INTERPOLATED(token::$constructor(ref x))) => {
+                    return (~[], (**x).clone())
                 }
                 _ => {}
             }
@@ -263,7 +265,7 @@ struct ParsedItemsAndViewItems {
 
 pub fn Parser(sess: @mut ParseSess,
               cfg: ast::CrateConfig,
-              rdr: @reader)
+              rdr: @mut reader)
            -> Parser {
     let tok0 = rdr.next_token();
     let interner = get_ident_interner();
@@ -313,7 +315,7 @@ pub struct Parser {
     tokens_consumed: @mut uint,
     restriction: @mut restriction,
     quote_depth: @mut uint, // not (yet) related to the quasiquoter
-    reader: @reader,
+    reader: @mut reader,
     interner: @token::ident_interner,
     /// The set of seen errors about obsolete syntax. Used to suppress
     /// extra detail when the same error is seen twice
@@ -937,7 +939,7 @@ pub fn parse_ret_ty(&self) -> (ret_style, Ty) {
     // Useless second parameter for compatibility with quasiquote macros.
     // Bleh!
     pub fn parse_ty(&self, _: bool) -> Ty {
-        maybe_whole!(self, nt_ty);
+        maybe_whole!(deref self, nt_ty);
 
         let lo = self.span.lo;
 
@@ -1291,7 +1293,7 @@ pub fn parse_path_non_global(&self) -> (~[ast::ident],span) {
 
     // parse a path that doesn't have type parameters attached
     pub fn parse_path_without_tps(&self) -> ast::Path {
-        maybe_whole!(self, nt_path);
+        maybe_whole!(deref self, nt_path);
         let (ids,is_global,sp) = self.parse_path();
         ast::Path { span: sp,
                      global: is_global,
@@ -1304,7 +1306,7 @@ pub fn parse_bounded_path_with_tps(&self, colons: bool,
                                         before_tps: Option<&fn()>) -> ast::Path {
         debug!("parse_path_with_tps(colons=%b)", colons);
 
-        maybe_whole!(self, nt_path);
+        maybe_whole!(deref self, nt_path);
         let lo = self.span.lo;
         let path = self.parse_path_without_tps();
         if colons && !self.eat(&token::MOD_SEP) {
@@ -3098,7 +3100,7 @@ fn expr_is_complete(&self, e: @expr) -> bool {
 
     // parse a block. No inner attrs are allowed.
     pub fn parse_block(&self) -> Block {
-        maybe_whole!(self, nt_block);
+        maybe_whole!(deref self, nt_block);
 
         let lo = self.span.lo;
         if self.eat_keyword(keywords::Unsafe) {
@@ -4181,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,
@@ -4191,7 +4201,7 @@ fn parse_item_foreign_mod(&self,
                                          self.this_token_to_str()));
                 }
 
-                (ast::anonymous,
+                (ast::anonymous, None,
                  special_idents::clownshoes_foreign_mod)
             }
         };
@@ -4230,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)
@@ -4302,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(),
@@ -4452,7 +4462,17 @@ fn parse_item_or_view_item(&self,
                                attrs: ~[Attribute],
                                macros_allowed: bool)
                                -> item_or_view_item {
-        maybe_whole!(iovi self, nt_item);
+        match *self.token {
+            INTERPOLATED(token::nt_item(item)) => {
+                self.bump();
+                let new_attrs = vec::append(attrs, item.attrs);
+                return iovi_item(@ast::item {
+                        attrs: new_attrs,
+                        ..(*item).clone()});
+            }
+            _ => {}
+        }
+
         let lo = self.span.lo;
 
         let visibility = self.parse_non_priv_visibility();
@@ -4812,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 fd491c1e890a0d8f140d56d06bd2a29e5ea34791..bdfd25ae644da2a85af997adc3b9bb922cebcd09 100644 (file)
@@ -99,13 +99,14 @@ pub enum Token {
 /// For interpolation during macro expansion.
 pub enum nonterminal {
     nt_item(@ast::item),
-    nt_block(ast::Block),
+    nt_block(~ast::Block),
     nt_stmt(@ast::stmt),
     nt_pat( @ast::pat),
     nt_expr(@ast::expr),
-    nt_ty(   ast::Ty),
-    nt_ident(ast::ident, bool),
-    nt_path( ast::Path),
+    nt_ty(  ~ast::Ty),
+    nt_ident(~ast::ident, bool),
+    nt_attr(@ast::Attribute),   // #[foo]
+    nt_path(~ast::Path),
     nt_tt(  @ast::token_tree), //needs @ed to break a circularity
     nt_matchers(~[ast::matcher])
 }
@@ -205,6 +206,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
       INTERPOLATED(ref nt) => {
         match nt {
             &nt_expr(e) => ::print::pprust::expr_to_str(e, input),
+            &nt_attr(e) => ::print::pprust::attribute_to_str(e, input),
             _ => {
                 ~"an interpolated " +
                     match (*nt) {
@@ -212,6 +214,7 @@ pub fn to_str(input: @ident_interner, t: &Token) -> ~str {
                       nt_block(*) => ~"block",
                       nt_stmt(*) => ~"statement",
                       nt_pat(*) => ~"pattern",
+                      nt_attr(*) => fail!("should have been handled"),
                       nt_expr(*) => fail!("should have been handled above"),
                       nt_ty(*) => ~"type",
                       nt_ident(*) => ~"identifier",
index f517179f6036613e100e2ed9290820d934db96b8..6a3d829aca0b037d8231ef90cc04e2dac0066220 100644 (file)
@@ -104,7 +104,7 @@ pub fn rust_printer_annotated(writer: @io::Writer,
 // copy forward.
 pub fn print_crate(cm: @CodeMap,
                    intr: @ident_interner,
-                   span_diagnostic: @diagnostic::span_handler,
+                   span_diagnostic: @mut diagnostic::span_handler,
                    crate: &ast::Crate,
                    filename: @str,
                    input: @io::Reader,
@@ -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 7aa52bc13e341af01b30b4d3703c8ef3f460238e..c3a5ba7116d9197cd9a207aded1c286829e045cd 100644 (file)
@@ -88,11 +88,11 @@ pub trait Visitor<E> {
     fn visit_struct_field(@mut self, @struct_field, E);
 }
 
-pub fn visit_crate<E:Clone>(visitor: @Visitor<E>, crate: &Crate, env: E) {
+pub fn visit_crate<E:Clone>(visitor: @mut Visitor<E>, crate: &Crate, env: E) {
     visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
 }
 
-pub fn visit_mod<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) {
+pub fn visit_mod<E:Clone>(visitor: @mut Visitor<E>, module: &_mod, env: E) {
     for view_item in module.view_items.iter() {
         visitor.visit_view_item(view_item, env.clone())
     }
@@ -101,11 +101,11 @@ pub fn visit_mod<E:Clone>(visitor: @Visitor<E>, module: &_mod, env: E) {
     }
 }
 
-pub fn visit_view_item<E:Clone>(_: @Visitor<E>, _: &view_item, _: E) {
+pub fn visit_view_item<E:Clone>(_: @mut Visitor<E>, _: &view_item, _: E) {
     // Empty!
 }
 
-pub fn visit_local<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) {
+pub fn visit_local<E:Clone>(visitor: @mut Visitor<E>, local: &Local, env: E) {
     visitor.visit_pat(local.pat, env.clone());
     visitor.visit_ty(&local.ty, env.clone());
     match local.init {
@@ -114,13 +114,13 @@ pub fn visit_local<E:Clone>(visitor: @Visitor<E>, local: &Local, env: E) {
     }
 }
 
-fn visit_trait_ref<E:Clone>(visitor: @Visitor<E>,
+fn visit_trait_ref<E:Clone>(visitor: @mut Visitor<E>,
                             trait_ref: &ast::trait_ref,
                             env: E) {
     visit_path(visitor, &trait_ref.path, env)
 }
 
-pub fn visit_item<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) {
+pub fn visit_item<E:Clone>(visitor: @mut Visitor<E>, item: &item, env: E) {
     match item.node {
         item_static(ref typ, _, expr) => {
             visitor.visit_ty(typ, env.clone());
@@ -187,7 +187,7 @@ pub fn visit_item<E:Clone>(visitor: @Visitor<E>, item: &item, env: E) {
     }
 }
 
-pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_enum_def<E:Clone>(visitor: @mut Visitor<E>,
                                enum_definition: &ast::enum_def,
                                generics: &Generics,
                                env: E) {
@@ -209,11 +209,11 @@ pub fn visit_enum_def<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn skip_ty<E>(_: @Visitor<E>, _: &Ty, _: E) {
+pub fn skip_ty<E>(_: @mut Visitor<E>, _: &Ty, _: E) {
     // Empty!
 }
 
-pub fn visit_ty<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) {
+pub fn visit_ty<E:Clone>(visitor: @mut Visitor<E>, typ: &Ty, env: E) {
     match typ.node {
         ty_box(ref mutable_type) | ty_uniq(ref mutable_type) |
         ty_vec(ref mutable_type) | ty_ptr(ref mutable_type) |
@@ -254,13 +254,13 @@ pub fn visit_ty<E:Clone>(visitor: @Visitor<E>, typ: &Ty, env: E) {
     }
 }
 
-pub fn visit_path<E:Clone>(visitor: @Visitor<E>, path: &Path, env: E) {
+pub fn visit_path<E:Clone>(visitor: @mut Visitor<E>, path: &Path, env: E) {
     for typ in path.types.iter() {
         visitor.visit_ty(typ, env.clone())
     }
 }
 
-pub fn visit_pat<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) {
+pub fn visit_pat<E:Clone>(visitor: @mut Visitor<E>, pattern: &pat, env: E) {
     match pattern.node {
         pat_enum(ref path, ref children) => {
             visit_path(visitor, path, env.clone());
@@ -313,7 +313,7 @@ pub fn visit_pat<E:Clone>(visitor: @Visitor<E>, pattern: &pat, env: E) {
     }
 }
 
-pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_foreign_item<E:Clone>(visitor: @mut Visitor<E>,
                                    foreign_item: &foreign_item,
                                    env: E) {
     match foreign_item.node {
@@ -325,7 +325,7 @@ pub fn visit_foreign_item<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_ty_param_bounds<E:Clone>(visitor: @mut Visitor<E>,
                                       bounds: &OptVec<TyParamBound>,
                                       env: E) {
     for bound in bounds.iter() {
@@ -338,7 +338,7 @@ pub fn visit_ty_param_bounds<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_generics<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_generics<E:Clone>(visitor: @mut Visitor<E>,
                                generics: &Generics,
                                env: E) {
     for type_parameter in generics.ty_params.iter() {
@@ -346,7 +346,7 @@ pub fn visit_generics<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_fn_decl<E:Clone>(visitor: @mut Visitor<E>,
                               function_declaration: &fn_decl,
                               env: E) {
     for argument in function_declaration.inputs.iter() {
@@ -360,7 +360,7 @@ pub fn visit_fn_decl<E:Clone>(visitor: @Visitor<E>,
 // visit_fn() and check for fk_method().  I named this visit_method_helper()
 // because it is not a default impl of any method, though I doubt that really
 // clarifies anything. - Niko
-pub fn visit_method_helper<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_method_helper<E:Clone>(visitor: @mut Visitor<E>,
                                     method: &method,
                                     env: E) {
     visitor.visit_fn(&fk_method(method.ident, &method.generics, method),
@@ -371,7 +371,7 @@ pub fn visit_method_helper<E:Clone>(visitor: @Visitor<E>,
                      env)
 }
 
-pub fn visit_fn<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_fn<E:Clone>(visitor: @mut Visitor<E>,
                          function_kind: &fn_kind,
                          function_declaration: &fn_decl,
                          function_body: &Block,
@@ -384,7 +384,7 @@ pub fn visit_fn<E:Clone>(visitor: @Visitor<E>,
     visitor.visit_block(function_body, env)
 }
 
-pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_ty_method<E:Clone>(visitor: @mut Visitor<E>,
                                 method_type: &TypeMethod,
                                 env: E) {
     for argument_type in method_type.decl.inputs.iter() {
@@ -394,7 +394,7 @@ pub fn visit_ty_method<E:Clone>(visitor: @Visitor<E>,
     visitor.visit_ty(&method_type.decl.output, env.clone())
 }
 
-pub fn visit_trait_method<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_trait_method<E:Clone>(visitor: @mut Visitor<E>,
                                    trait_method: &trait_method,
                                    env: E) {
     match *trait_method {
@@ -405,7 +405,7 @@ pub fn visit_trait_method<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_struct_def<E:Clone>(visitor: @mut Visitor<E>,
                                  struct_definition: @struct_def,
                                  _: ast::ident,
                                  _: &Generics,
@@ -416,13 +416,13 @@ pub fn visit_struct_def<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_struct_field<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_struct_field<E:Clone>(visitor: @mut Visitor<E>,
                                    struct_field: &struct_field,
                                    env: E) {
     visitor.visit_ty(&struct_field.node.ty, env)
 }
 
-pub fn visit_block<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) {
+pub fn visit_block<E:Clone>(visitor: @mut Visitor<E>, block: &Block, env: E) {
     for view_item in block.view_items.iter() {
         visitor.visit_view_item(view_item, env.clone())
     }
@@ -432,7 +432,7 @@ pub fn visit_block<E:Clone>(visitor: @Visitor<E>, block: &Block, env: E) {
     visit_expr_opt(visitor, block.expr, env)
 }
 
-pub fn visit_stmt<E>(visitor: @Visitor<E>, statement: &stmt, env: E) {
+pub fn visit_stmt<E>(visitor: @mut Visitor<E>, statement: &stmt, env: E) {
     match statement.node {
         stmt_decl(declaration, _) => visitor.visit_decl(declaration, env),
         stmt_expr(expression, _) | stmt_semi(expression, _) => {
@@ -442,14 +442,14 @@ pub fn visit_stmt<E>(visitor: @Visitor<E>, statement: &stmt, env: E) {
     }
 }
 
-pub fn visit_decl<E:Clone>(visitor: @Visitor<E>, declaration: &decl, env: E) {
+pub fn visit_decl<E:Clone>(visitor: @mut Visitor<E>, declaration: &decl, env: E) {
     match declaration.node {
         decl_local(ref local) => visitor.visit_local(*local, env),
         decl_item(item) => visitor.visit_item(item, env),
     }
 }
 
-pub fn visit_expr_opt<E>(visitor: @Visitor<E>,
+pub fn visit_expr_opt<E>(visitor: @mut Visitor<E>,
                          optional_expression: Option<@expr>,
                          env: E) {
     match optional_expression {
@@ -458,7 +458,7 @@ pub fn visit_expr_opt<E>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>,
+pub fn visit_exprs<E:Clone>(visitor: @mut Visitor<E>,
                             expressions: &[@expr],
                             env: E) {
     for expression in expressions.iter() {
@@ -466,11 +466,11 @@ pub fn visit_exprs<E:Clone>(visitor: @Visitor<E>,
     }
 }
 
-pub fn visit_mac<E>(_: @Visitor<E>, _: &mac, _: E) {
+pub fn visit_mac<E>(_: @mut Visitor<E>, _: &mac, _: E) {
     // Empty!
 }
 
-pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
+pub fn visit_expr<E:Clone>(visitor: @mut Visitor<E>, expression: @expr, env: E) {
     match expression.node {
         expr_vstore(subexpression, _) => {
             visitor.visit_expr(subexpression, env.clone())
@@ -595,7 +595,7 @@ pub fn visit_expr<E:Clone>(visitor: @Visitor<E>, expression: @expr, env: E) {
     visitor.visit_expr_post(expression, env.clone())
 }
 
-pub fn visit_arm<E:Clone>(visitor: @Visitor<E>, arm: &arm, env: E) {
+pub fn visit_arm<E:Clone>(visitor: @mut Visitor<E>, arm: &arm, env: E) {
     for pattern in arm.pats.iter() {
         visitor.visit_pat(*pattern, env.clone())
     }
@@ -630,7 +630,7 @@ pub trait SimpleVisitor {
 }
 
 pub struct SimpleVisitorVisitor {
-    simple_visitor: @SimpleVisitor,
+    simple_visitor: @mut SimpleVisitor,
 }
 
 impl Visitor<()> for SimpleVisitorVisitor {
@@ -640,58 +640,58 @@ fn visit_mod(@mut self,
                  node_id: NodeId,
                  env: ()) {
         self.simple_visitor.visit_mod(module, span, node_id);
-        visit_mod(self as @Visitor<()>, module, env)
+        visit_mod(self as @mut Visitor<()>, module, env)
     }
     fn visit_view_item(@mut self, view_item: &view_item, env: ()) {
         self.simple_visitor.visit_view_item(view_item);
-        visit_view_item(self as @Visitor<()>, view_item, env)
+        visit_view_item(self as @mut Visitor<()>, view_item, env)
     }
     fn visit_foreign_item(@mut self, foreign_item: @foreign_item, env: ()) {
         self.simple_visitor.visit_foreign_item(foreign_item);
-        visit_foreign_item(self as @Visitor<()>, foreign_item, env)
+        visit_foreign_item(self as @mut Visitor<()>, foreign_item, env)
     }
     fn visit_item(@mut self, item: @item, env: ()) {
         self.simple_visitor.visit_item(item);
-        visit_item(self as @Visitor<()>, item, env)
+        visit_item(self as @mut Visitor<()>, item, env)
     }
     fn visit_local(@mut self, local: @Local, env: ()) {
         self.simple_visitor.visit_local(local);
-        visit_local(self as @Visitor<()>, local, env)
+        visit_local(self as @mut Visitor<()>, local, env)
     }
     fn visit_block(@mut self, block: &Block, env: ()) {
         self.simple_visitor.visit_block(block);
-        visit_block(self as @Visitor<()>, block, env)
+        visit_block(self as @mut Visitor<()>, block, env)
     }
     fn visit_stmt(@mut self, statement: @stmt, env: ()) {
         self.simple_visitor.visit_stmt(statement);
-        visit_stmt(self as @Visitor<()>, statement, env)
+        visit_stmt(self as @mut Visitor<()>, statement, env)
     }
     fn visit_arm(@mut self, arm: &arm, env: ()) {
         self.simple_visitor.visit_arm(arm);
-        visit_arm(self as @Visitor<()>, arm, env)
+        visit_arm(self as @mut Visitor<()>, arm, env)
     }
     fn visit_pat(@mut self, pattern: @pat, env: ()) {
         self.simple_visitor.visit_pat(pattern);
-        visit_pat(self as @Visitor<()>, pattern, env)
+        visit_pat(self as @mut Visitor<()>, pattern, env)
     }
     fn visit_decl(@mut self, declaration: @decl, env: ()) {
         self.simple_visitor.visit_decl(declaration);
-        visit_decl(self as @Visitor<()>, declaration, env)
+        visit_decl(self as @mut Visitor<()>, declaration, env)
     }
     fn visit_expr(@mut self, expression: @expr, env: ()) {
         self.simple_visitor.visit_expr(expression);
-        visit_expr(self as @Visitor<()>, expression, env)
+        visit_expr(self as @mut Visitor<()>, expression, env)
     }
     fn visit_expr_post(@mut self, expression: @expr, _: ()) {
         self.simple_visitor.visit_expr_post(expression)
     }
     fn visit_ty(@mut self, typ: &Ty, env: ()) {
         self.simple_visitor.visit_ty(typ);
-        visit_ty(self as @Visitor<()>, typ, env)
+        visit_ty(self as @mut Visitor<()>, typ, env)
     }
     fn visit_generics(@mut self, generics: &Generics, env: ()) {
         self.simple_visitor.visit_generics(generics);
-        visit_generics(self as @Visitor<()>, generics, env)
+        visit_generics(self as @mut Visitor<()>, generics, env)
     }
     fn visit_fn(@mut self,
                 function_kind: &fn_kind,
@@ -705,7 +705,7 @@ fn visit_fn(@mut self,
                                      block,
                                      span,
                                      node_id);
-        visit_fn(self as @Visitor<()>,
+        visit_fn(self as @mut Visitor<()>,
                  function_kind,
                  function_declaration,
                  block,
@@ -715,11 +715,11 @@ fn visit_fn(@mut self,
     }
     fn visit_ty_method(@mut self, method_type: &TypeMethod, env: ()) {
         self.simple_visitor.visit_ty_method(method_type);
-        visit_ty_method(self as @Visitor<()>, method_type, env)
+        visit_ty_method(self as @mut Visitor<()>, method_type, env)
     }
     fn visit_trait_method(@mut self, trait_method: &trait_method, env: ()) {
         self.simple_visitor.visit_trait_method(trait_method);
-        visit_trait_method(self as @Visitor<()>, trait_method, env)
+        visit_trait_method(self as @mut Visitor<()>, trait_method, env)
     }
     fn visit_struct_def(@mut self,
                         struct_definition: @struct_def,
@@ -731,7 +731,7 @@ fn visit_struct_def(@mut self,
                                              identifier,
                                              generics,
                                              node_id);
-        visit_struct_def(self as @Visitor<()>,
+        visit_struct_def(self as @mut Visitor<()>,
                          struct_definition,
                          identifier,
                          generics,
@@ -740,7 +740,7 @@ fn visit_struct_def(@mut self,
     }
     fn visit_struct_field(@mut self, struct_field: @struct_field, env: ()) {
         self.simple_visitor.visit_struct_field(struct_field);
-        visit_struct_field(self as @Visitor<()>, struct_field, env)
+        visit_struct_field(self as @mut Visitor<()>, struct_field, env)
     }
 }
 
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 60ca5674b01638cf7a8e0c9982a2ed9e06422561..57538f1ec75dbf03c8e99c54b1f0bf02eaffce93 100644 (file)
@@ -58,6 +58,7 @@ struct type_desc {
     glue_fn *drop_glue;
     glue_fn *free_glue;
     glue_fn *visit_glue;
+    size_t borrow_offset;
 };
 
 extern "C" type_desc *rust_clone_type_desc(type_desc*);
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 4a15830e529a0fb59ce4262cb5a60cfd9248fbdb..28c69af427a32c54f75b8c0056b4b187f3b3444d 100644 (file)
@@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
     NULL, // drop_glue
     NULL, // free_glue
     NULL, // visit_glue
+    0, // borrow_offset
 };
 
 //
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 04c062072d6cb4d8fd9dc4152f0af3f028f95f25..db353036336c266f0711812212dc12f7614b3b94 100644 (file)
@@ -833,3 +833,7 @@ extern "C" LLVMValueRef LLVMDIBuilderCreateUnionType(
         unwrapDI<DIArray>(Elements),
         RunTimeLang));
 }
+
+extern "C" void LLVMSetUnnamedAddr(LLVMValueRef Value, LLVMBool Unnamed) {
+    unwrap<GlobalValue>(Value)->setUnnamedAddr(Unnamed);
+}
index 260a16dab9845b089a8c01f756dd2d7225aaf275..a2af7a18b4f8aca7b715fd4a6be00b30d5620cdd 100644 (file)
@@ -613,3 +613,4 @@ LLVMDIBuilderInsertDeclareBefore
 LLVMDIBuilderCreateEnumerator
 LLVMDIBuilderCreateEnumerationType
 LLVMDIBuilderCreateUnionType
+LLVMSetUnnamedAddr
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 }
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
+}
diff --git a/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs b/src/test/compile-fail/borrowck-borrow-mut-object-twice.rs
new file mode 100644 (file)
index 0000000..502d7e0
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+// Check that `&mut` objects cannot be borrowed twice, just like
+// other `&mut` pointers.
+
+trait Foo {
+    fn f1<'a>(&'a mut self) -> &'a ();
+    fn f2(&mut self);
+}
+
+fn test(x: &mut Foo) {
+    let _y = x.f1();
+    x.f2(); //~ ERROR cannot borrow `*x` as mutable more than once at a time
+}
+
+fn main() {}
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" }
diff --git a/src/test/compile-fail/borrowck-object-lifetime.rs b/src/test/compile-fail/borrowck-object-lifetime.rs
new file mode 100644 (file)
index 0000000..25d5be7
--- /dev/null
@@ -0,0 +1,42 @@
+// 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.
+
+trait Foo {
+    fn borrowed<'a>(&'a self) -> &'a ();
+}
+
+fn borrowed_receiver<'a>(x: &'a Foo) -> &'a () {
+    x.borrowed()
+}
+
+fn managed_receiver(x: @Foo) -> &() {
+    x.borrowed() //~ ERROR cannot root managed value long enough
+}
+
+fn managed_receiver_1(x: @Foo) {
+    *x.borrowed()
+}
+
+fn owned_receiver(x: ~Foo) -> &() {
+    x.borrowed() //~ ERROR borrowed value does not live long enough
+}
+
+fn mut_owned_receiver(mut x: ~Foo) {
+    let _y = x.borrowed();
+    let _z = &mut x; //~ ERROR cannot borrow
+}
+
+fn imm_owned_receiver(mut x: ~Foo) {
+    let _y = x.borrowed();
+    let _z = &x;
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/borrowck-object-mutability.rs b/src/test/compile-fail/borrowck-object-mutability.rs
new file mode 100644 (file)
index 0000000..1ea9e3c
--- /dev/null
@@ -0,0 +1,47 @@
+// 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.
+
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+}
+
+fn borrowed_receiver(x: &Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn managed_receiver(x: @Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn managed_mut_receiver(x: @mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn owned_receiver(x: ~Foo) {
+    x.borrowed();
+    x.borrowed_mut(); //~ ERROR cannot borrow
+}
+
+fn mut_owned_receiver(mut x: ~Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+}
+
+fn main() {}
+
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/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() {}
index 19b38769d95694886fc3532a26c93544d5318883..cf047674cd6c8d5007f70a1a24933e1af3f20d10 100644 (file)
@@ -31,5 +31,4 @@ fn main() {
     //~^ ERROR dereference of reference outside its lifetime
     //~^^ ERROR automatically borrowed pointer is not valid at the time of borrow
     //~^^^ ERROR lifetime of return value does not outlive the function call
-    //~^^^^ ERROR cannot infer an appropriate lifetime
 }
diff --git a/src/test/compile-fail/macro-inner-attributes.rs b/src/test/compile-fail/macro-inner-attributes.rs
new file mode 100644 (file)
index 0000000..95000f4
--- /dev/null
@@ -0,0 +1,21 @@
+macro_rules! test ( ($nm:ident,
+                     $a:attr,
+                     $i:item) => (mod $nm { $a; $i }); )
+
+test!(a,
+      #[cfg(qux)],
+      pub fn bar() { })
+
+test!(b,
+      #[cfg(not(qux))],
+      pub fn bar() { })
+
+#[qux]
+fn main() {
+    a::bar();
+    //~^ ERROR use of undeclared module `a`
+    //~^^ ERROR unresolved name
+    //~^^^ ERROR unresolved name `a::bar`
+    b::bar();
+}
+
diff --git a/src/test/compile-fail/macro-outer-attributes.rs b/src/test/compile-fail/macro-outer-attributes.rs
new file mode 100644 (file)
index 0000000..23c3e80
--- /dev/null
@@ -0,0 +1,19 @@
+macro_rules! test ( ($nm:ident,
+                     $a:attr,
+                     $i:item) => (mod $nm { $a $i }); )
+
+test!(a,
+      #[cfg(qux)],
+      pub fn bar() { })
+
+test!(b,
+      #[cfg(not(qux))],
+      pub fn bar() { })
+
+// test1!(#[bar])
+#[qux]
+fn main() {
+    a::bar(); //~ ERROR unresolved name `a::bar`
+    b::bar();
+}
+
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/object-pointer-types.rs b/src/test/compile-fail/object-pointer-types.rs
new file mode 100644 (file)
index 0000000..b7d320f
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.
+
+trait Foo {
+    fn borrowed(&self);
+    fn borrowed_mut(&mut self);
+
+    fn managed(@self);
+    fn managed_mut(@mut self);
+
+    fn owned(~self);
+}
+
+fn borrowed_receiver(x: &Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed(); //~ ERROR does not implement any method
+    x.managed_mut(); //~ ERROR does not implement any method
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn borrowed_mut_receiver(x: &mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+    x.managed(); //~ ERROR does not implement any method
+    x.managed_mut(); //~ ERROR does not implement any method
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn managed_receiver(x: @Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed();
+    x.managed_mut();  //~ ERROR does not implement any method
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn managed_mut_receiver(x: @mut Foo) {
+    x.borrowed();
+    x.borrowed_mut();
+    x.managed();  //~ ERROR does not implement any method
+    x.managed_mut();
+    x.owned(); //~ ERROR does not implement any method
+}
+
+fn owned_receiver(x: ~Foo) {
+    x.borrowed();
+    x.borrowed_mut(); // See [1]
+    x.managed();  //~ ERROR does not implement any method
+    x.managed_mut();  //~ ERROR does not implement any method
+    x.owned();
+}
+
+fn main() {}
+
+// [1]: These cases are illegal, but the error is not detected
+// until borrowck, so see the test borrowck-object-mutability.rs
index 220573660c5b08dca07205b2d8f4c6f3283db891..b5484b786a022e549127031ef7c7a7a7f05ed605 100644 (file)
@@ -13,7 +13,7 @@ trait add {
 }
 
 fn do_add(x: @add, y: @add) -> @add {
-    x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through a boxed trait
+    x.plus(y) //~ ERROR cannot call a method whose type contains a self-type through an object
 }
 
 fn main() {}
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
 }
diff --git a/src/test/run-fail/borrowck-wg-fail-object.rs b/src/test/run-fail/borrowck-wg-fail-object.rs
new file mode 100644 (file)
index 0000000..73f2cf0
--- /dev/null
@@ -0,0 +1,21 @@
+// error-pattern:borrowed
+
+trait Foo {
+    fn foo(&self, @mut int);
+}
+
+impl Foo for int {
+    fn foo(&self, x: @mut int) {
+        *x += *self;
+    }
+}
+
+fn main() {
+    let x = @mut 3_i;
+    let y = x as @mut Foo;
+
+    // The call to `y.foo(...)` should freeze `y` (and thus also `x`,
+    // since `x === y`). It is thus an error when `foo` tries to
+    // mutate `x`.
+    y.foo(x);
+}
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 a8ff9061216871f5e85e82e9c4a265c00ab96ce3..737253a956fc02f9fc19e53961d60754ae35970f 100644 (file)
@@ -56,6 +56,6 @@ fn cat(in_x : uint, in_y : int, in_name: ~str) -> cat {
 
 
 pub fn main() {
-  let mut nyan: @noisy = @cat(0u, 2, ~"nyan") as @noisy;
+  let nyan: @mut noisy = @mut cat(0u, 2, ~"nyan") as @mut noisy;
   nyan.speak();
 }
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() {}
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 522a68856b636526691074bda549e407115a2aa9..206dc383cb3d50cd488db1203b6645d33f99771e 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// xfail-test
 enum side { mayo, catsup, vinegar }
 enum order { hamburger, fries(side), shake }
 enum meal { to_go(order), for_here(order) }
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 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/objects-owned-object-borrowed-method-header.rs b/src/test/run-pass/objects-owned-object-borrowed-method-header.rs
new file mode 100644 (file)
index 0000000..23c271f
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+// Test invoked `&self` methods on owned objects where the values
+// closed over contain managed values. This implies that the ~ boxes
+// will have headers that must be skipped over.
+
+trait FooTrait {
+    fn foo(&self) -> uint;
+}
+
+struct BarStruct {
+    x: @uint
+}
+
+impl FooTrait for BarStruct {
+    fn foo(&self) -> uint {
+        *self.x
+    }
+}
+
+pub fn main() {
+    let foos: ~[ ~FooTrait: ] = ~[
+        ~BarStruct{ x: @0 } as ~FooTrait:,
+        ~BarStruct{ x: @1 } as ~FooTrait:,
+        ~BarStruct{ x: @2 } as ~FooTrait:
+    ];
+
+    for i in range(0u, foos.len()) {
+        assert_eq!(i, foos[i].foo());
+    }
+}
diff --git a/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs b/src/test/run-pass/objects-owned-object-borrowed-method-headerless.rs
new file mode 100644 (file)
index 0000000..72ae7cf
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+// Test invoked `&self` methods on owned objects where the values
+// closed over do not contain managed values, and thus the ~ boxes do
+// not have headers.
+
+trait FooTrait {
+    fn foo(&self) -> uint;
+}
+
+struct BarStruct {
+    x: uint
+}
+
+impl FooTrait for BarStruct {
+    fn foo(&self) -> uint {
+        self.x
+    }
+}
+
+pub fn main() {
+    let foos: ~[ ~FooTrait ] = ~[
+        ~BarStruct{ x: 0 } as ~FooTrait,
+        ~BarStruct{ x: 1 } as ~FooTrait,
+        ~BarStruct{ x: 2 } as ~FooTrait
+    ];
+
+    for i in range(0u, foos.len()) {
+        assert_eq!(i, foos[i].foo());
+    }
+}
diff --git a/src/test/run-pass/objects-owned-object-owned-method.rs b/src/test/run-pass/objects-owned-object-owned-method.rs
new file mode 100644 (file)
index 0000000..0d675c1
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+// Test invoked `&self` methods on owned objects where the values
+// closed over contain managed values. This implies that the ~ boxes
+// will have headers that must be skipped over.
+
+trait FooTrait {
+    fn foo(~self) -> uint;
+}
+
+struct BarStruct {
+    x: uint
+}
+
+impl FooTrait for BarStruct {
+    fn foo(~self) -> uint {
+        self.x
+    }
+}
+
+pub fn main() {
+    let foo = ~BarStruct{ x: 22 } as ~FooTrait;
+    assert_eq!(22, foo.foo());
+}
diff --git a/src/test/run-pass/owned-trait-objects.rs b/src/test/run-pass/owned-trait-objects.rs
deleted file mode 100644 (file)
index c9d0fde..0000000
+++ /dev/null
@@ -1,35 +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.
-
-trait FooTrait {
-    fn foo(&self) -> uint;
-}
-
-struct BarStruct {
-    x: uint
-}
-
-impl FooTrait for BarStruct {
-    fn foo(&self) -> uint {
-        self.x
-    }
-}
-
-pub fn main() {
-    let foos: ~[ ~FooTrait ] = ~[
-        ~BarStruct{ x: 0 } as ~FooTrait,
-        ~BarStruct{ x: 1 } as ~FooTrait,
-        ~BarStruct{ x: 2 } as ~FooTrait
-    ];
-
-    for i in range(0u, foos.len()) {
-        assert_eq!(i, foos[i].foo());
-    }
-}
index 2a91d1fc8b5ca96523474eabe9787a064265cc53..8ab1bef286c0ca10dc8f0fcf29ec05af34d656ef 100644 (file)
@@ -502,7 +502,7 @@ pub fn visit_inner(&self, inner: *TyDesc) -> bool {
         unsafe {
             let u = my_visitor(**self);
             let v = ptr_visit_adaptor::<my_visitor>(Inner {inner: u});
-            visit_tydesc(inner, @v as @TyVisitor);
+            visit_tydesc(inner, &v as &TyVisitor);
             true
         }
     }
@@ -662,7 +662,7 @@ pub fn main() {
         let td = get_tydesc_for(r);
         error!("tydesc sz: %u, align: %u",
                (*td).size, (*td).align);
-        let v = @v as @TyVisitor;
+        let v = &v as &TyVisitor;
         visit_tydesc(td, v);
 
         let r = u.vals.clone();
index 3ea597e0d59e37defe96a079d009f53e4313a960..544f42eb69f5eeffe5d0ba83add01ed21b7ae0dd 100644 (file)
@@ -79,7 +79,7 @@ fn visit_evec_box(&self, _mtbl: uint, _inner: *TyDesc) -> bool { true }
     fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"[");
         unsafe {
-            visit_tydesc(inner, (@*self) as @TyVisitor);
+            visit_tydesc(inner, (&*self) as &TyVisitor);
         }
         self.types.push(~"]");
         true
@@ -87,7 +87,7 @@ fn visit_evec_uniq(&self, _mtbl: uint, inner: *TyDesc) -> bool {
     fn visit_evec_uniq_managed(&self, _mtbl: uint, inner: *TyDesc) -> bool {
         self.types.push(~"[");
         unsafe {
-            visit_tydesc(inner, (@*self) as @TyVisitor);
+            visit_tydesc(inner, (&*self) as &TyVisitor);
         }
         self.types.push(~"]");
         true
@@ -154,7 +154,7 @@ fn visit_constr(&self, _inner: *TyDesc) -> bool { true }
     fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
 }
 
-fn visit_ty<T>(v: @TyVisitor) {
+fn visit_ty<T>(v: &TyVisitor) {
     unsafe {
         visit_tydesc(get_tydesc::<T>(), v);
     }
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/unique-object.rs b/src/test/run-pass/unique-object.rs
deleted file mode 100644 (file)
index e645f13..0000000
+++ /dev/null
@@ -1,29 +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.
-
-trait Foo {
-    fn f(&self) -> int;
-}
-
-struct Bar {
-    x: int
-}
-
-impl Foo for Bar {
-    fn f(&self) -> int {
-        self.x
-    }
-}
-
-pub fn main() {
-    let x = ~Bar { x: 10 };
-    let y = x as ~Foo;
-    assert_eq!(y.f(), 10);
-}
index d04deeac52e31aca1f2dddc5cadcff12776a0977..13a8e324d43062adf5efff02efbba031ff772b86 100644 (file)
@@ -1,22 +1,22 @@
 pub fn main() {
     let x = @[1, 2, 3];
     match x {
-        [2, .._] => ::std::util::unreachable(),
+        [2, .._] => fail!(),
         [1, ..tail] => {
             assert_eq!(tail, [2, 3]);
         }
-        [_] => ::std::util::unreachable(),
-        [] => ::std::util::unreachable()
+        [_] => fail!(),
+        [] => fail!()
     }
 
     let y = (~[(1, true), (2, false)], 0.5);
     match y {
-        ([_, _, _], 0.5) => ::std::util::unreachable(),
+        ([_, _, _], 0.5) => fail!(),
         ([(1, a), (b, false), ..tail], _) => {
             assert_eq!(a, true);
             assert_eq!(b, 2);
             assert!(tail.is_empty());
         }
-        ([..tail], _) => ::std::util::unreachable()
+        ([..tail], _) => fail!()
     }
 }
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..c09fb8d6bc7ef896ab44ad695bbc52f1dac7182a 100644 (file)
@@ -1,19 +1,19 @@
 fn a() {
-    let x = [1];
+    let x = ~[1];
     match x {
-        [_, _, _, _, _, .._] => ::std::util::unreachable(),
-        [.._, _, _, _, _] => ::std::util::unreachable(),
-        [_, .._, _, _] => ::std::util::unreachable(),
-        [_, _] => ::std::util::unreachable(),
+        [_, _, _, _, _, .._] => fail!(),
+        [.._, _, _, _, _] => fail!(),
+        [_, .._, _, _] => fail!(),
+        [_, _] => fail!(),
         [a] => {
             assert_eq!(a, 1);
         }
-        [] => ::std::util::unreachable()
+        [] => fail!()
     }
 }
 
 fn b() {
-    let x = [1, 2, 3];
+    let x = ~[1, 2, 3];
     match x {
         [a, b, ..c] => {
             assert_eq!(a, 1);
@@ -48,7 +48,28 @@ fn b() {
     }
 }
 
+fn c() {
+    let x = [1];
+    match x {
+        [2, .. _] => fail!(),
+        [.. _] => ()
+    }
+}
+
+fn d() {
+    let x = [1, 2, 3];
+    let branch = match x {
+        [1, 1, .. _] => 0,
+        [1, 2, 3, .. _] => 1,
+        [1, 2, .. _] => 2,
+        _ => 3
+    };
+    assert_eq!(branch, 1);
+}
+
 pub fn main() {
     a();
     b();
+    c();
+    d();
 }
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" }