]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #23607: mahkoh/cursor
authorAlex Crichton <alex@alexcrichton.com>
Mon, 23 Mar 2015 22:10:53 +0000 (15:10 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 23 Mar 2015 22:10:53 +0000 (15:10 -0700)
Closes #23599

r? @alexcrichton

271 files changed:
man/rustc.1
src/compiletest/compiletest.rs
src/compiletest/header.rs
src/compiletest/procsrv.rs
src/compiletest/runtest.rs
src/doc/reference.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/compound-data-types.md
src/doc/trpl/concurrency.md
src/doc/trpl/crates-and-modules.md
src/doc/trpl/standard-input.md
src/liballoc/heap.rs
src/libcollections/bit.rs
src/libcollections/borrow.rs
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/fmt.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollections/vec_map.rs
src/libcollectionstest/str.rs
src/libcore/convert.rs [new file with mode: 0644]
src/libcore/error.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/prelude.rs
src/libcore/result.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs
src/libcoretest/str.rs
src/libgraphviz/lib.rs
src/liblibc/lib.rs
src/librustc/README.md [new file with mode: 0644]
src/librustc/README.txt [deleted file]
src/librustc/lib.rs
src/librustc/metadata/cstore.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/graphviz.rs
src/librustc/middle/check_match.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dead.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/region_inference/graphviz.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/reachable.rs
src/librustc/middle/stability.rs
src/librustc/middle/traits/error_reporting.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty.rs
src/librustc/session/config.rs
src/librustc/session/search_paths.rs
src/librustc_back/archive.rs
src/librustc_back/fs.rs
src/librustc_back/lib.rs
src/librustc_back/rpath.rs
src/librustc_back/target/mod.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/lib.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_lint/builtin.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/README.txt
src/librustc_trans/back/link.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/asm.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/unsafety.rs
src/librustc_typeck/collect.rs
src/librustdoc/clean/mod.rs
src/librustdoc/externalfiles.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/plugins.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libserialize/lib.rs
src/libserialize/serialize.rs
src/libstd/collections/hash/map.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/ffi/c_str.rs
src/libstd/ffi/os_str.rs
src/libstd/fs/mod.rs
src/libstd/fs/tempdir.rs
src/libstd/io/buffered.rs
src/libstd/io/cursor.rs
src/libstd/io/prelude.rs
src/libstd/lib.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/num/mod.rs
src/libstd/old_io/buffered.rs
src/libstd/old_io/comm_adapters.rs
src/libstd/old_io/extensions.rs
src/libstd/old_io/fs.rs
src/libstd/old_io/mem.rs
src/libstd/old_io/mod.rs
src/libstd/old_io/net/pipe.rs
src/libstd/old_io/net/tcp.rs
src/libstd/old_io/pipe.rs
src/libstd/old_io/process.rs
src/libstd/old_io/result.rs
src/libstd/old_io/stdio.rs
src/libstd/old_io/tempfile.rs
src/libstd/old_io/test.rs
src/libstd/old_io/util.rs
src/libstd/old_path/mod.rs
src/libstd/old_path/posix.rs
src/libstd/old_path/windows.rs
src/libstd/os.rs
src/libstd/path.rs
src/libstd/prelude/v1.rs
src/libstd/process.rs
src/libstd/rt/util.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mutex.rs
src/libstd/sync/poison.rs
src/libstd/sys/common/thread_info.rs
src/libstd/sys/common/wtf8.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/fs2.rs
src/libstd/sys/unix/helper_signal.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/timer.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/pipe.rs
src/libstd/sys/windows/process.rs
src/libstd/sys/windows/tty.rs
src/libstd/thread.rs [deleted file]
src/libstd/thread/local.rs [new file with mode: 0644]
src/libstd/thread/mod.rs [new file with mode: 0644]
src/libstd/thread/scoped.rs [new file with mode: 0644]
src/libstd/thread_local/mod.rs [deleted file]
src/libstd/thread_local/scoped.rs [deleted file]
src/libsyntax/codemap.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/ext/format.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/parser.rs
src/libterm/lib.rs
src/libterm/terminfo/mod.rs
src/libterm/terminfo/searcher.rs
src/libtest/lib.rs
src/libtest/stats.rs
src/rustbook/book.rs
src/rustbook/build.rs
src/rustbook/error.rs
src/rustbook/main.rs
src/test/auxiliary/issue-2631-a.rs
src/test/auxiliary/linkage-visibility.rs
src/test/auxiliary/procedural_mbe_matching.rs
src/test/bench/core-std.rs
src/test/bench/shootout-fasta-redux.rs
src/test/bench/shootout-fasta.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-mandelbrot.rs
src/test/bench/shootout-reverse-complement.rs
src/test/compile-fail-fulldeps/gated-macro-reexports.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-overloaded-index-2.rs [deleted file]
src/test/compile-fail/borrowck-overloaded-index-and-overloaded-deref.rs
src/test/compile-fail/borrowck-overloaded-index-autoderef.rs
src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-overloaded-index-move-index.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-overloaded-index-ref-index.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-overloaded-index.rs [deleted file]
src/test/compile-fail/cannot-mutate-captured-non-mut-var.rs
src/test/compile-fail/coherence-default-trait-impl.rs
src/test/compile-fail/dst-index.rs
src/test/compile-fail/gated-box-patterns.rs [new file with mode: 0644]
src/test/compile-fail/gated-box-syntax.rs [new file with mode: 0644]
src/test/compile-fail/gated-simd-ffi.rs [new file with mode: 0644]
src/test/compile-fail/issue-11374.rs
src/test/compile-fail/issue-18400.rs
src/test/compile-fail/match-ref-mut-invariance.rs [new file with mode: 0644]
src/test/compile-fail/match-ref-mut-let-invariance.rs [new file with mode: 0644]
src/test/compile-fail/recursion_limit.rs
src/test/compile-fail/regions-trait-object-subtyping.rs [new file with mode: 0644]
src/test/run-fail/overflowing-lsh-1.rs [new file with mode: 0644]
src/test/run-fail/overflowing-lsh-2.rs [new file with mode: 0644]
src/test/run-fail/overflowing-lsh-3.rs [new file with mode: 0644]
src/test/run-fail/overflowing-lsh-4.rs [new file with mode: 0644]
src/test/run-fail/overflowing-rsh-1.rs [new file with mode: 0644]
src/test/run-fail/overflowing-rsh-2.rs [new file with mode: 0644]
src/test/run-fail/overflowing-rsh-3.rs [new file with mode: 0644]
src/test/run-fail/overflowing-rsh-4.rs [new file with mode: 0644]
src/test/run-make/cannot-read-embedded-idents/create_and_compile.rs
src/test/run-make/extern-fn-reachable/main.rs
src/test/run-make/rustdoc-default-impl/foo.rs
src/test/run-make/unicode-input/multiple_files.rs
src/test/run-make/unicode-input/span_length.rs
src/test/run-pass/backtrace-debuginfo.rs
src/test/run-pass/capturing-logging.rs
src/test/run-pass/colorful-write-macros.rs
src/test/run-pass/dst-index.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/into-iterator-type-inference-shift.rs
src/test/run-pass/issue-14940.rs
src/test/run-pass/issue-15734.rs
src/test/run-pass/issue-17121.rs
src/test/run-pass/issue-20644.rs
src/test/run-pass/issue-20797.rs
src/test/run-pass/issue-23550.rs [new file with mode: 0644]
src/test/run-pass/issue-2804-2.rs
src/test/run-pass/issue-2804.rs
src/test/run-pass/issue-5521.rs
src/test/run-pass/issue-7660.rs
src/test/run-pass/issue22346.rs
src/test/run-pass/match-ref-unsized.rs [new file with mode: 0644]
src/test/run-pass/operator-overloading.rs
src/test/run-pass/over-constrained-vregs.rs
src/test/run-pass/overloaded-index-assoc-list.rs
src/test/run-pass/overloaded-index-autoderef.rs
src/test/run-pass/overloaded-index-in-field.rs
src/test/run-pass/overloaded-index.rs
src/test/run-pass/process-spawn-with-unicode-params.rs
src/test/run-pass/rename-directory.rs
src/test/run-pass/shift-near-oflo.rs [new file with mode: 0644]
src/test/run-pass/sigpipe-should-be-ignored.rs
src/test/run-pass/slice.rs
src/test/run-pass/spawn2.rs
src/test/run-pass/stat.rs
src/test/run-pass/tcp-stress.rs
src/test/run-pass/tempfile.rs
src/test/run-pass/trait-coercion.rs
src/test/run-pass/unit-like-struct-drop-run.rs

index 33ef3f9ee4acba4e3078a5a3afb8ac6ccf3849d5..b15829db431dfef89f5d7b6a4fb6217c98874b3b 100644 (file)
@@ -242,7 +242,7 @@ full debug info with variable and type information.
 \fBopt\-level\fR=\fIVAL\fR
 Optimize with possible levels 0\[en]3
 
-.SH ENVIRONMENT VARIABLES
+.SH ENVIRONMENT
 
 Some of these affect the output of the compiler, while others affect programs
 which link to the standard library.
index 01c4e99b77c70a25daa503a95ac2f1d45a093f0d..1ee5917ac9c91b7dbdc734d4f114ed9b2dea7454 100644 (file)
@@ -20,6 +20,8 @@
 #![feature(std_misc)]
 #![feature(test)]
 #![feature(path_ext)]
+#![feature(convert)]
+#![feature(str_char)]
 
 #![deny(warnings)]
 
@@ -115,7 +117,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
 
     fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
         match m.opt_str(nm) {
-            Some(s) => PathBuf::new(&s),
+            Some(s) => PathBuf::from(&s),
             None => panic!("no option (=path) found for {}", nm),
         }
     }
@@ -130,10 +132,10 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
         compile_lib_path: matches.opt_str("compile-lib-path").unwrap(),
         run_lib_path: matches.opt_str("run-lib-path").unwrap(),
         rustc_path: opt_path(matches, "rustc-path"),
-        clang_path: matches.opt_str("clang-path").map(|s| PathBuf::new(&s)),
+        clang_path: matches.opt_str("clang-path").map(|s| PathBuf::from(&s)),
         valgrind_path: matches.opt_str("valgrind-path"),
         force_valgrind: matches.opt_present("force-valgrind"),
-        llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| PathBuf::new(&s)),
+        llvm_bin_path: matches.opt_str("llvm-bin-path").map(|s| PathBuf::from(&s)),
         src_base: opt_path(matches, "src-base"),
         build_base: opt_path(matches, "build-base"),
         aux_base: opt_path(matches, "aux-base"),
@@ -141,7 +143,7 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> PathBuf {
         mode: matches.opt_str("mode").unwrap().parse().ok().expect("invalid mode"),
         run_ignored: matches.opt_present("ignored"),
         filter: filter,
-        logfile: matches.opt_str("logfile").map(|s| PathBuf::new(&s)),
+        logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
         runtool: matches.opt_str("runtool"),
         host_rustcflags: matches.opt_str("host-rustcflags"),
         target_rustcflags: matches.opt_str("target-rustcflags"),
index 29123173f5baec5dbf3fa9c3a61065f0b009c503..e1ad66c69e44a27d72d525b9089751c366b6d6a9 100644 (file)
@@ -328,10 +328,10 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> {
 
 fn parse_pp_exact(line: &str, testfile: &Path) -> Option<PathBuf> {
     match parse_name_value_directive(line, "pp-exact") {
-      Some(s) => Some(PathBuf::new(&s)),
+      Some(s) => Some(PathBuf::from(&s)),
       None => {
         if parse_name_directive(line, "pp-exact") {
-            testfile.file_name().map(|s| PathBuf::new(s))
+            testfile.file_name().map(|s| PathBuf::from(s))
         } else {
             None
         }
index 56e37ca1093155175a1dcbc135ad0d74654f3307..ceed88b6236fd5f9a0f5c2bb588f1b49570bb126 100644 (file)
 
 #![allow(deprecated)] // for old path, for dynamic_lib
 
-use std::process::{ExitStatus, Command, Child, Output, Stdio};
-use std::io::prelude::*;
 use std::dynamic_lib::DynamicLibrary;
+use std::io::prelude::*;
+use std::old_path::Path;
+use std::process::{ExitStatus, Command, Child, Output, Stdio};
 
 fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
     // Need to be sure to put both the lib_path and the aux path in the dylib
index a754bd950f7f6006709fac0e228eda7cb706c8ec..319248cb8107d60ca3c18e59cf4f9eae31648285 100644 (file)
@@ -1440,7 +1440,7 @@ fn aux_output_dir_name(config: &Config, testfile: &Path) -> PathBuf {
 }
 
 fn output_testname(testfile: &Path) -> PathBuf {
-    PathBuf::new(testfile.file_stem().unwrap())
+    PathBuf::from(testfile.file_stem().unwrap())
 }
 
 fn output_base_name(config: &Config, testfile: &Path) -> PathBuf {
index 92573d792177362ad724278699f3d9d13cd2839c..415ec4e4fbf0a4bc661caa3ee26558908310b851 100644 (file)
@@ -1982,7 +1982,7 @@ the namespace hierarchy as it normally would.
 ## Attributes
 
 ```{.ebnf .gram}
-attribute : "#!" ? '[' meta_item ']' ;
+attribute : '#' '!' ? '[' meta_item ']' ;
 meta_item : ident [ '=' literal
                   | '(' meta_seq ')' ] ? ;
 meta_seq : meta_item [ ',' meta_seq ] ? ;
@@ -3158,7 +3158,7 @@ ten_times(|j| println!("hello, {}", j));
 ### While loops
 
 ```{.ebnf .gram}
-while_expr : "while" no_struct_literal_expr '{' block '}' ;
+while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
 ```
 
 A `while` loop begins by evaluating the boolean loop conditional expression.
@@ -3223,7 +3223,7 @@ A `continue` expression is only permitted in the body of a loop.
 ### For expressions
 
 ```{.ebnf .gram}
-for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ;
+for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
 ```
 
 A `for` expression is a syntactic construct for looping over elements provided
index 6ff51e8d1b92cb9af4426e41da40125362e1b150..76f8b6c97381818dc3a79b4e7aa87696d58a8377 100644 (file)
@@ -1,6 +1,6 @@
 # Summary
 
-* [I: The Basics](basic.md)
+* [The Basics](basic.md)
     * [Installing Rust](installing-rust.md)
     * [Hello, world!](hello-world.md)
     * [Hello, Cargo!](hello-cargo.md)
@@ -14,7 +14,7 @@
     * [Strings](strings.md)
     * [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md)
     * [Standard Input](standard-input.md)
-* [II: Intermediate Rust](intermediate.md)
+* [Intermediate Rust](intermediate.md)
     * [Crates and Modules](crates-and-modules.md)
     * [Testing](testing.md)
     * [Pointers](pointers.md)
@@ -31,7 +31,7 @@
     * [Concurrency](concurrency.md)
     * [Error Handling](error-handling.md)
     * [Documentation](documentation.md)
-* [III: Advanced Topics](advanced.md)
+* [Advanced Topics](advanced.md)
     * [FFI](ffi.md)
     * [Unsafe Code](unsafe.md)
     * [Advanced Macros](advanced-macros.md)
index e09922fd390a9b037cedaab162908449a42d2eb2..d531a22d0e0dd55d2b2a0d5d913b88f9d3912c73 100644 (file)
@@ -47,7 +47,7 @@ This pattern is very powerful, and we'll see it repeated more later.
 
 There are also a few things you can do with a tuple as a whole, without
 destructuring. You can assign one tuple into another, if they have the same
-contained types and arity. Tuples have the same arity when they have the same
+contained types and [arity]. Tuples have the same arity when they have the same
 length.
 
 ```rust
@@ -196,8 +196,9 @@ Now, we have actual names, rather than positions. Good names are important,
 and with a struct, we have actual names.
 
 There _is_ one case when a tuple struct is very useful, though, and that's a
-tuple struct with only one element. We call this a *newtype*, because it lets
-you create a new type that's similar to another one:
+tuple struct with only one element. We call this the *newtype* pattern, because
+it allows you to create a new type, distinct from that of its contained value
+and expressing its own semantic meaning:
 
 ```{rust}
 struct Inches(i32);
@@ -216,7 +217,7 @@ destructuring `let`, as we discussed previously in 'tuples.' In this case, the
 
 Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
 feature of Rust, and are used throughout the standard library. An `enum` is
-a type which ties a set of alternates to a specific name. For example, below
+a type which relates a set of alternates to a specific name. For example, below
 we define `Character` to be either a `Digit` or something else. These
 can be used via their fully scoped names: `Character::Other` (more about `::`
 below).
@@ -228,8 +229,8 @@ enum Character {
 }
 ```
 
-An `enum` variant can be defined as most normal types. Below are some example
-types which also would be allowed in an `enum`.
+Most normal types are allowed as the variant components of an `enum`. Here are
+some examples:
 
 ```rust
 struct Empty;
@@ -239,15 +240,15 @@ struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
 struct HeightDatabase(Vec<i32>);
 ```
 
-So you see that depending on the sub-datastructure, the `enum` variant, same as
-a struct, may or may not hold data. That is, in `Character`, `Digit` is a name
-tied to an `i32` where `Other` is just a name. However, the fact that they are
-distinct makes this very useful.
+You see that, depending on its type, an `enum` variant may or may not hold data.
+In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
+value, where `Other` is only a name. However, the fact that they represent
+distinct categories of `Character` is a very useful property.
 
-As with structures, enums don't by default have access to operators such as
-compare ( `==` and `!=`), binary operations (`*` and `+`), and order
-(`<` and `>=`). As such, using the previous `Character` type, the
-following code is invalid:
+As with structures, the variants of an enum by default are not comparable with
+equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not
+support other binary operations such as `*` and `+`. As such, the following code
+is invalid for the example `Character` type:
 
 ```{rust,ignore}
 // These assignments both succeed
@@ -265,9 +266,10 @@ let four_equals_ten = four == ten;
 ```
 
 This may seem rather limiting, but it's a limitation which we can overcome.
-There are two ways: by implementing equality ourselves, or by using the
-[`match`][match] keyword. We don't know enough about Rust to implement equality
-yet, but we can use the `Ordering` enum from the standard library, which does:
+There are two ways: by implementing equality ourselves, or by pattern matching
+variants with [`match`][match] expressions, which you'll learn in the next
+chapter. We don't know enough about Rust to implement equality yet, but we can
+use the `Ordering` enum from the standard library, which does:
 
 ```
 enum Ordering {
@@ -277,9 +279,8 @@ enum Ordering {
 }
 ```
 
-Because we did not define `Ordering`, we must import it (from the std
-library) with the `use` keyword. Here's an example of how `Ordering` is
-used:
+Because `Ordering` has already been defined for us, we will import it with the
+`use` keyword. Here's an example of how it is used:
 
 ```{rust}
 use std::cmp::Ordering;
@@ -313,17 +314,17 @@ the standard library if you need them.
 
 Okay, let's talk about the actual code in the example. `cmp` is a function that
 compares two things, and returns an `Ordering`. We return either
-`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on if
-the two values are less, greater, or equal. Note that each variant of the
-`enum` is namespaced under the `enum` itself: it's `Ordering::Greater` not
-`Greater`.
+`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on
+whether the first value is less than, greater than, or equal to the second. Note
+that each variant of the `enum` is namespaced under the `enum` itself: it's
+`Ordering::Greater`, not `Greater`.
 
 The `ordering` variable has the type `Ordering`, and so contains one of the
 three values. We then do a bunch of `if`/`else` comparisons to check which
 one it is.
 
-This `Ordering::Greater` notation is too long. Let's use `use` to import the
-`enum` variants instead. This will avoid full scoping:
+This `Ordering::Greater` notation is too long. Let's use another form of `use`
+to import the `enum` variants instead. This will avoid full scoping:
 
 ```{rust}
 use std::cmp::Ordering::{self, Equal, Less, Greater};
@@ -347,16 +348,18 @@ fn main() {
 ```
 
 Importing variants is convenient and compact, but can also cause name conflicts,
-so do this with caution. It's considered good style to rarely import variants
-for this reason.
+so do this with caution. For this reason, it's normally considered better style
+to `use` an enum rather than its variants directly.
 
-As you can see, `enum`s are quite a powerful tool for data representation, and are
-even more useful when they're [generic][generics] across types. Before we
-get to generics, though, let's talk about how to use them with pattern matching, a
-tool that will let us deconstruct this sum type (the type theory term for enums)
-in a very elegant way and avoid all these messy `if`/`else`s.
+As you can see, `enum`s are quite a powerful tool for data representation, and
+are even more useful when they're [generic][generics] across types. Before we
+get to generics, though, let's talk about how to use enums with pattern
+matching, a tool that will let us deconstruct sum types (the type theory term
+for enums) like `Ordering` in a very elegant way that avoids all these messy
+and brittle `if`/`else`s.
 
 
+[arity]: ./glossary.html#arity
 [match]: ./match.html
 [game]: ./guessing-game.html#comparing-guesses
 [generics]: ./generics.html
index 4a16db63950ddd0ff76983b8df988bea5b5ffc91..5d301cc0aef6ebbd31d1b78148ade07f75cdfd80 100644 (file)
@@ -40,14 +40,14 @@ us enforce that it can't leave the current thread.
 
 ### `Sync`
 
-The second of these two trait is called [`Sync`](../std/marker/trait.Sync.html).
+The second of these traits is called [`Sync`](../std/marker/trait.Sync.html).
 When a type `T` implements `Sync`, it indicates to the compiler that something
 of this type has no possibility of introducing memory unsafety when used from
 multiple threads concurrently.
 
 For example, sharing immutable data with an atomic reference count is
 threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`,
-so that it could be safely shared between threads.
+so it is safe to share between threads.
 
 These two traits allow you to use the type system to make strong guarantees
 about the properties of your code under concurrency. Before we demonstrate
@@ -69,7 +69,7 @@ fn main() {
 }
 ```
 
-The `Thread::scoped()` method accepts a closure, which is executed in a new
+The `thread::scoped()` method accepts a closure, which is executed in a new
 thread. It's called `scoped` because this thread returns a join guard:
 
 ```
@@ -208,10 +208,10 @@ Here's the error:
 
 ```text
 <anon>:11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
-<anon>:11         Thread::spawn(move || {
+<anon>:11         thread::spawn(move || {
                   ^~~~~~~~~~~~~
 <anon>:11:9: 11:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
-<anon>:11         Thread::spawn(move || {
+<anon>:11         thread::spawn(move || {
                   ^~~~~~~~~~~~~
 ```
 
@@ -322,7 +322,6 @@ While this channel is just sending a generic signal, we can send any data that
 is `Send` over the channel!
 
 ```
-use std::sync::{Arc, Mutex};
 use std::thread;
 use std::sync::mpsc;
 
index 65ff42ffdcef411804fc99d4a1967b1632d0a637..0cc54c9b16598b10eb2e8b945cc6224b6fbea20b 100644 (file)
@@ -1,6 +1,6 @@
 % Crates and Modules
 
-When a project starts getting large, it's considered good software
+When a project starts getting large, it's considered good software
 engineering practice to split it up into a bunch of smaller pieces, and then
 fit them together. It's also important to have a well-defined interface, so
 that some of your functionality is private, and some is public. To facilitate
@@ -24,23 +24,23 @@ in different languages. To keep things simple, we'll stick to "greetings" and
 two languages for those phrases to be in. We'll use this module layout:
 
 ```text
-                                +-----------+
-                            +---| greetings |
-                            |   +-----------+
-              +---------+   |
-              | english |---+
-              +---------+   |   +-----------+
-              |             +---| farewells |
-+---------+   |                 +-----------+
+                                    +-----------+
+                                +---| greetings |
+                                |   +-----------+
+                  +---------+   |
+              +---| english |---+
+              |   +---------+   |   +-----------+
+              |                 +---| farewells |
++---------+   |                     +-----------+
 | phrases |---+
-+---------+   |                  +-----------+
-              |              +---| greetings |
-              +----------+   |   +-----------+
-              | japanese |---+
-              +----------+   |
-                             |   +-----------+
-                             +---| farewells |
-                                 +-----------+
++---------+   |                     +-----------+
+              |                 +---| greetings |
+              |   +----------+  |   +-----------+
+              +---| japanese |--+
+                  +----------+  |
+                                |   +-----------+
+                                +---| farewells |
+                                    +-----------+
 ```
 
 In this example, `phrases` is the name of our crate. All of the rest are
@@ -76,25 +76,19 @@ To define each of our modules, we use the `mod` keyword. Let's make our
 `src/lib.rs` look like this:
 
 ```
-// in src/lib.rs
-
 mod english {
     mod greetings {
-
     }
 
     mod farewells {
-
     }
 }
 
 mod japanese {
     mod greetings {
-
     }
 
     mod farewells {
-
     }
 }
 ```
@@ -145,11 +139,7 @@ mod english;
 ```
 
 If we do that, Rust will expect to find either a `english.rs` file, or a
-`english/mod.rs` file with the contents of our module:
-
-```{rust,ignore}
-// contents of our module go here
-```
+`english/mod.rs` file with the contents of our module.
 
 Note that in these files, you don't need to re-declare the module: that's
 already been done with the initial `mod` declaration.
@@ -181,10 +171,7 @@ $ tree .
 `src/lib.rs` is our crate root, and looks like this:
 
 ```{rust,ignore}
-// in src/lib.rs
-
 mod english;
-
 mod japanese;
 ```
 
@@ -195,10 +182,7 @@ chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
 like this:
 
 ```{rust,ignore}
-// both src/english/mod.rs and src/japanese/mod.rs
-
 mod greetings;
-
 mod farewells;
 ```
 
@@ -214,8 +198,6 @@ both empty at the moment. Let's add some functions.
 Put this in `src/english/greetings.rs`:
 
 ```rust
-// in src/english/greetings.rs
-
 fn hello() -> String {
     "Hello!".to_string()
 }
@@ -224,8 +206,6 @@ fn hello() -> String {
 Put this in `src/english/farewells.rs`:
 
 ```rust
-// in src/english/farewells.rs
-
 fn goodbye() -> String {
     "Goodbye.".to_string()
 }
@@ -248,8 +228,6 @@ about the module system.
 Put this in `src/japanese/farewells.rs`:
 
 ```rust
-// in src/japanese/farewells.rs
-
 fn goodbye() -> String {
     "さようなら".to_string()
 }
@@ -265,11 +243,9 @@ another crate.
 We have a library crate. Let's make an executable crate that imports and uses
 our library.
 
-Make a `src/main.rs` and put this in it: (it won't quite compile yet)
+Make a `src/main.rs` and put this in it (it won't quite compile yet):
 
 ```rust,ignore
-// in src/main.rs
-
 extern crate phrases;
 
 fn main() {
@@ -320,8 +296,6 @@ keyword. Let's focus on the `english` module first, so let's reduce our `src/mai
 to just this:
 
 ```{rust,ignore}
-// in src/main.rs
-
 extern crate phrases;
 
 fn main() {
@@ -333,28 +307,20 @@ fn main() {
 In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
 
 ```{rust,ignore}
-// in src/lib.rs
-
 pub mod english;
-
 mod japanese;
 ```
 
 And in our `src/english/mod.rs`, let's make both `pub`:
 
 ```{rust,ignore}
-// in src/english/mod.rs
-
 pub mod greetings;
-
 pub mod farewells;
 ```
 
 In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
 
 ```{rust,ignore}
-// in src/english/greetings.rs
-
 pub fn hello() -> String {
     "Hello!".to_string()
 }
@@ -363,8 +329,6 @@ pub fn hello() -> String {
 And also in `src/english/farewells.rs`:
 
 ```{rust,ignore}
-// in src/english/farewells.rs
-
 pub fn goodbye() -> String {
     "Goodbye.".to_string()
 }
@@ -400,8 +364,6 @@ Rust has a `use` keyword, which allows us to import names into our local scope.
 Let's change our `src/main.rs` to look like this:
 
 ```{rust,ignore}
-// in src/main.rs
-
 extern crate phrases;
 
 use phrases::english::greetings;
@@ -430,7 +392,7 @@ fn main() {
 }
 ```
 
-But it is not idiomatic. This is significantly more likely to introducing a
+But it is not idiomatic. This is significantly more likely to introduce a
 naming conflict. In our short program, it's not a big deal, but as it grows, it
 becomes a problem. If we have conflicting names, Rust will give a compilation
 error. For example, if we made the `japanese` functions public, and tried to do
@@ -460,21 +422,19 @@ Could not compile `phrases`.
 ```
 
 If we're importing multiple names from the same module, we don't have to type it out
-twice. Rust has a shortcut syntax for writing this:
+twice. Instead of this:
 
 ```{rust,ignore}
 use phrases::english::greetings;
 use phrases::english::farewells;
 ```
 
-You use curly braces:
+We can use this shortcut:
 
 ```{rust,ignore}
 use phrases::english::{greetings, farewells};
 ```
 
-These two declarations are equivalent, but the second is a lot less typing.
-
 ## Re-exporting with `pub use`
 
 You don't just use `use` to shorten identifiers. You can also use it inside of your crate
@@ -484,8 +444,6 @@ interface that may not directly map to your internal code organization.
 Let's look at an example. Modify your `src/main.rs` to read like this:
 
 ```{rust,ignore}
-// in src/main.rs
-
 extern crate phrases;
 
 use phrases::english::{greetings,farewells};
@@ -503,18 +461,13 @@ fn main() {
 Then, modify your `src/lib.rs` to make the `japanese` mod public:
 
 ```{rust,ignore}
-// in src/lib.rs
-
 pub mod english;
-
 pub mod japanese;
 ```
 
 Next, make the two functions public, first in `src/japanese/greetings.rs`:
 
 ```{rust,ignore}
-// in src/japanese/greetings.rs
-
 pub fn hello() -> String {
     "こんにちは".to_string()
 }
@@ -523,8 +476,6 @@ pub fn hello() -> String {
 And then in `src/japanese/farewells.rs`:
 
 ```{rust,ignore}
-// in src/japanese/farewells.rs
-
 pub fn goodbye() -> String {
     "さようなら".to_string()
 }
@@ -533,13 +484,10 @@ pub fn goodbye() -> String {
 Finally, modify your `src/japanese/mod.rs` to read like this:
 
 ```{rust,ignore}
-// in src/japanese/mod.rs
-
 pub use self::greetings::hello;
 pub use self::farewells::goodbye;
 
 mod greetings;
-
 mod farewells;
 ```
 
index 794b1df7563de7cde12943cf122762f1265806e5..228891f9f052b3a33a59c5f5862155f933562ce8 100644 (file)
@@ -115,8 +115,9 @@ doesn't work, so we're okay with that. In most cases, we would want to handle
 the error case explicitly. `expect()` allows us to give an error message if
 this crash happens.
 
-We will cover the exact details of how all of this works later in the Guide.
-For now, this gives you enough of a basic understanding to work with.
+We will cover the exact details of how all of this works later in the Guide in
+[Error Handling]. For now, this gives you enough of a basic understanding to
+work with.
 
 Back to the code we were working on! Here's a refresher:
 
@@ -157,3 +158,6 @@ here.
 
 That's all you need to get basic input from the standard input! It's not too
 complicated, but there are a number of small parts.
+
+
+[Error Handling]: ./error-handling.html
index aaf6e76237ca5669b7d6266f4b4ff853ed7dfec0..3733350412e499a8c4d3623cf6fea8aeea403bc6 100644 (file)
@@ -26,6 +26,9 @@ pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
 ///
 /// On failure, return a null pointer and leave the original allocation intact.
 ///
+/// If the allocation was relocated, the memory at the passed-in pointer is
+/// undefined after the call.
+///
 /// Behavior is undefined if the requested size is 0 or the alignment is not a
 /// power of 2. The alignment must be no larger than the largest supported page
 /// size on the platform.
index 90fbe04d3482f9f73fbcea9d4c1d90bea4cb4207..e494527b6a67c921af62f1992a9595c7dab35124 100644 (file)
@@ -169,6 +169,8 @@ pub struct BitVec {
 impl Index<usize> for BitVec {
     type Output = bool;
 
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, i: &usize) -> &bool {
         if self.get(*i).expect("index out of bounds") {
@@ -177,6 +179,16 @@ fn index(&self, i: &usize) -> &bool {
             &FALSE
         }
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, i: usize) -> &bool {
+        if self.get(i).expect("index out of bounds") {
+            &TRUE
+        } else {
+            &FALSE
+        }
+    }
 }
 
 /// Computes how many blocks are needed to store that many bits
index 4bedbdeb368769a4b2565a184f4168ec85dfb0ec..88d59f699d183030c7c2f665ee3ecd2bd813813a 100644 (file)
@@ -14,6 +14,7 @@
 
 use core::clone::Clone;
 use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
+use core::convert::AsRef;
 use core::hash::{Hash, Hasher};
 use core::marker::Sized;
 use core::ops::Deref;
@@ -291,10 +292,9 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 }
 
 /// Trait for moving into a `Cow`
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "into_cow", reason = "may be replaced by `convert::Into`")]
 pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
     /// Moves `self` into `Cow`
-    #[stable(feature = "rust1", since = "1.0.0")]
     fn into_cow(self) -> Cow<'a, B>;
 }
 
@@ -304,3 +304,10 @@ fn into_cow(self) -> Cow<'a, B> {
         self
     }
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: Clone> AsRef<T> for Cow<'a, T> {
+    fn as_ref(&self) -> &T {
+        self
+    }
+}
index c7e1e3c91766ef297d71fbad17905910d2530c61..59fe74c255b9a446ed44e6dac495bd4b7ce0c806 100644 (file)
@@ -24,7 +24,7 @@
 use core::fmt::Debug;
 use core::hash::{Hash, Hasher};
 use core::iter::{Map, FromIterator, IntoIterator};
-use core::ops::{Index, IndexMut};
+use core::ops::{Index};
 use core::{iter, fmt, mem, usize};
 use Bound::{self, Included, Excluded, Unbounded};
 
@@ -78,6 +78,7 @@ pub struct BTreeMap<K, V> {
 }
 
 /// An abstract base over-which all other BTree iterators are built.
+#[derive(Clone)]
 struct AbsIter<T> {
     traversals: VecDeque<T>,
     size: usize,
@@ -264,7 +265,7 @@ pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: Or
     ///     Some(x) => *x = "b",
     ///     None => (),
     /// }
-    /// assert_eq!(map[1], "b");
+    /// assert_eq!(map[&1], "b");
     /// ```
     // See `get` for implementation notes, this is basically a copy-paste with mut's added
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -326,7 +327,7 @@ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where K: Borrow<
     ///
     /// map.insert(37, "b");
     /// assert_eq!(map.insert(37, "c"), Some("b"));
-    /// assert_eq!(map[37], "c");
+    /// assert_eq!(map[&37], "c");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
@@ -914,23 +915,29 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
     where K: Borrow<Q>, Q: Ord
 {
     type Output = V;
 
+    #[inline]
     fn index(&self, key: &Q) -> &V {
         self.get(key).expect("no entry found for key")
     }
 }
 
+#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
+impl<'a, K: Ord, Q: ?Sized, V> Index<&'a Q> for BTreeMap<K, V>
     where K: Borrow<Q>, Q: Ord
 {
-    fn index_mut(&mut self, key: &Q) -> &mut V {
-        self.get_mut(key).expect("no entry found for key")
+    type Output = V;
+
+    #[inline]
+    fn index(&self, key: &Q) -> &V {
+        self.get(key).expect("no entry found for key")
     }
 }
 
@@ -1034,6 +1041,9 @@ fn next_back(&mut self) -> Option<(K, V)> {
     }
 }
 
+impl<'a, K, V> Clone for Iter<'a, K, V> {
+    fn clone(&self) -> Iter<'a, K, V> { Iter { inner: self.inner.clone() } }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
@@ -1076,6 +1086,9 @@ fn next_back(&mut self) -> Option<(K, V)> { self.inner.next_back() }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> ExactSizeIterator for IntoIter<K, V> {}
 
+impl<'a, K, V> Clone for Keys<'a, K, V> {
+    fn clone(&self) -> Keys<'a, K, V> { Keys { inner: self.inner.clone() } }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
@@ -1091,6 +1104,9 @@ fn next_back(&mut self) -> Option<(&'a K)> { self.inner.next_back() }
 impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {}
 
 
+impl<'a, K, V> Clone for Values<'a, K, V> {
+    fn clone(&self) -> Values<'a, K, V> { Values { inner: self.inner.clone() } }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
@@ -1105,6 +1121,9 @@ fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
 
+impl<'a, K, V> Clone for Range<'a, K, V> {
+    fn clone(&self) -> Range<'a, K, V> { Range { inner: self.inner.clone() } }
+}
 impl<'a, K, V> Iterator for Range<'a, K, V> {
     type Item = (&'a K, &'a V);
 
index bfac3b2df5a5cba8cc1a200ed9be1053bea87f53..23eafa41d8a01d4075737d74cae3b39171b6a5cd 100644 (file)
@@ -1326,6 +1326,7 @@ trait TraversalImpl {
 
 /// A `TraversalImpl` that actually is backed by two iterators. This works in the non-moving case,
 /// as no deallocation needs to be done.
+#[derive(Clone)]
 struct ElemsAndEdges<Elems, Edges>(Elems, Edges);
 
 impl<K, V, E, Elems: DoubleEndedIterator, Edges: DoubleEndedIterator>
@@ -1404,6 +1405,7 @@ fn drop(&mut self) {
 }
 
 /// An abstraction over all the different kinds of traversals a node supports
+#[derive(Clone)]
 struct AbsTraversal<Impl> {
     inner: Impl,
     head_is_edge: bool,
@@ -1522,6 +1524,7 @@ fn search_linear<Q: ?Sized>(&self, key: &Q) -> (usize, bool)
             }
 
             /// Returns a sub-slice with elements starting with `min_key`.
+            #[cfg(stage0)]
             pub fn slice_from(self, min_key: &K) -> $NodeSlice<'a, K, V> {
                 //  _______________
                 // |_1_|_3_|_5_|_7_|
@@ -1549,7 +1552,37 @@ pub fn slice_from(self, min_key: &K) -> $NodeSlice<'a, K, V> {
                 }
             }
 
+            /// Returns a sub-slice with elements starting with `min_key`.
+            #[cfg(not(stage0))]
+            pub fn slice_from(self, min_key: &K) -> $NodeSlice<'a, K, V> {
+                //  _______________
+                // |_1_|_3_|_5_|_7_|
+                // |   |   |   |   |
+                // 0 0 1 1 2 2 3 3 4  index
+                // |   |   |   |   |
+                // \___|___|___|___/  slice_from(&0); pos = 0
+                //     \___|___|___/  slice_from(&2); pos = 1
+                //     |___|___|___/  slice_from(&3); pos = 1; result.head_is_edge = false
+                //         \___|___/  slice_from(&4); pos = 2
+                //             \___/  slice_from(&6); pos = 3
+                //                \|/ slice_from(&999); pos = 4
+                let (pos, pos_is_kv) = self.search_linear(min_key);
+                $NodeSlice {
+                    has_edges: self.has_edges,
+                    edges: if !self.has_edges {
+                        self.edges
+                    } else {
+                        self.edges.$index(pos ..)
+                    },
+                    keys: &self.keys[pos ..],
+                    vals: self.vals.$index(pos ..),
+                    head_is_edge: !pos_is_kv,
+                    tail_is_edge: self.tail_is_edge,
+                }
+            }
+
             /// Returns a sub-slice with elements up to and including `max_key`.
+            #[cfg(stage0)]
             pub fn slice_to(self, max_key: &K) -> $NodeSlice<'a, K, V> {
                 //  _______________
                 // |_1_|_3_|_5_|_7_|
@@ -1577,6 +1610,36 @@ pub fn slice_to(self, max_key: &K) -> $NodeSlice<'a, K, V> {
                     tail_is_edge: !pos_is_kv,
                 }
             }
+
+            /// Returns a sub-slice with elements up to and including `max_key`.
+            #[cfg(not(stage0))]
+            pub fn slice_to(self, max_key: &K) -> $NodeSlice<'a, K, V> {
+                //  _______________
+                // |_1_|_3_|_5_|_7_|
+                // |   |   |   |   |
+                // 0 0 1 1 2 2 3 3 4  index
+                // |   |   |   |   |
+                //\|/  |   |   |   |  slice_to(&0); pos = 0
+                // \___/   |   |   |  slice_to(&2); pos = 1
+                // \___|___|   |   |  slice_to(&3); pos = 1; result.tail_is_edge = false
+                // \___|___/   |   |  slice_to(&4); pos = 2
+                // \___|___|___/   |  slice_to(&6); pos = 3
+                // \___|___|___|___/  slice_to(&999); pos = 4
+                let (pos, pos_is_kv) = self.search_linear(max_key);
+                let pos = pos + if pos_is_kv { 1 } else { 0 };
+                $NodeSlice {
+                    has_edges: self.has_edges,
+                    edges: if !self.has_edges {
+                        self.edges
+                    } else {
+                        self.edges.$index(.. (pos + 1))
+                    },
+                    keys: &self.keys[..pos],
+                    vals: self.vals.$index(.. pos),
+                    head_is_edge: self.head_is_edge,
+                    tail_is_edge: !pos_is_kv,
+                }
+            }
         }
 
         impl<'a, K: 'a, V: 'a> $NodeSlice<'a, K, V> {
index 5616d36ce0ba9ffadb9a1619b0616218a0fab4c7..c0e4a32eee09ec8511f97320115ba3636747fc16 100644 (file)
@@ -628,6 +628,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'a, T> Clone for Iter<'a, T> {
+    fn clone(&self) -> Iter<'a, T> { Iter { iter: self.iter.clone() } }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Iter<'a, T> {
     type Item = &'a T;
@@ -658,6 +661,9 @@ fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
 
+impl<'a, T> Clone for Range<'a, T> {
+    fn clone(&self) -> Range<'a, T> { Range { iter: self.iter.clone() } }
+}
 impl<'a, T> Iterator for Range<'a, T> {
     type Item = &'a T;
 
@@ -677,6 +683,11 @@ fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>,
     }
 }
 
+impl<'a, T> Clone for Difference<'a, T> {
+    fn clone(&self) -> Difference<'a, T> {
+        Difference { a: self.a.clone(), b: self.b.clone() }
+    }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for Difference<'a, T> {
     type Item = &'a T;
@@ -692,6 +703,11 @@ fn next(&mut self) -> Option<&'a T> {
     }
 }
 
+impl<'a, T> Clone for SymmetricDifference<'a, T> {
+    fn clone(&self) -> SymmetricDifference<'a, T> {
+        SymmetricDifference { a: self.a.clone(), b: self.b.clone() }
+    }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> {
     type Item = &'a T;
@@ -707,6 +723,11 @@ fn next(&mut self) -> Option<&'a T> {
     }
 }
 
+impl<'a, T> Clone for Intersection<'a, T> {
+    fn clone(&self) -> Intersection<'a, T> {
+        Intersection { a: self.a.clone(), b: self.b.clone() }
+    }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for Intersection<'a, T> {
     type Item = &'a T;
@@ -728,6 +749,11 @@ fn next(&mut self) -> Option<&'a T> {
     }
 }
 
+impl<'a, T> Clone for Union<'a, T> {
+    fn clone(&self) -> Union<'a, T> {
+        Union { a: self.a.clone(), b: self.b.clone() }
+    }
+}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: Ord> Iterator for Union<'a, T> {
     type Item = &'a T;
index d2abb59ffabc582eb8f0cb67cd93bd62b068e4f5..3af7485b237efc9c14782f39b511890739c9e67a 100644 (file)
 //!
 //! ```
 //! # #![allow(unused_must_use)]
+//! use std::io::Write;
 //! let mut w = Vec::new();
 //! write!(&mut w, "Hello {}!", "world");
 //! ```
 //!
 //! ```
 //! use std::fmt;
-//! use std::old_io;
+//! use std::io::{self, Write};
 //!
 //! fmt::format(format_args!("this returns {}", "String"));
 //!
-//! let mut some_writer = old_io::stdout();
+//! let mut some_writer = io::stdout();
 //! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro"));
 //!
 //! fn my_fmt_fn(args: fmt::Arguments) {
-//!     write!(&mut old_io::stdout(), "{}", args);
+//!     write!(&mut io::stdout(), "{}", args);
 //! }
 //! my_fmt_fn(format_args!("or a {} too", "function"));
 //! ```
index c4a014967633321e10a765c2c9a53edfe87bb738..156c90f1e84012e552f4754453b1c2d81dcf5c6d 100644 (file)
@@ -36,6 +36,7 @@
 #![feature(unsafe_no_drop_flag)]
 #![feature(step_by)]
 #![feature(str_char)]
+#![feature(convert)]
 #![cfg_attr(test, feature(rand, rustc_private, test))]
 #![cfg_attr(test, allow(deprecated))] // rand
 
index 45864153dd799598783557075b2e5115be246e79..0a0307aef322e093dbd8b4ad7491edec6a085770 100644 (file)
@@ -88,6 +88,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use alloc::boxed::Box;
+use core::convert::AsRef;
 use core::clone::Clone;
 use core::cmp::Ordering::{self, Greater, Less};
 use core::cmp::{self, Ord, PartialEq};
@@ -1088,23 +1089,23 @@ pub trait SliceConcatExt<T: ?Sized, U> {
     fn connect(&self, sep: &T) -> U;
 }
 
-impl<T: Clone, V: AsSlice<T>> SliceConcatExt<T, Vec<T>> for [V] {
+impl<T: Clone, V: AsRef<[T]>> SliceConcatExt<T, Vec<T>> for [V] {
     fn concat(&self) -> Vec<T> {
-        let size = self.iter().fold(0, |acc, v| acc + v.as_slice().len());
+        let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len());
         let mut result = Vec::with_capacity(size);
         for v in self {
-            result.push_all(v.as_slice())
+            result.push_all(v.as_ref())
         }
         result
     }
 
     fn connect(&self, sep: &T) -> Vec<T> {
-        let size = self.iter().fold(0, |acc, v| acc + v.as_slice().len());
+        let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len());
         let mut result = Vec::with_capacity(size + self.len());
         let mut first = true;
         for v in self {
             if first { first = false } else { result.push(sep.clone()) }
-            result.push_all(v.as_slice())
+            result.push_all(v.as_ref())
         }
         result
     }
index 3a289e4ef37389b6838671f60aa0109bff6c6fda..ebd55aa7ce7048ee95b441a08250720e43775a6c 100644 (file)
 use core::iter::{Iterator, IteratorExt, Extend};
 use core::option::Option::{self, Some, None};
 use core::result::Result;
-use core::slice::AsSlice;
 use core::str as core_str;
 use unicode::str::{UnicodeStr, Utf16Encoder};
 
+use core::convert::AsRef;
 use vec_deque::VecDeque;
 use borrow::{Borrow, ToOwned};
 use string::String;
@@ -74,8 +74,8 @@
 
 pub use core::str::{FromStr, Utf8Error, Str};
 pub use core::str::{Lines, LinesAny, MatchIndices, SplitStr, CharRange};
-pub use core::str::{Split, SplitTerminator};
-pub use core::str::{SplitN, RSplitN};
+pub use core::str::{Split, SplitTerminator, SplitN};
+pub use core::str::{RSplit, RSplitN};
 pub use core::str::{from_utf8, CharEq, Chars, CharIndices, Bytes};
 pub use core::str::{from_utf8_unchecked, from_c_str, ParseBoolError};
 pub use unicode::str::{Words, Graphemes, GraphemeIndices};
 Section: Creating a string
 */
 
-impl<S: Str> SliceConcatExt<str, String> for [S] {
+impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
     fn concat(&self) -> String {
-        let s = self.as_slice();
-
-        if s.is_empty() {
+        if self.is_empty() {
             return String::new();
         }
 
         // `len` calculation may overflow but push_str will check boundaries
-        let len = s.iter().map(|s| s.as_slice().len()).sum();
+        let len = self.iter().map(|s| s.as_ref().len()).sum();
         let mut result = String::with_capacity(len);
 
-        for s in s {
-            result.push_str(s.as_slice())
+        for s in self {
+            result.push_str(s.as_ref())
         }
 
         result
     }
 
     fn connect(&self, sep: &str) -> String {
-        let s = self.as_slice();
-
-        if s.is_empty() {
+        if self.is_empty() {
             return String::new();
         }
 
         // concat is faster
         if sep.is_empty() {
-            return s.concat();
+            return self.concat();
         }
 
         // this is wrong without the guarantee that `self` is non-empty
         // `len` calculation may overflow but push_str but will check boundaries
-        let len = sep.len() * (s.len() - 1)
-            + s.iter().map(|s| s.as_slice().len()).sum();
+        let len = sep.len() * (self.len() - 1)
+            + self.iter().map(|s| s.as_ref().len()).sum();
         let mut result = String::with_capacity(len);
         let mut first = true;
 
-        for s in s {
+        for s in self {
             if first {
                 first = false;
             } else {
                 result.push_str(sep);
             }
-            result.push_str(s.as_slice());
+            result.push_str(s.as_ref());
         }
         result
     }
@@ -699,23 +695,48 @@ pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator
         core_str::StrExt::split_terminator(&self[..], pat)
     }
 
-    /// An iterator over substrings of `self`, separated by characters matched by a pattern,
+    /// An iterator over substrings of `self`, separated by a pattern,
     /// starting from the end of the string.
     ///
-    /// Restricted to splitting at most `count` times.
+    /// # Examples
     ///
-    /// The pattern can be a simple `&str`, or a closure that determines the split.
+    /// Simple patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplit(' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "a", "had", "Mary"]);
+    ///
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplit("::").collect();
+    /// assert_eq!(v, ["leopard", "tiger", "lion"]);
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1def2ghi".rsplit(|c: char| c.is_numeric()).collect();
+    /// assert_eq!(v, ["ghi", "def", "abc"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        core_str::StrExt::rsplit(&self[..], pat)
+    }
+
+    /// An iterator over substrings of `self`, separated by a pattern,
+    /// starting from the end of the string, restricted to splitting
+    /// at most `count` times.
     ///
     /// # Examples
     ///
-    /// Simple `&str` patterns:
+    /// Simple patterns:
     ///
     /// ```
     /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
     /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
     ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
-    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(1, "::").collect();
+    /// assert_eq!(v, ["leopard", "lion::tiger"]);
     /// ```
     ///
     /// More complex patterns with a lambda:
@@ -725,7 +746,9 @@ pub fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator
     /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> {
+    pub fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
         core_str::StrExt::rsplitn(&self[..], count, pat)
     }
 
index cd6f27bf65f6e5ab2e96fae662080cce247f503e..0d55dc7dba95380025dc413e342372f549f542e2 100644 (file)
@@ -25,6 +25,7 @@
 use core::ops::{self, Deref, Add, Index};
 use core::ptr;
 use core::slice;
+use core::str::Pattern;
 use unicode::str as unicode_str;
 use unicode::str::Utf16Item;
 
@@ -765,6 +766,25 @@ fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) {
     }
 }
 
+/// A convenience impl that delegates to the impl for `&str`
+impl<'a, 'b> Pattern<'a> for &'b String {
+    type Searcher = <&'b str as Pattern<'a>>::Searcher;
+
+    fn into_searcher(self, haystack: &'a str) -> <&'b str as Pattern<'a>>::Searcher {
+        self[..].into_searcher(haystack)
+    }
+
+    #[inline]
+    fn is_contained_in(self, haystack: &'a str) -> bool {
+        self[..].is_contained_in(haystack)
+    }
+
+    #[inline]
+    fn is_prefix_of(self, haystack: &'a str) -> bool {
+        self[..].is_prefix_of(haystack)
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq for String {
     #[inline]
@@ -814,6 +834,7 @@ fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&**self, &**other) }
 }
 
 #[unstable(feature = "collections", reason = "waiting on Str stabilization")]
+#[allow(deprecated)]
 impl Str for String {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -870,34 +891,66 @@ fn add(mut self, other: &str) -> String {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::Range<usize>> for String {
     type Output = str;
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::Range<usize>) -> &str {
         &self[..][*index]
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::Range<usize>) -> &str {
+        &self[..][index]
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::RangeTo<usize>> for String {
     type Output = str;
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeTo<usize>) -> &str {
         &self[..][*index]
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeTo<usize>) -> &str {
+        &self[..][index]
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::RangeFrom<usize>> for String {
     type Output = str;
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeFrom<usize>) -> &str {
         &self[..][*index]
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeFrom<usize>) -> &str {
+        &self[..][index]
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::RangeFull> for String {
     type Output = str;
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, _index: &ops::RangeFull) -> &str {
         unsafe { mem::transmute(&*self.vec) }
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, _index: ops::RangeFull) -> &str {
+        unsafe { mem::transmute(&*self.vec) }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -973,6 +1026,27 @@ fn to_string(&self) -> String {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<str> for String {
+    fn as_ref(&self) -> &str {
+        self
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a str> for String {
+    fn from(s: &'a str) -> String {
+        s.to_string()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Into<Vec<u8>> for String {
+    fn into(self) -> Vec<u8> {
+        self.into_bytes()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl IntoCow<'static, str> for String {
     #[inline]
@@ -989,6 +1063,7 @@ fn into_cow(self) -> Cow<'a, str> {
     }
 }
 
+#[allow(deprecated)]
 impl<'a> Str for Cow<'a, str> {
     #[inline]
     fn as_slice<'b>(&'b self) -> &'b str {
index b0e8dc7d0b6226d004480ffd3d7f85a2b6ff88c8..1d76224bd841955573eb0314129eb53a30f7ef37 100644 (file)
@@ -1323,90 +1323,178 @@ fn hash<H: hash::Hasher>(&self, state: &mut H) {
 impl<T> Index<usize> for Vec<T> {
     type Output = T;
 
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &usize) -> &T {
         // NB built-in indexing via `&[T]`
         &(**self)[*index]
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: usize) -> &T {
+        // NB built-in indexing via `&[T]`
+        &(**self)[index]
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> IndexMut<usize> for Vec<T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &usize) -> &mut T {
         // NB built-in indexing via `&mut [T]`
         &mut (**self)[*index]
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut T {
+        // NB built-in indexing via `&mut [T]`
+        &mut (**self)[index]
+    }
 }
 
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::Range<usize>> for Vec<T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::Range<usize>) -> &[T] {
         Index::index(&**self, index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::Range<usize>) -> &[T] {
+        Index::index(&**self, index)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeTo<usize>> for Vec<T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeTo<usize>) -> &[T] {
         Index::index(&**self, index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
+        Index::index(&**self, index)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeFrom<usize>> for Vec<T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeFrom<usize>) -> &[T] {
         Index::index(&**self, index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
+        Index::index(&**self, index)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeFull> for Vec<T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, _index: &ops::RangeFull) -> &[T] {
+        self
+    }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, _index: ops::RangeFull) -> &[T] {
         self.as_slice()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::Range<usize>> for Vec<T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::Range<usize>) -> &mut [T] {
         IndexMut::index_mut(&mut **self, index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
+        IndexMut::index_mut(&mut **self, index)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeTo<usize>> for Vec<T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::RangeTo<usize>) -> &mut [T] {
         IndexMut::index_mut(&mut **self, index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
+        IndexMut::index_mut(&mut **self, index)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeFrom<usize>> for Vec<T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::RangeFrom<usize>) -> &mut [T] {
         IndexMut::index_mut(&mut **self, index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
+        IndexMut::index_mut(&mut **self, index)
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeFull> for Vec<T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, _index: &ops::RangeFull) -> &mut [T] {
         self.as_mut_slice()
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] {
+        self.as_mut_slice()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Deref for Vec<T> {
     type Target = [T];
 
-    fn deref(&self) -> &[T] { self.as_slice() }
+    fn deref(&self) -> &[T] {
+        unsafe {
+            let p = *self.ptr;
+            assume(p != 0 as *mut T);
+            slice::from_raw_parts(p, self.len)
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1548,6 +1636,7 @@ fn cmp(&self, other: &Vec<T>) -> Ordering {
     }
 }
 
+#[allow(deprecated)]
 impl<T> AsSlice<T> for Vec<T> {
     /// Returns a slice into `self`.
     ///
@@ -1562,11 +1651,7 @@ impl<T> AsSlice<T> for Vec<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn as_slice(&self) -> &[T] {
-        unsafe {
-            let p = *self.ptr;
-            assume(p != 0 as *mut T);
-            slice::from_raw_parts(p, self.len)
-        }
+        self
     }
 }
 
@@ -1614,6 +1699,41 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> AsRef<Vec<T>> for Vec<T> {
+    fn as_ref(&self) -> &Vec<T> {
+        self
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Into<Vec<T>> for Vec<T> {
+    fn into(self) -> Vec<T> {
+        self
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> AsRef<[T]> for Vec<T> {
+    fn as_ref(&self) -> &[T] {
+        self
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: Clone> From<&'a [T]> for Vec<T> {
+    fn from(s: &'a [T]) -> Vec<T> {
+        s.to_vec()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a str> for Vec<u8> {
+    fn from(s: &'a str) -> Vec<u8> {
+        s.as_bytes().to_vec()
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Clone-on-write
 ////////////////////////////////////////////////////////////////////////////////
index 56ca74dab1f0fd6d040e3b6bb6ed92cb68b4676e..591ad48f57912316e9bccf26d97132862ce34706 100644 (file)
@@ -1689,18 +1689,32 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 impl<A> Index<usize> for VecDeque<A> {
     type Output = A;
 
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, i: &usize) -> &A {
         self.get(*i).expect("Out of bounds access")
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, i: usize) -> &A {
+        self.get(i).expect("Out of bounds access")
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> IndexMut<usize> for VecDeque<A> {
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, i: &usize) -> &mut A {
         self.get_mut(*i).expect("Out of bounds access")
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, i: usize) -> &mut A {
+        self.get_mut(i).expect("Out of bounds access")
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 6e67d8763273d7c0156473b126b4662d061911f3..05693ec52756ad0e9a95505e603c75e456ebf987 100644 (file)
@@ -798,6 +798,7 @@ fn extend<I: IntoIterator<Item=(usize, V)>>(&mut self, iter: I) {
     }
 }
 
+#[cfg(stage0)]
 impl<V> Index<usize> for VecMap<V> {
     type Output = V;
 
@@ -807,10 +808,49 @@ fn index<'a>(&'a self, i: &usize) -> &'a V {
     }
 }
 
+#[cfg(not(stage0))]
+impl<V> Index<usize> for VecMap<V> {
+    type Output = V;
+
+    #[inline]
+    fn index<'a>(&'a self, i: usize) -> &'a V {
+        self.get(&i).expect("key not present")
+    }
+}
+
+#[cfg(not(stage0))]
+impl<'a,V> Index<&'a usize> for VecMap<V> {
+    type Output = V;
+
+    #[inline]
+    fn index(&self, i: &usize) -> &V {
+        self.get(i).expect("key not present")
+    }
+}
+
+#[cfg(stage0)]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<V> IndexMut<usize> for VecMap<V> {
+    #[inline]
+    fn index_mut(&mut self, i: &usize) -> &mut V {
+        self.get_mut(&i).expect("key not present")
+    }
+}
+
+#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<V> IndexMut<usize> for VecMap<V> {
     #[inline]
-    fn index_mut<'a>(&'a mut self, i: &usize) -> &'a mut V {
+    fn index_mut(&mut self, i: usize) -> &mut V {
+        self.get_mut(&i).expect("key not present")
+    }
+}
+
+#[cfg(not(stage0))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, V> IndexMut<&'a usize> for VecMap<V> {
+    #[inline]
+    fn index_mut(&mut self, i: &usize) -> &mut V {
         self.get_mut(i).expect("key not present")
     }
 }
index 79c2d719862a9e014849518573432df247c6a32c..5cfa800905415dd855554be725c97731ac513448 100644 (file)
@@ -910,6 +910,34 @@ fn test_split_char_iterator_no_trailing() {
     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
 }
 
+#[test]
+fn test_rsplit() {
+    let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+    let split: Vec<&str> = data.rsplit(' ').collect();
+    assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
+
+    let split: Vec<&str> = data.rsplit("lämb").collect();
+    assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
+
+    let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
+    assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
+}
+
+#[test]
+fn test_rsplitn() {
+    let data = "\nMäry häd ä little lämb\nLittle lämb\n";
+
+    let split: Vec<&str> = data.rsplitn(1, ' ').collect();
+    assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
+
+    let split: Vec<&str> = data.rsplitn(1, "lämb").collect();
+    assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
+
+    let split: Vec<&str> = data.rsplitn(1, |c: char| c == 'ä').collect();
+    assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
+}
+
 #[test]
 fn test_words() {
     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
new file mode 100644 (file)
index 0000000..65a226d
--- /dev/null
@@ -0,0 +1,113 @@
+// Copyright 2014 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.
+
+//! Traits for conversions between types.
+//!
+//! The traits in this module provide a general way to talk about
+//! conversions from one type to another. They follow the standard
+//! Rust conventions of `as`/`to`/`into`/`from`.
+
+#![unstable(feature = "convert",
+            reason = "recently added, experimental traits")]
+
+use marker::Sized;
+
+/// A cheap, reference-to-reference conversion.
+pub trait AsRef<T: ?Sized> {
+    /// Perform the conversion.
+    fn as_ref(&self) -> &T;
+}
+
+/// A cheap, mutable reference-to-mutable reference conversion.
+pub trait AsMut<T: ?Sized> {
+    /// Perform the conversion.
+    fn as_mut(&mut self) -> &mut T;
+}
+
+/// A conversion that consumes `self`, which may or may not be
+/// expensive.
+pub trait Into<T>: Sized {
+    /// Perform the conversion.
+    fn into(self) -> T;
+}
+
+/// Construct `Self` via a conversion.
+pub trait From<T> {
+    /// Perform the conversion.
+    fn from(T) -> Self;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GENERIC IMPLS
+////////////////////////////////////////////////////////////////////////////////
+
+// As implies Into
+impl<'a, T: ?Sized, U: ?Sized> Into<&'a U> for &'a T where T: AsRef<U> {
+    fn into(self) -> &'a U {
+        self.as_ref()
+    }
+}
+
+// As lifts over &
+impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U> {
+    fn as_ref(&self) -> &U {
+        <T as AsRef<U>>::as_ref(*self)
+    }
+}
+
+// As lifts over &mut
+impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a mut T where T: AsRef<U> {
+    fn as_ref(&self) -> &U {
+        <T as AsRef<U>>::as_ref(*self)
+    }
+}
+
+// AsMut implies Into
+impl<'a, T: ?Sized, U: ?Sized> Into<&'a mut U> for &'a mut T where T: AsMut<U> {
+    fn into(self) -> &'a mut U {
+        (*self).as_mut()
+    }
+}
+
+// AsMut lifts over &mut
+impl<'a, T: ?Sized, U: ?Sized> AsMut<U> for &'a mut T where T: AsMut<U> {
+    fn as_mut(&mut self) -> &mut U {
+        (*self).as_mut()
+    }
+}
+
+// From implies Into
+impl<T, U> Into<U> for T where U: From<T> {
+    fn into(self) -> U {
+        U::from(self)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// CONCRETE IMPLS
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T> AsRef<[T]> for [T] {
+    fn as_ref(&self) -> &[T] {
+        self
+    }
+}
+
+impl<T> AsMut<[T]> for [T] {
+    fn as_mut(&mut self) -> &mut [T] {
+        self
+    }
+}
+
+impl AsRef<str> for str {
+    fn as_ref(&self) -> &str {
+        self
+    }
+}
index 161f6c78921630e68c952fdeb90de7fe4627620c..d29964d63a58ed95ab07cbd5d1a43947287e4058 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use prelude::*;
-use fmt::Display;
+use fmt::{Debug, Display};
 
 /// Base functionality for all errors in Rust.
-#[unstable(feature = "core",
-           reason = "the exact API of this trait may change")]
-pub trait Error: Display {
-    /// A short description of the error; usually a static string.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Error: Debug + Display + Send {
+    /// A short description of the error.
+    ///
+    /// The description should not contain newlines or sentence-ending
+    /// punctuation, to facilitate embedding in larger user-facing
+    /// strings.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn description(&self) -> &str;
 
     /// The lower-level cause of this error, if any.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn cause(&self) -> Option<&Error> { None }
 }
 
index 29cc11d5a60a18e7ad7062c4c36c6aa8f33bca1e..e31542c183a69122a65c3b8d0caa9e2c1179159d 100644 (file)
 pub mod cmp;
 pub mod clone;
 pub mod default;
+pub mod convert;
 
 /* Core types and methods on primitives */
 
index 6dcae9879a0d0fd5da3f30e61823e1e472153327..c647b037944aec0c401ac1fe14c618024f2effec 100644 (file)
@@ -176,6 +176,7 @@ macro_rules! try {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
+/// use std::io::Write;
 ///
 /// let mut w = Vec::new();
 /// write!(&mut w, "test");
index 1b866501b8ea1a3d0fb62d347f1af1af990ddabf..0197ee82c77407104edd4647c1a9816a4a8683fa 100644 (file)
@@ -39,6 +39,8 @@ pub unsafe trait Send : MarkerTrait {
     // empty.
 }
 
+unsafe impl Send for .. { }
+
 impl<T> !Send for *const T { }
 impl<T> !Send for *mut T { }
 impl !Send for Managed { }
@@ -203,6 +205,8 @@ pub unsafe trait Sync : MarkerTrait {
     // Empty
 }
 
+unsafe impl Sync for .. { }
+
 impl<T> !Sync for *const T { }
 impl<T> !Sync for *mut T { }
 impl !Sync for Managed { }
index 6324e8fa874439bf54d850809716a54146753534..6e6f97a7af7d9e1d2595309f78ef918885ba4965 100644 (file)
@@ -898,7 +898,7 @@ macro_rules! shr_impl_all {
 /// impl Index<Bar> for Foo {
 ///     type Output = Foo;
 ///
-///     fn index<'a>(&'a self, _index: &Bar) -> &'a Foo {
+///     fn index<'a>(&'a self, _index: Bar) -> &'a Foo {
 ///         println!("Indexing!");
 ///         self
 ///     }
@@ -917,8 +917,14 @@ pub trait Index<Idx: ?Sized> {
     type Output: ?Sized;
 
     /// The method for the indexing (`Foo[Bar]`) operation
+    #[cfg(stage0)]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn index<'a>(&'a self, index: &Idx) -> &'a Self::Output;
+
+    /// The method for the indexing (`Foo[Bar]`) operation
+    #[cfg(not(stage0))]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn index<'a>(&'a self, index: Idx) -> &'a Self::Output;
 }
 
 /// The `IndexMut` trait is used to specify the functionality of indexing
@@ -939,13 +945,13 @@ pub trait Index<Idx: ?Sized> {
 /// impl Index<Bar> for Foo {
 ///     type Output = Foo;
 ///
-///     fn index<'a>(&'a self, _index: &Bar) -> &'a Foo {
+///     fn index<'a>(&'a self, _index: Bar) -> &'a Foo {
 ///         self
 ///     }
 /// }
 ///
 /// impl IndexMut<Bar> for Foo {
-///     fn index_mut<'a>(&'a mut self, _index: &Bar) -> &'a mut Foo {
+///     fn index_mut<'a>(&'a mut self, _index: Bar) -> &'a mut Foo {
 ///         println!("Indexing!");
 ///         self
 ///     }
@@ -960,8 +966,14 @@ pub trait Index<Idx: ?Sized> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
     /// The method for the indexing (`Foo[Bar]`) operation
+    #[cfg(stage0)]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn index_mut<'a>(&'a mut self, index: &Idx) -> &'a mut Self::Output;
+
+    /// The method for the indexing (`Foo[Bar]`) operation
+    #[cfg(not(stage0))]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn index_mut<'a>(&'a mut self, index: Idx) -> &'a mut Self::Output;
 }
 
 /// An unbounded range.
index 455c68d4319d670ae952fd374a0da4b307b65a4b..4a1e24c1f406d03b72d0f96f189ce518269c45ba 100644 (file)
 use ops::{Deref, FnOnce};
 use result::Result::{Ok, Err};
 use result::Result;
+#[allow(deprecated)]
 use slice::AsSlice;
 use slice;
 
@@ -701,6 +702,19 @@ pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
     pub fn take(&mut self) -> Option<T> {
         mem::replace(self, None)
     }
+
+    /// Convert from `Option<T>` to `&[T]` (without copying)
+    #[inline]
+    #[unstable(feature = "as_slice", since = "unsure of the utility here")]
+    pub fn as_slice<'a>(&'a self) -> &'a [T] {
+        match *self {
+            Some(ref x) => slice::ref_slice(x),
+            None => {
+                let result: &[_] = &[];
+                result
+            }
+        }
+    }
 }
 
 impl<'a, T: Clone, D: Deref<Target=T>> Option<D> {
@@ -752,6 +766,9 @@ pub fn unwrap_or_default(self) -> T {
 
 #[unstable(feature = "core",
            reason = "waiting on the stability of the trait itself")]
+#[deprecated(since = "1.0.0",
+             reason = "use the inherent method instead")]
+#[allow(deprecated)]
 impl<T> AsSlice<T> for Option<T> {
     /// Convert from `Option<T>` to `&[T]` (without copying)
     #[inline]
index c668fe80d14520420c6ebb4e1921ad96a98e559a..424829939b92e89fbea8898bdcb7b71ff09dba54 100644 (file)
@@ -29,8 +29,6 @@
 pub use ops::{Drop, Fn, FnMut, FnOnce};
 
 // Reexported functions
-#[allow(deprecated)]
-pub use iter::range;
 pub use mem::drop;
 
 // Reexported types and traits
@@ -38,6 +36,7 @@
 pub use char::CharExt;
 pub use clone::Clone;
 pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
+pub use convert::{AsRef, AsMut, Into, From};
 pub use iter::{Extend, IteratorExt};
 pub use iter::{Iterator, DoubleEndedIterator};
 pub use iter::{ExactSizeIterator};
index a5b2fddfd5df61dc9d70cea7e11d0e8003ec6c6f..4b3cda46c1df3c84e3a0e13406946d3917d43dc6 100644 (file)
@@ -78,7 +78,7 @@
 //! let bad_result: Result<int, int> = bad_result.or_else(|i| Ok(11));
 //!
 //! // Consume the result and return the contents with `unwrap`.
-//! let final_awesome_result = good_result.ok().unwrap();
+//! let final_awesome_result = good_result.unwrap();
 //! ```
 //!
 //! # Results must be used
 //! something like this:
 //!
 //! ```{.ignore}
-//! use std::old_io::{File, Open, Write};
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write);
 //! // If `write_line` errors, then we'll never know, because the return
 //! a marginally useful message indicating why:
 //!
 //! ```{.no_run}
-//! use std::old_io::{File, Open, Write};
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write);
 //! file.write_line("important message").ok().expect("failed to write message");
 //! You might also simply assert success:
 //!
 //! ```{.no_run}
-//! # use std::old_io::{File, Open, Write};
+//! # use std::old_io::*;
+//! # use std::old_path::Path;
 //!
 //! # let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write);
 //! assert!(file.write_line("important message").is_ok());
 //! Or propagate the error up the call stack with `try!`:
 //!
 //! ```
-//! # use std::old_io::{File, Open, Write, IoError};
+//! # use std::old_io::*;
+//! # use std::old_path::Path;
 //! fn write_message() -> Result<(), IoError> {
 //!     let mut file = File::open_mode(&Path::new("valuable_data.txt"), Open, Write);
 //!     try!(file.write_line("important message"));
 //! It replaces this:
 //!
 //! ```
-//! use std::old_io::{File, Open, Write, IoError};
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! struct Info {
 //!     name: String,
 //! With this:
 //!
 //! ```
-//! use std::old_io::{File, Open, Write, IoError};
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! struct Info {
 //!     name: String,
            FromIterator, ExactSizeIterator, IntoIterator};
 use ops::{FnMut, FnOnce};
 use option::Option::{self, None, Some};
+#[allow(deprecated)]
 use slice::AsSlice;
 use slice;
 
@@ -402,6 +409,20 @@ pub fn as_mut(&mut self) -> Result<&mut T, &mut E> {
         }
     }
 
+    /// Convert from `Result<T, E>` to `&[T]` (without copying)
+    #[inline]
+    #[unstable(feature = "as_slice", since = "unsure of the utility here")]
+    pub fn as_slice(&self) -> &[T] {
+        match *self {
+            Ok(ref x) => slice::ref_slice(x),
+            Err(_) => {
+                // work around lack of implicit coercion from fixed-size array to slice
+                let emp: &[_] = &[];
+                emp
+            }
+        }
+    }
+
     /// Convert from `Result<T, E>` to `&mut [T]` (without copying)
     ///
     /// ```
@@ -446,7 +467,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     /// ignoring I/O and parse errors:
     ///
     /// ```
-    /// use std::old_io::IoResult;
+    /// use std::old_io::*;
     ///
     /// let mut buffer: &[u8] = b"1\n2\n3\n4\n";
     /// let mut buffer = &mut buffer;
@@ -460,7 +481,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     ///         line.trim_right().parse::<int>().unwrap_or(0)
     ///     });
     ///     // Add the value if there were no errors, otherwise add 0
-    ///     sum += val.ok().unwrap_or(0);
+    ///     sum += val.unwrap_or(0);
     /// }
     ///
     /// assert!(sum == 10);
@@ -782,10 +803,14 @@ pub fn unwrap_err(self) -> E {
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
 
+#[unstable(feature = "core",
+           reason = "waiting on the stability of the trait itself")]
+#[deprecated(since = "1.0.0",
+             reason = "use inherent method instead")]
+#[allow(deprecated)]
 impl<T, E> AsSlice<T> for Result<T, E> {
     /// Convert from `Result<T, E>` to `&[T]` (without copying)
     #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_slice<'a>(&'a self) -> &'a [T] {
         match *self {
             Ok(ref x) => slice::ref_slice(x),
index 907b2eba80c5b872a1f5fc1fb9964901c73c1251..8826cfc5ee35885d41d8d5078a2a330ad21a477f 100644 (file)
@@ -263,6 +263,7 @@ fn get_mut(&mut self, index: usize) -> Option<&mut T> {
     #[inline]
     fn as_mut_slice(&mut self) -> &mut [T] { self }
 
+    #[cfg(stage0)]
     #[inline]
     fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
         unsafe {
@@ -273,6 +274,17 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
         }
     }
 
+    #[cfg(not(stage0))]
+    #[inline]
+    fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
+        unsafe {
+            let self2: &mut [T] = mem::transmute_copy(&self);
+
+            (ops::IndexMut::index_mut(self, ops::RangeTo { end: mid } ),
+             ops::IndexMut::index_mut(self2, ops::RangeFrom { start: mid } ))
+        }
+    }
+
     #[inline]
     fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
         unsafe {
@@ -495,25 +507,45 @@ fn clone_from_slice(&mut self, src: &[T]) -> usize where T: Clone {
 impl<T> ops::Index<usize> for [T] {
     type Output = T;
 
+    #[cfg(stage0)]
     fn index(&self, &index: &usize) -> &T {
         assert!(index < self.len());
 
         unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
     }
+
+    #[cfg(not(stage0))]
+    fn index(&self, index: usize) -> &T {
+        assert!(index < self.len());
+
+        unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<usize> for [T] {
+    #[cfg(stage0)]
+    #[inline]
     fn index_mut(&mut self, &index: &usize) -> &mut T {
         assert!(index < self.len());
 
         unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: usize) -> &mut T {
+        assert!(index < self.len());
+
+        unsafe { mem::transmute(self.repr().data.offset(index as isize)) }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::Range<usize>> for [T] {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::Range<usize>) -> &[T] {
         assert!(index.start <= index.end);
@@ -525,34 +557,72 @@ fn index(&self, index: &ops::Range<usize>) -> &[T] {
             )
         }
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::Range<usize>) -> &[T] {
+        assert!(index.start <= index.end);
+        assert!(index.end <= self.len());
+        unsafe {
+            from_raw_parts (
+                self.as_ptr().offset(index.start as isize),
+                index.end - index.start
+            )
+        }
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeTo<usize>> for [T] {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeTo<usize>) -> &[T] {
         self.index(&ops::Range{ start: 0, end: index.end })
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
+        self.index(ops::Range{ start: 0, end: index.end })
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<ops::RangeFrom<usize>> for [T] {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeFrom<usize>) -> &[T] {
         self.index(&ops::Range{ start: index.start, end: self.len() })
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
+        self.index(ops::Range{ start: index.start, end: self.len() })
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::Index<RangeFull> for [T] {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, _index: &RangeFull) -> &[T] {
         self
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, _index: RangeFull) -> &[T] {
+        self
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::Range<usize>> for [T] {
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::Range<usize>) -> &mut [T] {
         assert!(index.start <= index.end);
@@ -564,28 +634,64 @@ fn index_mut(&mut self, index: &ops::Range<usize>) -> &mut [T] {
             )
         }
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
+        assert!(index.start <= index.end);
+        assert!(index.end <= self.len());
+        unsafe {
+            from_raw_parts_mut(
+                self.as_mut_ptr().offset(index.start as isize),
+                index.end - index.start
+            )
+        }
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeTo<usize>> for [T] {
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::RangeTo<usize>) -> &mut [T] {
         self.index_mut(&ops::Range{ start: 0, end: index.end })
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
+        self.index_mut(ops::Range{ start: 0, end: index.end })
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<ops::RangeFrom<usize>> for [T] {
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::RangeFrom<usize>) -> &mut [T] {
         let len = self.len();
         self.index_mut(&ops::Range{ start: index.start, end: len })
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
+        let len = self.len();
+        self.index_mut(ops::Range{ start: index.start, end: len })
+    }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ops::IndexMut<RangeFull> for [T] {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, _index: &RangeFull) -> &mut [T] {
         self
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, _index: RangeFull) -> &mut [T] {
+        self
+    }
 }
 
 
@@ -596,24 +702,29 @@ fn index_mut(&mut self, _index: &RangeFull) -> &mut [T] {
 /// Data that is viewable as a slice.
 #[unstable(feature = "core",
            reason = "will be replaced by slice syntax")]
+#[deprecated(since = "1.0.0",
+             reason = "use std::convert::AsRef<[T]> instead")]
 pub trait AsSlice<T> {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a [T];
 }
 
 #[unstable(feature = "core", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<T> AsSlice<T> for [T] {
     #[inline(always)]
     fn as_slice<'a>(&'a self) -> &'a [T] { self }
 }
 
 #[unstable(feature = "core", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
 }
 
 #[unstable(feature = "core", reason = "trait is experimental")]
+#[allow(deprecated)]
 impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
     #[inline(always)]
     fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
@@ -763,37 +874,69 @@ unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<usize>> for Iter<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::Range<usize>) -> &[T] {
         self.as_slice().index(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::Range<usize>) -> &[T] {
+        self.as_slice().index(index)
+    }
 }
 
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeTo<usize>> for Iter<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeTo<usize>) -> &[T] {
         self.as_slice().index(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
+        self.as_slice().index(index)
+    }
 }
 
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeFrom<usize>> for Iter<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeFrom<usize>) -> &[T] {
         self.as_slice().index(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
+        self.as_slice().index(index)
+    }
 }
 
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<RangeFull> for Iter<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, _index: &RangeFull) -> &[T] {
         self.as_slice()
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, _index: RangeFull) -> &[T] {
+        self.as_slice()
+    }
 }
 
 impl<'a, T> Iter<'a, T> {
@@ -856,63 +999,126 @@ unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<usize>> for IterMut<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::Range<usize>) -> &[T] {
         self.index(&RangeFull).index(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::Range<usize>) -> &[T] {
+        self.index(RangeFull).index(index)
+    }
 }
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeTo<usize>> for IterMut<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeTo<usize>) -> &[T] {
         self.index(&RangeFull).index(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
+        self.index(RangeFull).index(index)
+    }
 }
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::RangeFrom<usize>> for IterMut<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, index: &ops::RangeFrom<usize>) -> &[T] {
         self.index(&RangeFull).index(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
+        self.index(RangeFull).index(index)
+    }
 }
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<RangeFull> for IterMut<'a, T> {
     type Output = [T];
+
+    #[cfg(stage0)]
     #[inline]
     fn index(&self, _index: &RangeFull) -> &[T] {
         make_slice!(T => &[T]: self.ptr, self.end)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index(&self, _index: RangeFull) -> &[T] {
+        make_slice!(T => &[T]: self.ptr, self.end)
+    }
 }
 
 #[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::Range<usize>> for IterMut<'a, T> {
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::Range<usize>) -> &mut [T] {
         self.index_mut(&RangeFull).index_mut(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
+        self.index_mut(RangeFull).index_mut(index)
+    }
 }
 #[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::RangeTo<usize>> for IterMut<'a, T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::RangeTo<usize>) -> &mut [T] {
         self.index_mut(&RangeFull).index_mut(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
+        self.index_mut(RangeFull).index_mut(index)
+    }
 }
 #[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<ops::RangeFrom<usize>> for IterMut<'a, T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, index: &ops::RangeFrom<usize>) -> &mut [T] {
         self.index_mut(&RangeFull).index_mut(index)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
+        self.index_mut(RangeFull).index_mut(index)
+    }
 }
 #[unstable(feature = "core")]
 impl<'a, T> ops::IndexMut<RangeFull> for IterMut<'a, T> {
+
+    #[cfg(stage0)]
     #[inline]
     fn index_mut(&mut self, _index: &RangeFull) -> &mut [T] {
         make_mut_slice!(T => &mut [T]: self.ptr, self.end)
     }
+
+    #[cfg(not(stage0))]
+    #[inline]
+    fn index_mut(&mut self, _index: RangeFull) -> &mut [T] {
+        make_mut_slice!(T => &mut [T]: self.ptr, self.end)
+    }
 }
 
 
index e8181395b5c1e5a19538eb3eef1942014577daa4..b7285d30a7309cc9451a22aef5e4ba7170a3c250 100644 (file)
@@ -111,7 +111,24 @@ fn size_hint(&self) -> (usize, Option<usize>) {
                 self.0.size_hint()
             }
         }
-    }
+    };
+    (pattern reverse $te:ty : $ti:ty) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, P: Pattern<'a>> Iterator for $ti
+            where P::Searcher: ReverseSearcher<'a>
+        {
+            type Item = $te;
+
+            #[inline]
+            fn next(&mut self) -> Option<$te> {
+                self.0.next()
+            }
+            #[inline]
+            fn size_hint(&self) -> (usize, Option<usize>) {
+                self.0.size_hint()
+            }
+        }
+    };
 }
 
 /// A trait to abstract the idea of creating a new instance of a type from a
@@ -550,7 +567,26 @@ struct CharSplitsN<'a, P: Pattern<'a>> {
     iter: CharSplits<'a, P>,
     /// The number of splits remaining
     count: usize,
-    invert: bool,
+}
+
+/// An iterator over the substrings of a string, separated by a
+/// pattern, in reverse order.
+struct RCharSplits<'a, P: Pattern<'a>> {
+    /// The slice remaining to be iterated
+    start: usize,
+    end: usize,
+    matcher: P::Searcher,
+    /// Whether an empty string at the end of iteration is allowed
+    allow_final_empty: bool,
+    finished: bool,
+}
+
+/// An iterator over the substrings of a string, separated by a
+/// pattern, splitting at most `count` times, in reverse order.
+struct RCharSplitsN<'a, P: Pattern<'a>> {
+    iter: RCharSplits<'a, P>,
+    /// The number of splits remaining
+    count: usize,
 }
 
 /// An iterator over the lines of a string, separated by `\n`.
@@ -631,21 +667,74 @@ fn next_back(&mut self) -> Option<&'a str> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P>
-where P::Searcher: DoubleEndedSearcher<'a> {
+impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P> {
     type Item = &'a str;
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
         if self.count != 0 {
             self.count -= 1;
-            if self.invert { self.iter.next_back() } else { self.iter.next() }
+            self.iter.next()
         } else {
             self.iter.get_end()
         }
     }
 }
 
+impl<'a, P: Pattern<'a>> RCharSplits<'a, P> {
+    #[inline]
+    fn get_remainder(&mut self) -> Option<&'a str> {
+        if !self.finished && (self.allow_final_empty || self.end - self.start > 0) {
+            self.finished = true;
+            unsafe {
+                let string = self.matcher.haystack().slice_unchecked(self.start, self.end);
+                Some(string)
+            }
+        } else {
+            None
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, P: Pattern<'a>> Iterator for RCharSplits<'a, P>
+    where P::Searcher: ReverseSearcher<'a>
+{
+    type Item = &'a str;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a str> {
+        if self.finished { return None }
+
+        let haystack = self.matcher.haystack();
+        match self.matcher.next_match_back() {
+            Some((a, b)) => unsafe {
+                let elt = haystack.slice_unchecked(b, self.end);
+                self.end = a;
+                Some(elt)
+            },
+            None => self.get_remainder(),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, P: Pattern<'a>> Iterator for RCharSplitsN<'a, P>
+    where P::Searcher: ReverseSearcher<'a>
+{
+    type Item = &'a str;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a str> {
+        if self.count != 0 {
+            self.count -= 1;
+            self.iter.next()
+        } else {
+            self.iter.get_remainder()
+        }
+    }
+}
+
 /// The internal state of an iterator that searches for matches of a substring
 /// within a larger string using two-way search
 #[derive(Clone)]
@@ -1203,6 +1292,7 @@ fn partial_cmp(&self, other: &str) -> Option<Ordering> {
     /// // byte 100 is outside the string
     /// // &s[3 .. 100];
     /// ```
+    #[cfg(stage0)]
     #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::Range<usize>> for str {
         type Output = str;
@@ -1219,6 +1309,49 @@ fn index(&self, index: &ops::Range<usize>) -> &str {
         }
     }
 
+    /// Returns a slice of the given string from the byte range
+    /// [`begin`..`end`).
+    ///
+    /// This operation is `O(1)`.
+    ///
+    /// Panics when `begin` and `end` do not point to valid characters
+    /// or point beyond the last character of the string.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    /// assert_eq!(&s[0 .. 1], "L");
+    ///
+    /// assert_eq!(&s[1 .. 9], "öwe 老");
+    ///
+    /// // these will panic:
+    /// // byte 2 lies within `ö`:
+    /// // &s[2 ..3];
+    ///
+    /// // byte 8 lies within `老`
+    /// // &s[1 .. 8];
+    ///
+    /// // byte 100 is outside the string
+    /// // &s[3 .. 100];
+    /// ```
+    #[cfg(not(stage0))]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    impl ops::Index<ops::Range<usize>> for str {
+        type Output = str;
+        #[inline]
+        fn index(&self, index: ops::Range<usize>) -> &str {
+            // is_char_boundary checks that the index is in [0, .len()]
+            if index.start <= index.end &&
+               self.is_char_boundary(index.start) &&
+               self.is_char_boundary(index.end) {
+                unsafe { self.slice_unchecked(index.start, index.end) }
+            } else {
+                super::slice_error_fail(self, index.start, index.end)
+            }
+        }
+    }
+
     /// Returns a slice of the string from the beginning to byte
     /// `end`.
     ///
@@ -1229,6 +1362,8 @@ fn index(&self, index: &ops::Range<usize>) -> &str {
     #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::RangeTo<usize>> for str {
         type Output = str;
+
+        #[cfg(stage0)]
         #[inline]
         fn index(&self, index: &ops::RangeTo<usize>) -> &str {
             // is_char_boundary checks that the index is in [0, .len()]
@@ -1238,6 +1373,17 @@ fn index(&self, index: &ops::RangeTo<usize>) -> &str {
                 super::slice_error_fail(self, 0, index.end)
             }
         }
+
+        #[cfg(not(stage0))]
+        #[inline]
+        fn index(&self, index: ops::RangeTo<usize>) -> &str {
+            // is_char_boundary checks that the index is in [0, .len()]
+            if self.is_char_boundary(index.end) {
+                unsafe { self.slice_unchecked(0, index.end) }
+            } else {
+                super::slice_error_fail(self, 0, index.end)
+            }
+        }
     }
 
     /// Returns a slice of the string from `begin` to its end.
@@ -1249,6 +1395,8 @@ fn index(&self, index: &ops::RangeTo<usize>) -> &str {
     #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::RangeFrom<usize>> for str {
         type Output = str;
+
+        #[cfg(stage0)]
         #[inline]
         fn index(&self, index: &ops::RangeFrom<usize>) -> &str {
             // is_char_boundary checks that the index is in [0, .len()]
@@ -1258,15 +1406,34 @@ fn index(&self, index: &ops::RangeFrom<usize>) -> &str {
                 super::slice_error_fail(self, index.start, self.len())
             }
         }
+
+        #[cfg(not(stage0))]
+        #[inline]
+        fn index(&self, index: ops::RangeFrom<usize>) -> &str {
+            // is_char_boundary checks that the index is in [0, .len()]
+            if self.is_char_boundary(index.start) {
+                unsafe { self.slice_unchecked(index.start, self.len()) }
+            } else {
+                super::slice_error_fail(self, index.start, self.len())
+            }
+        }
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     impl ops::Index<ops::RangeFull> for str {
         type Output = str;
+
+        #[cfg(stage0)]
         #[inline]
         fn index(&self, _index: &ops::RangeFull) -> &str {
             self
         }
+
+        #[cfg(not(stage0))]
+        #[inline]
+        fn index(&self, _index: ops::RangeFull) -> &str {
+            self
+        }
     }
 }
 
@@ -1275,16 +1442,20 @@ fn index(&self, _index: &ops::RangeFull) -> &str {
            reason = "Instead of taking this bound generically, this trait will be \
                      replaced with one of slicing syntax (&foo[..]), deref coercions, or \
                      a more generic conversion trait")]
+#[deprecated(since = "1.0.0",
+             reason = "use std::convert::AsRef<str> instead")]
 pub trait Str {
     /// Work with `self` as a slice.
     fn as_slice<'a>(&'a self) -> &'a str;
 }
 
+#[allow(deprecated)]
 impl Str for str {
     #[inline]
     fn as_slice<'a>(&'a self) -> &'a str { self }
 }
 
+#[allow(deprecated)]
 impl<'a, S: ?Sized> Str for &'a S where S: Str {
     #[inline]
     fn as_slice(&self) -> &str { Str::as_slice(*self) }
@@ -1293,23 +1464,7 @@ fn as_slice(&self) -> &str { Str::as_slice(*self) }
 /// Return type of `StrExt::split`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Split<'a, P: Pattern<'a>>(CharSplits<'a, P>);
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, P: Pattern<'a>> Iterator for Split<'a, P> {
-    type Item = &'a str;
-
-    #[inline]
-    fn next(&mut self) -> Option<&'a str> {
-        self.0.next()
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, P: Pattern<'a>> DoubleEndedIterator for Split<'a, P>
-where P::Searcher: DoubleEndedSearcher<'a> {
-    #[inline]
-    fn next_back(&mut self) -> Option<&'a str> {
-        self.0.next_back()
-    }
-}
+delegate_iter!{pattern &'a str : Split<'a, P>}
 
 /// Return type of `StrExt::split_terminator`
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1321,10 +1476,15 @@ fn next_back(&mut self) -> Option<&'a str> {
 pub struct SplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>);
 delegate_iter!{pattern forward &'a str : SplitN<'a, P>}
 
+/// Return type of `StrExt::rsplit`
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct RSplit<'a, P: Pattern<'a>>(RCharSplits<'a, P>);
+delegate_iter!{pattern reverse &'a str : RSplit<'a, P>}
+
 /// Return type of `StrExt::rsplitn`
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct RSplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>);
-delegate_iter!{pattern forward &'a str : RSplitN<'a, P>}
+pub struct RSplitN<'a, P: Pattern<'a>>(RCharSplitsN<'a, P>);
+delegate_iter!{pattern reverse &'a str : RSplitN<'a, P>}
 
 /// Methods for string slices
 #[allow(missing_docs)]
@@ -1340,7 +1500,10 @@ pub trait StrExt {
     fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P>;
     fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P>;
     fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P>;
-    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>;
+    fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
+        where P::Searcher: ReverseSearcher<'a>;
+    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
+        where P::Searcher: ReverseSearcher<'a>;
     fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P>;
     #[allow(deprecated) /* for SplitStr */]
     fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P>;
@@ -1424,7 +1587,6 @@ fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
         SplitN(CharSplitsN {
             iter: self.split(pat).0,
             count: count,
-            invert: false,
         })
     }
 
@@ -1437,11 +1599,25 @@ fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a,
     }
 
     #[inline]
-    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> {
-        RSplitN(CharSplitsN {
-            iter: self.split(pat).0,
+    fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        RSplit(RCharSplits {
+            start: 0,
+            end: self.len(),
+            matcher: pat.into_searcher(self),
+            allow_final_empty: true,
+            finished: false,
+        })
+    }
+
+    #[inline]
+    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        RSplitN(RCharSplitsN {
+            iter: self.rsplit(pat).0,
             count: count,
-            invert: true,
         })
     }
 
index 7bf248917a5cd20596312e917142777035701041..98b6533980dd913728ff45724e01793ee26d1122 100644 (file)
@@ -474,22 +474,16 @@ impl<'a, 'b> Pattern<'a> for &'b [char] {
                       s, CharEqPattern(s));
 }
 
+/// A convenience impl that delegates to the impl for `&str`
+impl<'a, 'b> Pattern<'a> for &'b &'b str {
+    type Searcher =   <&'b str as Pattern<'a>>::Searcher;
+    associated_items!(<&'b str as Pattern<'a>>::Searcher,
+                      s, (*s));
+}
+
 /// Searches for chars that match the given predicate
 impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
     type Searcher =   <CharEqPattern<Self> as Pattern<'a>>::Searcher;
     associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
                       s, CharEqPattern(s));
 }
-
-// Deref-forward impl
-
-use ops::Deref;
-
-/// Delegates to the next deref coercion of `Self` that implements `Pattern`
-impl<'a, 'b, P: 'b + ?Sized, T: Deref<Target = P> + ?Sized> Pattern<'a> for &'b T
-    where &'b P: Pattern<'a>
-{
-    type Searcher =   <&'b P as Pattern<'a>>::Searcher;
-    associated_items!(<&'b P as Pattern<'a>>::Searcher,
-                      s, (&**s));
-}
index a89d3380707051cbdf8613a9484464f82699d133..38cab4f0e0942440063c16e0bd3b1a3813fd9451 100644 (file)
@@ -13,9 +13,7 @@ fn test_pattern_deref_forward() {
     let data = "aabcdaa";
     assert!(data.contains("bcd"));
     assert!(data.contains(&"bcd"));
-    assert!(data.contains(&&"bcd"));
     assert!(data.contains(&"bcd".to_string()));
-    assert!(data.contains(&&"bcd".to_string()));
 }
 
 #[test]
@@ -35,7 +33,7 @@ fn test_bool_from_str() {
 fn check_contains_all_substrings(s: &str) {
     assert!(s.contains(""));
     for i in 0..s.len() {
-        for j in range(i+1, s.len() + 1) {
+        for j in i+1..s.len() + 1 {
             assert!(s.contains(&s[i..j]));
         }
     }
index 0e0804593443d5d733bb4e16b51fa1939b31d937..6d95d5e07247c1f07209cb55a1da6e00e92d2b98 100644 (file)
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 #![feature(int_uint)]
 #![feature(collections)]
+#![feature(into_cow)]
 
 use self::LabelText::*;
 
index 893781e6220908ae2823a6eda6ac3e86519fa8e1..f9783f40f7b668998c13c378549ec2fc32a929cb 100644 (file)
@@ -2495,10 +2495,24 @@ pub mod bsd44 {
 
             pub const TCP_NODELAY: c_int = 0x0001;
             pub const SOL_SOCKET: c_int = 0xffff;
-            pub const SO_KEEPALIVE: c_int = 8;
-            pub const SO_BROADCAST: c_int = 32;
-            pub const SO_REUSEADDR: c_int = 4;
+
+            pub const SO_DEBUG: c_int = 0x0001;
+            pub const SO_ACCEPTCONN: c_int = 0x0002;
+            pub const SO_REUSEADDR: c_int = 0x0004;
+            pub const SO_KEEPALIVE: c_int = 0x0008;
+            pub const SO_DONTROUTE: c_int = 0x0010;
+            pub const SO_BROADCAST: c_int = 0x0020;
+            pub const SO_USELOOPBACK: c_int = 0x0040;
+            pub const SO_LINGER: c_int = 0x0080;
+            pub const SO_OOBINLINE: c_int = 0x0100;
+            pub const SO_SNDBUF: c_int = 0x1001;
+            pub const SO_RCVBUF: c_int = 0x1002;
+            pub const SO_SNDLOWAT: c_int = 0x1003;
+            pub const SO_RCVLOWAT: c_int = 0x1004;
+            pub const SO_SNDTIMEO: c_int = 0x1005;
+            pub const SO_RCVTIMEO: c_int = 0x1006;
             pub const SO_ERROR: c_int = 0x1007;
+            pub const SO_TYPE: c_int = 0x1008;
 
             pub const IFF_LOOPBACK: c_int = 4;
 
@@ -3441,10 +3455,24 @@ pub mod bsd44 {
 
             pub const TCP_NODELAY: c_int = 1;
             pub const SOL_SOCKET: c_int = 1;
-            pub const SO_KEEPALIVE: c_int = 9;
-            pub const SO_BROADCAST: c_int = 6;
+
+            pub const SO_DEBUG: c_int = 1;
             pub const SO_REUSEADDR: c_int = 2;
+            pub const SO_TYPE: c_int = 3;
             pub const SO_ERROR: c_int = 4;
+            pub const SO_DONTROUTE: c_int = 5;
+            pub const SO_BROADCAST: c_int = 6;
+            pub const SO_SNDBUF: c_int = 7;
+            pub const SO_RCVBUF: c_int = 8;
+            pub const SO_KEEPALIVE: c_int = 9;
+            pub const SO_OOBINLINE: c_int = 10;
+            pub const SO_LINGER: c_int = 13;
+            pub const SO_REUSEPORT: c_int = 15;
+            pub const SO_RCVLOWAT: c_int = 18;
+            pub const SO_SNDLOWAT: c_int = 19;
+            pub const SO_RCVTIMEO: c_int = 20;
+            pub const SO_SNDTIMEO: c_int = 21;
+            pub const SO_ACCEPTCONN: c_int = 30;
 
             pub const SHUT_RD: c_int = 0;
             pub const SHUT_WR: c_int = 1;
@@ -3487,10 +3515,24 @@ pub mod bsd44 {
 
             pub const TCP_NODELAY: c_int = 1;
             pub const SOL_SOCKET: c_int = 65535;
-            pub const SO_KEEPALIVE: c_int = 8;
-            pub const SO_BROADCAST: c_int = 32;
-            pub const SO_REUSEADDR: c_int = 4;
-            pub const SO_ERROR: c_int = 4103;
+
+            pub const SO_DEBUG: c_int = 0x0001;
+            pub const SO_REUSEADDR: c_int = 0x0004;
+            pub const SO_KEEPALIVE: c_int = 0x0008;
+            pub const SO_DONTROUTE: c_int = 0x0010;
+            pub const SO_BROADCAST: c_int = 0x0020;
+            pub const SO_LINGER: c_int = 0x0080;
+            pub const SO_OOBINLINE: c_int = 0x100;
+            pub const SO_REUSEPORT: c_int = 0x0200;
+            pub const SO_SNDBUF: c_int = 0x1001;
+            pub const SO_RCVBUF: c_int = 0x1002;
+            pub const SO_SNDLOWAT: c_int = 0x1003;
+            pub const SO_RCVLOWAT: c_int = 0x1004;
+            pub const SO_SNDTIMEO: c_int = 0x1005;
+            pub const SO_RCVTIMEO: c_int = 0x1006;
+            pub const SO_ERROR: c_int = 0x1007;
+            pub const SO_TYPE: c_int = 0x1008;
+            pub const SO_ACCEPTCONN: c_int = 0x1009;
 
             pub const SHUT_RD: c_int = 0;
             pub const SHUT_WR: c_int = 1;
@@ -4002,10 +4044,24 @@ pub mod bsd44 {
             pub const TCP_NODELAY: c_int = 1;
             pub const TCP_KEEPIDLE: c_int = 256;
             pub const SOL_SOCKET: c_int = 0xffff;
+            pub const SO_DEBUG: c_int = 0x01;
+            pub const SO_ACCEPTCONN: c_int = 0x0002;
+            pub const SO_REUSEADDR: c_int = 0x0004;
             pub const SO_KEEPALIVE: c_int = 0x0008;
+            pub const SO_DONTROUTE: c_int = 0x0010;
             pub const SO_BROADCAST: c_int = 0x0020;
-            pub const SO_REUSEADDR: c_int = 0x0004;
+            pub const SO_USELOOPBACK: c_int = 0x0040;
+            pub const SO_LINGER: c_int = 0x0080;
+            pub const SO_OOBINLINE: c_int = 0x0100;
+            pub const SO_REUSEPORT: c_int = 0x0200;
+            pub const SO_SNDBUF: c_int = 0x1001;
+            pub const SO_RCVBUF: c_int = 0x1002;
+            pub const SO_SNDLOWAT: c_int = 0x1003;
+            pub const SO_RCVLOWAT: c_int = 0x1004;
+            pub const SO_SNDTIMEO: c_int = 0x1005;
+            pub const SO_RCVTIMEO: c_int = 0x1006;
             pub const SO_ERROR: c_int = 0x1007;
+            pub const SO_TYPE: c_int = 0x1008;
 
             pub const IFF_LOOPBACK: c_int = 0x8;
 
@@ -4403,10 +4459,24 @@ pub mod bsd44 {
 
             pub const TCP_NODELAY: c_int = 0x01;
             pub const SOL_SOCKET: c_int = 0xffff;
+            pub const SO_DEBUG: c_int = 0x01;
+            pub const SO_ACCEPTCONN: c_int = 0x0002;
+            pub const SO_REUSEADDR: c_int = 0x0004;
             pub const SO_KEEPALIVE: c_int = 0x0008;
+            pub const SO_DONTROUTE: c_int = 0x0010;
             pub const SO_BROADCAST: c_int = 0x0020;
-            pub const SO_REUSEADDR: c_int = 0x0004;
+            pub const SO_USELOOPBACK: c_int = 0x0040;
+            pub const SO_LINGER: c_int = 0x0080;
+            pub const SO_OOBINLINE: c_int = 0x0100;
+            pub const SO_REUSEPORT: c_int = 0x0200;
+            pub const SO_SNDBUF: c_int = 0x1001;
+            pub const SO_RCVBUF: c_int = 0x1002;
+            pub const SO_SNDLOWAT: c_int = 0x1003;
+            pub const SO_RCVLOWAT: c_int = 0x1004;
+            pub const SO_SNDTIMEO: c_int = 0x1005;
+            pub const SO_RCVTIMEO: c_int = 0x1006;
             pub const SO_ERROR: c_int = 0x1007;
+            pub const SO_TYPE: c_int = 0x1008;
 
             pub const IFF_LOOPBACK: c_int = 0x8;
 
@@ -4820,10 +4890,25 @@ pub mod bsd44 {
             pub const TCP_NODELAY: c_int = 0x01;
             pub const TCP_KEEPALIVE: c_int = 0x10;
             pub const SOL_SOCKET: c_int = 0xffff;
+
+            pub const SO_DEBUG: c_int = 0x01;
+            pub const SO_ACCEPTCONN: c_int = 0x0002;
+            pub const SO_REUSEADDR: c_int = 0x0004;
             pub const SO_KEEPALIVE: c_int = 0x0008;
+            pub const SO_DONTROUTE: c_int = 0x0010;
             pub const SO_BROADCAST: c_int = 0x0020;
-            pub const SO_REUSEADDR: c_int = 0x0004;
+            pub const SO_USELOOPBACK: c_int = 0x0040;
+            pub const SO_LINGER: c_int = 0x0080;
+            pub const SO_OOBINLINE: c_int = 0x0100;
+            pub const SO_REUSEPORT: c_int = 0x0200;
+            pub const SO_SNDBUF: c_int = 0x1001;
+            pub const SO_RCVBUF: c_int = 0x1002;
+            pub const SO_SNDLOWAT: c_int = 0x1003;
+            pub const SO_RCVLOWAT: c_int = 0x1004;
+            pub const SO_SNDTIMEO: c_int = 0x1005;
+            pub const SO_RCVTIMEO: c_int = 0x1006;
             pub const SO_ERROR: c_int = 0x1007;
+            pub const SO_TYPE: c_int = 0x1008;
 
             pub const IFF_LOOPBACK: c_int = 0x8;
 
@@ -4849,6 +4934,15 @@ pub mod extra {
             pub const MAP_STACK : c_int = 0;
 
             pub const IPPROTO_RAW : c_int = 255;
+
+            pub const SO_NREAD: c_int = 0x1020;
+            pub const SO_NKE: c_int = 0x1021;
+            pub const SO_NOSIGPIPE: c_int = 0x1022;
+            pub const SO_NOADDRERR: c_int = 0x1023;
+            pub const SO_NWRITE: c_int = 0x1024;
+            pub const SO_DONTTRUNC: c_int = 0x2000;
+            pub const SO_WANTMORE: c_int = 0x4000;
+            pub const SO_WANTOOBFLAG: c_int = 0x8000;
         }
         pub mod sysconf {
             use types::os::arch::c95::c_int;
diff --git a/src/librustc/README.md b/src/librustc/README.md
new file mode 100644 (file)
index 0000000..31812e1
--- /dev/null
@@ -0,0 +1,128 @@
+An informal guide to reading and working on the rustc compiler.
+==================================================================
+
+If you wish to expand on this document, or have a more experienced
+Rust contributor add anything else to it, please get in touch:
+
+* http://internals.rust-lang.org/
+* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
+
+or file a bug:
+
+https://github.com/rust-lang/rust/issues
+
+Your concerns are probably the same as someone else's.
+
+The crates of rustc
+===================
+
+Rustc consists of a number of crates, including `libsyntax`,
+`librustc`, `librustc_back`, `librustc_trans`, and `librustc_driver`
+(the names and divisions are not set in stone and may change;
+in general, a finer-grained division of crates is preferable):
+
+- `libsyntax` contains those things concerned purely with syntax –
+  that is, the AST, parser, pretty-printer, lexer, macro expander, and
+  utilities for traversing ASTs – are in a separate crate called
+  "syntax", whose files are in `./../libsyntax`, where `.` is the
+  current directory (that is, the parent directory of front/, middle/,
+  back/, and so on).
+
+- `librustc` (the current directory) contains the high-level analysis
+  passes, such as the type checker, borrow checker, and so forth.
+  It is the heart of the compiler.
+
+- `librustc_back` contains some very low-level details that are
+  specific to different LLVM targets and so forth.
+
+- `librustc_trans` contains the code to convert from Rust IR into LLVM
+  IR, and then from LLVM IR into machine code, as well as the main
+  driver that orchestrates all the other passes and various other bits
+  of miscellany. In general it contains code that runs towards the
+  end of the compilation process.
+
+- `librustc_driver` invokes the compiler from `libsyntax`, then the
+  analysis phases from `librustc`, and finally the lowering and
+  codegen passes from `librustc_trans`.
+
+Roughly speaking the "order" of the three crates is as follows:
+
+    libsyntax -> librustc -> librustc_trans
+    |                                     |
+    +-----------------+-------------------+
+                      |
+              librustc_driver
+
+
+Modules in the rustc crate
+==========================
+
+The rustc crate itself consists of the following submodules
+(mostly, but not entirely, in their own directories):
+
+- session: options and data that pertain to the compilation session as
+  a whole
+- middle: middle-end: name resolution, typechecking, LLVM code
+  generation
+- metadata: encoder and decoder for data required by separate
+  compilation
+- plugin: infrastructure for compiler plugins
+- lint: infrastructure for compiler warnings
+- util: ubiquitous types and helper functions
+- lib: bindings to LLVM
+
+The entry-point for the compiler is main() in the librustc_trans
+crate.
+
+The 3 central data structures:
+------------------------------
+
+1. `./../libsyntax/ast.rs` defines the AST. The AST is treated as
+   immutable after parsing, but it depends on mutable context data
+   structures (mainly hash maps) to give it meaning.
+
+   - Many – though not all – nodes within this data structure are
+     wrapped in the type `spanned<T>`, meaning that the front-end has
+     marked the input coordinates of that node. The member `node` is
+     the data itself, the member `span` is the input location (file,
+     line, column; both low and high).
+
+   - Many other nodes within this data structure carry a
+     `def_id`. These nodes represent the 'target' of some name
+     reference elsewhere in the tree. When the AST is resolved, by
+     `middle/resolve.rs`, all names wind up acquiring a def that they
+     point to. So anything that can be pointed-to by a name winds
+     up with a `def_id`.
+
+2. `middle/ty.rs` defines the datatype `sty`. This is the type that
+   represents types after they have been resolved and normalized by
+   the middle-end. The typeck phase converts every ast type to a
+   `ty::sty`, and the latter is used to drive later phases of
+   compilation. Most variants in the `ast::ty` tag have a
+   corresponding variant in the `ty::sty` tag.
+
+3. `./../librustc_llvm/lib.rs` defines the exported types
+   `ValueRef`, `TypeRef`, `BasicBlockRef`, and several others.
+   Each of these is an opaque pointer to an LLVM type,
+   manipulated through the `lib::llvm` interface.
+
+
+Control and information flow within the compiler:
+-------------------------------------------------
+
+- main() in lib.rs assumes control on startup. Options are
+  parsed, platform is detected, etc.
+
+- `./../libsyntax/parse/parser.rs` parses the input files and produces
+  an AST that represents the input crate.
+
+- Multiple middle-end passes (`middle/resolve.rs`, `middle/typeck.rs`)
+  analyze the semantics of the resulting AST. Each pass generates new
+  information about the AST and stores it in various environment data
+  structures. The driver passes environments to each compiler pass
+  that needs to refer to them.
+
+- Finally, the `trans` module in `librustc_trans` translates the Rust
+  AST to LLVM bitcode in a type-directed way. When it's finished
+  synthesizing LLVM values, rustc asks LLVM to write them out in some
+  form (`.bc`, `.o`) and possibly run the system linker.
diff --git a/src/librustc/README.txt b/src/librustc/README.txt
deleted file mode 100644 (file)
index 9b36476..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-An informal guide to reading and working on the rustc compiler.
-==================================================================
-
-If you wish to expand on this document, or have a more experienced
-Rust contributor add anything else to it, please get in touch:
-
-* http://internals.rust-lang.org/
-* https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
-
-or file a bug:
-
-https://github.com/rust-lang/rust/issues
-
-Your concerns are probably the same as someone else's.
-
-The crates of rustc
-===================
-
-Rustc consists of four crates altogether: `libsyntax`, `librustc`,
-`librustc_back`, and `librustc_trans` (the names and divisions are not
-set in stone and may change; in general, a finer-grained division of
-crates is preferable):
-
-- `libsyntax` contains those things concerned purely with syntax --
-  that is, the AST, parser, pretty-printer, lexer, macro expander, and
-  utilities for traversing ASTs -- are in a separate crate called
-  "syntax", whose files are in ./../libsyntax, where . is the current
-  directory (that is, the parent directory of front/, middle/, back/,
-  and so on).
-
-- `librustc` (the current directory) contains the high-level analysis
-  passes, such as the type checker, borrow checker, and so forth.
-  It is the heart of the compiler.
-
-- `librustc_back` contains some very low-level details that are
-  specific to different LLVM targets and so forth.
-
-- `librustc_trans` contains the code to convert from Rust IR into LLVM
-  IR, and then from LLVM IR into machine code, as well as the main
-  driver that orchestrates all the other passes and various other bits
-  of miscellany. In general it contains code that runs towards the
-  end of the compilation process.
-
-Roughly speaking the "order" of the three crates is as follows:
-
-    libsyntax -> librustc -> librustc_trans
-    |                                     |
-    +-----------------+-------------------+
-                      |
-             librustc_trans/driver
-
-Here the role of `librustc_trans/driver` is to invoke the compiler
-from libsyntax, then the analysis phases from librustc, and finally
-the lowering and codegen passes from librustc_trans.
-
-Modules in the rustc crate
-==========================
-
-The rustc crate itself consists of the following subdirectories
-(mostly, but not entirely, in their own directories):
-
-session  - options and data that pertain to the compilation session as a whole
-middle   - middle-end: name resolution, typechecking, LLVM code
-                  generation
-metadata - encoder and decoder for data required by
-                    separate compilation
-util     - ubiquitous types and helper functions
-lib      - bindings to LLVM
-
-The entry-point for the compiler is main() in the librustc_trans
-crate.
-
-The 3 central data structures:
-------------------------------
-
-#1: ./../libsyntax/ast.rs defines the AST. The AST is treated as immutable
-    after parsing, but it depends on mutable context data structures
-    (mainly hash maps) to give it meaning.
-
-      - Many -- though not all -- nodes within this data structure are
-        wrapped in the type `spanned<T>`, meaning that the front-end has
-        marked the input coordinates of that node. The member .node is
-        the data itself, the member .span is the input location (file,
-        line, column; both low and high).
-
-      - Many other nodes within this data structure carry a
-        def_id. These nodes represent the 'target' of some name
-        reference elsewhere in the tree. When the AST is resolved, by
-        middle/resolve.rs, all names wind up acquiring a def that they
-        point to. So anything that can be pointed-to by a name winds
-        up with a def_id.
-
-#2: middle/ty.rs defines the datatype sty.  This is the type that
-    represents types after they have been resolved and normalized by
-    the middle-end. The typeck phase converts every ast type to a
-    ty::sty, and the latter is used to drive later phases of
-    compilation.  Most variants in the ast::ty tag have a
-    corresponding variant in the ty::sty tag.
-
-#3: lib/llvm.rs (in librustc_trans) defines the exported types
-    ValueRef, TypeRef, BasicBlockRef, and several others. Each of
-    these is an opaque pointer to an LLVM type, manipulated through
-    the lib::llvm interface.
-
-
-Control and information flow within the compiler:
--------------------------------------------------
-
-- main() in lib.rs assumes control on startup. Options are
-  parsed, platform is detected, etc.
-
-- ./../libsyntax/parse/parser.rs parses the input files and produces an AST
-  that represents the input crate.
-
-- Multiple middle-end passes (middle/resolve.rs, middle/typeck.rs)
-  analyze the semantics of the resulting AST. Each pass generates new
-  information about the AST and stores it in various environment data
-  structures. The driver passes environments to each compiler pass
-  that needs to refer to them.
-
-- Finally, the `trans` module in `librustc_trans` translates the Rust
-  AST to LLVM bitcode in a type-directed way. When it's finished
-  synthesizing LLVM values, rustc asks LLVM to write them out in some
-  form (.bc, .o) and possibly run the system linker.
index 97ed391fdfc7842470d6ba283928c6f6bf0f6369..793eff6a9da6fc9763c02e68a72ee7ccecd5a5f6 100644 (file)
@@ -43,6 +43,8 @@
 #![feature(path_ext)]
 #![feature(str_words)]
 #![feature(str_char)]
+#![feature(convert)]
+#![feature(into_cow)]
 #![cfg_attr(test, feature(test))]
 
 extern crate arena;
index 47ec31c0f1ab7d0c26b7d366282cf54d368121b9..f201ff374ea0f058db497bebce436a4dc34d06ea 100644 (file)
@@ -111,7 +111,7 @@ pub fn next_crate_num(&self) -> ast::CrateNum {
     }
 
     pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<crate_metadata> {
-        (*self.metas.borrow())[cnum].clone()
+        self.metas.borrow().get(&cnum).unwrap().clone()
     }
 
     pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
@@ -243,7 +243,7 @@ pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
 impl MetadataBlob {
     pub fn as_slice<'a>(&'a self) -> &'a [u8] {
         let slice = match *self {
-            MetadataVec(ref vec) => vec.as_slice(),
+            MetadataVec(ref vec) => &vec[..],
             MetadataArchive(ref ar) => ar.as_slice(),
         };
         if slice.len() < 4 {
index 10461e3d2aedfc38b2f51f9a0bd78f6fe97e5bde..fa8d0b2a56e4ee34b8e062ed0bac19948f730897 100644 (file)
@@ -375,7 +375,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
     match ecx.tcx.inherent_impls.borrow().get(&exp.def_id) {
         Some(implementations) => {
             for base_impl_did in &**implementations {
-                for &method_did in &*(*impl_items)[*base_impl_did] {
+                for &method_did in impl_items.get(base_impl_did).unwrap() {
                     let impl_item = ty::impl_or_trait_item(
                         ecx.tcx,
                         method_did.def_id());
@@ -1175,7 +1175,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
         let impl_items = tcx.impl_items.borrow();
-        let items = &(*impl_items)[def_id];
+        let items = impl_items.get(&def_id).unwrap();
 
         add_to_index(item, rbml_w, index);
         rbml_w.start_tag(tag_items_data_item);
@@ -1816,7 +1816,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
         if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
-            let def_id = self.ecx.tcx.def_map.borrow()[trait_ref.ref_id].def_id();
+            let def_id = self.ecx.tcx.def_map.borrow().get(&trait_ref.ref_id).unwrap().def_id();
 
             // Load eagerly if this is an implementation of the Drop trait
             // or if the trait is not defined in this crate.
index 22a4a6fc978dc055a9a79ae360b03c0d51feca7e..284e76b328a6912323692c82f0f6180e8f29f97e 100644 (file)
@@ -156,7 +156,7 @@ pub fn get_dylib_search_paths(&self) -> Vec<PathBuf> {
 
     // Returns a list of directories where target-specific tool binaries are located.
     pub fn get_tools_search_paths(&self) -> Vec<PathBuf> {
-        let mut p = PathBuf::new(self.sysroot);
+        let mut p = PathBuf::from(self.sysroot);
         p.push(&find_libdir(self.sysroot));
         p.push(&rustlibdir());
         p.push(&self.triple);
@@ -166,7 +166,7 @@ pub fn get_tools_search_paths(&self) -> Vec<PathBuf> {
 }
 
 pub fn relative_target_lib_path(sysroot: &Path, target_triple: &str) -> PathBuf {
-    let mut p = PathBuf::new(&find_libdir(sysroot));
+    let mut p = PathBuf::from(&find_libdir(sysroot));
     assert!(p.is_relative());
     p.push(&rustlibdir());
     p.push(target_triple);
@@ -224,7 +224,7 @@ pub fn rust_path() -> Vec<PathBuf> {
         Some(env_path) => {
             let env_path_components =
                 env_path.split(PATH_ENTRY_SEPARATOR);
-            env_path_components.map(|s| PathBuf::new(s)).collect()
+            env_path_components.map(|s| PathBuf::from(s)).collect()
         }
         None => Vec::new()
     };
index e466dc8a3a0181db8a7a3b99983fdffe748e5ea4..7854db811466517bbd3f675ab3ac0e80b9edc643 100644 (file)
@@ -628,7 +628,7 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
         let mut rlibs = HashMap::new();
         let mut dylibs = HashMap::new();
         {
-            let locs = locs.iter().map(|l| PathBuf::new(&l[..])).filter(|loc| {
+            let locs = locs.iter().map(|l| PathBuf::from(l)).filter(|loc| {
                 if !loc.exists() {
                     sess.err(&format!("extern location for {} does not exist: {}",
                                      self.crate_name, loc.display()));
index 8b2a94025f337441a3fa44b86d7e9d4dd549b228..801350e8a1e9c1d50d29d9f28d66f9c7add566ad 100644 (file)
@@ -43,6 +43,7 @@
 use std::io::prelude::*;
 use std::num::FromPrimitive;
 use std::rc::Rc;
+use std::fmt::Debug;
 
 use rbml::reader;
 use rbml::writer::Encoder;
@@ -313,9 +314,11 @@ trait def_id_encoder_helpers {
     fn emit_def_id(&mut self, did: ast::DefId);
 }
 
-impl<S:serialize::Encoder> def_id_encoder_helpers for S {
+impl<S:serialize::Encoder> def_id_encoder_helpers for S
+    where <S as serialize::serialize::Encoder>::Error: Debug
+{
     fn emit_def_id(&mut self, did: ast::DefId) {
-        did.encode(self).ok().unwrap()
+        did.encode(self).unwrap()
     }
 }
 
@@ -325,15 +328,18 @@ fn read_def_id_nodcx(&mut self,
                          cdata: &cstore::crate_metadata) -> ast::DefId;
 }
 
-impl<D:serialize::Decoder> def_id_decoder_helpers for D {
+impl<D:serialize::Decoder> def_id_decoder_helpers for D
+    where <D as serialize::serialize::Decoder>::Error: Debug
+{
     fn read_def_id(&mut self, dcx: &DecodeContext) -> ast::DefId {
-        let did: ast::DefId = Decodable::decode(self).ok().unwrap();
+        let did: ast::DefId = Decodable::decode(self).unwrap();
         did.tr(dcx)
     }
 
     fn read_def_id_nodcx(&mut self,
-                         cdata: &cstore::crate_metadata) -> ast::DefId {
-        let did: ast::DefId = Decodable::decode(self).ok().unwrap();
+                         cdata: &cstore::crate_metadata)
+                         -> ast::DefId {
+        let did: ast::DefId = Decodable::decode(self).unwrap();
         decoder::translate_def_id(cdata, did)
     }
 }
@@ -1222,7 +1228,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
                     var_id: var_id,
                     closure_expr_id: id
                 };
-                let upvar_capture = tcx.upvar_capture_map.borrow()[upvar_id].clone();
+                let upvar_capture = tcx.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone();
                 var_id.encode(rbml_w);
                 upvar_capture.encode(rbml_w);
             })
@@ -1784,7 +1790,7 @@ fn read_unsize_kind<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
     fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
                                  -> ty::ClosureKind
     {
-        Decodable::decode(self).ok().unwrap()
+        Decodable::decode(self).unwrap()
     }
 
     fn read_closure_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
index ac6524dad805792385953260aac1d9c850ed84ec..3a6966ab112905bee06966be07b48ff0c911175c 100644 (file)
@@ -54,10 +54,10 @@ fn replace_newline_with_backslash_l(s: String) -> String {
 }
 
 impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
-    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).ok().unwrap() }
+    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).unwrap() }
 
     fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
-        dot::Id::new(format!("N{}", i.node_id())).ok().unwrap()
+        dot::Id::new(format!("N{}", i.node_id())).unwrap()
     }
 
     fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
index 496c96c7c8adc1dd5bebd412b258c7a352db670d..97cd9456098b1bbab4fb5b8947975d9d46af1399 100644 (file)
@@ -874,7 +874,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         }
 
         ast::PatEnum(_, ref args) => {
-            let def = cx.tcx.def_map.borrow()[pat_id].full_def();
+            let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
                 DefConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@@ -892,7 +892,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
 
         ast::PatStruct(_, ref pattern_fields, _) => {
             // Is this a struct or an enum variant?
-            let def = cx.tcx.def_map.borrow()[pat_id].full_def();
+            let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             let class_id = match def {
                 DefConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
index 96433729a9b96ff675d29d4d7f8183b3a380cf4c..f9598237ff460805cc0494475f97820ff385fb3d 100644 (file)
@@ -150,7 +150,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
 
         ast::ExprCall(ref callee, ref args) => {
-            let def = tcx.def_map.borrow()[callee.id];
+            let def = *tcx.def_map.borrow().get(&callee.id).unwrap();
             if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
                entry.insert(def);
             }
index 5efea66ab0c6cc751cff9f1550057df4657780f7..6d4d759476ed5330edde04b58b498f294dc99498 100644 (file)
@@ -158,7 +158,7 @@ fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: uint) {
 
     fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
                                   pats: &[codemap::Spanned<ast::FieldPat>]) {
-        let id = match self.tcx.def_map.borrow()[lhs.id].full_def() {
+        let id = match self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def() {
             def::DefVariant(_, id, _) => id,
             _ => {
                 match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
@@ -496,7 +496,7 @@ fn symbol_is_live(&mut self, id: ast::NodeId,
             None => (),
             Some(impl_list) => {
                 for impl_did in &**impl_list {
-                    for item_did in &(*impl_items)[*impl_did] {
+                    for item_did in &*impl_items.get(impl_did).unwrap() {
                         if self.live_symbols.contains(&item_did.def_id()
                                                                .node) {
                             return true;
index 378f3db0823391064cc40409021c97497134dddd..5d970c59f639bd5e3b4a289a7419ce7ddb52dfd0 100644 (file)
@@ -141,7 +141,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
         match expr.node {
             ast::ExprMethodCall(_, _, _) => {
                 let method_call = MethodCall::expr(expr.id);
-                let base_type = (*self.tcx.method_map.borrow())[method_call].ty;
+                let base_type = self.tcx.method_map.borrow().get(&method_call).unwrap().ty;
                 debug!("effect: method call case, base type is {}",
                        ppaux::ty_to_string(self.tcx, base_type));
                 if type_is_unsafe_function(base_type) {
index 6d2392054f9d578efd6786583c204d89302d00c0..97314b57ef656802a6b773495566051c7a27978c 100644 (file)
@@ -442,7 +442,7 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
                 if !self.walk_overloaded_operator(expr,
                                                   &**lhs,
                                                   vec![&**rhs],
-                                                  PassArgs::ByRef) {
+                                                  PassArgs::ByValue) {
                     self.select_from_expr(&**lhs);
                     self.consume_expr(&**rhs);
                 }
@@ -1012,7 +1012,7 @@ fn walk_pat(&mut self,
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
-                let def = def_map.borrow()[pat.id].full_def();
+                let def = def_map.borrow().get(&pat.id).unwrap().full_def();
                 match mc.cat_def(pat.id, pat.span, pat_ty, def) {
                     Ok(binding_cmt) => {
                         delegate.mutate(pat.id, pat.span, binding_cmt, Init);
index 94c9699e30cc42ad73d545f3471c3a18b1a91616..930e95d1f939a474590138324dbacc9dd1b5dac7 100644 (file)
@@ -557,18 +557,7 @@ pub fn super_tys<'tcx, C>(this: &C,
 
         (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
             let r = try!(this.regions_with_variance(ty::Contravariant, *a_r, *b_r));
-
-            // FIXME(14985)  If we have mutable references to trait objects, we
-            // used to use covariant subtyping. I have preserved this behaviour,
-            // even though it is probably incorrect. So don't go down the usual
-            // path which would require invariance.
-            let mt = match (&a_mt.ty.sty, &b_mt.ty.sty) {
-                (&ty::ty_trait(..), &ty::ty_trait(..)) if a_mt.mutbl == b_mt.mutbl => {
-                    let ty = try!(this.tys(a_mt.ty, b_mt.ty));
-                    ty::mt { ty: ty, mutbl: a_mt.mutbl }
-                }
-                _ => try!(this.mts(a_mt, b_mt))
-            };
+            let mt = try!(this.mts(a_mt, b_mt));
             Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
         }
 
index 6211fde79198af387731e8c3840abedef50a42b3..5be3310926c8764efa6ca14d2bc42a43070428e3 100644 (file)
@@ -69,13 +69,13 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
         return;
     }
 
-    let requested_output = env::var("RUST_REGION_GRAPH").ok();
+    let requested_output = env::var("RUST_REGION_GRAPH");
     debug!("requested_output: {:?} requested_node: {:?}",
            requested_output, requested_node);
 
     let output_path = {
         let output_template = match requested_output {
-            Some(ref s) if &**s == "help" => {
+            Ok(ref s) if &**s == "help" => {
                 static PRINTED_YET: AtomicBool = ATOMIC_BOOL_INIT;
                 if !PRINTED_YET.load(Ordering::SeqCst) {
                     print_help_message();
@@ -84,8 +84,8 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
                 return;
             }
 
-            Some(other_path) => other_path,
-            None => "/tmp/constraints.node%.dot".to_string(),
+            Ok(other_path) => other_path,
+            Err(_) => "/tmp/constraints.node%.dot".to_string(),
         };
 
         if output_template.len() == 0 {
@@ -171,7 +171,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
 
 impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
     fn graph_id(&self) -> dot::Id {
-        dot::Id::new(&*self.graph_name).ok().unwrap()
+        dot::Id::new(&*self.graph_name).unwrap()
     }
     fn node_id(&self, n: &Node) -> dot::Id {
         let node_id = match self.node_ids.get(n) {
index 759d7357df1931d71b0843e61594c2dd4624cbcb..553e3601806677ed1bc37f4ba22ddc4a9fbe7a3e 100644 (file)
@@ -1533,7 +1533,7 @@ fn process_edges<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
                     ConstrainVarSubReg(_, region) => {
                         state.result.push(RegionAndOrigin {
                             region: region,
-                            origin: this.constraints.borrow()[edge.data].clone()
+                            origin: this.constraints.borrow().get(&edge.data).unwrap().clone()
                         });
                     }
                 }
index 932c9c61ef1fbb53ef4006201de88feea96f0f31..705f20559afde27711c2c0934f7aba5c68aa5df0 100644 (file)
@@ -448,7 +448,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
       ast::ExprPath(..) => {
-        let def = ir.tcx.def_map.borrow()[expr.id].full_def();
+        let def = ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let DefLocal(..) = def {
             ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@@ -1302,7 +1302,7 @@ fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
 
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
                    -> LiveNode {
-        match self.ir.tcx.def_map.borrow()[expr.id].full_def() {
+        match self.ir.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
           DefLocal(nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0 {
@@ -1564,7 +1564,9 @@ fn check_ret(&self,
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
             ast::ExprPath(..) => {
-                if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() {
+                if let DefLocal(nid) = self.ir.tcx.def_map.borrow().get(&expr.id)
+                                                                   .unwrap()
+                                                                   .full_def() {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
index 5237a86ebb6300f5c76f16a32587b866d51edd34..bdcfc67f92b997a370cad0693f2eab1f729c626f 100644 (file)
@@ -531,7 +531,7 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
           }
 
           ast::ExprPath(..) => {
-            let def = self.tcx().def_map.borrow()[expr.id].full_def();
+            let def = self.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
 
index c5abff3b96360bceaa9ca8b8d8124e02ad4fb08e..4f365beed213f2a44f57d238779cb69d84cebcd7 100644 (file)
@@ -119,6 +119,24 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
     contains_bindings
 }
 
+/// Checks if the pattern contains any `ref` or `ref mut` bindings.
+pub fn pat_contains_ref_binding(dm: &DefMap, pat: &ast::Pat) -> bool {
+    let mut result = false;
+    pat_bindings(dm, pat, |mode, _, _, _| {
+        match mode {
+            ast::BindingMode::BindByRef(_) => { result = true; }
+            ast::BindingMode::BindByValue(_) => { }
+        }
+    });
+    result
+}
+
+/// Checks if the patterns for this arm contain any `ref` or `ref mut`
+/// bindings.
+pub fn arm_contains_ref_binding(dm: &DefMap, arm: &ast::Arm) -> bool {
+    arm.pats.iter().any(|pat| pat_contains_ref_binding(dm, pat))
+}
+
 /// Checks if the pattern contains any patterns that bind something to
 /// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
 pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
index 7ded344414ce698bf328818b6ea1ef645553bd0d..1bd45b5fc86017cd5a8afea2c994c2e181397d9e 100644 (file)
@@ -128,7 +128,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
             }
             ast::ExprMethodCall(..) => {
                 let method_call = ty::MethodCall::expr(expr.id);
-                match (*self.tcx.method_map.borrow())[method_call].origin {
+                match (*self.tcx.method_map.borrow()).get(&method_call).unwrap().origin {
                     ty::MethodStatic(def_id) => {
                         if is_local(def_id) {
                             if self.def_id_represents_local_inlined_item(def_id) {
index 01766b0de085f0c4d32d5f2b70aec2a3d6257366..d12b737619c8db4d1086a2dab3422f346ff8bb39 100644 (file)
@@ -319,7 +319,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
         // individually as it's possible to have a stable trait with unstable
         // items.
         ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
-            let trait_did = tcx.def_map.borrow()[t.ref_id].def_id();
+            let trait_did = tcx.def_map.borrow().get(&t.ref_id).unwrap().def_id();
             let trait_items = ty::trait_items(tcx, trait_did);
 
             for impl_item in impl_items {
index d2b5b460d142002b174a88910a9972944f3f7316..d10ff060418ccb05cdca1061c2e816224c9fbacf 100644 (file)
@@ -12,6 +12,7 @@
     FulfillmentError,
     FulfillmentErrorCode,
     MismatchedProjectionTypes,
+    Obligation,
     ObligationCauseCode,
     OutputTypeParameterMismatch,
     PredicateObligation,
@@ -21,6 +22,7 @@
 use fmt_macros::{Parser, Piece, Position};
 use middle::infer::InferCtxt;
 use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef};
+use middle::ty_fold::TypeFoldable;
 use std::collections::HashMap;
 use syntax::codemap::{DUMMY_SP, Span};
 use syntax::attr::{AttributeMethods, AttrMetaMethods};
@@ -137,24 +139,36 @@ trait definition for {} must have a value, \
     report
 }
 
+/// Reports that an overflow has occurred and halts compilation. We
+/// halt compilation unconditionally because it is important that
+/// overflows never be masked -- they basically represent computations
+/// whose result could not be truly determined and thus we can't say
+/// if the program type checks or not -- and they are unusual
+/// occurrences in any case.
+pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+                                          obligation: &Obligation<'tcx, T>)
+                                          -> !
+    where T: UserString<'tcx> + TypeFoldable<'tcx>
+{
+    let predicate =
+        infcx.resolve_type_vars_if_possible(&obligation.predicate);
+    span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
+              "overflow evaluating the requirement `{}`",
+              predicate.user_string(infcx.tcx));
+
+    suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
+
+    note_obligation_cause(infcx, obligation);
+
+    infcx.tcx.sess.abort_if_errors();
+    unreachable!();
+}
+
 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                         obligation: &PredicateObligation<'tcx>,
                                         error: &SelectionError<'tcx>)
 {
     match *error {
-        SelectionError::Overflow => {
-            // We could track the stack here more precisely if we wanted, I imagine.
-            let predicate =
-                infcx.resolve_type_vars_if_possible(&obligation.predicate);
-            span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
-                    "overflow evaluating the requirement `{}`",
-                    predicate.user_string(infcx.tcx));
-
-            suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
-
-            note_obligation_cause(infcx, obligation);
-        }
-
         SelectionError::Unimplemented => {
             match &obligation.cause.code {
                 &ObligationCauseCode::CompareImplMethodObligation => {
@@ -309,8 +323,9 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
-fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                   obligation: &PredicateObligation<'tcx>)
+fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+                                      obligation: &Obligation<'tcx, T>)
+    where T: UserString<'tcx>
 {
     note_obligation_cause_code(infcx,
                                &obligation.predicate,
@@ -318,10 +333,11 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                &obligation.cause.code);
 }
 
-fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        predicate: &ty::Predicate<'tcx>,
-                                        cause_span: Span,
-                                        cause_code: &ObligationCauseCode<'tcx>)
+fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
+                                           predicate: &T,
+                                           cause_span: Span,
+                                           cause_code: &ObligationCauseCode<'tcx>)
+    where T: UserString<'tcx>
 {
     let tcx = infcx.tcx;
     match *cause_code {
index f46cac308287ba769d34378ddc19421d5aee3233..24b201c960f16ffe001b9914c2010b81170e4946 100644 (file)
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
-use util::ppaux::{Repr, UserString};
+use util::ppaux::Repr;
 
 pub use self::error_reporting::report_fulfillment_errors;
+pub use self::error_reporting::report_overflow_error;
 pub use self::error_reporting::suggest_new_overflow_limit;
 pub use self::coherence::orphan_check;
 pub use self::coherence::overlapping_impls;
@@ -151,7 +152,6 @@ pub struct DerivedObligationCause<'tcx> {
 #[derive(Clone,Debug)]
 pub enum SelectionError<'tcx> {
     Unimplemented,
-    Overflow,
     OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
                                 ty::PolyTraitRef<'tcx>,
                                 ty::type_err<'tcx>),
@@ -327,16 +327,9 @@ pub fn evaluate_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     let result = match fulfill_cx.select_all_or_error(infcx, typer) {
         Ok(()) => Ok(Some(())), // Success, we know it implements Copy.
         Err(errors) => {
-            // Check if overflow occurred anywhere and propagate that.
-            if errors.iter().any(
-                |err| match err.code { CodeSelectionError(Overflow) => true, _ => false })
-            {
-                return Err(Overflow);
-            }
-
-            // Otherwise, if there were any hard errors, propagate an
-            // arbitrary one of those. If no hard errors at all,
-            // report ambiguity.
+            // If there were any hard errors, propagate an arbitrary
+            // one of those. If no hard errors at all, report
+            // ambiguity.
             let sel_error =
                 errors.iter()
                       .filter_map(|err| {
@@ -384,16 +377,8 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
             // soldering on, so just treat this like not implemented
             false
         }
-        Err(Overflow) => {
-            span_err!(infcx.tcx.sess, span, E0285,
-                "overflow evaluating whether `{}` is `{}`",
-                      ty.user_string(infcx.tcx),
-                      bound.user_string(infcx.tcx));
-            suggest_new_overflow_limit(infcx.tcx, span);
-            false
-        }
         Err(_) => {
-            // other errors: not implemented.
+            // errors: not implemented.
             false
         }
     }
@@ -652,15 +637,6 @@ fn new(obligation: PredicateObligation<'tcx>,
     {
         FulfillmentError { obligation: obligation, code: code }
     }
-
-    pub fn is_overflow(&self) -> bool {
-        match self.code {
-            CodeAmbiguity => false,
-            CodeSelectionError(Overflow) => true,
-            CodeSelectionError(_) => false,
-            CodeProjectionError(_) => false,
-        }
-    }
 }
 
 impl<'tcx> TraitObligation<'tcx> {
index 6b66d7227d300d00ca6e4280ebf7ea778b69d18c..92d54887308d645e1de0e11c96b388aca2721060 100644 (file)
@@ -11,9 +11,9 @@
 //! Code for projecting associated types out of trait references.
 
 use super::elaborate_predicates;
+use super::report_overflow_error;
 use super::Obligation;
 use super::ObligationCause;
-use super::Overflow;
 use super::PredicateObligation;
 use super::SelectionContext;
 use super::SelectionError;
@@ -442,7 +442,7 @@ fn project_type<'cx,'tcx>(
     let recursion_limit = selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
-        return Err(ProjectionTyError::TraitSelectionError(Overflow));
+        report_overflow_error(selcx.infcx(), &obligation);
     }
 
     let obligation_trait_ref =
@@ -854,10 +854,10 @@ fn confirm_impl_candidate<'cx,'tcx>(
     let impl_items_map = selcx.tcx().impl_items.borrow();
     let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow();
 
-    let impl_items = &impl_items_map[impl_vtable.impl_def_id];
+    let impl_items = impl_items_map.get(&impl_vtable.impl_def_id).unwrap();
     let mut impl_ty = None;
     for impl_item in impl_items {
-        let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] {
+        let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() {
             ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
             ty::MethodTraitItem(..) => { continue; }
         };
index 7dfbccea0dccd160f4c8ecfb6a0470083d6c28c1..9878661c9f69c414221e9378eab8ba2d69812592 100644 (file)
@@ -21,8 +21,9 @@
 use super::project;
 use super::project::{normalize_with_depth, Normalized};
 use super::{PredicateObligation, TraitObligation, ObligationCause};
+use super::{report_overflow_error};
 use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
-use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
+use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
 use super::{Selection};
 use super::{SelectionResult};
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
@@ -561,10 +562,7 @@ fn candidate_from_obligation<'o>(&mut self,
         // not update) the cache.
         let recursion_limit = self.infcx.tcx.sess.recursion_limit.get();
         if stack.obligation.recursion_depth >= recursion_limit {
-            debug!("{} --> overflow (limit={})",
-                   stack.obligation.repr(self.tcx()),
-                   recursion_limit);
-            return Err(Overflow)
+            report_overflow_error(self.infcx(), &stack.obligation);
         }
 
         // Check the cache. Note that we skolemize the trait-ref
@@ -1762,7 +1760,7 @@ fn collect_predicates_for_types(&mut self,
 
         match obligations {
             Ok(mut obls) => {
-                obls.push_all(normalized.obligations.as_slice());
+                obls.push_all(&normalized.obligations);
                 obls
             },
             Err(ErrorReported) => Vec::new()
@@ -2582,11 +2580,13 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 impl<'tcx> EvaluationResult<'tcx> {
     fn may_apply(&self) -> bool {
         match *self {
-            EvaluatedToOk
-            | EvaluatedToAmbig
-            | EvaluatedToErr(Overflow)
-            | EvaluatedToErr(OutputTypeParameterMismatch(..)) => true,
-            EvaluatedToErr(Unimplemented) => false,
+            EvaluatedToOk |
+            EvaluatedToAmbig |
+            EvaluatedToErr(OutputTypeParameterMismatch(..)) =>
+                true,
+
+            EvaluatedToErr(Unimplemented) =>
+                false,
         }
     }
 }
index 88b721ce958622c7b345dbe53c7c88b9e1b389b4..965aaf12044ec20692b20ca403d9234580c25a04 100644 (file)
@@ -514,9 +514,6 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 impl<'tcx> Repr<'tcx> for super::SelectionError<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
-            super::Overflow =>
-                format!("Overflow"),
-
             super::Unimplemented =>
                 format!("Unimplemented"),
 
index 99c35c6e5425824a20b3e8ba2144f5d885dd4aba..e5e89c3fbd4b9802ed729631f7ad8dbafec6195f 100644 (file)
@@ -52,6 +52,7 @@
 use middle::region;
 use middle::resolve_lifetime;
 use middle::infer;
+use middle::pat_util;
 use middle::stability;
 use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
@@ -2667,7 +2668,7 @@ pub fn mk_region(&self, region: Region) -> &'tcx Region {
     }
 
     pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind {
-        self.closure_kinds.borrow()[def_id]
+        *self.closure_kinds.borrow().get(&def_id).unwrap()
     }
 
     pub fn closure_type(&self,
@@ -2675,14 +2676,22 @@ pub fn closure_type(&self,
                         substs: &subst::Substs<'tcx>)
                         -> ty::ClosureTy<'tcx>
     {
-        self.closure_tys.borrow()[def_id].subst(self, substs)
+        self.closure_tys.borrow().get(&def_id).unwrap().subst(self, substs)
     }
 
     pub fn type_parameter_def(&self,
                               node_id: ast::NodeId)
                               -> TypeParameterDef<'tcx>
     {
-        self.ty_param_defs.borrow()[node_id].clone()
+        self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
+    }
+
+    pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> bool {
+        pat_util::pat_contains_ref_binding(&self.def_map, pat)
+    }
+
+    pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> bool {
+        pat_util::arm_contains_ref_binding(&self.def_map, arm)
     }
 }
 
@@ -5980,10 +5989,7 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
 
 pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool {
     populate_implementations_for_trait_if_necessary(tcx, trait_def_id);
-    match tcx.lang_items.to_builtin_kind(trait_def_id) {
-        Some(BoundSend) | Some(BoundSync) => true,
-        _ => tcx.traits_with_default_impls.borrow().contains_key(&trait_def_id),
-    }
+    tcx.traits_with_default_impls.borrow().contains_key(&trait_def_id)
 }
 
 /// Records a trait-to-implementation mapping.
@@ -6540,7 +6546,7 @@ pub fn is_method_call(&self, expr_id: ast::NodeId) -> bool {
     }
 
     pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
-        Some(self.upvar_capture_map.borrow()[upvar_id].clone())
+        Some(self.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone())
     }
 }
 
index e368a6691332caa6b78d96c546d28d894bbd6a82..a7c67a0863182e6af468f5e4ba104a01b3c5a50c 100644 (file)
@@ -907,7 +907,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let cg = build_codegen_options(matches);
 
-    let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::new(&m));
+    let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
     let target = matches.opt_str("target").unwrap_or(
         host_triple().to_string());
     let opt_level = {
index 3c5d97445058b2d7ed3743a35192bb3bf4d5c910..3dc31f9524effe1e5b32668c7c7d707bbf9ce1fb 100644 (file)
@@ -54,7 +54,7 @@ pub fn add_path(&mut self, path: &str) {
         if path.is_empty() {
             early_error("empty search path given via `-L`");
         }
-        self.paths.push((kind, PathBuf::new(path)));
+        self.paths.push((kind, PathBuf::from(path)));
     }
 
     pub fn iter(&self, kind: PathKind) -> Iter {
index aec8ac38a5ad3a48fc94aff7b690e14c32576621..2cc51a723f2370c96a362fb87b2de0e83ecd18ed 100644 (file)
@@ -319,7 +319,7 @@ fn add_archive<F>(&mut self, archive: &Path, name: &str,
             };
             let new_filename = self.work_dir.path().join(&filename[..]);
             try!(fs::rename(&file, &new_filename));
-            self.members.push(PathBuf::new(&filename));
+            self.members.push(PathBuf::from(filename));
         }
         Ok(())
     }
index 6a6502800f683e17bec25099fd490f4683f36ca6..6d8891dd4fe078f058ed3ed958ede8b891013147 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::io;
-#[allow(deprecated)] use std::old_path;
+#[allow(deprecated)] use std::old_path::{self, GenericPath};
 #[allow(deprecated)] use std::old_io;
 use std::path::{Path, PathBuf};
 
@@ -19,7 +19,7 @@
 pub fn realpath(original: &Path) -> io::Result<PathBuf> {
     let old = old_path::Path::new(original.to_str().unwrap());
     match old_realpath(&old) {
-        Ok(p) => Ok(PathBuf::new(p.as_str().unwrap())),
+        Ok(p) => Ok(PathBuf::from(p.as_str().unwrap())),
         Err(e) => Err(io::Error::new(io::ErrorKind::Other,
                                      "realpath error",
                                      Some(e.to_string())))
@@ -72,6 +72,7 @@ mod test {
     use std::old_io::fs::{File, symlink, mkdir, mkdir_recursive};
     use super::old_realpath as realpath;
     use std::old_io::TempDir;
+    use std::old_path::{Path, GenericPath};
 
     #[test]
     fn realpath_works() {
index 99d24a6013078f90be120d67ffadaf33a0b168bc..086742f740cdb362e0394a7658a4eb7a5d4cc9ea 100644 (file)
@@ -49,6 +49,7 @@
 #![feature(std_misc)]
 #![feature(path_relative_from)]
 #![feature(step_by)]
+#![feature(convert)]
 
 extern crate syntax;
 extern crate serialize;
index 4f9f1447d8a731b918f765666306916435348de4..68d21abb50ef5e74fd21f4a071ac3efa413bfc92 100644 (file)
@@ -99,30 +99,58 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
     lib.pop();
     let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
     output.pop();
-    let relative = relativize(&lib, &output);
+    let relative = path_relative_from(&lib, &output)
+        .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
     // FIXME (#9639): This needs to handle non-utf8 paths
     format!("{}/{}", prefix,
             relative.to_str().expect("non-utf8 component in path"))
 }
 
-fn relativize(path: &Path, rel: &Path) -> PathBuf {
-    let mut res = PathBuf::new("");
-    let mut cur = rel;
-    while !path.starts_with(cur) {
-        res.push("..");
-        match cur.parent() {
-            Some(p) => cur = p,
-            None => panic!("can't create relative paths across filesystems"),
+// This routine is adapted from the *old* Path's `path_relative_from`
+// function, which works differently from the new `relative_from` function.
+// In particular, this handles the case on unix where both paths are
+// absolute but with only the root as the common directory.
+fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
+    use std::path::Component;
+
+    if path.is_absolute() != base.is_absolute() {
+        if path.is_absolute() {
+            Some(PathBuf::new(path))
+        } else {
+            None
         }
+    } else {
+        let mut ita = path.components();
+        let mut itb = base.components();
+        let mut comps: Vec<Component> = vec![];
+        loop {
+            match (ita.next(), itb.next()) {
+                (None, None) => break,
+                (Some(a), None) => {
+                    comps.push(a);
+                    comps.extend(ita.by_ref());
+                    break;
+                }
+                (None, _) => comps.push(Component::ParentDir),
+                (Some(a), Some(b)) if comps.is_empty() && a == b => (),
+                (Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
+                (Some(_), Some(b)) if b == Component::ParentDir => return None,
+                (Some(a), Some(_)) => {
+                    comps.push(Component::ParentDir);
+                    for _ in itb {
+                        comps.push(Component::ParentDir);
+                    }
+                    comps.push(a);
+                    comps.extend(ita.by_ref());
+                    break;
+                }
+            }
+        }
+        Some(comps.iter().map(|c| c.as_os_str()).collect())
     }
-    match path.relative_from(cur) {
-        Some(s) => { res.push(s); res }
-        None => panic!("couldn't create relative path from {:?} to {:?}",
-                       rel, path),
-    }
-
 }
 
+
 fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
     let path = (config.get_install_prefix_lib_path)();
     let path = env::current_dir().unwrap().join(&path);
index 4663901a7b4c1f84114586dc066bf05feecf5aac..c464658f447acd973d1568b93dca9285c59dd21b 100644 (file)
@@ -393,11 +393,11 @@ macro_rules! load_specific {
         let path = {
             let mut target = target.to_string();
             target.push_str(".json");
-            PathBuf::new(&target)
+            PathBuf::from(target)
         };
 
         let target_path = env::var_os("RUST_TARGET_PATH")
-                              .unwrap_or(OsString::from_str(""));
+                              .unwrap_or(OsString::new());
 
         // FIXME 16351: add a sane default search path?
 
index d51ad6e0c97b5f3b9a44b73454add2b96f471eae..7d77eb23b6ed01c5f961e1aed739e48c92b2f5c1 100644 (file)
@@ -491,7 +491,7 @@ fn visit_expr(&mut self, ex: &Expr) {
         if let ast::ExprAddrOf(mutbl, ref base) = ex.node {
             let param_env = ty::empty_parameter_environment(self.bccx.tcx);
             let mc = mc::MemCategorizationContext::new(&param_env);
-            let base_cmt = mc.cat_expr(&**base).ok().unwrap();
+            let base_cmt = mc.cat_expr(&**base).unwrap();
             let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);
             // Check that we don't allow borrows of unsafe static items.
             if check_aliasability(self.bccx, ex.span, euv::AddrOf,
index 8846f70fbd335febf9b005813b07dfc2b885bb03..2834fce5278c85ab7b3caf36f3de0a47425e6a30 100644 (file)
@@ -486,7 +486,7 @@ fn add_gen_kills(&self,
             match path.loan_path.kind {
                 LpVar(..) | LpUpvar(..) | LpDowncast(..) => {
                     let kill_scope = path.loan_path.kill_scope(tcx);
-                    let path = self.path_map.borrow()[path.loan_path];
+                    let path = *self.path_map.borrow().get(&path.loan_path).unwrap();
                     self.kill_moves(path, kill_scope.node_id(), dfcx_moves);
                 }
                 LpExtend(..) => {}
index e09457970e12f776513d60245527aab02288f6c5..e927ea5b86cdd27bc3416ced57069c96bf3b5e22 100644 (file)
@@ -28,6 +28,7 @@
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(unsafe_destructor)]
+#![feature(into_cow)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
index dc27a30110950454f813cf5ac82003408a379e37..4c654cbf27de05fd5bfecd79ba31d0b91a3a857e 100644 (file)
@@ -468,7 +468,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
             // dependent dlls. Note that this uses cfg!(windows) as opposed to
             // targ_cfg because syntax extensions are always loaded for the host
             // compiler, not for the target.
-            let mut _old_path = OsString::from_str("");
+            let mut _old_path = OsString::new();
             if cfg!(windows) {
                 _old_path = env::var_os("PATH").unwrap_or(_old_path);
                 let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
@@ -752,7 +752,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
 pub fn phase_6_link_output(sess: &Session,
                            trans: &trans::CrateTranslation,
                            outputs: &OutputFilenames) {
-    let old_path = env::var_os("PATH").unwrap_or(OsString::from_str(""));
+    let old_path = env::var_os("PATH").unwrap_or(OsString::new());
     let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
     new_path.extend(env::split_paths(&old_path));
     env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
@@ -927,7 +927,7 @@ pub fn build_output_filenames(input: &Input,
             // We want to toss everything after the final '.'
             let dirpath = match *odir {
                 Some(ref d) => d.clone(),
-                None => PathBuf::new("")
+                None => PathBuf::new()
             };
 
             // If a crate name is present, we use it as the link name
index 0071e4434efa4a5ae8cc1aff523c887388c41c67..5e6f2fb835bb2a01787ebf36f027bcf5e1a4ed58 100644 (file)
@@ -39,6 +39,7 @@
 #![feature(io)]
 #![feature(set_stdio)]
 #![feature(unicode)]
+#![feature(convert)]
 
 extern crate arena;
 extern crate flate;
@@ -163,8 +164,8 @@ macro_rules! do_or_return {($expr: expr) => {
 
 // Extract output directory and file from matches.
 fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>) {
-    let odir = matches.opt_str("out-dir").map(|o| PathBuf::new(&o));
-    let ofile = matches.opt_str("o").map(|o| PathBuf::new(&o));
+    let odir = matches.opt_str("out-dir").map(|o| PathBuf::from(&o));
+    let ofile = matches.opt_str("o").map(|o| PathBuf::from(&o));
     (odir, ofile)
 }
 
@@ -177,7 +178,7 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> {
             io::stdin().read_to_string(&mut src).unwrap();
             Some((Input::Str(src), None))
         } else {
-            Some((Input::File(PathBuf::new(ifile)), Some(PathBuf::new(ifile))))
+            Some((Input::File(PathBuf::from(ifile)), Some(PathBuf::from(ifile))))
         }
     } else {
         None
@@ -858,9 +859,9 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry {
     use syntax::diagnostics::registry::Registry;
 
     let all_errors = Vec::new() +
-        rustc::diagnostics::DIAGNOSTICS.as_slice() +
-        rustc_typeck::diagnostics::DIAGNOSTICS.as_slice() +
-        rustc_resolve::diagnostics::DIAGNOSTICS.as_slice();
+        &rustc::diagnostics::DIAGNOSTICS[..] +
+        &rustc_typeck::diagnostics::DIAGNOSTICS[..] +
+        &rustc_resolve::diagnostics::DIAGNOSTICS[..];
 
     Registry::new(&*all_errors)
 }
index f6f82c65374bd2bf9f0f8f5c2be28576892d6c28..e65fe904dd29af28eb5e1a3e1dad8e836afde366 100644 (file)
@@ -418,7 +418,7 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     fn check_def(&mut self, sp: Span, id: ast::NodeId) {
-        match self.cx.tcx.def_map.borrow()[id].full_def() {
+        match self.cx.tcx.def_map.borrow().get(&id).unwrap().full_def() {
             def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => {
                 self.cx.span_lint(IMPROPER_CTYPES, sp,
                                   "found rust type `isize` in foreign module, while \
@@ -2056,7 +2056,7 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
                 }
             },
             ast::ItemStatic(..) => {
-                if attr::contains_name(it.attrs.as_slice(), "no_mangle") &&
+                if attr::contains_name(&it.attrs, "no_mangle") &&
                        !cx.exported_items.contains(&it.id) {
                     let msg = format!("static {} is marked #[no_mangle], but not exported",
                                       it.ident);
@@ -2064,7 +2064,7 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
                 }
             },
             ast::ItemConst(..) => {
-                if attr::contains_name(it.attrs.as_slice(), "no_mangle") {
+                if attr::contains_name(&it.attrs, "no_mangle") {
                     // Const items do not refer to a particular location in memory, and therefore
                     // don't have anything to attach a symbol to
                     let msg = "const items should never be #[no_mangle], consider instead using \
index bfce2f0062de48f8591406f4af87b2f0a3d85a43..2e7fe91365a13475dabf5e99106be2e2b82421dd 100644 (file)
@@ -253,7 +253,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
                     ast::TyPath(..) => {
-                        match self.tcx.def_map.borrow()[ty.id].full_def() {
+                        match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                             def::DefPrimTy(..) => true,
                             def => {
                                 let did = def.def_id();
@@ -317,7 +317,7 @@ fn visit_item(&mut self, item: &ast::Item) {
 
             ast::ItemTy(ref ty, _) if public_first => {
                 if let ast::TyPath(..) = ty.node {
-                    match self.tcx.def_map.borrow()[ty.id].full_def() {
+                    match self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def() {
                         def::DefPrimTy(..) | def::DefTyParam(..) => {},
                         def => {
                             let did = def.def_id();
@@ -349,7 +349,7 @@ fn visit_mod(&mut self, m: &ast::Mod, _sp: Span, id: ast::NodeId) {
         // crate module gets processed as well.
         if self.prev_exported {
             assert!(self.export_map.contains_key(&id), "wut {}", id);
-            for export in &self.export_map[id] {
+            for export in self.export_map.get(&id).unwrap() {
                 if is_local(export.def_id) {
                     self.reexports.insert(export.def_id.node);
                 }
@@ -525,7 +525,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
             // if we've reached the root, then everything was allowable and this
             // access is public.
             if closest_private_id == ast::CRATE_NODE_ID { return Allowable }
-            closest_private_id = self.parents[closest_private_id];
+            closest_private_id = *self.parents.get(&closest_private_id).unwrap();
 
             // If we reached the top, then we were public all the way down and
             // we can allow this access.
@@ -543,7 +543,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
     /// whether the node is accessible by the current module that iteration is
     /// inside.
     fn private_accessible(&self, id: ast::NodeId) -> bool {
-        let parent = self.parents[id];
+        let parent = *self.parents.get(&id).unwrap();
         debug!("privacy - accessible parent {}", self.nodestr(parent));
 
         // After finding `did`'s closest private member, we roll ourselves back
@@ -567,7 +567,7 @@ fn private_accessible(&self, id: ast::NodeId) -> bool {
                 _ => {}
             }
 
-            cur = self.parents[cur];
+            cur = *self.parents.get(&cur).unwrap();
         }
     }
 
@@ -622,7 +622,7 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId,
                             ast::TyPath(..) => {}
                             _ => return Some((err_span, err_msg, None)),
                         };
-                        let def = self.tcx.def_map.borrow()[ty.id].full_def();
+                        let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
                         let did = def.def_id();
                         assert!(is_local(did));
                         match self.tcx.map.get(did.node) {
@@ -708,7 +708,7 @@ fn check_static_method(&mut self,
     // Checks that a path is in scope.
     fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) {
         debug!("privacy - path {}", self.nodestr(path_id));
-        let path_res = self.tcx.def_map.borrow()[path_id];
+        let path_res = *self.tcx.def_map.borrow().get(&path_id).unwrap();
         let ck = |tyname: &str| {
             let ck_public = |def: ast::DefId| {
                 debug!("privacy - ck_public {:?}", def);
@@ -881,7 +881,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                         }
                     }
                     ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow()[expr.id].full_def() {
+                        match self.tcx.def_map.borrow().get(&expr.id).unwrap().full_def() {
                             def::DefVariant(_, variant_id, _) => {
                                 for field in fields {
                                     self.check_field(expr.span, variant_id,
index b619c6a77d009597eef5b2f806a9ac4d0722d566..566af2590e6c07cd0ec1a256856951ee36478222 100644 (file)
@@ -900,7 +900,7 @@ fn record_import_use(&mut self, import_id: NodeId, name: Name) {
             return;
         }
         if self.glob_map.contains_key(&import_id) {
-            self.glob_map[import_id].insert(name);
+            self.glob_map.get_mut(&import_id).unwrap().insert(name);
             return;
         }
 
index 737ec71cab3da09273b69f94d3653d37674e91eb..46451019760dd478aa179449473532a32d15fe63 100644 (file)
@@ -603,7 +603,7 @@ fn get_binding(this: &mut Resolver,
 
         // We've successfully resolved the import. Write the results in.
         let mut import_resolutions = module_.import_resolutions.borrow_mut();
-        let import_resolution = &mut (*import_resolutions)[target];
+        let import_resolution = import_resolutions.get_mut(&target).unwrap();
 
         {
             let mut check_and_write_import = |namespace, result: &_, used_public: &mut bool| {
index 3904db4433c892a69bffc712ea2d01afa73788c0..1f416d5404d2778d0fdea4768371232068e2bae8 100644 (file)
@@ -1 +1 @@
-See the README.txt in ../librustc.
+See the README.md in ../librustc.
index 34a23f3efac42c3011bbb2773d05f58f01aea631..bb7880161d5d4e364b2ebc7701468e64d3820a77 100644 (file)
@@ -877,7 +877,7 @@ fn link_args(cmd: &mut Command,
         if t.options.is_like_osx {
             let morestack = lib_path.join("libmorestack.a");
 
-            let mut v = OsString::from_str("-Wl,-force_load,");
+            let mut v = OsString::from("-Wl,-force_load,");
             v.push(&morestack);
             cmd.arg(&v);
         } else {
@@ -1002,7 +1002,7 @@ fn link_args(cmd: &mut Command,
             cmd.args(&["-dynamiclib", "-Wl,-dylib"]);
 
             if sess.opts.cg.rpath {
-                let mut v = OsString::from_str("-Wl,-install_name,@rpath/");
+                let mut v = OsString::from("-Wl,-install_name,@rpath/");
                 v.push(out_filename.file_name().unwrap());
                 cmd.arg(&v);
             }
@@ -1020,7 +1020,7 @@ fn link_args(cmd: &mut Command,
         let mut get_install_prefix_lib_path = || {
             let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
             let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
-            let mut path = PathBuf::new(install_prefix);
+            let mut path = PathBuf::from(install_prefix);
             path.push(&tlib);
 
             path
@@ -1102,7 +1102,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
                                             &sess.target.target.options.staticlib_suffix,
                                             &search_path[..],
                                             &sess.diagnostic().handler);
-            let mut v = OsString::from_str("-Wl,-force_load,");
+            let mut v = OsString::from("-Wl,-force_load,");
             v.push(&lib);
             cmd.arg(&v);
         }
@@ -1141,9 +1141,9 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
     // involves just passing the right -l flag.
 
     let data = if dylib {
-        &trans.crate_formats[config::CrateTypeDylib]
+        trans.crate_formats.get(&config::CrateTypeDylib).unwrap()
     } else {
-        &trans.crate_formats[config::CrateTypeExecutable]
+        trans.crate_formats.get(&config::CrateTypeExecutable).unwrap()
     };
 
     // Invoke get_used_crates to ensure that we get a topological sorting of
index efc81da560b6e262e0cc9ed52f9eaa50fe4781ad..176e3805a311f3a0865b8b6cb65caba291ba9930 100644 (file)
@@ -41,6 +41,7 @@
 #![feature(path_ext)]
 #![feature(fs)]
 #![feature(hash)]
+#![feature(convert)]
 #![feature(path_relative_from)]
 
 extern crate arena;
index 83bb5efb425d26564f746145dcba376b4086f67b..53aa6d44fe7e86f014df2b7a65737af761883975 100644 (file)
@@ -219,7 +219,7 @@ fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
             self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
                                   ref_id));
         }
-        let def = self.analysis.ty_cx.def_map.borrow()[ref_id].full_def();
+        let def = self.analysis.ty_cx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
             def::DefPrimTy(_) => None,
             _ => Some(def.def_id()),
@@ -232,7 +232,7 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
             self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind",
                                              ref_id));
         }
-        let def = def_map[ref_id].full_def();
+        let def = def_map.get(&ref_id).unwrap().full_def();
         match def {
             def::DefMod(_) |
             def::DefForeignMod(_) => Some(recorder::ModRef),
@@ -269,8 +269,10 @@ fn process_formals(&mut self, formals: &Vec<ast::Arg>, qualname: &str) {
             self.collecting = false;
             let span_utils = self.span.clone();
             for &(id, ref p, _, _) in &self.collected_paths {
-                let typ = ppaux::ty_to_string(&self.analysis.ty_cx,
-                    (*self.analysis.ty_cx.node_types.borrow())[id]);
+                let typ =
+                    ppaux::ty_to_string(
+                        &self.analysis.ty_cx,
+                        *self.analysis.ty_cx.node_types.borrow().get(&id).unwrap());
                 // get the span only for the name of the variable (I hope the path is only ever a
                 // variable name, but who knows?)
                 self.fmt.formal_str(p.span,
@@ -431,8 +433,10 @@ fn process_struct_field_def(&mut self,
             ast::NamedField(ident, _) => {
                 let name = get_ident(ident);
                 let qualname = format!("{}::{}", qualname, name);
-                let typ = ppaux::ty_to_string(&self.analysis.ty_cx,
-                    (*self.analysis.ty_cx.node_types.borrow())[field.node.id]);
+                let typ =
+                    ppaux::ty_to_string(
+                        &self.analysis.ty_cx,
+                        *self.analysis.ty_cx.node_types.borrow().get(&field.node.id).unwrap());
                 match self.span.sub_span_before_token(field.span, token::Colon) {
                     Some(sub_span) => self.fmt.field_str(field.span,
                                                          Some(sub_span),
@@ -789,7 +793,7 @@ fn process_path(&mut self,
             self.sess.span_bug(span,
                                &format!("def_map has no key for {} in visit_expr", id));
         }
-        let def = def_map[id].full_def();
+        let def = def_map.get(&id).unwrap().full_def();
         let sub_span = self.span.span_for_last_ident(span);
         match def {
             def::DefUpvar(..) |
@@ -832,7 +836,8 @@ fn process_path(&mut self,
                                                  .ty_cx
                                                  .impl_items
                                                  .borrow();
-                            Some((*impl_items)[def_id]
+                            Some(impl_items.get(&def_id)
+                                           .unwrap()
                                            .iter()
                                            .find(|mr| {
                                                 ty::impl_or_trait_item(
@@ -941,7 +946,7 @@ fn process_method_call(&mut self,
                            ex: &ast::Expr,
                            args: &Vec<P<ast::Expr>>) {
         let method_map = self.analysis.ty_cx.method_map.borrow();
-        let method_callee = &(*method_map)[ty::MethodCall::expr(ex.id)];
+        let method_callee = method_map.get(&ty::MethodCall::expr(ex.id)).unwrap();
         let (def_id, decl_id) = match method_callee.origin {
             ty::MethodStatic(def_id) |
             ty::MethodStaticClosure(def_id) => {
@@ -1001,7 +1006,7 @@ fn process_pat(&mut self, p:&ast::Pat) {
                 self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef));
                 visit::walk_path(self, path);
 
-                let def = self.analysis.ty_cx.def_map.borrow()[p.id].full_def();
+                let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def();
                 let struct_def = match def {
                     def::DefConst(..) => None,
                     def::DefVariant(_, variant_id, _) => Some(variant_id),
@@ -1113,7 +1118,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                         let glob_map = &self.analysis.glob_map;
                         let glob_map = glob_map.as_ref().unwrap();
                         if glob_map.contains_key(&item.id) {
-                            for n in &glob_map[item.id] {
+                            for n in glob_map.get(&item.id).unwrap() {
                                 if name_string.len() > 0 {
                                     name_string.push_str(", ");
                                 }
@@ -1406,7 +1411,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                                    &format!("def_map has no key for {} in visit_arm",
                                            id));
             }
-            let def = def_map[id].full_def();
+            let def = def_map.get(&id).unwrap().full_def();
             match def {
                 def::DefLocal(id)  => {
                     let value = if *immut {
@@ -1467,7 +1472,7 @@ fn visit_local(&mut self, l: &ast::Local) {
         for &(id, ref p, ref immut, _) in &self.collected_paths {
             let value = if *immut { value.to_string() } else { "<mutable>".to_string() };
             let types = self.analysis.ty_cx.node_types.borrow();
-            let typ = ppaux::ty_to_string(&self.analysis.ty_cx, (*types)[id]);
+            let typ = ppaux::ty_to_string(&self.analysis.ty_cx, *types.get(&id).unwrap());
             // Get the span only for the name of the variable (I hope the path
             // is only ever a variable name, but who knows?).
             let sub_span = self.span.span_for_last_ident(p.span);
@@ -1509,10 +1514,10 @@ pub fn process_crate(sess: &Session,
 
     // find a path to dump our data to
     let mut root_path = match env::var_os("DXR_RUST_TEMP_FOLDER") {
-        Some(val) => PathBuf::new(&val),
+        Some(val) => PathBuf::from(val),
         None => match odir {
             Some(val) => val.join("dxr"),
-            None => PathBuf::new("dxr-temp"),
+            None => PathBuf::from("dxr-temp"),
         },
     };
 
index 44f6d1bfd0b07fa1a5378096530191e45647a488..eb759393ac6eca125f2432641e792c9d37575c2d 100644 (file)
@@ -326,7 +326,7 @@ pub enum OptResult<'blk, 'tcx: 'blk> {
     LowerBound(Result<'blk, 'tcx>)
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq)]
 pub enum TransBindingMode {
     TrByCopy(/* llbinding */ ValueRef),
     TrByMove,
@@ -1017,9 +1017,14 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         None => {
             let data = &m[0].data;
             for &(ref ident, ref value_ptr) in &m[0].bound_ptrs {
-                let llmatch = data.bindings_map[*ident].llmatch;
-                call_lifetime_start(bcx, llmatch);
-                Store(bcx, *value_ptr, llmatch);
+                let binfo = *data.bindings_map.get(ident).unwrap();
+                call_lifetime_start(bcx, binfo.llmatch);
+                if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) {
+                    expr::copy_fat_ptr(bcx, *value_ptr, binfo.llmatch);
+                }
+                else {
+                    Store(bcx, *value_ptr, binfo.llmatch);
+                }
             }
             match data.arm.guard {
                 Some(ref guard_expr) => {
@@ -1087,7 +1092,6 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             _ => None
         }
     };
-
     match adt_vals {
         Some(field_vals) => {
             let pats = enter_match(bcx, dm, m, col, val, |pats|
@@ -1694,8 +1698,14 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
                             ast::BindByRef(_) => {
                                 // By ref binding: the value of the variable
-                                // is the pointer `val` itself.
-                                Store(bcx, val, llval);
+                                // is the pointer `val` itself or fat pointer referenced by `val`
+                                if type_is_fat_ptr(bcx.tcx(), ty) {
+                                    expr::copy_fat_ptr(bcx, val, llval);
+                                }
+                                else {
+                                    Store(bcx, val, llval);
+                                }
+
                                 bcx
                             }
                         }
index a3bd0cf6b1a623bac1cf719408aa45f7d1696859..33817bb952e98967eb428e326b3654d173505839 100644 (file)
@@ -76,43 +76,33 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
     // no failure occurred preparing operands, no need to cleanup
     fcx.pop_custom_cleanup_scope(temp_scope);
 
-    let mut constraints = constraints.iter()
-                                     .map(|s| s.to_string())
-                                     .chain(ext_constraints.into_iter())
-                                     .collect::<Vec<String>>()
-                                     .connect(",");
-
-    let mut clobbers = ia.clobbers.iter()
-                                  .map(|s| format!("~{{{}}}", &s))
-                                  .collect::<Vec<String>>()
-                                  .connect(",");
-    let more_clobbers = get_clobbers();
-    if !more_clobbers.is_empty() {
-        if !clobbers.is_empty() {
-            clobbers.push(',');
-        }
-        clobbers.push_str(&more_clobbers[..]);
-    }
-
-    // Add the clobbers to our constraints list
-    if clobbers.len() != 0 && constraints.len() != 0 {
-        constraints.push(',');
-        constraints.push_str(&clobbers[..]);
-    } else {
-        constraints.push_str(&clobbers[..]);
-    }
+    let clobbers = ia.clobbers.iter()
+                              .map(|s| format!("~{{{}}}", &s));
+
+    // Default per-arch clobbers
+    // Basically what clang does
+    let arch_clobbers = match bcx.sess().target.target.arch.as_slice() {
+        "x86" | "x86_64" => vec!("~{dirflag}", "~{fpsr}", "~{flags}"),
+        _                => Vec::new()
+    };
 
-    debug!("Asm Constraints: {}", &constraints[..]);
+    let all_constraints= constraints.iter()
+                                    .map(|s| s.to_string())
+                                    .chain(ext_constraints.into_iter())
+                                    .chain(clobbers)
+                                    .chain(arch_clobbers.iter()
+                                               .map(|s| s.to_string()))
+                                    .collect::<Vec<String>>()
+                                    .connect(",");
 
-    let num_outputs = outputs.len();
+    debug!("Asm Constraints: {}", &all_constraints[..]);
 
     // Depending on how many outputs we have, the return type is different
-    let output_type = if num_outputs == 0 {
-        Type::void(bcx.ccx())
-    } else if num_outputs == 1 {
-        output_types[0]
-    } else {
-        Type::struct_(bcx.ccx(), &output_types[..], false)
+    let num_outputs = outputs.len();
+    let output_type = match num_outputs {
+        0 => Type::void(bcx.ccx()),
+        1 => output_types[0],
+        _ => Type::struct_(bcx.ccx(), &output_types[..], false)
     };
 
     let dialect = match ia.dialect {
@@ -121,10 +111,10 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
     };
 
     let asm = CString::new(ia.asm.as_bytes()).unwrap();
-    let constraints = CString::new(constraints).unwrap();
+    let constraint_cstr = CString::new(all_constraints).unwrap();
     let r = InlineAsmCall(bcx,
                           asm.as_ptr(),
-                          constraints.as_ptr(),
+                          constraint_cstr.as_ptr(),
                           &inputs,
                           output_type,
                           ia.volatile,
@@ -158,15 +148,3 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
 
 }
 
-// Default per-arch clobbers
-// Basically what clang does
-
-#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
-fn get_clobbers() -> String {
-    "".to_string()
-}
-
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-fn get_clobbers() -> String {
-    "~{dirflag},~{fpsr},~{flags}".to_string()
-}
index f584de7c47f3b88a22befaa1328e41c4d56053bb..62ac6a81b1923dc042357256d2ac8e4dec0a184c 100644 (file)
@@ -269,7 +269,7 @@ pub fn self_type_for_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 }
 
 pub fn kind_for_closure(ccx: &CrateContext, closure_id: ast::DefId) -> ty::ClosureKind {
-    ccx.tcx().closure_kinds.borrow()[closure_id]
+    *ccx.tcx().closure_kinds.borrow().get(&closure_id).unwrap()
 }
 
 pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -756,7 +756,7 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
 }
 
 pub fn cast_shift_expr_rhs(cx: Block,
-                           op: ast::BinOp,
+                           op: ast::BinOp_,
                            lhs: ValueRef,
                            rhs: ValueRef)
                            -> ValueRef {
@@ -765,24 +765,24 @@ pub fn cast_shift_expr_rhs(cx: Block,
                    |a,b| ZExt(cx, a, b))
 }
 
-pub fn cast_shift_const_rhs(op: ast::BinOp,
+pub fn cast_shift_const_rhs(op: ast::BinOp_,
                             lhs: ValueRef, rhs: ValueRef) -> ValueRef {
     cast_shift_rhs(op, lhs, rhs,
                    |a, b| unsafe { llvm::LLVMConstTrunc(a, b.to_ref()) },
                    |a, b| unsafe { llvm::LLVMConstZExt(a, b.to_ref()) })
 }
 
-pub fn cast_shift_rhs<F, G>(op: ast::BinOp,
-                            lhs: ValueRef,
-                            rhs: ValueRef,
-                            trunc: F,
-                            zext: G)
-                            -> ValueRef where
+fn cast_shift_rhs<F, G>(op: ast::BinOp_,
+                        lhs: ValueRef,
+                        rhs: ValueRef,
+                        trunc: F,
+                        zext: G)
+                        -> ValueRef where
     F: FnOnce(ValueRef, Type) -> ValueRef,
     G: FnOnce(ValueRef, Type) -> ValueRef,
 {
     // Shifts may have any size int on the rhs
-    if ast_util::is_shift_binop(op.node) {
+    if ast_util::is_shift_binop(op) {
         let mut rhs_llty = val_ty(rhs);
         let mut lhs_llty = val_ty(lhs);
         if rhs_llty.kind() == Vector { rhs_llty = rhs_llty.element_type() }
@@ -983,56 +983,72 @@ pub fn load_if_immediate<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 /// gives us better information about what we are loading.
 pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                            ptr: ValueRef, t: Ty<'tcx>) -> ValueRef {
-    if type_is_zero_size(cx.ccx(), t) {
-        C_undef(type_of::type_of(cx.ccx(), t))
-    } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
-        // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
-        // for this leads to bad optimizations, so its arg type is an appropriately sized integer
-        // and we have to convert it
-        Load(cx, BitCast(cx, ptr, type_of::arg_type_of(cx.ccx(), t).ptr_to()))
-    } else {
-        unsafe {
-            let global = llvm::LLVMIsAGlobalVariable(ptr);
-            if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
-                let val = llvm::LLVMGetInitializer(global);
-                if !val.is_null() {
-                    // This could go into its own function, for DRY.
-                    // (something like "pre-store packing/post-load unpacking")
-                    if ty::type_is_bool(t) {
-                        return Trunc(cx, val, Type::i1(cx.ccx()));
-                    } else {
-                        return val;
-                    }
-                }
+    if cx.unreachable.get() || type_is_zero_size(cx.ccx(), t) {
+        return C_undef(type_of::type_of(cx.ccx(), t));
+    }
+
+    let ptr = to_arg_ty_ptr(cx, ptr, t);
+
+    if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
+        return Load(cx, ptr);
+    }
+
+    unsafe {
+        let global = llvm::LLVMIsAGlobalVariable(ptr);
+        if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True {
+            let val = llvm::LLVMGetInitializer(global);
+            if !val.is_null() {
+                return from_arg_ty(cx, val, t);
             }
         }
-        if ty::type_is_bool(t) {
-            Trunc(cx, LoadRangeAssert(cx, ptr, 0, 2, llvm::False), Type::i1(cx.ccx()))
-        } else if ty::type_is_char(t) {
-            // a char is a Unicode codepoint, and so takes values from 0
-            // to 0x10FFFF inclusive only.
-            LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
-        } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
-                  && !common::type_is_fat_ptr(cx.tcx(), t) {
-            LoadNonNull(cx, ptr)
-        } else {
-            Load(cx, ptr)
-        }
     }
+
+    let val =  if ty::type_is_bool(t) {
+        LoadRangeAssert(cx, ptr, 0, 2, llvm::False)
+    } else if ty::type_is_char(t) {
+        // a char is a Unicode codepoint, and so takes values from 0
+        // to 0x10FFFF inclusive only.
+        LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
+    } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
+        && !common::type_is_fat_ptr(cx.tcx(), t) {
+            LoadNonNull(cx, ptr)
+    } else {
+        Load(cx, ptr)
+    };
+
+    from_arg_ty(cx, val, t)
 }
 
 /// Helper for storing values in memory. Does the necessary conversion if the in-memory type
 /// differs from the type used for SSA values.
 pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t: Ty<'tcx>) {
-    if ty::type_is_bool(t) {
-        Store(cx, ZExt(cx, v, Type::i8(cx.ccx())), dst);
-    } else if type_is_immediate(cx.ccx(), t) && type_of::type_of(cx.ccx(), t).is_aggregate() {
+    Store(cx, to_arg_ty(cx, v, t), to_arg_ty_ptr(cx, dst, t));
+}
+
+pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
+    if ty::type_is_bool(ty) {
+        ZExt(bcx, val, Type::i8(bcx.ccx()))
+    } else {
+        val
+    }
+}
+
+pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
+    if ty::type_is_bool(ty) {
+        Trunc(bcx, val, Type::i1(bcx.ccx()))
+    } else {
+        val
+    }
+}
+
+pub fn to_arg_ty_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ptr: ValueRef, ty: Ty<'tcx>) -> ValueRef {
+    if type_is_immediate(bcx.ccx(), ty) && type_of::type_of(bcx.ccx(), ty).is_aggregate() {
         // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
         // for this leads to bad optimizations, so its arg type is an appropriately sized integer
         // and we have to convert it
-        Store(cx, v, BitCast(cx, dst, type_of::arg_type_of(cx.ccx(), t).ptr_to()));
+        BitCast(bcx, ptr, type_of::arg_type_of(bcx.ccx(), ty).ptr_to())
     } else {
-        Store(cx, v, dst);
+        ptr
     }
 }
 
@@ -2306,7 +2322,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                                          static");
               }
 
-              let v = ccx.static_values().borrow()[item.id].clone();
+              let v = ccx.static_values().borrow().get(&item.id).unwrap().clone();
               unsafe {
                   if !(llvm::LLVMConstIntGetZExtValue(v) != 0) {
                       ccx.sess().span_fatal(expr.span, "static assertion failed");
index cf36ec1f3ed96f49954a1ec836a582ae23c6460c..088a34857e753a8991be403b55d93da17de960b4 100644 (file)
@@ -511,7 +511,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
             let ref_ty = match node {
                 ExprId(id) => ty::node_id_to_type(tcx, id),
                 MethodCallKey(method_call) => {
-                    (*tcx.method_map.borrow())[method_call].ty
+                    tcx.method_map.borrow().get(&method_call).unwrap().ty
                 }
             };
             let ref_ty = monomorphize::apply_param_substs(tcx,
index 8f5dbfe2ec000ad2a52fb2516c3ea76387ef03ee..61cdde3bfbecd775a24346f063341a12e8bff644 100644 (file)
@@ -709,7 +709,7 @@ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent>
     }
 
     fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> {
-        Some(self.tcx().upvar_capture_map.borrow()[upvar_id].clone())
+        Some(self.tcx().upvar_capture_map.borrow().get(&upvar_id).unwrap().clone())
     }
 
     fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
@@ -1025,8 +1025,9 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // shallow result we are looking for -- that is, what specific impl.
     let typer = NormalizingClosureTyper::new(tcx);
     let mut selcx = traits::SelectionContext::new(&infcx, &typer);
-    let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
-                                             trait_ref.to_poly_trait_predicate());
+    let obligation =
+        traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
+                                trait_ref.to_poly_trait_predicate());
     let selection = match selcx.select(&obligation) {
         Ok(Some(selection)) => selection,
         Ok(None) => {
@@ -1081,7 +1082,7 @@ pub fn predicates_hold<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let obligation = traits::Obligation::new(traits::ObligationCause::dummy(), predicate);
         fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }
-    drain_fulfillment_cx(DUMMY_SP, &infcx, &mut fulfill_cx, &()).is_ok()
+    drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
 }
 
 pub struct NormalizingClosureTyper<'a,'tcx:'a> {
@@ -1138,7 +1139,7 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
                                                 -> T
     where T : TypeFoldable<'tcx> + Repr<'tcx>
 {
-    match drain_fulfillment_cx(span, infcx, fulfill_cx, result) {
+    match drain_fulfillment_cx(infcx, fulfill_cx, result) {
         Ok(v) => v,
         Err(errors) => {
             infcx.tcx.sess.span_bug(
@@ -1156,8 +1157,7 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
 /// inference variables that appear in `result` to be unified, and
 /// hence we need to process those obligations to get the complete
 /// picture of the type.
-pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
-                                       infcx: &infer::InferCtxt<'a,'tcx>,
+pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
                                        fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
                                        result: &T)
                                        -> StdResult<T,Vec<traits::FulfillmentError<'tcx>>>
@@ -1173,14 +1173,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
     match fulfill_cx.select_all_or_error(infcx, &typer) {
         Ok(()) => { }
         Err(errors) => {
-            // We always want to surface any overflow errors, no matter what.
-            if errors.iter().all(|e| e.is_overflow()) {
-                infcx.tcx.sess.span_fatal(
-                    span,
-                    "reached the recursion limit during monomorphization");
-            } else {
-                return Err(errors);
-            }
+            return Err(errors);
         }
     }
 
@@ -1213,7 +1206,7 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             ty::node_id_item_substs(tcx, id).substs
         }
         MethodCallKey(method_call) => {
-            (*tcx.method_map.borrow())[method_call].substs.clone()
+            tcx.method_map.borrow().get(&method_call).unwrap().substs.clone()
         }
     };
 
index 2a3fcd66195b340e456ac5301002f19058a9506f..4b1a03e47e7aebb1f2ef30bf261659b61204e2b4 100644 (file)
@@ -187,7 +187,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // Special-case constants to cache a common global for all uses.
     match expr.node {
         ast::ExprPath(..) => {
-            let def = ccx.tcx().def_map.borrow()[expr.id].full_def();
+            let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
             match def {
                 def::DefConst(def_id) => {
                     if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
@@ -376,7 +376,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let signed = ty::type_is_signed(intype);
 
             let (te2, _) = const_expr(cx, &**e2, param_substs);
-            let te2 = base::cast_shift_const_rhs(b, te1, te2);
+            let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
 
             match b.node {
               ast::BiAdd   => {
@@ -665,7 +665,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           }
           ast::ExprPath(..) => {
-            let def = cx.tcx().def_map.borrow()[e.id].full_def();
+            let def = cx.tcx().def_map.borrow().get(&e.id).unwrap().full_def();
             match def {
                 def::DefFn(..) | def::DefMethod(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
@@ -751,7 +751,7 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) {
         let g = base::get_item_val(ccx, id);
         // At this point, get_item_val has already translated the
         // constant's initializer to determine its LLVM type.
-        let v = ccx.static_values().borrow()[id].clone();
+        let v = ccx.static_values().borrow().get(&id).unwrap().clone();
         // boolean SSA values are i1, but they have to be stored in i8 slots,
         // otherwise some LLVM optimization passes don't work as expected
         let v = if llvm::LLVMTypeOf(v) == Type::i1(ccx).to_ref() {
index 3e8cc46e2550107d9fede430516be79e4e3b289c..b9c59a0bc78d671f59e3b8a13b74a8b4612f9931 100644 (file)
@@ -1695,7 +1695,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     let name = CString::new(name.as_bytes()).unwrap();
-    match (variable_access, [].as_slice()) {
+    match (variable_access, &[][..]) {
         (DirectVariable { alloca }, address_operations) |
         (IndirectVariable {alloca, address_operations}, _) => {
             let metadata = unsafe {
index c316308c618bcb42a12ec9646e99ffd7d1663ab8..ceb9a29efa8879a9d30ad4544d812c579e87f97f 100644 (file)
@@ -126,7 +126,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         return datum.store_to_dest(bcx, dest, expr.id);
     }
 
-    let qualif = bcx.tcx().const_qualif_map.borrow()[expr.id];
+    let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
     if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) {
         if !qualif.intersects(check_const::PREFER_IN_PLACE) {
             if let SaveIn(lldest) = dest {
@@ -209,7 +209,7 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let mut bcx = bcx;
     let fcx = bcx.fcx;
-    let qualif = bcx.tcx().const_qualif_map.borrow()[expr.id];
+    let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
     let adjusted_global = !qualif.intersects(check_const::NON_STATIC_BORROWS);
     let global = if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) {
         let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
@@ -285,6 +285,11 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
     GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
 }
 
+pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
+    Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
+    Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));
+}
+
 // Retrieve the information we are losing (making dynamic) in an unsizing
 // adjustment.
 //
@@ -838,7 +843,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                base_datum,
                                                vec![(ix_datum, idx.id)],
                                                Some(SaveIn(scratch.val)),
-                                               true));
+                                               false));
             let datum = scratch.to_expr_datum();
             if type_is_sized(bcx.tcx(), elt_ty) {
                 Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
@@ -1400,7 +1405,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
                         ty.repr(tcx)));
                 }
                 Some(node_id) => {
-                    let def = tcx.def_map.borrow()[node_id].full_def();
+                    let def = tcx.def_map.borrow().get(&node_id).unwrap().full_def();
                     match def {
                         def::DefVariant(enum_id, variant_id, _) => {
                             let variant_info = ty::enum_variant_with_id(tcx, enum_id, variant_id);
@@ -1765,7 +1770,6 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
     let is_float = ty::type_is_fp(intype);
     let is_signed = ty::type_is_signed(intype);
-    let rhs = base::cast_shift_expr_rhs(bcx, op, lhs, rhs);
     let info = expr_info(binop_expr);
 
     let binop_debug_loc = binop_expr.debug_loc();
@@ -1838,13 +1842,17 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
       ast::BiBitOr => Or(bcx, lhs, rhs, binop_debug_loc),
       ast::BiBitAnd => And(bcx, lhs, rhs, binop_debug_loc),
       ast::BiBitXor => Xor(bcx, lhs, rhs, binop_debug_loc),
-      ast::BiShl => Shl(bcx, lhs, rhs, binop_debug_loc),
+      ast::BiShl => {
+          let (newbcx, res) = with_overflow_check(
+              bcx, OverflowOp::Shl, info, lhs_t, lhs, rhs, binop_debug_loc);
+          bcx = newbcx;
+          res
+      }
       ast::BiShr => {
-        if is_signed {
-            AShr(bcx, lhs, rhs, binop_debug_loc)
-        } else {
-            LShr(bcx, lhs, rhs, binop_debug_loc)
-        }
+          let (newbcx, res) = with_overflow_check(
+              bcx, OverflowOp::Shr, info, lhs_t, lhs, rhs, binop_debug_loc);
+          bcx = newbcx;
+          res
       }
       ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
         if is_simd {
@@ -1956,7 +1964,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                    dest: Option<Dest>,
                                    autoref: bool)
                                    -> Result<'blk, 'tcx> {
-    let method_ty = (*bcx.tcx().method_map.borrow())[method_call].ty;
+    let method_ty = bcx.tcx().method_map.borrow().get(&method_call).unwrap().ty;
     callee::trans_call_inner(bcx,
                              expr.debug_loc(),
                              monomorphize_type(bcx, method_ty),
@@ -1977,10 +1985,12 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                          dest: Option<Dest>)
                                          -> Block<'blk, 'tcx> {
     let method_call = MethodCall::expr(expr.id);
-    let method_type = (*bcx.tcx()
-                           .method_map
-                           .borrow())[method_call]
-                           .ty;
+    let method_type = bcx.tcx()
+                         .method_map
+                         .borrow()
+                         .get(&method_call)
+                         .unwrap()
+                         .ty;
     let mut all_args = vec!(callee);
     all_args.extend(args.iter().map(|e| &**e));
     unpack_result!(bcx,
@@ -2384,9 +2394,38 @@ enum OverflowOp {
     Add,
     Sub,
     Mul,
+    Shl,
+    Shr,
 }
 
 impl OverflowOp {
+    fn codegen_strategy(&self) -> OverflowCodegen {
+        use self::OverflowCodegen::{ViaIntrinsic, ViaInputCheck};
+        match *self {
+            OverflowOp::Add => ViaIntrinsic(OverflowOpViaIntrinsic::Add),
+            OverflowOp::Sub => ViaIntrinsic(OverflowOpViaIntrinsic::Sub),
+            OverflowOp::Mul => ViaIntrinsic(OverflowOpViaIntrinsic::Mul),
+
+            OverflowOp::Shl => ViaInputCheck(OverflowOpViaInputCheck::Shl),
+            OverflowOp::Shr => ViaInputCheck(OverflowOpViaInputCheck::Shr),
+        }
+    }
+}
+
+enum OverflowCodegen {
+    ViaIntrinsic(OverflowOpViaIntrinsic),
+    ViaInputCheck(OverflowOpViaInputCheck),
+}
+
+enum OverflowOpViaInputCheck { Shl, Shr, }
+
+enum OverflowOpViaIntrinsic { Add, Sub, Mul, }
+
+impl OverflowOpViaIntrinsic {
+    fn to_intrinsic<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, lhs_ty: Ty) -> ValueRef {
+        let name = self.to_intrinsic_name(bcx.tcx(), lhs_ty);
+        bcx.ccx().get_intrinsic(&name)
+    }
     fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
         use syntax::ast::IntTy::*;
         use syntax::ast::UintTy::*;
@@ -2408,7 +2447,7 @@ fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
         };
 
         match *self {
-            OverflowOp::Add => match new_sty {
+            OverflowOpViaIntrinsic::Add => match new_sty {
                 ty_int(TyI8) => "llvm.sadd.with.overflow.i8",
                 ty_int(TyI16) => "llvm.sadd.with.overflow.i16",
                 ty_int(TyI32) => "llvm.sadd.with.overflow.i32",
@@ -2421,7 +2460,7 @@ fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
 
                 _ => unreachable!(),
             },
-            OverflowOp::Sub => match new_sty {
+            OverflowOpViaIntrinsic::Sub => match new_sty {
                 ty_int(TyI8) => "llvm.ssub.with.overflow.i8",
                 ty_int(TyI16) => "llvm.ssub.with.overflow.i16",
                 ty_int(TyI32) => "llvm.ssub.with.overflow.i32",
@@ -2434,7 +2473,7 @@ fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
 
                 _ => unreachable!(),
             },
-            OverflowOp::Mul => match new_sty {
+            OverflowOpViaIntrinsic::Mul => match new_sty {
                 ty_int(TyI8) => "llvm.smul.with.overflow.i8",
                 ty_int(TyI16) => "llvm.smul.with.overflow.i16",
                 ty_int(TyI32) => "llvm.smul.with.overflow.i32",
@@ -2449,16 +2488,14 @@ fn to_intrinsic_name(&self, tcx: &ty::ctxt, ty: Ty) -> &'static str {
             },
         }
     }
-}
-
 
-fn with_overflow_check<'a, 'b>(bcx: Block<'a, 'b>, oop: OverflowOp, info: NodeIdAndSpan,
-                               lhs_t: Ty, lhs: ValueRef, rhs: ValueRef, binop_debug_loc: DebugLoc)
-                               -> (Block<'a, 'b>, ValueRef) {
-    if bcx.unreachable.get() { return (bcx, _Undef(lhs)); }
-    if bcx.ccx().check_overflow() {
-        let name = oop.to_intrinsic_name(bcx.tcx(), lhs_t);
-        let llfn = bcx.ccx().get_intrinsic(&name);
+    fn build_intrinsic_call<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>,
+                                        info: NodeIdAndSpan,
+                                        lhs_t: Ty<'tcx>, lhs: ValueRef,
+                                        rhs: ValueRef,
+                                        binop_debug_loc: DebugLoc)
+                                        -> (Block<'blk, 'tcx>, ValueRef) {
+        let llfn = self.to_intrinsic(bcx, lhs_t);
 
         let val = Call(bcx, llfn, &[lhs, rhs], None, binop_debug_loc);
         let result = ExtractValue(bcx, val, 0); // iN operation result
@@ -2477,11 +2514,118 @@ fn with_overflow_check<'a, 'b>(bcx: Block<'a, 'b>, oop: OverflowOp, info: NodeId
                     InternedString::new("arithmetic operation overflowed")));
 
         (bcx, result)
+    }
+}
+
+impl OverflowOpViaInputCheck {
+    fn build_with_input_check<'blk, 'tcx>(&self,
+                                          bcx: Block<'blk, 'tcx>,
+                                          info: NodeIdAndSpan,
+                                          lhs_t: Ty<'tcx>,
+                                          lhs: ValueRef,
+                                          rhs: ValueRef,
+                                          binop_debug_loc: DebugLoc)
+                                          -> (Block<'blk, 'tcx>, ValueRef)
+    {
+        let lhs_llty = val_ty(lhs);
+        let rhs_llty = val_ty(rhs);
+
+        // Panic if any bits are set outside of bits that we always
+        // mask in.
+        //
+        // Note that the mask's value is derived from the LHS type
+        // (since that is where the 32/64 distinction is relevant) but
+        // the mask's type must match the RHS type (since they will
+        // both be fed into a and-binop)
+        let invert_mask = !shift_mask_val(lhs_llty);
+        let invert_mask = C_integral(rhs_llty, invert_mask, true);
+
+        let outer_bits = And(bcx, rhs, invert_mask, binop_debug_loc);
+        let cond = ICmp(bcx, llvm::IntNE, outer_bits,
+                        C_integral(rhs_llty, 0, false), binop_debug_loc);
+        let result = match *self {
+            OverflowOpViaInputCheck::Shl =>
+                build_unchecked_lshift(bcx, lhs, rhs, binop_debug_loc),
+            OverflowOpViaInputCheck::Shr =>
+                build_unchecked_rshift(bcx, lhs_t, lhs, rhs, binop_debug_loc),
+        };
+        let bcx =
+            base::with_cond(bcx, cond, |bcx|
+                controlflow::trans_fail(bcx, info,
+                    InternedString::new("shift operation overflowed")));
+
+        (bcx, result)
+    }
+}
+
+fn shift_mask_val(llty: Type) -> u64 {
+    // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
+    llty.int_width() - 1
+}
+
+// To avoid UB from LLVM, these two functions mask RHS with an
+// appropriate mask unconditionally (i.e. the fallback behavior for
+// all shifts). For 32- and 64-bit types, this matches the semantics
+// of Java. (See related discussion on #1877 and #10183.)
+
+fn build_unchecked_lshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                      lhs: ValueRef,
+                                      rhs: ValueRef,
+                                      binop_debug_loc: DebugLoc) -> ValueRef {
+    let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShl, lhs, rhs);
+    // #1877, #10183: Ensure that input is always valid
+    let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
+    Shl(bcx, lhs, rhs, binop_debug_loc)
+}
+
+fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                      lhs_t: Ty<'tcx>,
+                                      lhs: ValueRef,
+                                      rhs: ValueRef,
+                                      binop_debug_loc: DebugLoc) -> ValueRef {
+    let rhs = base::cast_shift_expr_rhs(bcx, ast::BinOp_::BiShr, lhs, rhs);
+    // #1877, #10183: Ensure that input is always valid
+    let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
+    let is_signed = ty::type_is_signed(lhs_t);
+    if is_signed {
+        AShr(bcx, lhs, rhs, binop_debug_loc)
+    } else {
+        LShr(bcx, lhs, rhs, binop_debug_loc)
+    }
+}
+
+fn shift_mask_rhs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                              rhs: ValueRef,
+                              debug_loc: DebugLoc) -> ValueRef {
+    let rhs_llty = val_ty(rhs);
+    let mask = shift_mask_val(rhs_llty);
+    And(bcx, rhs, C_integral(rhs_llty, mask, false), debug_loc)
+}
+
+fn with_overflow_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, oop: OverflowOp, info: NodeIdAndSpan,
+                                   lhs_t: Ty<'tcx>, lhs: ValueRef,
+                                   rhs: ValueRef,
+                                   binop_debug_loc: DebugLoc)
+                                   -> (Block<'blk, 'tcx>, ValueRef) {
+    if bcx.unreachable.get() { return (bcx, _Undef(lhs)); }
+    if bcx.ccx().check_overflow() {
+
+        match oop.codegen_strategy() {
+            OverflowCodegen::ViaIntrinsic(oop) =>
+                oop.build_intrinsic_call(bcx, info, lhs_t, lhs, rhs, binop_debug_loc),
+            OverflowCodegen::ViaInputCheck(oop) =>
+                oop.build_with_input_check(bcx, info, lhs_t, lhs, rhs, binop_debug_loc),
+        }
     } else {
         let res = match oop {
             OverflowOp::Add => Add(bcx, lhs, rhs, binop_debug_loc),
             OverflowOp::Sub => Sub(bcx, lhs, rhs, binop_debug_loc),
             OverflowOp::Mul => Mul(bcx, lhs, rhs, binop_debug_loc),
+
+            OverflowOp::Shl =>
+                build_unchecked_lshift(bcx, lhs, rhs, binop_debug_loc),
+            OverflowOp::Shr =>
+                build_unchecked_rshift(bcx, lhs_t, lhs, rhs, binop_debug_loc),
         };
         (bcx, res)
     }
index 69ca9a5e81cbc81b933e4ac5ed62022cdb261787..d158cfa7b88765b77f12dba0808328ebd9ef630b 100644 (file)
@@ -446,10 +446,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                              call_debug_location)
         }
         (_, "volatile_load") => {
-            VolatileLoad(bcx, llargs[0])
+            let tp_ty = *substs.types.get(FnSpace, 0);
+            let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+            from_arg_ty(bcx, VolatileLoad(bcx, ptr), tp_ty)
         },
         (_, "volatile_store") => {
-            VolatileStore(bcx, llargs[1], llargs[0]);
+            let tp_ty = *substs.types.get(FnSpace, 0);
+            let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+            let val = to_arg_ty(bcx, llargs[1], tp_ty);
+            VolatileStore(bcx, val, ptr);
             C_nil(ccx)
         },
 
@@ -709,8 +714,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                             llvm::SequentiallyConsistent
                     };
 
-                    let res = AtomicCmpXchg(bcx, llargs[0], llargs[1],
-                                            llargs[2], order,
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let cmp = to_arg_ty(bcx, llargs[1], tp_ty);
+                    let src = to_arg_ty(bcx, llargs[2], tp_ty);
+                    let res = AtomicCmpXchg(bcx, ptr, cmp, src, order,
                                             strongest_failure_ordering);
                     if unsafe { llvm::LLVMVersionMinor() >= 5 } {
                         ExtractValue(bcx, res, 0)
@@ -720,10 +728,15 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 }
 
                 "load" => {
-                    AtomicLoad(bcx, llargs[0], order)
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    from_arg_ty(bcx, AtomicLoad(bcx, ptr, order), tp_ty)
                 }
                 "store" => {
-                    AtomicStore(bcx, llargs[1], llargs[0], order);
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let val = to_arg_ty(bcx, llargs[1], tp_ty);
+                    AtomicStore(bcx, val, ptr, order);
                     C_nil(ccx)
                 }
 
@@ -749,7 +762,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         _ => ccx.sess().fatal("unknown atomic operation")
                     };
 
-                    AtomicRMW(bcx, atom_op, llargs[0], llargs[1], order)
+                    let tp_ty = *substs.types.get(FnSpace, 0);
+                    let ptr = to_arg_ty_ptr(bcx, llargs[0], tp_ty);
+                    let val = to_arg_ty(bcx, llargs[1], tp_ty);
+                    AtomicRMW(bcx, atom_op, ptr, val, order)
                 }
             }
 
index 28e7027b2124a2e2135e7d0b4007851de08b46ff..71900855266e9f4e7fc1b411d13cd65909460e11 100644 (file)
@@ -1046,7 +1046,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         return (tcx.types.err, ty_path_def);
     };
 
-    let ty_param_name = tcx.ty_param_defs.borrow()[ty_param_node_id].name;
+    let ty_param_name = tcx.ty_param_defs.borrow().get(&ty_param_node_id).unwrap().name;
 
     let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) {
         Ok(v) => v,
index 8e2f4dcefa02231db95ee7d5d576e8dc7df057b7..e8da19efa06afd790bb966de830e877e5f9e498f 100644 (file)
@@ -119,7 +119,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
         ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
-            let const_did = tcx.def_map.borrow()[pat.id].def_id();
+            let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
             let const_scheme = ty::lookup_item_type(tcx, const_did);
             assert!(const_scheme.generics.is_empty());
             let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
@@ -163,7 +163,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
             // if there are multiple arms, make sure they all agree on
             // what the type of the binding `x` ought to be
-            let canon_id = pcx.map[path.node];
+            let canon_id = *pcx.map.get(&path.node).unwrap();
             if canon_id != pat.id {
                 let ct = fcx.local_ty(pat.span, canon_id);
                 demand::eqtype(fcx, pat.span, ct, typ);
@@ -287,10 +287,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     // (nmatsakis) an hour or two debugging to remember, so I thought
     // I'd write them down this time.
     //
-    // 1. Most importantly, there is no loss of expressiveness
-    // here. What we are saying is that the type of `x`
-    // becomes *exactly* what is expected. This might seem
-    // like it will cause errors in a case like this:
+    // 1. There is no loss of expressiveness here, though it does
+    // cause some inconvenience. What we are saying is that the type
+    // of `x` becomes *exactly* what is expected. This can cause unnecessary
+    // errors in some cases, such as this one:
+    // it will cause errors in a case like this:
     //
     // ```
     // fn foo<'x>(x: &'x int) {
@@ -361,8 +362,21 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              match_src: ast::MatchSource) {
     let tcx = fcx.ccx.tcx;
 
-    let discrim_ty = fcx.infcx().next_ty_var();
-    check_expr_has_type(fcx, discrim, discrim_ty);
+    // Not entirely obvious: if matches may create ref bindings, we
+    // want to use the *precise* type of the discriminant, *not* some
+    // supertype, as the "discriminant type" (issue #23116).
+    let contains_ref_bindings = arms.iter().any(|a| tcx.arm_contains_ref_binding(a));
+    let discrim_ty;
+    if contains_ref_bindings {
+        check_expr(fcx, discrim);
+        discrim_ty = fcx.expr_ty(discrim);
+    } else {
+        // ...but otherwise we want to use any supertype of the
+        // discriminant. This is sort of a workaround, see note (*) in
+        // `check_pat` for some details.
+        discrim_ty = fcx.infcx().next_ty_var();
+        check_expr_has_type(fcx, discrim, discrim_ty);
+    };
 
     // Typecheck the patterns first, so that we get types for all the
     // bindings.
@@ -449,7 +463,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    let def = tcx.def_map.borrow()[pat.id].full_def();
+    let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
     let (enum_def_id, variant_def_id) = match def {
         def::DefTrait(_) => {
             let name = pprust::path_to_string(path);
@@ -518,7 +532,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    let def = tcx.def_map.borrow()[pat.id].full_def();
+    let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
     let enum_def = def.variant_def_ids()
         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
 
index a82ebcd9175fa43d9be6d03ede273282c3134d8c..f731507ba906dbeb7f0af6bfbc8bf6ea17ac875b 100644 (file)
@@ -92,6 +92,12 @@ fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
         Ok(None) // No coercion required.
     }
 
+    fn outlives(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ()> {
+        let sub = Sub(self.fcx.infcx().combine_fields(false, self.trace.clone()));
+        try!(sub.regions(b, a));
+        Ok(())
+    }
+
     fn unpack_actual_value<T, F>(&self, a: Ty<'tcx>, f: F) -> T where
         F: FnOnce(Ty<'tcx>) -> T,
     {
@@ -340,21 +346,40 @@ fn unsize_ty(&self,
                     Some((ty, ty::UnsizeLength(len)))
                 }
                 (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
-                    // For now, we only support upcasts from
-                    // `Foo+Send` to `Foo` (really, any time there are
-                    // fewer builtin bounds then before). These are
-                    // convenient because they don't require any sort
-                    // of change to the vtable at runtime.
-                    if data_a.bounds.builtin_bounds != data_b.bounds.builtin_bounds &&
-                        data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds)
-                    {
+                    // Upcasts permit two things:
+                    //
+                    // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
+                    // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
+                    //
+                    // Note that neither of these changes requires any
+                    // change at runtime.  Eventually this will be
+                    // generalized.
+                    //
+                    // We always upcast when we can because of reason
+                    // #2 (region bounds).
+                    if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
+                        // construct a type `a1` which is a version of
+                        // `a` using the upcast bounds from `b`
                         let bounds_a1 = ty::ExistentialBounds {
-                            region_bound: data_a.bounds.region_bound,
+                            // From type b
+                            region_bound: data_b.bounds.region_bound,
                             builtin_bounds: data_b.bounds.builtin_bounds,
+
+                            // From type a
                             projection_bounds: data_a.bounds.projection_bounds.clone(),
                         };
                         let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
-                        match self.fcx.infcx().try(|_| self.subtype(ty_a1, ty_b)) {
+
+                        // relate `a1` to `b`
+                        let result = self.fcx.infcx().try(|_| {
+                            // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
+                            try!(self.outlives(data_a.bounds.region_bound,
+                                               data_b.bounds.region_bound));
+                            self.subtype(ty_a1, ty_b)
+                        });
+
+                        // if that was successful, we have a coercion
+                        match result {
                             Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
                             Err(_) => None,
                         }
index 45d4a1edc6b2414074ecc573012ad832a40e819d..0eb71244ac075fe661dbcc224e643b190d8d696b 100644 (file)
@@ -368,7 +368,7 @@ fn closure_type(&self,
                     substs: &subst::Substs<'tcx>)
                     -> ty::ClosureTy<'tcx>
     {
-        self.inh.closure_tys.borrow()[def_id].subst(self.tcx(), substs)
+        self.inh.closure_tys.borrow().get(&def_id).unwrap().subst(self.tcx(), substs)
     }
 
     fn closure_upvars(&self,
@@ -549,7 +549,7 @@ fn visit_local(&mut self, local: &'tcx ast::Local) {
         debug!("Local variable {} is assigned type {}",
                self.fcx.pat_to_string(&*local.pat),
                self.fcx.infcx().ty_to_string(
-                   self.fcx.inh.locals.borrow()[local.id].clone()));
+                   self.fcx.inh.locals.borrow().get(&local.id).unwrap().clone()));
         visit::walk_local(self, local);
     }
 
@@ -565,7 +565,7 @@ fn visit_pat(&mut self, p: &'tcx ast::Pat) {
                 debug!("Pattern binding {} is assigned to {} with type {}",
                        token::get_ident(path1.node),
                        self.fcx.infcx().ty_to_string(
-                           self.fcx.inh.locals.borrow()[p.id].clone()),
+                           self.fcx.inh.locals.borrow().get(&p.id).unwrap().clone()),
                        var_ty.repr(self.fcx.tcx()));
             }
         }
@@ -3327,7 +3327,7 @@ fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 let mut missing_fields = Vec::new();
                 for class_field in field_types {
                     let name = class_field.name;
-                    let (_, seen) = class_field_map[name];
+                    let (_, seen) = *class_field_map.get(&name).unwrap();
                     if !seen {
                         missing_fields.push(
                             format!("`{}`", &token::get_name(name)))
@@ -4242,11 +4242,27 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 }
 
 pub fn check_decl_initializer<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                                       nid: ast::NodeId,
+                                       local: &'tcx ast::Local,
                                        init: &'tcx ast::Expr)
 {
-    let local_ty = fcx.local_ty(init.span, nid);
-    check_expr_coercable_to_type(fcx, init, local_ty)
+    let ref_bindings = fcx.tcx().pat_contains_ref_binding(&local.pat);
+
+    let local_ty = fcx.local_ty(init.span, local.id);
+    if !ref_bindings {
+        check_expr_coercable_to_type(fcx, init, local_ty)
+    } else {
+        // Somewhat subtle: if we have a `ref` binding in the pattern,
+        // we want to avoid introducing coercions for the RHS. This is
+        // both because it helps preserve sanity and, in the case of
+        // ref mut, for soundness (issue #23116). In particular, in
+        // the latter case, we need to be clear that the type of the
+        // referent for the reference that results is *equal to* the
+        // type of the lvalue it is referencing, and not some
+        // supertype thereof.
+        check_expr(fcx, init);
+        let init_ty = fcx.expr_ty(init);
+        demand::eqtype(fcx, init.span, init_ty, local_ty);
+    };
 }
 
 pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)  {
@@ -4256,7 +4272,7 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)
     fcx.write_ty(local.id, t);
 
     if let Some(ref init) = local.init {
-        check_decl_initializer(fcx, local.id, &**init);
+        check_decl_initializer(fcx, local, &**init);
         let init_ty = fcx.expr_ty(&**init);
         if ty::type_is_error(init_ty) {
             fcx.write_ty(local.id, init_ty);
@@ -4428,7 +4444,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     let inh = static_inherited_fields(ccx);
     let rty = ty::node_id_to_type(ccx.tcx, id);
     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
-    let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
+    let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
     check_const_with_ty(&fcx, sp, e, declty);
 }
 
index 09592db8a116d399abd4bf2d815942672ff56e9c..340cca7d47e7a395619bb5ae60ce9d1724e800a6 100644 (file)
@@ -380,7 +380,7 @@ fn try_adjust_upvar_deref(&self,
                 // borrow_kind of the upvar to make sure it
                 // is inferred to mutable if necessary
                 let mut upvar_capture_map = self.fcx.inh.upvar_capture_map.borrow_mut();
-                let ub = &mut upvar_capture_map[upvar_id];
+                let ub = upvar_capture_map.get_mut(&upvar_id).unwrap();
                 self.adjust_upvar_borrow_kind(upvar_id, ub, borrow_kind);
 
                 // also need to be in an FnMut closure since this is not an ImmBorrow
@@ -448,7 +448,7 @@ fn adjust_closure_kind(&self,
 
         let closure_def_id = ast_util::local_def(closure_id);
         let mut closure_kinds = self.fcx.inh.closure_kinds.borrow_mut();
-        let existing_kind = closure_kinds[closure_def_id];
+        let existing_kind = *closure_kinds.get(&closure_def_id).unwrap();
 
         debug!("adjust_closure_kind: closure_id={}, existing_kind={:?}, new_kind={:?}",
                closure_id, existing_kind, new_kind);
index 6b0fb8ac71af0479f8b3ab85cc304448da19fac6..ffd99ff2eece081f7390195ea24506fe83ebb302 100644 (file)
@@ -269,7 +269,7 @@ fn add_trait_impl(&self, base_def_id: DefId, impl_def_id: DefId) {
 
     fn get_self_type_for_implementation(&self, impl_did: DefId)
                                         -> TypeScheme<'tcx> {
-        self.crate_context.tcx.tcache.borrow()[impl_did].clone()
+        self.crate_context.tcx.tcache.borrow().get(&impl_did).unwrap().clone()
     }
 
     // Converts an implementation in the AST to a vector of items.
@@ -387,7 +387,7 @@ fn populate_destructor_table(&self) {
         };
 
         for &impl_did in &*trait_impls.borrow() {
-            let items = &(*impl_items)[impl_did];
+            let items = impl_items.get(&impl_did).unwrap();
             if items.len() < 1 {
                 // We'll error out later. For now, just don't ICE.
                 continue;
index 867dea9588568b515c68d7f699b258505e9da37c..e4926b119d5dbe551808b3e8bb2db99d0afd7d12 100644 (file)
@@ -27,55 +27,66 @@ struct UnsafetyChecker<'cx, 'tcx:'cx> {
     tcx: &'cx ty::ctxt<'tcx>
 }
 
-impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &'v ast::Item) {
-        match item.node {
-            ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
-                match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
-                    None => {
-                        // Inherent impl.
-                        match unsafety {
-                            ast::Unsafety::Normal => { /* OK */ }
-                            ast::Unsafety::Unsafe => {
-                                span_err!(self.tcx.sess, item.span, E0197,
-                                    "inherent impls cannot be declared as unsafe");
-                            }
-                        }
+impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
+    fn check_unsafety_coherence(&mut self, item: &'v ast::Item,
+                                unsafety: ast::Unsafety,
+                                polarity: ast::ImplPolarity) {
+        match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
+            None => {
+                // Inherent impl.
+                match unsafety {
+                    ast::Unsafety::Normal => { /* OK */ }
+                    ast::Unsafety::Unsafe => {
+                        span_err!(self.tcx.sess, item.span, E0197,
+                                  "inherent impls cannot be declared as unsafe");
                     }
+                }
+            }
 
-                    Some(trait_ref) => {
-                        let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
-                        match (trait_def.unsafety, unsafety, polarity) {
-                            (ast::Unsafety::Unsafe,
-                             ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
-                                span_err!(self.tcx.sess, item.span, E0198,
-                                    "negative implementations are not unsafe");
-                            }
+            Some(trait_ref) => {
+                let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
+                match (trait_def.unsafety, unsafety, polarity) {
+                    (ast::Unsafety::Unsafe,
+                     ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
+                        span_err!(self.tcx.sess, item.span, E0198,
+                                  "negative implementations are not unsafe");
+                    }
 
-                            (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
-                                span_err!(self.tcx.sess, item.span, E0199,
-                                    "implementing the trait `{}` is not unsafe",
-                                            trait_ref.user_string(self.tcx));
-                            }
+                    (ast::Unsafety::Normal, ast::Unsafety::Unsafe, _) => {
+                        span_err!(self.tcx.sess, item.span, E0199,
+                                  "implementing the trait `{}` is not unsafe",
+                                  trait_ref.user_string(self.tcx));
+                    }
 
-                            (ast::Unsafety::Unsafe,
-                             ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
-                                span_err!(self.tcx.sess, item.span, E0200,
-                                    "the trait `{}` requires an `unsafe impl` declaration",
-                                            trait_ref.user_string(self.tcx));
-                            }
+                    (ast::Unsafety::Unsafe,
+                     ast::Unsafety::Normal, ast::ImplPolarity::Positive) => {
+                        span_err!(self.tcx.sess, item.span, E0200,
+                                  "the trait `{}` requires an `unsafe impl` declaration",
+                                  trait_ref.user_string(self.tcx));
+                    }
 
-                            (ast::Unsafety::Unsafe,
-                             ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
-                            (ast::Unsafety::Unsafe,
-                             ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
-                            (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
-                                /* OK */
-                            }
-                        }
+                    (ast::Unsafety::Unsafe,
+                     ast::Unsafety::Normal, ast::ImplPolarity::Negative) |
+                    (ast::Unsafety::Unsafe,
+                     ast::Unsafety::Unsafe, ast::ImplPolarity::Positive) |
+                    (ast::Unsafety::Normal, ast::Unsafety::Normal, _) => {
+                        /* OK */
                     }
                 }
             }
+        }
+    }
+}
+
+impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> {
+    fn visit_item(&mut self, item: &'v ast::Item) {
+        match item.node {
+            ast::ItemDefaultImpl(unsafety, _) => {
+                self.check_unsafety_coherence(item, unsafety, ast::ImplPolarity::Positive);
+            }
+            ast::ItemImpl(unsafety, polarity, _, _, _, _) => {
+                self.check_unsafety_coherence(item, unsafety, polarity);
+            }
             _ => { }
         }
 
index 97cc3ac7c48a78aa2a79c1051be851fbf0e93b5e..5efc26825eab19ef63b9c939aa5ee9c2ad588980 100644 (file)
@@ -194,7 +194,7 @@ fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,
 
     fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
         let def_id = local_def(method_id);
-        match self.tcx.impl_or_trait_items.borrow()[def_id] {
+        match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
             ty::MethodTraitItem(ref mty) => mty.clone(),
             ty::TypeTraitItem(..) => {
                 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
@@ -545,7 +545,7 @@ fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
                   -> bool
 {
     if let ast::TyPath(None, _) = ast_ty.node {
-        let path_res = tcx.def_map.borrow()[ast_ty.id];
+        let path_res = *tcx.def_map.borrow().get(&ast_ty.id).unwrap();
         match path_res.base_def {
             def::DefSelfTy(node_id) =>
                 path_res.depth == 0 && node_id == param_id,
@@ -690,7 +690,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      container: ImplOrTraitItemContainer,
                                      ident: ast::Ident,
                                      id: ast::NodeId,
@@ -835,7 +835,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                               "associated items are not allowed in inherent impls");
                         }
 
-                        convert_associated_type(ccx, ImplContainer(local_def(it.id)),
+                        as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
                                                 impl_item.ident, impl_item.id, impl_item.vis);
 
                         let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
@@ -917,7 +917,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 match trait_item.node {
                     ast::MethodTraitItem(..) => {}
                     ast::TypeTraitItem(..) => {
-                        convert_associated_type(ccx, TraitContainer(local_def(it.id)),
+                        as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
                                                 trait_item.ident, trait_item.id, ast::Public);
                     }
                 }
@@ -1040,9 +1040,13 @@ fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 tcx.predicates.borrow_mut().insert(local_def(ctor_id), predicates);
             } else if struct_def.fields[0].node.kind.is_unnamed() {
                 // Tuple-like.
-                let inputs: Vec<_> = struct_def.fields.iter().map(
-                        |field| (*tcx.tcache.borrow())[
-                            local_def(field.node.id)].ty).collect();
+                let inputs: Vec<_> =
+                    struct_def.fields
+                              .iter()
+                              .map(|field| tcx.tcache.borrow().get(&local_def(field.node.id))
+                                                              .unwrap()
+                                                              .ty)
+                              .collect();
                 let ctor_fn_ty = ty::mk_ctor_fn(tcx,
                                                 local_def(ctor_id),
                                                 &inputs[..],
@@ -1987,7 +1991,7 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
         builtin_bounds,
         trait_bounds,
         region_bounds
-    } = astconv::partition_bounds(tcx, span, ast_bounds.as_slice());
+    } = astconv::partition_bounds(tcx, span, &ast_bounds);
 
     let mut projection_bounds = Vec::new();
 
index 421549f8b7ecb8ab838ed60dfeec7ea940299e39..8e9408c9ebc48e3d111431fbadab122279935d2a 100644 (file)
@@ -188,7 +188,7 @@ fn clean(&self, cx: &DocContext) -> Crate {
 
         let src = match cx.input {
             Input::File(ref path) => path.clone(),
-            Input::Str(_) => PathBuf::new("") // FIXME: this is wrong
+            Input::Str(_) => PathBuf::new() // FIXME: this is wrong
         };
 
         Crate {
index c2b6c940caea29291b36fa179c28d706e05b315c..57cb87e1b2d011fb7a4c08147bfc1a491e687f8c 100644 (file)
@@ -47,7 +47,7 @@ pub fn load_string(input: &Path) -> io::Result<Option<String>> {
 macro_rules! load_or_return {
     ($input: expr, $cant_read: expr, $not_utf8: expr) => {
         {
-            let input = PathBuf::new($input);
+            let input = PathBuf::from(&$input[..]);
             match ::externalfiles::load_string(&input) {
                 Err(e) => {
                     let _ = writeln!(&mut io::stderr(),
index 03a2d708ee43aa5b742c2efc9c19aacdf4764ecf..4d15abb91dc148f5044498eae7a42de4ded5e3d9 100644 (file)
@@ -290,7 +290,7 @@ fn resolved_path(w: &mut fmt::Formatter, did: ast::DefId, p: &clean::Path,
             if ast_util::is_local(did) || cache.inlined.contains(&did) {
                 Some(repeat("../").take(loc.len()).collect::<String>())
             } else {
-                match cache.extern_locations[did.krate] {
+                match cache.extern_locations[&did.krate] {
                     render::Remote(ref s) => Some(s.to_string()),
                     render::Local => {
                         Some(repeat("../").take(loc.len()).collect::<String>())
@@ -404,11 +404,11 @@ fn primitive_link(f: &mut fmt::Formatter,
             needs_termination = true;
         }
         Some(&cnum) => {
-            let path = &m.paths[ast::DefId {
+            let path = &m.paths[&ast::DefId {
                 krate: cnum,
                 node: ast::CRATE_NODE_ID,
             }];
-            let loc = match m.extern_locations[cnum] {
+            let loc = match m.extern_locations[&cnum] {
                 render::Remote(ref s) => Some(s.to_string()),
                 render::Local => {
                     let len = CURRENT_LOCATION_KEY.with(|s| s.borrow().len());
index 81daac7b90f0d018fb86ed71288a9f088ce8fffe..1b2fc5964ab9802e24dfe83f1f9b7fbe1acf2983 100644 (file)
@@ -300,7 +300,7 @@ pub fn run(mut krate: clean::Crate,
            passes: HashSet<String>) -> io::Result<()> {
     let src_root = match krate.src.parent() {
         Some(p) => p.to_path_buf(),
-        None => PathBuf::new(""),
+        None => PathBuf::new(),
     };
     let mut cx = Context {
         dst: dst,
@@ -784,7 +784,7 @@ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
 impl<'a> SourceCollector<'a> {
     /// Renders the given filename into its corresponding HTML source file.
     fn emit_source(&mut self, filename: &str) -> io::Result<()> {
-        let p = PathBuf::new(filename);
+        let p = PathBuf::from(filename);
 
         // If we couldn't open this file, then just returns because it
         // probably means that it's some standard library macro thing and we
@@ -819,7 +819,7 @@ fn emit_source(&mut self, filename: &str) -> io::Result<()> {
         let mut fname = p.file_name().expect("source has no filename")
                          .to_os_string();
         fname.push(".html");
-        cur.push(&fname);
+        cur.push(&fname[..]);
         let mut w = BufWriter::new(try!(File::create(&cur)));
 
         let title = format!("{} -- source", cur.file_name().unwrap()
@@ -1404,8 +1404,8 @@ fn href(&self, cx: &Context) -> Option<String> {
         // located, then we return `None`.
         } else {
             let cache = cache();
-            let path = &cache.external_paths[self.item.def_id];
-            let root = match cache.extern_locations[self.item.def_id.krate] {
+            let path = &cache.external_paths[&self.item.def_id];
+            let root = match cache.extern_locations[&self.item.def_id.krate] {
                 Remote(ref s) => s.to_string(),
                 Local => self.cx.root_path.clone(),
                 Unknown => return None,
@@ -1863,7 +1863,7 @@ fn trait_item(w: &mut fmt::Formatter, m: &clean::Item)
                 path = if ast_util::is_local(it.def_id) {
                     cx.current.connect("/")
                 } else {
-                    let path = &cache.external_paths[it.def_id];
+                    let path = &cache.external_paths[&it.def_id];
                     path[..path.len() - 1].connect("/")
                 },
                 ty = shortty(it).to_static_str(),
index 0650b4d515860902ab9409444b96822042a5611c..12baa849cc94d10086e6722cea4a362f7ac38398 100644 (file)
@@ -38,6 +38,7 @@
 #![feature(file_path)]
 #![feature(path_ext)]
 #![feature(path_relative_from)]
+#![feature(convert)]
 
 extern crate arena;
 extern crate getopts;
@@ -64,6 +65,8 @@
 use std::rc::Rc;
 use std::sync::mpsc::channel;
 
+#[allow(deprecated)] use std::old_path::Path;
+
 use externalfiles::ExternalHtml;
 use serialize::Decodable;
 use serialize::json::{self, Json};
@@ -249,7 +252,7 @@ pub fn main_args(args: &[String]) -> int {
     let should_test = matches.opt_present("test");
     let markdown_input = input.ends_with(".md") || input.ends_with(".markdown");
 
-    let output = matches.opt_str("o").map(|s| PathBuf::new(&s));
+    let output = matches.opt_str("o").map(|s| PathBuf::from(&s));
     let cfgs = matches.opt_strs("cfg");
 
     let external_html = match ExternalHtml::load(
@@ -269,7 +272,7 @@ pub fn main_args(args: &[String]) -> int {
             return test::run(input, cfgs, libs, externs, test_args, crate_name)
         }
         (false, true) => return markdown::render(input,
-                                                 output.unwrap_or(PathBuf::new("doc")),
+                                                 output.unwrap_or(PathBuf::from("doc")),
                                                  &matches, &external_html,
                                                  !matches.opt_present("markdown-no-toc")),
         (false, false) => {}
@@ -287,7 +290,7 @@ pub fn main_args(args: &[String]) -> int {
     match matches.opt_str("w").as_ref().map(|s| &**s) {
         Some("html") | None => {
             match html::render::run(krate, &external_html,
-                                    output.unwrap_or(PathBuf::new("doc")),
+                                    output.unwrap_or(PathBuf::from("doc")),
                                     passes.into_iter().collect()) {
                 Ok(()) => {}
                 Err(e) => panic!("failed to generate documentation: {}", e),
@@ -295,7 +298,7 @@ pub fn main_args(args: &[String]) -> int {
         }
         Some("json") => {
             match json_output(krate, json_plugins,
-                              output.unwrap_or(PathBuf::new("doc.json"))) {
+                              output.unwrap_or(PathBuf::from("doc.json"))) {
                 Ok(()) => {}
                 Err(e) => panic!("failed to write json: {}", e),
             }
@@ -374,7 +377,7 @@ fn rust_input(cratefile: &str, externs: core::Externs, matches: &getopts::Matche
     let cfgs = matches.opt_strs("cfg");
     let triple = matches.opt_str("target");
 
-    let cr = PathBuf::new(cratefile);
+    let cr = PathBuf::from(cratefile);
     info!("starting to run rustc");
 
     let (tx, rx) = channel();
index 3db0162969f46b04a5a45f7e8f92d95182b11bea..fac8f2e2a9cc2cef926786095fa4466075c2b85d 100644 (file)
@@ -16,6 +16,7 @@
 use serialize::json;
 use std::mem;
 use std::string::String;
+use std::old_path::{Path, GenericPath};
 
 pub type PluginJson = Option<(String, json::Json)>;
 pub type PluginResult = (clean::Crate, PluginJson);
index e2f8a6f82c6442df51e271223ddc4e82b91fa95b..0b79fa7970dfd745e19a73df778d155cb4804141 100644 (file)
@@ -46,7 +46,7 @@ pub fn run(input: &str,
            mut test_args: Vec<String>,
            crate_name: Option<String>)
            -> int {
-    let input_path = PathBuf::new(input);
+    let input_path = PathBuf::from(input);
     let input = config::Input::File(input_path.clone());
 
     let sessopts = config::Options {
index d53954b29b585422bc3305b821476fa41e8e45e8..11e10cc2aa7a16cf004fdb8933d7e47283df978d 100644 (file)
@@ -196,7 +196,7 @@ fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>,
             Some(tcx) => tcx,
             None => return false
         };
-        let def = tcx.def_map.borrow()[id].def_id();
+        let def = tcx.def_map.borrow()[&id].def_id();
         if !ast_util::is_local(def) { return false }
         let analysis = match self.analysis {
             Some(analysis) => analysis, None => return false
index 529ed8598b1ac13e9ccb2daa4ad0dcac6c62b5cd..abbfc82319f5b30e24035442aedaaa532c0e80a4 100644 (file)
@@ -1218,6 +1218,7 @@ pub fn as_null(&self) -> Option<()> {
     }
 }
 
+#[cfg(stage0)]
 impl<'a> Index<&'a str>  for Json {
     type Output = Json;
 
@@ -1226,6 +1227,16 @@ fn index(&self, idx: & &str) -> &Json {
     }
 }
 
+#[cfg(not(stage0))]
+impl<'a> Index<&'a str>  for Json {
+    type Output = Json;
+
+    fn index(&self, idx: &'a str) -> &Json {
+        self.find(idx).unwrap()
+    }
+}
+
+#[cfg(stage0)]
 impl Index<uint> for Json {
     type Output = Json;
 
@@ -1237,6 +1248,18 @@ fn index<'a>(&'a self, idx: &uint) -> &'a Json {
     }
 }
 
+#[cfg(not(stage0))]
+impl Index<uint> for Json {
+    type Output = Json;
+
+    fn index<'a>(&'a self, idx: uint) -> &'a Json {
+        match self {
+            &Json::Array(ref v) => &v[idx],
+            _ => panic!("can only index Json with uint if it is an array")
+        }
+    }
+}
+
 /// The output of the streaming parser.
 #[derive(PartialEq, Clone, Debug)]
 pub enum JsonEvent {
@@ -2622,6 +2645,7 @@ mod tests {
     use std::{i64, u64, f32, f64};
     use std::collections::BTreeMap;
     use std::string;
+    use std::old_io::Writer;
 
     #[derive(RustcDecodable, Eq, PartialEq, Debug)]
     struct OptionData {
index 90cb88046e53d008416577d3934a927888b6dbe9..f320f723c2ed6286bf6656819729de2c2ba57cdb 100644 (file)
@@ -37,6 +37,7 @@
 #![feature(std_misc)]
 #![feature(unicode)]
 #![feature(str_char)]
+#![feature(convert)]
 #![cfg_attr(test, feature(test))]
 
 // test harness access
index 77e2da7ec79139332a256923f5e8a476bcafa6ae..5e9baa9b9e903557236e407db817a01b0790fe3b 100644 (file)
@@ -15,7 +15,7 @@
 */
 
 #[allow(deprecated)]
-use std::old_path;
+use std::old_path::{self, GenericPath};
 use std::path;
 use std::rc::Rc;
 use std::cell::{Cell, RefCell};
@@ -579,7 +579,7 @@ fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
 impl Decodable for path::PathBuf {
     fn decode<D: Decoder>(d: &mut D) -> Result<path::PathBuf, D::Error> {
         let bytes: String = try!(Decodable::decode(d));
-        Ok(path::PathBuf::new(&bytes))
+        Ok(path::PathBuf::from(bytes))
     }
 }
 
index 60b1738d2c98918351082c0da31efbfc78b08aed..86664d7eb0cf14ad9b81eaba3c3fe7a5be344bd0 100644 (file)
@@ -23,7 +23,7 @@
 use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
 use marker::Sized;
 use mem::{self, replace};
-use ops::{Deref, FnMut, Index, IndexMut};
+use ops::{Deref, FnMut, Index};
 use option::Option::{self, Some, None};
 use rand::{self, Rng};
 use result::Result::{self, Ok, Err};
@@ -1088,7 +1088,7 @@ pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
     ///     Some(x) => *x = "b",
     ///     None => (),
     /// }
-    /// assert_eq!(map[1], "b");
+    /// assert_eq!(map[&1], "b");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
@@ -1111,7 +1111,7 @@ pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
     ///
     /// map.insert(37, "b");
     /// assert_eq!(map.insert(37, "c"), Some("b"));
-    /// assert_eq!(map[37], "c");
+    /// assert_eq!(map[&37], "c");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
@@ -1244,6 +1244,7 @@ fn default() -> HashMap<K, V, S> {
     }
 }
 
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, Q: ?Sized, V, S> Index<Q> for HashMap<K, V, S>
     where K: Eq + Hash + Borrow<Q>,
@@ -1258,15 +1259,18 @@ fn index<'a>(&'a self, index: &Q) -> &'a V {
     }
 }
 
+#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
+impl<'a, K, Q: ?Sized, V, S> Index<&'a Q> for HashMap<K, V, S>
     where K: Eq + Hash + Borrow<Q>,
           Q: Eq + Hash,
           S: HashState,
 {
+    type Output = V;
+
     #[inline]
-    fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
-        self.get_mut(index).expect("no entry found for key")
+    fn index(&self, index: &Q) -> &V {
+        self.get(index).expect("no entry found for key")
     }
 }
 
@@ -2197,7 +2201,7 @@ fn test_index() {
         map.insert(2, 1);
         map.insert(3, 4);
 
-        assert_eq!(map[2], 1);
+        assert_eq!(map[&2], 1);
     }
 
     #[test]
@@ -2209,7 +2213,7 @@ fn test_index_nonexistent() {
         map.insert(2, 1);
         map.insert(3, 4);
 
-        map[4];
+        map[&4];
     }
 
     #[test]
index a42809127bf5c8912c0568a281607db410f23047..085bf01612d30519172fe94f26775d63fff2a881 100644 (file)
 
 use prelude::v1::*;
 
+use env;
 use ffi::CString;
 use mem;
-use env;
-use str;
+use old_path::{Path, GenericPath};
 use os;
+use str;
 
 pub struct DynamicLibrary {
     handle: *mut u8
@@ -133,6 +134,7 @@ mod test {
     use super::*;
     use prelude::v1::*;
     use libc;
+    use old_path::Path;
     use mem;
 
     #[test]
@@ -140,8 +142,7 @@ mod test {
     fn test_loading_cosine() {
         // The math library does not need to be loaded since it is already
         // statically linked in
-        let none: Option<&Path> = None; // appease the typechecker
-        let libm = match DynamicLibrary::open(none) {
+        let libm = match DynamicLibrary::open(None) {
             Err(error) => panic!("Could not load self as module: {}", error),
             Ok(libm) => libm
         };
index 4b6fbe01f760bbe0b19b85d22f21a34b6561f55a..9d6933ce9c89c673d008f103e9bbca800e853280 100644 (file)
@@ -23,7 +23,7 @@
 use ffi::{OsString, AsOsStr};
 use fmt;
 use io;
-use path::{AsPath, PathBuf};
+use path::{self, Path, PathBuf};
 use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
 use sync::{StaticMutex, MUTEX_INIT};
 use sys::os as os_imp;
@@ -67,8 +67,8 @@ pub fn current_dir() -> io::Result<PathBuf> {
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
-pub fn set_current_dir<P: AsPath + ?Sized>(p: &P) -> io::Result<()> {
-    os_imp::chdir(p.as_path())
+pub fn set_current_dir<P: AsRef<Path> + ?Sized>(p: &P) -> io::Result<()> {
+    os_imp::chdir(p.as_ref())
 }
 
 static ENV_LOCK: StaticMutex = MUTEX_INIT;
@@ -729,10 +729,11 @@ mod arch {
 mod tests {
     use prelude::v1::*;
     use super::*;
+
     use iter::repeat;
     use rand::{self, Rng};
     use ffi::{OsString, OsStr};
-    use path::PathBuf;
+    use path::{Path, PathBuf};
 
     fn make_rand_name() -> OsString {
         let mut rng = rand::thread_rng();
index fc4f03ff3a54a808d3a28a27a6074a57caa29ddd..1760445a0fcd4ec7c4693150f734711dc4ec1967 100644 (file)
@@ -10,6 +10,7 @@
 
 #![unstable(feature = "std_misc")]
 
+use convert::Into;
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
 use error::{Error, FromError};
 use fmt;
@@ -130,6 +131,8 @@ pub struct CStr {
 
 /// A conversion trait used by the constructor of `CString` for types that can
 /// be converted to a vector of bytes.
+#[deprecated(since = "1.0.0", reason = "use std::convert::Into<Vec<u8>> instead")]
+#[unstable(feature = "std_misc")]
 pub trait IntoBytes {
     /// Consumes this container, returning a vector of bytes.
     fn into_bytes(self) -> Vec<u8>;
@@ -163,8 +166,8 @@ impl CString {
     /// internal 0 byte. The error returned will contain the bytes as well as
     /// the position of the nul byte.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new<T: IntoBytes>(t: T) -> Result<CString, NulError> {
-        let bytes = t.into_bytes();
+    pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
+        let bytes = t.into();
         match bytes.iter().position(|x| *x == 0) {
             Some(i) => Err(NulError(i, bytes)),
             None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
@@ -433,15 +436,19 @@ pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
     slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
 }
 
+#[allow(deprecated)]
 impl<'a> IntoBytes for &'a str {
     fn into_bytes(self) -> Vec<u8> { self.as_bytes().to_vec() }
 }
+#[allow(deprecated)]
 impl<'a> IntoBytes for &'a [u8] {
     fn into_bytes(self) -> Vec<u8> { self.to_vec() }
 }
+#[allow(deprecated)]
 impl IntoBytes for String {
     fn into_bytes(self) -> Vec<u8> { self.into_bytes() }
 }
+#[allow(deprecated)]
 impl IntoBytes for Vec<u8> {
     fn into_bytes(self) -> Vec<u8> { self }
 }
index feacbf1e98b81e9fe0e3a9cec8b1975a606041fd..5851c6e2998095923c744da0d01fceeb6556355b 100644 (file)
@@ -63,16 +63,18 @@ pub struct OsStr {
 impl OsString {
     /// Constructs an `OsString` at no cost by consuming a `String`.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "use `from` instead")]
     pub fn from_string(s: String) -> OsString {
-        OsString { inner: Buf::from_string(s) }
+        OsString::from(s)
     }
 
     /// Constructs an `OsString` by copying from a `&str` slice.
     ///
     /// Equivalent to: `OsString::from_string(String::from_str(s))`.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[deprecated(since = "1.0.0", reason = "use `from` instead")]
     pub fn from_str(s: &str) -> OsString {
-        OsString { inner: Buf::from_str(s) }
+        OsString::from(s)
     }
 
     /// Constructs a new empty `OsString`.
@@ -98,11 +100,40 @@ pub fn push_os_str(&mut self, s: &OsStr) {
 
     /// Extend the string with the given `&OsStr` slice.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn push<T: AsOsStr + ?Sized>(&mut self, s: &T) {
-        self.inner.push_slice(&s.as_os_str().inner)
+    pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
+        self.inner.push_slice(&s.as_ref().inner)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl From<String> for OsString {
+    fn from(s: String) -> OsString {
+        OsString { inner: Buf::from_string(s) }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a String> for OsString {
+    fn from(s: &'a String) -> OsString {
+        OsString { inner: Buf::from_str(s) }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a str> for OsString {
+    fn from(s: &'a str) -> OsString {
+        OsString { inner: Buf::from_str(s) }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a OsStr> for OsString {
+    fn from(s: &'a OsStr) -> OsString {
+        OsString { inner: s.inner.to_owned() }
     }
 }
 
+#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::RangeFull> for OsString {
     type Output = OsStr;
@@ -113,6 +144,17 @@ fn index(&self, _index: &ops::RangeFull) -> &OsStr {
     }
 }
 
+#[cfg(not(stage0))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ops::Index<ops::RangeFull> for OsString {
+    type Output = OsStr;
+
+    #[inline]
+    fn index(&self, _index: ops::RangeFull) -> &OsStr {
+        unsafe { mem::transmute(self.inner.as_slice()) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Deref for OsString {
     type Target = OsStr;
@@ -316,37 +358,76 @@ fn to_owned(&self) -> OsString { self.to_os_string() }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl<'a, T: AsOsStr + ?Sized> AsOsStr for &'a T {
     fn as_os_str(&self) -> &OsStr {
         (*self).as_os_str()
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for OsStr {
     fn as_os_str(&self) -> &OsStr {
         self
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for OsString {
     fn as_os_str(&self) -> &OsStr {
         &self[..]
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for str {
     fn as_os_str(&self) -> &OsStr {
         OsStr::from_str(self)
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for String {
     fn as_os_str(&self) -> &OsStr {
         OsStr::from_str(&self[..])
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for OsStr {
+    fn as_ref(&self) -> &OsStr {
+        self
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for OsString {
+    fn as_ref(&self) -> &OsStr {
+        self
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for str {
+    fn as_ref(&self) -> &OsStr {
+        OsStr::from_str(self)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for String {
+    fn as_ref(&self) -> &OsStr {
+        OsStr::from_str(&self[..])
+    }
+}
+
 #[allow(deprecated)]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for Path {
     #[cfg(unix)]
     fn as_os_str(&self) -> &OsStr {
index c56852cb18a0577b93ca8895a34c44a1d0c44965..ab65004f5d1f9984d7f869857db0f6e4964e21c7 100644 (file)
@@ -20,7 +20,7 @@
 use core::prelude::*;
 
 use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
-use path::{AsPath, Path, PathBuf};
+use path::{Path, PathBuf};
 use sys::fs2 as fs_imp;
 use sys_common::{AsInnerMut, FromInner, AsInner};
 use vec::Vec;
@@ -129,7 +129,7 @@ impl File {
     /// This function will return an error if `path` does not already exist.
     /// Other errors may also be returned according to `OpenOptions::open`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn open<P: AsPath>(path: P) -> io::Result<File> {
+    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
         OpenOptions::new().read(true).open(path)
     }
 
@@ -140,7 +140,7 @@ pub fn open<P: AsPath>(path: P) -> io::Result<File> {
     ///
     /// See the `OpenOptions::open` function for more details.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn create<P: AsPath>(path: P) -> io::Result<File> {
+    pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
         OpenOptions::new().write(true).create(true).truncate(true).open(path)
     }
 
@@ -302,8 +302,8 @@ pub fn create(&mut self, create: bool) -> &mut OpenOptions {
     ///   permissions for
     /// * Filesystem-level errors (full disk, etc)
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn open<P: AsPath>(&self, path: P) -> io::Result<File> {
-        let path = path.as_path();
+    pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
+        let path = path.as_ref();
         let inner = try!(fs_imp::File::open(path, &self.0));
         Ok(File { path: path.to_path_buf(), inner: inner })
     }
@@ -415,8 +415,8 @@ pub fn path(&self) -> PathBuf { self.0.path() }
 /// user lacks permissions to remove the file, or if some other filesystem-level
 /// error occurs.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn remove_file<P: AsPath>(path: P) -> io::Result<()> {
-    fs_imp::unlink(path.as_path())
+pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
+    fs_imp::unlink(path.as_ref())
 }
 
 /// Given a path, query the file system to get information about a file,
@@ -443,8 +443,8 @@ pub fn remove_file<P: AsPath>(path: P) -> io::Result<()> {
 /// permissions to perform a `metadata` call on the given `path` or if there
 /// is no entry in the filesystem at the provided path.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn metadata<P: AsPath>(path: P) -> io::Result<Metadata> {
-    fs_imp::stat(path.as_path()).map(Metadata)
+pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
+    fs_imp::stat(path.as_ref()).map(Metadata)
 }
 
 /// Rename a file or directory to a new name.
@@ -464,8 +464,8 @@ pub fn metadata<P: AsPath>(path: P) -> io::Result<Metadata> {
 /// reside on separate filesystems, or if some other intermittent I/O error
 /// occurs.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn rename<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<()> {
-    fs_imp::rename(from.as_path(), to.as_path())
+pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
+    fs_imp::rename(from.as_ref(), to.as_ref())
 }
 
 /// Copies the contents of one file to another. This function will also
@@ -494,9 +494,9 @@ pub fn rename<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<()> {
 /// * The current process does not have the permission rights to access
 ///   `from` or write `to`
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn copy<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<u64> {
-    let from = from.as_path();
-    let to = to.as_path();
+pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
+    let from = from.as_ref();
+    let to = to.as_ref();
     if !from.is_file() {
         return Err(Error::new(ErrorKind::InvalidInput,
                               "the source path is not an existing file",
@@ -517,16 +517,16 @@ pub fn copy<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<u64> {
 /// The `dst` path will be a link pointing to the `src` path. Note that systems
 /// often require these two paths to both be located on the same filesystem.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn hard_link<P: AsPath, Q: AsPath>(src: P, dst: Q) -> io::Result<()> {
-    fs_imp::link(src.as_path(), dst.as_path())
+pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
+    fs_imp::link(src.as_ref(), dst.as_ref())
 }
 
 /// Creates a new soft link on the filesystem.
 ///
 /// The `dst` path will be a soft link pointing to the `src` path.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn soft_link<P: AsPath, Q: AsPath>(src: P, dst: Q) -> io::Result<()> {
-    fs_imp::symlink(src.as_path(), dst.as_path())
+pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
+    fs_imp::symlink(src.as_ref(), dst.as_ref())
 }
 
 /// Reads a soft link, returning the file that the link points to.
@@ -537,8 +537,8 @@ pub fn soft_link<P: AsPath, Q: AsPath>(src: P, dst: Q) -> io::Result<()> {
 /// reading a file that does not exist or reading a file that is not a soft
 /// link.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn read_link<P: AsPath>(path: P) -> io::Result<PathBuf> {
-    fs_imp::readlink(path.as_path())
+pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
+    fs_imp::readlink(path.as_ref())
 }
 
 /// Create a new, empty directory at the provided path
@@ -556,8 +556,8 @@ pub fn read_link<P: AsPath>(path: P) -> io::Result<PathBuf> {
 /// This function will return an error if the user lacks permissions to make a
 /// new directory at the provided `path`, or if the directory already exists.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn create_dir<P: AsPath>(path: P) -> io::Result<()> {
-    fs_imp::mkdir(path.as_path())
+pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
+    fs_imp::mkdir(path.as_ref())
 }
 
 /// Recursively create a directory and all of its parent components if they
@@ -570,8 +570,8 @@ pub fn create_dir<P: AsPath>(path: P) -> io::Result<()> {
 /// error conditions for when a directory is being created (after it is
 /// determined to not exist) are outlined by `fs::create_dir`.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn create_dir_all<P: AsPath>(path: P) -> io::Result<()> {
-    let path = path.as_path();
+pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
+    let path = path.as_ref();
     if path.is_dir() { return Ok(()) }
     if let Some(p) = path.parent() { try!(create_dir_all(p)) }
     create_dir(path)
@@ -592,8 +592,8 @@ pub fn create_dir_all<P: AsPath>(path: P) -> io::Result<()> {
 /// This function will return an error if the user lacks permissions to remove
 /// the directory at the provided `path`, or if the directory isn't empty.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn remove_dir<P: AsPath>(path: P) -> io::Result<()> {
-    fs_imp::rmdir(path.as_path())
+pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
+    fs_imp::rmdir(path.as_ref())
 }
 
 /// Removes a directory at this path, after removing all its contents. Use
@@ -606,8 +606,8 @@ pub fn remove_dir<P: AsPath>(path: P) -> io::Result<()> {
 ///
 /// See `file::remove_file` and `fs::remove_dir`
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn remove_dir_all<P: AsPath>(path: P) -> io::Result<()> {
-    let path = path.as_path();
+pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
+    let path = path.as_ref();
     for child in try!(read_dir(path)) {
         let child = try!(child).path();
         let stat = try!(lstat(&*child));
@@ -659,8 +659,8 @@ fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
 /// the process lacks permissions to view the contents or if the `path` points
 /// at a non-directory file
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn read_dir<P: AsPath>(path: P) -> io::Result<ReadDir> {
-    fs_imp::readdir(path.as_path()).map(ReadDir)
+pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
+    fs_imp::readdir(path.as_ref()).map(ReadDir)
 }
 
 /// Returns an iterator that will recursively walk the directory structure
@@ -675,7 +675,7 @@ pub fn read_dir<P: AsPath>(path: P) -> io::Result<ReadDir> {
            reason = "the precise semantics and defaults for a recursive walk \
                      may change and this may end up accounting for files such \
                      as symlinks differently")]
-pub fn walk_dir<P: AsPath>(path: P) -> io::Result<WalkDir> {
+pub fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<WalkDir> {
     let start = try!(read_dir(path));
     Ok(WalkDir { cur: Some(start), stack: Vec::new() })
 }
@@ -761,9 +761,9 @@ fn is_dir(&self) -> bool {
            reason = "the argument type of u64 is not quite appropriate for \
                      this function and may change if the standard library \
                      gains a type to represent a moment in time")]
-pub fn set_file_times<P: AsPath>(path: P, accessed: u64,
+pub fn set_file_times<P: AsRef<Path>>(path: P, accessed: u64,
                                  modified: u64) -> io::Result<()> {
-    fs_imp::utimes(path.as_path(), accessed, modified)
+    fs_imp::utimes(path.as_ref(), accessed, modified)
 }
 
 /// Changes the permissions found on a file or a directory.
@@ -790,8 +790,8 @@ pub fn set_file_times<P: AsPath>(path: P, accessed: u64,
            reason = "a more granual ability to set specific permissions may \
                      be exposed on the Permissions structure itself and this \
                      method may not always exist")]
-pub fn set_permissions<P: AsPath>(path: P, perm: Permissions) -> io::Result<()> {
-    fs_imp::set_perm(path.as_path(), perm.0)
+pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
+    fs_imp::set_perm(path.as_ref(), perm.0)
 }
 
 #[cfg(test)]
@@ -801,6 +801,7 @@ mod tests {
     use prelude::v1::*;
     use io::prelude::*;
 
+    use env;
     use fs::{self, File, OpenOptions};
     use io::{ErrorKind, SeekFrom};
     use path::PathBuf;
@@ -848,8 +849,7 @@ fn drop(&mut self) {
     }
 
     pub fn tmpdir() -> TempDir {
-        let s = os::tmpdir();
-        let p = Path2::new(s.as_str().unwrap());
+        let p = env::temp_dir();
         let ret = p.join(&format!("rust-{}", rand::random::<u32>()));
         check!(fs::create_dir(&ret));
         TempDir(ret)
@@ -1082,7 +1082,7 @@ fn file_test_directoryinfo_readdir() {
         let dir = &tmpdir.join("di_readdir");
         check!(fs::create_dir(dir));
         let prefix = "foo";
-        for n in range(0, 3) {
+        for n in 0..3 {
             let f = dir.join(&format!("{}.txt", n));
             let mut w = check!(File::create(&f));
             let msg_str = format!("{}{}", prefix, n.to_string());
@@ -1537,7 +1537,7 @@ fn utime_noexist() {
     #[test]
     fn binary_file() {
         let mut bytes = [0; 1024];
-        StdRng::new().ok().unwrap().fill_bytes(&mut bytes);
+        StdRng::new().unwrap().fill_bytes(&mut bytes);
 
         let tmpdir = tmpdir();
 
index 8f32d7a586459241324a3a249a6ede228c4bce55..a9717e36323392a74e55325916a306f9b52bd503 100644 (file)
@@ -18,7 +18,7 @@
 use env;
 use io::{self, Error, ErrorKind};
 use fs;
-use path::{self, PathBuf, AsPath};
+use path::{self, PathBuf};
 use rand::{thread_rng, Rng};
 
 /// A wrapper for a path to temporary directory implementing automatic
@@ -43,10 +43,9 @@ impl TempDir {
     ///
     /// If no directory can be created, `Err` is returned.
     #[allow(deprecated)] // rand usage
-    pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
-                                      -> io::Result<TempDir> {
+    pub fn new_in<P: AsRef<path::Path>>(tmpdir: P, prefix: &str) -> io::Result<TempDir> {
         let storage;
-        let mut tmpdir = tmpdir.as_path();
+        let mut tmpdir = tmpdir.as_ref();
         if !tmpdir.is_absolute() {
             let cur_dir = try!(env::current_dir());
             storage = cur_dir.join(tmpdir);
index 43eec695274208213e2a1f4e9850a2c58879037f..4def601f1c0e7657f6a3e7da1c057ec3c53da99a 100644 (file)
@@ -258,7 +258,7 @@ fn from_error(iie: IntoInnerError<W>) -> Error { iie.1 }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> error::Error for IntoInnerError<W> {
+impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
     fn description(&self) -> &str {
         error::Error::description(self.error())
     }
index e6debeb2a9ce7757fd16f1ff7598c14e5518624e..0dde464267786dcb3dd8a367f7934ad8803b900e 100644 (file)
@@ -278,7 +278,7 @@ fn test_mem_reader() {
     fn read_to_end() {
         let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
         let mut v = Vec::new();
-        reader.read_to_end(&mut v).ok().unwrap();
+        reader.read_to_end(&mut v).unwrap();
         assert_eq!(v, [0, 1, 2, 3, 4, 5, 6, 7]);
     }
 
index 6bf0ebd1a59e9c8b0a744e7be449f6f83c2d18ef..a2ceacbe1f897ba62c6d4ba46b3daf2ecd4884d9 100644 (file)
@@ -23,8 +23,5 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-pub use super::{Read, Write, BufRead};
+pub use super::{Read, Write, BufRead, Seek};
 pub use fs::PathExt;
-
-// FIXME: pub use as `Seek` when the name isn't in the actual prelude any more
-pub use super::Seek as NewSeek;
index b055796ba547fefc9ce9ea8df62d797373d89cc9..fbec96e9310f16c442695ba2a0c297a74f7f7d9b 100644 (file)
 #![feature(hash)]
 #![feature(int_uint)]
 #![feature(unique)]
+#![feature(convert)]
 #![feature(allow_internal_unstable)]
 #![feature(str_char)]
+#![feature(into_cow)]
 #![cfg_attr(test, feature(test, rustc_private))]
 
 // Don't link to std. We are std.
 pub use core::cell;
 pub use core::clone;
 #[cfg(not(test))] pub use core::cmp;
+pub use core::convert;
 pub use core::default;
 #[allow(deprecated)]
 pub use core::finally;
 /* Runtime and platform support */
 
 #[macro_use]
-pub mod thread_local;
+pub mod thread;
 
+pub mod collections;
 pub mod dynamic_lib;
+pub mod env;
 pub mod ffi;
-pub mod old_io;
-pub mod io;
 pub mod fs;
+pub mod io;
 pub mod net;
+pub mod old_io;
+pub mod old_path;
 pub mod os;
-pub mod env;
 pub mod path;
-pub mod old_path;
 pub mod process;
 pub mod rand;
-pub mod time;
-
-/* Common data structures */
-
-pub mod collections;
-
-/* Threads and communication */
-
-pub mod thread;
 pub mod sync;
+pub mod time;
 
 #[macro_use]
 #[path = "sys/common/mod.rs"] mod sys_common;
@@ -305,7 +301,7 @@ mod std {
     pub use rt; // used for panic!()
     pub use vec; // used for vec![]
     pub use cell; // used for tls!
-    pub use thread_local; // used for thread_local!
+    pub use thread; // used for thread_local!
     pub use marker;  // used for tls!
     pub use ops; // used for bitflags!
 
index 702f81db8e22faa07971f65d089ce5125b6da1f8..872411170438cfda13687f5366493105895c849e 100644 (file)
@@ -617,7 +617,7 @@ fn check(str_addr: &str, unspec: bool, loopback: bool,
                  unique_local: bool, global: bool,
                  u_link_local: bool, u_site_local: bool, u_global: bool,
                  m_scope: Option<Ipv6MulticastScope>) {
-            let ip: Ipv6Addr = str_addr.parse().ok().unwrap();
+            let ip: Ipv6Addr = str_addr.parse().unwrap();
             assert_eq!(str_addr, ip.to_string());
 
             assert_eq!(ip.is_unspecified(), unspec);
index 73c2464a6b2cb9b33449568b3149c34a3e0e3a9e..d737ad17ff8ecf7220cdb3d894b735ef3246b151 100644 (file)
@@ -374,7 +374,6 @@ fn fmt_subslice(segments: &[u16]) -> String {
                             .iter()
                             .map(|&seg| format!("{:x}", seg))
                             .collect::<Vec<String>>()
-                            .as_slice()
                             .connect(":")
                     }
 
index 082dad613b5561891bd11be67406f354e198fa9b..562094a87f4e5db0a8a1ccefa2a67e5217d8b490 100644 (file)
@@ -1650,7 +1650,7 @@ fn $test_name() {
                 #![test]
                 assert_eq!((0 as $T).next_power_of_two(), 1);
                 let mut next_power = 1;
-                for i in range::<$T>(1, 40) {
+                for i in 1 as $T..40 {
                      assert_eq!(i.next_power_of_two(), next_power);
                      if i == next_power { next_power *= 2 }
                 }
@@ -1673,7 +1673,7 @@ fn $test_name() {
                 assert_eq!(($T::MAX - 1).checked_next_power_of_two(), None);
                 assert_eq!($T::MAX.checked_next_power_of_two(), None);
                 let mut next_power = 1;
-                for i in range::<$T>(1, 40) {
+                for i in 1 as $T..40 {
                      assert_eq!(i.checked_next_power_of_two(), Some(next_power));
                      if i == next_power { next_power *= 2 }
                 }
index 56bc21303bbcac039278545be16de691caf08894..3e5f732e345453d3f7c9eb396137433d56ad1486 100644 (file)
@@ -33,7 +33,8 @@
 /// # Examples
 ///
 /// ```
-/// use std::old_io::{BufferedReader, File};
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let file = File::open(&Path::new("message.txt"));
 /// let mut reader = BufferedReader::new(file);
@@ -136,7 +137,8 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 /// # Examples
 ///
 /// ```
-/// use std::old_io::{BufferedWriter, File};
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let file = File::create(&Path::new("message.txt")).unwrap();
 /// let mut writer = BufferedWriter::new(file);
@@ -323,7 +325,8 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::{BufferedStream, File};
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let file = File::open(&Path::new("message.txt"));
 /// let mut stream = BufferedStream::new(file);
@@ -422,7 +425,7 @@ fn flush(&mut self) -> IoResult<()> {
 #[cfg(test)]
 mod test {
     extern crate test;
-    use old_io;
+    use old_io::{self, Reader, Writer, Buffer, BufferPrelude};
     use prelude::v1::*;
     use super::*;
     use super::super::{IoResult, EndOfFile};
index 2dc61f409e2a4524cf6e8fa4f7e9698376b926a7..7e62a21f105cd8d43ab16c8c98458db6c9f9f440 100644 (file)
@@ -24,7 +24,7 @@
 ///
 /// ```
 /// use std::sync::mpsc::channel;
-/// use std::old_io::ChanReader;
+/// use std::old_io::*;
 ///
 /// let (tx, rx) = channel();
 /// # drop(tx);
@@ -116,7 +116,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 /// ```
 /// # #![allow(unused_must_use)]
 /// use std::sync::mpsc::channel;
-/// use std::old_io::ChanWriter;
+/// use std::old_io::*;
 ///
 /// let (tx, rx) = channel();
 /// # drop(rx);
@@ -160,7 +160,7 @@ mod test {
 
     use sync::mpsc::channel;
     use super::*;
-    use old_io;
+    use old_io::{self, Reader, Writer, Buffer};
     use thread;
 
     #[test]
index 12c9970aa84393f8ca2b8746e8b22fdec81e25a3..2990c1c265d54fcb14b2efd5fd3d73d5587fb2e8 100644 (file)
@@ -179,7 +179,7 @@ pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
 #[cfg(test)]
 mod test {
     use prelude::v1::*;
-    use old_io;
+    use old_io::{self, Reader, Writer};
     use old_io::{MemReader, BytesReader};
 
     struct InitialZeroByteReader {
index 2df925beb3667e9afe882821f1ae0eacf3733216..87e5b91fc2820d84729252d9234b0a1dcbc5f66b 100644 (file)
@@ -32,7 +32,8 @@
 //! ```rust
 //! # #![allow(unused_must_use)]
 //! use std::old_io::fs::PathExtensions;
-//! use std::old_io::{File, fs};
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! let path = Path::new("foo.txt");
 //!
@@ -104,7 +105,8 @@ impl File {
     /// # Examples
     ///
     /// ```rust,should_fail
-    /// use std::old_io::{File, Open, ReadWrite};
+    /// use std::old_io::*;
+    /// use std::old_path::Path;
     ///
     /// let p = Path::new("/some/file/path.txt");
     ///
@@ -175,7 +177,8 @@ pub fn open_mode(path: &Path,
     /// # Examples
     ///
     /// ```
-    /// use std::old_io::File;
+    /// use std::old_io::*;
+    /// use std::old_path::Path;
     ///
     /// let contents = File::open(&Path::new("foo.txt")).read_to_end();
     /// ```
@@ -195,7 +198,8 @@ pub fn open(path: &Path) -> IoResult<File> {
     ///
     /// ```
     /// # #![allow(unused_must_use)]
-    /// use std::old_io::File;
+    /// use std::old_io::*;
+    /// use std::old_path::Path;
     ///
     /// let mut f = File::create(&Path::new("foo.txt"));
     /// f.write(b"This is a sample file");
@@ -286,7 +290,8 @@ pub fn stat(&self) -> IoResult<FileStat> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let p = Path::new("/some/file/path.txt");
 /// fs::unlink(&p);
@@ -316,7 +321,8 @@ pub fn unlink(path: &Path) -> IoResult<()> {
 /// # Examples
 ///
 /// ```
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let p = Path::new("/some/file/path.txt");
 /// match fs::stat(&p) {
@@ -359,7 +365,8 @@ pub fn lstat(path: &Path) -> IoResult<FileStat> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// fs::rename(&Path::new("foo"), &Path::new("bar"));
 /// ```
@@ -387,7 +394,8 @@ pub fn rename(from: &Path, to: &Path) -> IoResult<()> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt"));
 /// ```
@@ -438,7 +446,8 @@ fn update_err<T>(result: IoResult<T>, from: &Path, to: &Path) -> IoResult<T> {
 /// ```
 /// # #![allow(unused_must_use)]
 /// use std::old_io;
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// fs::chmod(&Path::new("file.txt"), old_io::USER_FILE);
 /// fs::chmod(&Path::new("file.txt"), old_io::USER_READ | old_io::USER_WRITE);
@@ -509,7 +518,8 @@ pub fn readlink(path: &Path) -> IoResult<Path> {
 /// ```
 /// # #![allow(unused_must_use)]
 /// use std::old_io;
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let p = Path::new("/some/dir");
 /// fs::mkdir(&p, old_io::USER_RWX);
@@ -532,7 +542,8 @@ pub fn mkdir(path: &Path, mode: FilePermission) -> IoResult<()> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::fs;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// let p = Path::new("/some/dir");
 /// fs::rmdir(&p);
@@ -556,8 +567,9 @@ pub fn rmdir(path: &Path) -> IoResult<()> {
 ///
 /// ```
 /// use std::old_io::fs::PathExtensions;
-/// use std::old_io::fs;
 /// use std::old_io;
+/// use std::old_io::*;
+/// use std::old_path::Path;
 ///
 /// // one possible implementation of fs::walk_dir only visiting files
 /// fn visit_dirs<F>(dir: &Path, cb: &mut F) -> old_io::IoResult<()> where
@@ -881,7 +893,8 @@ fn access_string(access: FileAccess) -> &'static str {
 mod test {
     use prelude::v1::*;
     use old_io::{SeekSet, SeekCur, SeekEnd, Read, Open, ReadWrite, FileType};
-    use old_io;
+    use old_io::{self, Reader, Writer, Seek};
+    use old_path::{Path, GenericPath};
     use str;
     use old_io::fs::*;
 
@@ -1608,7 +1621,7 @@ fn binary_file() {
         use rand::{StdRng, Rng};
 
         let mut bytes = [0; 1024];
-        StdRng::new().ok().unwrap().fill_bytes(&mut bytes);
+        StdRng::new().unwrap().fill_bytes(&mut bytes);
 
         let tmpdir = tmpdir();
 
index eb7691361d45c502661c84566411cccde681323a..1acc6abc8506f435f3cf47487670edaba65c132b 100644 (file)
@@ -55,7 +55,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::MemWriter;
+/// use std::old_io::*;
 ///
 /// let mut w = MemWriter::new();
 /// w.write(&[0, 1, 2]);
@@ -115,7 +115,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::MemReader;
+/// use std::old_io::*;
 ///
 /// let mut r = MemReader::new(vec!(0, 1, 2));
 ///
@@ -245,7 +245,7 @@ fn consume(&mut self, amt: uint) {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::BufWriter;
+/// use std::old_io::*;
 ///
 /// let mut buf = [0; 4];
 /// {
@@ -317,7 +317,7 @@ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::old_io::BufReader;
+/// use std::old_io::*;
 ///
 /// let buf = [0, 1, 2, 3];
 /// let mut r = BufReader::new(&buf);
@@ -394,8 +394,8 @@ fn fill_buf(&mut self) -> IoResult<&[u8]> {
 #[cfg(test)]
 mod test {
     extern crate "test" as test_crate;
-    use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek};
-    use prelude::v1::{Ok, Err, range,  Vec, Buffer,  AsSlice};
+    use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek, Buffer};
+    use prelude::v1::{Ok, Err, Vec,  AsSlice};
     use prelude::v1::IteratorExt;
     use old_io;
     use iter::repeat;
index 6b6c36a31ec5bd32592db5ada18125febf97cc72..6dfb54fd66cc4107d167ab893ea4cbd6f57802c8 100644 (file)
@@ -49,6 +49,7 @@
 //!
 //!     ```rust
 //!     use std::old_io as io;
+//!     use std::old_io::*;
 //!
 //!     let mut stdin = io::stdin();
 //!     for line in stdin.lock().lines() {
@@ -59,7 +60,8 @@
 //! * Read a complete file
 //!
 //!     ```rust
-//!     use std::old_io::File;
+//!     use std::old_io::*;
+//!     use std::old_path::Path;
 //!
 //!     let contents = File::open(&Path::new("message.txt")).read_to_end();
 //!     ```
@@ -68,7 +70,8 @@
 //!
 //!     ```rust
 //!     # #![allow(unused_must_use)]
-//!     use std::old_io::File;
+//!     use std::old_io::*;
+//!     use std::old_path::Path;
 //!
 //!     let mut file = File::create(&Path::new("message.txt"));
 //!     file.write_all(b"hello, file!\n");
@@ -79,8 +82,8 @@
 //! * Iterate over the lines of a file
 //!
 //!     ```rust,no_run
-//!     use std::old_io::BufferedReader;
-//!     use std::old_io::File;
+//!     use std::old_io::*;
+//!     use std::old_path::Path;
 //!
 //!     let path = Path::new("message.txt");
 //!     let mut file = BufferedReader::new(File::open(&path));
@@ -92,8 +95,8 @@
 //! * Pull the lines of a file into a vector of strings
 //!
 //!     ```rust,no_run
-//!     use std::old_io::BufferedReader;
-//!     use std::old_io::File;
+//!     use std::old_io::*;
+//!     use std::old_path::Path;
 //!
 //!     let path = Path::new("message.txt");
 //!     let mut file = BufferedReader::new(File::open(&path));
 //!
 //!     ```rust
 //!     # #![allow(unused_must_use)]
-//!     use std::old_io::TcpStream;
+//!     use std::old_io::*;
 //!
 //!     # // connection doesn't fail if a server is running on 8080
 //!     # // locally, we still want to be type checking this code, so lets
 //!     # fn main() { }
 //!     # fn foo() {
 //!     # #![allow(dead_code)]
-//!     use std::old_io::{TcpListener, TcpStream};
-//!     use std::old_io::{Acceptor, Listener};
+//!     use std::old_io::*;
 //!     use std::thread;
 //!
 //!     let listener = TcpListener::bind("127.0.0.1:80");
 //!
 //! ```rust
 //! # #![allow(unused_must_use)]
-//! use std::old_io::File;
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! match File::create(&Path::new("diary.txt")).write_all(b"Met a girl.\n") {
 //!     Ok(()) => (), // succeeded
 //! If you wanted to read several `u32`s from a file and return their product:
 //!
 //! ```rust
-//! use std::old_io::{File, IoResult};
+//! use std::old_io::*;
+//! use std::old_path::Path;
 //!
 //! fn file_product(p: &Path) -> IoResult<u32> {
 //!     let mut f = File::open(p);
@@ -945,7 +949,7 @@ unsafe fn slice_vec_capacity<'a, T>(v: &'a mut Vec<T>, start: uint, end: uint) -
 ///
 /// ```
 /// use std::old_io as io;
-/// use std::old_io::ByRefReader;
+/// use std::old_io::*;
 /// use std::old_io::util::LimitReader;
 ///
 /// fn process_input<R: Reader>(r: R) {}
@@ -1279,7 +1283,7 @@ fn flush(&mut self) -> IoResult<()> { (**self).flush() }
 ///
 /// ```
 /// use std::old_io::util::TeeReader;
-/// use std::old_io::{stdin, ByRefWriter};
+/// use std::old_io::*;
 ///
 /// fn process_input<R: Reader>(r: R) {}
 ///
@@ -1403,7 +1407,7 @@ pub trait Buffer: Reader {
     /// # Examples
     ///
     /// ```
-    /// use std::old_io::BufReader;
+    /// use std::old_io::*;
     ///
     /// let mut reader = BufReader::new(b"hello\nworld");
     /// assert_eq!("hello\n", &*reader.read_line().unwrap());
@@ -1717,6 +1721,7 @@ pub enum FileType {
 /// ```no_run
 ///
 /// use std::old_io::fs::PathExtensions;
+/// use std::old_path::Path;
 ///
 /// let info = match Path::new("foo.txt").stat() {
 ///     Ok(stat) => stat,
@@ -1845,7 +1850,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 mod tests {
     use self::BadReaderBehavior::*;
     use super::{IoResult, Reader, MemReader, NoProgress, InvalidInput, Writer};
-    use prelude::v1::{Ok, Vec, Buffer};
+    use super::Buffer;
+    use prelude::v1::{Ok, Vec};
     use usize;
 
     #[derive(Clone, PartialEq, Debug)]
index ad0e7a7284de48c2fb8fe47ddbbe2947b61a4ea1..77efedbc327d4cd06b81195d7de646740f5c53d5 100644 (file)
@@ -31,6 +31,7 @@
 use ffi::CString;
 use old_path::BytesContainer;
 use old_io::{Listener, Acceptor, IoResult, TimedOut, standard_error};
+use old_io::{Reader, Writer};
 use sys::pipe::UnixAcceptor as UnixAcceptorImp;
 use sys::pipe::UnixListener as UnixListenerImp;
 use sys::pipe::UnixStream as UnixStreamImp;
@@ -55,6 +56,8 @@ impl UnixStream {
     /// ```
     /// # #![allow(unused_must_use)]
     /// use std::old_io::net::pipe::UnixStream;
+    /// use std::old_io::*;
+    /// use std::old_path::Path;
     ///
     /// let server = Path::new("path/to/my/socket");
     /// let mut stream = UnixStream::connect(&server);
@@ -180,7 +183,8 @@ impl UnixListener {
     /// ```
     /// # fn foo() {
     /// use std::old_io::net::pipe::UnixListener;
-    /// use std::old_io::{Listener, Acceptor};
+    /// use std::old_io::*;
+    /// use std::old_path::Path;
     ///
     /// let server = Path::new("/path/to/my/socket");
     /// let stream = UnixListener::bind(&server);
@@ -285,6 +289,7 @@ mod tests {
     use old_io::{EndOfFile, TimedOut, ShortWrite, IoError, ConnectionReset};
     use old_io::{NotConnected, BrokenPipe, FileNotFound, InvalidInput, OtherIoError};
     use old_io::{PermissionDenied, Acceptor, Listener};
+    use old_io::{Reader, Writer};
     use old_io::test::*;
     use super::*;
     use sync::mpsc::channel;
index 6fb8020a3d602526393a2b5c6a65d860b5856e62..dbf3c4a4b1ecbf8d153615b18d06c86eef25281d 100644 (file)
@@ -41,7 +41,7 @@
 /// # Examples
 ///
 /// ```no_run
-/// use std::old_io::TcpStream;
+/// use std::old_io::*;
 ///
 /// {
 ///     let mut stream = TcpStream::connect("127.0.0.1:34254");
@@ -134,8 +134,7 @@ pub fn set_keepalive(&mut self, delay_in_seconds: Option<uint>) -> IoResult<()>
     ///
     /// ```no_run
     /// # #![allow(unused_must_use)]
-    /// use std::old_io::timer;
-    /// use std::old_io::TcpStream;
+    /// use std::old_io::*;
     /// use std::time::Duration;
     /// use std::thread;
     ///
@@ -280,8 +279,7 @@ fn as_inner(&self) -> &TcpStreamImp {
 ///
 /// ```
 /// # fn foo() {
-/// use std::old_io::{TcpListener, TcpStream};
-/// use std::old_io::{Acceptor, Listener};
+/// use std::old_io::*;
 /// use std::thread;
 ///
 /// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
@@ -376,8 +374,7 @@ impl TcpAcceptor {
     /// # Examples
     ///
     /// ```no_run
-    /// use std::old_io::TcpListener;
-    /// use std::old_io::{Listener, Acceptor, TimedOut};
+    /// use std::old_io::*;
     ///
     /// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap();
     ///
@@ -420,7 +417,7 @@ impl TcpAcceptor {
     /// # Examples
     ///
     /// ```
-    /// use std::old_io::{TcpListener, Listener, Acceptor, EndOfFile};
+    /// use std::old_io::*;
     /// use std::thread;
     ///
     /// let mut a = TcpListener::bind("127.0.0.1:8482").listen().unwrap();
@@ -496,6 +493,7 @@ mod test {
     use old_io::{ConnectionReset, NotConnected, PermissionDenied, OtherIoError};
     use old_io::{InvalidInput};
     use old_io::{Acceptor, Listener};
+    use old_io::{Reader, Writer};
 
     // FIXME #11530 this fails on android because tests are run as root
     #[cfg_attr(any(windows, target_os = "android"), ignore)]
index b78c8acb1900d2e312ceccc4aaf555c0405c2c39..b2b28453c890514637237e5e77b5e27abe108eb5 100644 (file)
@@ -17,7 +17,7 @@
 
 use prelude::v1::*;
 
-use old_io::IoResult;
+use old_io::{IoResult, Reader, Writer};
 use libc;
 use sync::Arc;
 
@@ -49,7 +49,7 @@ impl PipeStream {
     /// # #![allow(unused_must_use)]
     /// extern crate libc;
     ///
-    /// use std::old_io::pipe::PipeStream;
+    /// use std::old_io::*;
     ///
     /// fn main() {
     ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
@@ -114,6 +114,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 mod test {
     use prelude::v1::*;
 
+    use old_io::{Writer, Reader};
     use sync::mpsc::channel;
     use thread;
 
index 53b126ec00038f5ca8205abbc0cc9d2fc4055521..54fd20f45e298bd7ae44bf2f49c51075219a19c2 100644 (file)
@@ -24,8 +24,9 @@
 use ffi::CString;
 use fmt;
 use old_io::pipe::{PipeStream, PipePair};
-use old_io::{IoResult, IoError};
+use old_io::{IoResult, IoError, Reader, Writer};
 use old_io;
+use old_path::{Path, GenericPath};
 use libc;
 use os;
 use old_path::BytesContainer;
@@ -60,7 +61,7 @@
 /// # Examples
 ///
 /// ```should_fail
-/// use std::old_io::Command;
+/// use std::old_io::*;
 ///
 /// let mut child = match Command::new("/bin/cat").arg("file.txt").spawn() {
 ///     Ok(child) => child,
@@ -163,7 +164,7 @@ fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
 /// to be changed (for example, by adding arguments) prior to spawning:
 ///
 /// ```
-/// use std::old_io::Command;
+/// use std::old_io::*;
 ///
 /// let mut process = match Command::new("sh").arg("-c").arg("echo hello").spawn() {
 ///   Ok(p) => p,
@@ -759,9 +760,11 @@ fn drop(&mut self) {
 #[cfg(test)]
 mod tests {
     use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound};
-    use prelude::v1::{Ok, Err, range, drop, Some, None, Vec};
-    use prelude::v1::{Path, String, Reader, Writer, Clone};
-    use prelude::v1::{Str, AsSlice, ToString, GenericPath};
+    use old_io::{Reader, Writer};
+    use prelude::v1::{Ok, Err, drop, Some, None, Vec};
+    use prelude::v1::{String, Clone};
+    use prelude::v1::{Str, AsSlice, ToString};
+    use old_path::{GenericPath, Path};
     use old_io::fs::PathExtensions;
     use old_io::timer::*;
     use rt::running_on_valgrind;
index cdf2bae1cbad3c260e28e36b682b1db6b1a4a201..9dcb487cdb0df0ff78ac9c4948beffb2ad863249 100644 (file)
@@ -80,7 +80,7 @@ fn accept(&mut self) -> IoResult<T> {
 mod test {
     use prelude::v1::*;
     use super::super::mem::*;
-    use old_io;
+    use old_io::{self, Reader, Writer};
 
     #[test]
     fn test_option_writer() {
index 4ca403823753d625a7220f407c0f2a796d89a022..a1c8630e0ec319efb0bfcb3537cbb9e6b8303d30 100644 (file)
@@ -20,6 +20,7 @@
 //! ```rust
 //! # #![allow(unused_must_use)]
 //! use std::old_io;
+//! use std::old_io::*;
 //!
 //! let mut out = old_io::stdout();
 //! out.write_all(b"Hello, world!");
@@ -140,6 +141,7 @@ impl StdinReader {
     ///
     /// ```
     /// use std::old_io;
+    /// use std::old_io::*;
     ///
     /// let mut stdin = old_io::stdin();
     /// for line in stdin.lock().lines() {
index 04bfd4409cf20b68412f39a3a59ba790891b579e..90b3d1004c0b35d95d9b0454e7c3fc89f403855e 100644 (file)
@@ -29,7 +29,8 @@
 /// # Examples
 ///
 /// ```no_run
-/// use std::old_io::TempDir;
+/// use std::old_io::*;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// {
 ///     // create a temporary directory
index 9fbdac84a80dbc79e5fad48372ec75072a92df14..db409ecde452612be8b1fedf2a55c22fc6dbfb63 100644 (file)
@@ -14,7 +14,8 @@
 
 use env;
 use libc;
-use std::old_io::net::ip::*;
+use old_io::net::ip::*;
+use old_path::{Path, GenericPath};
 use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
 /// Get a port number, starting at 9600, for use in tests
index 413184c84d2a8e2c9c2373c911b6bdf65e01ff3a..1f782b6f221802308f20d06f18086835396a9a76 100644 (file)
@@ -14,7 +14,7 @@
 
 use prelude::v1::*;
 use cmp;
-use old_io;
+use old_io::{self, Reader, Writer, Buffer};
 use slice::bytes::MutableByteVector;
 
 /// Wraps a `Reader`, limiting the number of bytes that can be read from it.
@@ -325,7 +325,7 @@ fn read(&mut self, buf: &mut [u8]) -> old_io::IoResult<uint> {
 mod test {
     use prelude::v1::*;
 
-    use old_io::{MemReader, ByRefReader};
+    use old_io::{MemReader, ByRefReader, Reader, Writer, Buffer};
     use old_io;
     use super::*;
 
index fd117838f2f5b9d4b5e201a0ac99b90db8190c19..909fa4062b6042086e0748061d613f0d530019cd 100644 (file)
@@ -50,6 +50,7 @@
 //!
 //! ```rust
 //! use std::old_io::fs::PathExtensions;
+//! use std::old_path::{Path, GenericPath};
 //!
 //! let mut path = Path::new("/tmp/path");
 //! println!("path: {}", path.display());
@@ -142,6 +143,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -166,6 +168,7 @@ fn new<T: BytesContainer>(path: T) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -188,6 +191,7 @@ fn new_opt<T: BytesContainer>(path: T) -> Option<Self> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -205,6 +209,7 @@ fn as_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -219,6 +224,7 @@ fn as_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -234,6 +240,7 @@ fn as_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -252,6 +259,7 @@ fn display<'a>(&'a self) -> Display<'a, Self> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -269,6 +277,7 @@ fn filename_display<'a>(&'a self) -> Display<'a, Self> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -284,6 +293,7 @@ fn filename_display<'a>(&'a self) -> Display<'a, Self> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -303,6 +313,7 @@ fn dirname_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -318,6 +329,7 @@ fn dirname_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -337,6 +349,7 @@ fn filename_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -364,6 +377,7 @@ fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -384,6 +398,7 @@ fn filestem_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -411,6 +426,7 @@ fn extension<'a>(&'a self) -> Option<&'a [u8]> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -429,6 +445,7 @@ fn extension_str<'a>(&'a self) -> Option<&'a str> {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -455,6 +472,7 @@ fn set_filename<T: BytesContainer>(&mut self, filename: T) {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -505,6 +523,7 @@ fn set_extension<T: BytesContainer>(&mut self, extension: T) {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -530,6 +549,7 @@ fn with_filename<T: BytesContainer>(&self, filename: T) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -554,6 +574,7 @@ fn with_extension<T: BytesContainer>(&self, extension: T) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -573,6 +594,7 @@ fn dir_path(&self) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -588,6 +610,7 @@ fn dir_path(&self) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -612,6 +635,7 @@ fn push<T: BytesContainer>(&mut self, path: T) {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -641,6 +665,7 @@ fn push_many<T: BytesContainer>(&mut self, paths: &[T]) {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -658,6 +683,7 @@ fn push_many<T: BytesContainer>(&mut self, paths: &[T]) {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -683,6 +709,7 @@ fn join<T: BytesContainer>(&self, path: T) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -705,6 +732,7 @@ fn join_many<T: BytesContainer>(&self, paths: &[T]) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -722,6 +750,7 @@ fn join_many<T: BytesContainer>(&self, paths: &[T]) -> Self {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -740,6 +769,7 @@ fn is_relative(&self) -> bool {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -759,6 +789,7 @@ fn is_relative(&self) -> bool {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
@@ -775,6 +806,7 @@ fn is_relative(&self) -> bool {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// # foo();
     /// # #[cfg(windows)] fn foo() {}
     /// # #[cfg(unix)] fn foo() {
index 4f28e9e44f12ef0fd173652ee1d1c1120c1ea2b6..0ab8612a7cb52eacc8ca7a5f65340876b94dfaec 100644 (file)
@@ -1224,7 +1224,8 @@ mod bench {
     extern crate test;
     use self::test::Bencher;
     use super::*;
-    use prelude::v1::{Clone, GenericPath};
+    use old_path::GenericPath;
+    use prelude::v1::Clone;
 
     #[bench]
     fn join_home_dir(b: &mut Bencher) {
index ef873265b7bcdbe21d0a93a9b9eea4e0d9ad9037..cea2c238ecec29d2fe5e565bd1e72d363146e089 100644 (file)
@@ -605,6 +605,7 @@ impl Path {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// println!("{}", Path::new(r"C:\some\path").display());
     /// ```
     #[inline]
@@ -619,6 +620,7 @@ pub fn new<T: BytesContainer>(path: T) -> Path {
     /// # Examples
     ///
     /// ```
+    /// use std::old_path::{Path, GenericPath};
     /// let path = Path::new_opt(r"C:\some\path");
     ///
     /// match path {
index a1a3afca7a9a50196be3730d0709aeecace962e5..72f9338b456718faa8610acbd52d4a5f9929d7cf 100644 (file)
@@ -38,6 +38,7 @@
 
 use boxed::Box;
 use clone::Clone;
+use convert::From;
 use env;
 use error::{FromError, Error};
 use ffi::{OsString, OsStr};
@@ -79,12 +80,12 @@ fn err2old(new: ::io::Error) -> IoError {
 
 #[cfg(windows)]
 fn path2new(path: &Path) -> PathBuf {
-    PathBuf::new(path.as_str().unwrap())
+    PathBuf::from(path.as_str().unwrap())
 }
 #[cfg(unix)]
 fn path2new(path: &Path) -> PathBuf {
     use os::unix::prelude::*;
-    PathBuf::new(<OsStr as OsStrExt>::from_bytes(path.as_vec()))
+    PathBuf::from(<OsStr as OsStrExt>::from_bytes(path.as_vec()))
 }
 
 #[cfg(unix)]
@@ -126,6 +127,7 @@ pub fn num_cpus() -> uint {
 ///
 /// ```
 /// use std::os;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// // We assume that we are in a valid directory.
 /// let current_working_directory = os::getcwd().unwrap();
@@ -265,6 +267,7 @@ pub fn unsetenv(n: &str) {
 ///
 /// ```
 /// use std::os;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// let key = "PATH";
 /// match os::getenv_as_bytes(key) {
@@ -358,6 +361,7 @@ pub fn dll_filename(base: &str) -> String {
 ///
 /// ```
 /// use std::os;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// match os::self_exe_name() {
 ///     Some(exe_path) => println!("Path of this executable is: {}", exe_path.display()),
@@ -378,6 +382,7 @@ pub fn self_exe_name() -> Option<Path> {
 ///
 /// ```
 /// use std::os;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// match os::self_exe_path() {
 ///     Some(exe_path) => println!("Executable's Path is: {}", exe_path.display()),
@@ -407,6 +412,7 @@ pub fn self_exe_path() -> Option<Path> {
 ///
 /// ```
 /// use std::os;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// match os::homedir() {
 ///     Some(ref p) => println!("{}", p.display()),
@@ -497,7 +503,7 @@ fn lookup() -> Path {
 ///
 /// ```
 /// use std::os;
-/// use std::old_path::Path;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// // Assume we're in a path like /home/someuser
 /// let rel_path = Path::new("..");
@@ -529,7 +535,7 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
 ///
 /// ```
 /// use std::os;
-/// use std::old_path::Path;
+/// use std::old_path::{Path, GenericPath};
 ///
 /// let root = Path::new("/");
 /// assert!(os::change_dir(&root).is_ok());
@@ -1496,6 +1502,8 @@ mod tests {
     use os;
     use rand::Rng;
     use rand;
+    use old_path::{Path, GenericPath};
+    use old_io::{Reader, Writer, Seek};
 
     #[test]
     pub fn last_os_error() {
index ddceed14cc6ce51a49ea3bbb680be1a71d56fd97..8ee33e94fe7276f9404a65b2e5cdb202a340b9bb 100644 (file)
 use iter::{self, IntoIterator};
 use mem;
 use ops::{self, Deref};
+use string::String;
 use vec::Vec;
 use fmt;
 
@@ -527,6 +528,13 @@ pub fn as_os_str(self) -> &'a OsStr {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> AsRef<OsStr> for Component<'a> {
+    fn as_ref(&self) -> &OsStr {
+        self.as_os_str()
+    }
+}
+
 /// The core iterator giving the components of a path.
 ///
 /// See the module documentation for an in-depth explanation of components and
@@ -601,6 +609,7 @@ fn is_sep_byte(&self, b: u8) -> bool {
     }
 
     /// Extract a slice corresponding to the portion of the path remaining for iteration.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_path(&self) -> &'a Path {
         let mut comps = self.clone();
         if comps.front == State::Body { comps.trim_left(); }
@@ -695,6 +704,20 @@ pub fn peek(&self) -> Option<Component<'a>> {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> AsRef<Path> for Components<'a> {
+    fn as_ref(&self) -> &Path {
+        self.as_path()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> AsRef<OsStr> for Components<'a> {
+    fn as_ref(&self) -> &OsStr {
+        self.as_path().as_os_str()
+    }
+}
+
 impl<'a> Iter<'a> {
     /// Extract a slice corresponding to the portion of the path remaining for iteration.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -703,6 +726,20 @@ pub fn as_path(&self) -> &'a Path {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> AsRef<Path> for Iter<'a> {
+    fn as_ref(&self) -> &Path {
+        self.as_path()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> AsRef<OsStr> for Iter<'a> {
+    fn as_ref(&self) -> &OsStr {
+        self.as_path().as_os_str()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Iter<'a> {
     type Item = &'a OsStr;
@@ -873,11 +910,10 @@ fn as_mut_vec(&mut self) -> &mut Vec<u8> {
         unsafe { mem::transmute(self) }
     }
 
-    /// Allocate a `PathBuf` with initial contents given by the
-    /// argument.
+    /// Allocate an empty `PathBuf`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new<S: AsOsStr>(s: S) -> PathBuf {
-        PathBuf { inner: s.as_os_str().to_os_string() }
+    pub fn new() -> PathBuf {
+        PathBuf { inner: OsString::new() }
     }
 
     /// Extend `self` with `path`.
@@ -890,8 +926,8 @@ pub fn new<S: AsOsStr>(s: S) -> PathBuf {
     ///   replaces everything except for the prefix (if any) of `self`.
     /// * if `path` has a prefix but no root, it replaces `self.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn push<P: AsPath>(&mut self, path: P) {
-        let path = path.as_path();
+    pub fn push<P: AsRef<Path>>(&mut self, path: P) {
+        let path = path.as_ref();
 
         // in general, a separator is needed if the rightmost byte is not a separator
         let mut need_sep = self.as_mut_vec().last().map(|c| !is_sep_byte(*c)).unwrap_or(false);
@@ -958,12 +994,12 @@ pub fn pop(&mut self) -> bool {
     /// assert!(buf == PathBuf::new("/baz.txt"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn set_file_name<S: AsOsStr>(&mut self, file_name: S) {
+    pub fn set_file_name<S: AsRef<OsStr>>(&mut self, file_name: S) {
         if self.file_name().is_some() {
             let popped = self.pop();
             debug_assert!(popped);
         }
-        self.push(file_name.as_os_str());
+        self.push(file_name.as_ref());
     }
 
     /// Updates `self.extension()` to `extension`.
@@ -973,15 +1009,15 @@ pub fn set_file_name<S: AsOsStr>(&mut self, file_name: S) {
     /// Otherwise, returns `true`; if `self.extension()` is `None`, the extension
     /// is added; otherwise it is replaced.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn set_extension<S: AsOsStr>(&mut self, extension: S) -> bool {
+    pub fn set_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
         if self.file_name().is_none() { return false; }
 
         let mut stem = match self.file_stem() {
             Some(stem) => stem.to_os_string(),
-            None => OsString::from_str(""),
+            None => OsString::new(),
         };
 
-        let extension = extension.as_os_str();
+        let extension = extension.as_ref();
         if os_str_as_u8_slice(extension).len() > 0 {
             stem.push(".");
             stem.push(extension);
@@ -999,16 +1035,65 @@ pub fn into_os_string(self) -> OsString {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<P: AsPath> iter::FromIterator<P> for PathBuf {
+impl<'a> From<&'a Path> for PathBuf {
+    fn from(s: &'a Path) -> PathBuf {
+        s.to_path_buf()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a str> for PathBuf {
+    fn from(s: &'a str) -> PathBuf {
+        PathBuf::from(OsString::from(s))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a String> for PathBuf {
+    fn from(s: &'a String) -> PathBuf {
+        PathBuf::from(OsString::from(s))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl From<String> for PathBuf {
+    fn from(s: String) -> PathBuf {
+        PathBuf::from(OsString::from(s))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a OsStr> for PathBuf {
+    fn from(s: &'a OsStr) -> PathBuf {
+        PathBuf::from(OsString::from(s))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> From<&'a OsString> for PathBuf {
+    fn from(s: &'a OsString) -> PathBuf {
+        PathBuf::from(s.to_os_string())
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl From<OsString> for PathBuf {
+    fn from(s: OsString) -> PathBuf {
+        PathBuf { inner: s }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<P: AsRef<Path>> iter::FromIterator<P> for PathBuf {
     fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> PathBuf {
-        let mut buf = PathBuf::new("");
+        let mut buf = PathBuf::new();
         buf.extend(iter);
         buf
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<P: AsPath> iter::Extend<P> for PathBuf {
+impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
     fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
         for p in iter {
             self.push(p)
@@ -1084,12 +1169,27 @@ fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for PathBuf {
+    fn as_ref(&self) -> &OsStr {
+        &self.inner[..]
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for PathBuf {
     fn as_os_str(&self) -> &OsStr {
         &self.inner[..]
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Into<OsString> for PathBuf {
+    fn into(self) -> OsString {
+        self.inner
+    }
+}
+
 /// A slice of a path (akin to `str`).
 ///
 /// This type supports a number of operations for inspecting a path, including
@@ -1133,8 +1233,14 @@ fn as_u8_slice(&self) -> &[u8] {
     ///
     /// This is a cost-free conversion.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new<S: ?Sized + AsOsStr>(s: &S) -> &Path {
-        unsafe { mem::transmute(s.as_os_str()) }
+    pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
+        unsafe { mem::transmute(s.as_ref()) }
+    }
+
+    /// Yield the underlying `OsStr` slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn as_os_str(&self) -> &OsStr {
+        &self.inner
     }
 
     /// Yield a `&str` slice if the `Path` is valid unicode.
@@ -1156,7 +1262,7 @@ pub fn to_string_lossy(&self) -> Cow<str> {
     /// Convert a `Path` to an owned `PathBuf`.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_path_buf(&self) -> PathBuf {
-        PathBuf::new(self)
+        PathBuf::from(self.inner.to_os_string())
     }
 
     /// A path is *absolute* if it is independent of the current directory.
@@ -1243,23 +1349,25 @@ pub fn file_name(&self) -> Option<&OsStr> {
     }
 
     /// Returns a path that, when joined onto `base`, yields `self`.
+    ///
+    /// If `base` is not a prefix of `self` (i.e. `starts_with`
+    /// returns false), then `relative_from` returns `None`.
     #[unstable(feature = "path_relative_from", reason = "see #23284")]
-    pub fn relative_from<'a, P: ?Sized>(&'a self, base: &'a P) -> Option<&Path> where
-        P: AsPath
+    pub fn relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Option<&Path>
     {
-        iter_after(self.components(), base.as_path().components()).map(|c| c.as_path())
+        iter_after(self.components(), base.as_ref().components()).map(|c| c.as_path())
     }
 
     /// Determines whether `base` is a prefix of `self`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn starts_with<P: AsPath>(&self, base: P) -> bool {
-        iter_after(self.components(), base.as_path().components()).is_some()
+    pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
+        iter_after(self.components(), base.as_ref().components()).is_some()
     }
 
     /// Determines whether `child` is a suffix of `self`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn ends_with<P: AsPath>(&self, child: P) -> bool {
-        iter_after(self.components().rev(), child.as_path().components().rev()).is_some()
+    pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
+        iter_after(self.components().rev(), child.as_ref().components().rev()).is_some()
     }
 
     /// Extract the stem (non-extension) portion of `self.file()`.
@@ -1292,7 +1400,7 @@ pub fn extension(&self) -> Option<&OsStr> {
     ///
     /// See `PathBuf::push` for more details on what it means to adjoin a path.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn join<P: AsPath>(&self, path: P) -> PathBuf {
+    pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
         let mut buf = self.to_path_buf();
         buf.push(path);
         buf
@@ -1302,7 +1410,7 @@ pub fn join<P: AsPath>(&self, path: P) -> PathBuf {
     ///
     /// See `PathBuf::set_file_name` for more details.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_file_name<S: AsOsStr>(&self, file_name: S) -> PathBuf {
+    pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
         let mut buf = self.to_path_buf();
         buf.set_file_name(file_name);
         buf
@@ -1312,7 +1420,7 @@ pub fn with_file_name<S: AsOsStr>(&self, file_name: S) -> PathBuf {
     ///
     /// See `PathBuf::set_extension` for more details.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_extension<S: AsOsStr>(&self, extension: S) -> PathBuf {
+    pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
         let mut buf = self.to_path_buf();
         buf.set_extension(extension);
         buf
@@ -1346,6 +1454,14 @@ pub fn display(&self) -> Display {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<OsStr> for Path {
+    fn as_ref(&self) -> &OsStr {
+        &self.inner
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for Path {
     fn as_os_str(&self) -> &OsStr {
         &self.inner
@@ -1405,6 +1521,7 @@ fn cmp(&self, other: &Path) -> cmp::Ordering {
 
 /// Freely convertible to a `Path`.
 #[unstable(feature = "std_misc")]
+#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef<Path> instead")]
 pub trait AsPath {
     /// Convert to a `Path`.
     #[unstable(feature = "std_misc")]
@@ -1412,10 +1529,42 @@ pub trait AsPath {
 }
 
 #[unstable(feature = "std_misc")]
+#[deprecated(since = "1.0.0", reason = "use std::convert::AsRef<Path> instead")]
+#[allow(deprecated)]
 impl<T: AsOsStr + ?Sized> AsPath for T {
     fn as_path(&self) -> &Path { Path::new(self.as_os_str()) }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<Path> for Path {
+    fn as_ref(&self) -> &Path { self }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<Path> for OsStr {
+    fn as_ref(&self) -> &Path { Path::new(self) }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<Path> for OsString {
+    fn as_ref(&self) -> &Path { Path::new(self) }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<Path> for str {
+    fn as_ref(&self) -> &Path { Path::new(self) }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<Path> for String {
+    fn as_ref(&self) -> &Path { Path::new(self) }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRef<Path> for PathBuf {
+    fn as_ref(&self) -> &Path { self }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
index 2aaf6e8280086b54bc8e84f3ce9a3988e43e70cb..6e12ac1a226592b864354231aed50703fd0f8e4f 100644 (file)
@@ -29,6 +29,8 @@
 #[doc(no_inline)] pub use clone::Clone;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
+#[unstable(feature = "convert")]
+#[doc(no_inline)] pub use convert::{AsRef, AsMut, Into, From};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use iter::DoubleEndedIterator;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use result::Result::{self, Ok, Err};
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 #[doc(no_inline)] pub use slice::{SliceConcatExt, AsSlice};
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow(deprecated)]
 #[doc(no_inline)] pub use str::Str;
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use string::{String, ToString};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use vec::Vec;
 
-// NB: remove when path reform lands
-#[doc(no_inline)] pub use old_path::{Path, GenericPath};
-// NB: remove when I/O reform lands
-#[doc(no_inline)] pub use old_io::{Buffer, Writer, Reader, Seek, BufferPrelude};
-// NB: remove when range syntax lands
-#[allow(deprecated)]
-#[doc(no_inline)] pub use iter::range;
-
+// FIXME(#23454) should these be here?
 #[doc(no_inline)] pub use num::wrapping::{Wrapping, WrappingOps};
index cda37b19c48680b4815e579acb839be6faa891ff..d11c3d221445f3220aedc8881d494a770c1c35df 100644 (file)
@@ -19,8 +19,8 @@
 use ffi::AsOsStr;
 use fmt;
 use io::{self, Error, ErrorKind};
-use path::AsPath;
 use libc;
+use path;
 use sync::mpsc::{channel, Receiver};
 use sys::pipe2::{self, AnonPipe};
 use sys::process2::Process as ProcessImp;
@@ -198,8 +198,8 @@ pub fn env_clear(&mut self) -> &mut Command {
 
     /// Set the working directory for the child process.
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn current_dir<P: AsPath>(&mut self, dir: P) -> &mut Command {
-        self.inner.cwd(dir.as_path().as_os_str());
+    pub fn current_dir<P: AsRef<path::Path>>(&mut self, dir: P) -> &mut Command {
+        self.inner.cwd(dir.as_ref().as_os_str());
         self
     }
 
@@ -533,8 +533,8 @@ mod tests {
     use io::prelude::*;
     use prelude::v1::{Ok, Err, drop, Some, Vec};
     use prelude::v1::{String, Clone};
-    use prelude::v1::{Str, AsSlice, ToString, GenericPath};
-    use old_path;
+    use prelude::v1::{Str, AsSlice, ToString};
+    use old_path::{self, GenericPath};
     use old_io::fs::PathExtensions;
     use rt::running_on_valgrind;
     use str;
index f1c43a07e6e3895ef35cc52369876cc8f0cc7350..cf627ca254809c95cedafc730dba3d5ef942640a 100644 (file)
@@ -10,7 +10,6 @@
 //
 // ignore-lexer-test FIXME #15677
 
-use prelude::v1::*;
 use io::prelude::*;
 
 use env;
index 01eeed4fb54d018af47bacd1fe249aa4a2364a0b..35125125d141d721618115c0e29b8695ed63756c 100644 (file)
@@ -592,7 +592,7 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
                                 // asleep (we're looking at it), so the receiver
                                 // can't go away.
                                 (*a.get()).send(t).ok().unwrap();
-                        token.signal();
+                                token.signal();
                                 (a, Ok(()))
                             }
                         }
@@ -977,7 +977,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> error::Error for SendError<T> {
+impl<T: Send> error::Error for SendError<T> {
 
     fn description(&self) -> &str {
         "sending on a closed channel"
@@ -1013,7 +1013,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> error::Error for TrySendError<T> {
+impl<T: Send> error::Error for TrySendError<T> {
 
     fn description(&self) -> &str {
         match *self {
index 1cbfbbf29278f1b03663400c2ea0fddc459c0a8a..130fd1d7dc83b36841ee5ca4afbf89ec575188f5 100644 (file)
@@ -40,7 +40,7 @@
 /// among threads to ensure that a possibly invalid invariant is not witnessed.
 ///
 /// A poisoned mutex, however, does not prevent all access to the underlying
-/// data. The `PoisonError` type has an `into_guard` method which will return
+/// data. The `PoisonError` type has an `into_inner` method which will return
 /// the guard that would have otherwise been returned on a successful lock. This
 /// allows access to the data, despite the lock being poisoned.
 ///
 /// // pattern matched on to return the underlying guard on both branches.
 /// let mut guard = match lock.lock() {
 ///     Ok(guard) => guard,
-///     Err(poisoned) => poisoned.into_guard(),
+///     Err(poisoned) => poisoned.into_inner(),
 /// };
 ///
 /// *guard += 1;
index 2587ff5238ea7b86eb29d107856be5ed31629198..c07c83d37f48881b041966d9c9cfbf48d82f5d8a 100644 (file)
@@ -105,11 +105,11 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Display for PoisonError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.description().fmt(f)
+        "poisoned lock: another task failed inside".fmt(f)
     }
 }
 
-impl<T> Error for PoisonError<T> {
+impl<T: Send> Error for PoisonError<T> {
     fn description(&self) -> &str {
         "poisoned lock: another task failed inside"
     }
@@ -161,13 +161,13 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> fmt::Display for TryLockError<T> {
+impl<T: Send> fmt::Display for TryLockError<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.description().fmt(f)
     }
 }
 
-impl<T> Error for TryLockError<T> {
+impl<T: Send> Error for TryLockError<T> {
     fn description(&self) -> &str {
         match *self {
             TryLockError::Poisoned(ref p) => p.description(),
index e4985e703ba7645243ec3efd7e41a407eefa47c3..90526b8f4f318faa941d26c8cdd9be788e2be001 100644 (file)
@@ -15,7 +15,7 @@
 use cell::RefCell;
 use string::String;
 use thread::Thread;
-use thread_local::State;
+use thread::LocalKeyState;
 
 struct ThreadInfo {
     stack_guard: uint,
@@ -26,7 +26,7 @@ struct ThreadInfo {
 
 impl ThreadInfo {
     fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R {
-        if THREAD_INFO.state() == State::Destroyed {
+        if THREAD_INFO.state() == LocalKeyState::Destroyed {
             panic!("Use of std::thread::current() is not possible after \
                     the thread's local data has been destroyed");
         }
index 3cc91bf54b4d92dec95082b79f2f223acba8b81e..9f3dae34c7a4bff3a127111110fa955d335748e3 100644 (file)
@@ -634,6 +634,7 @@ fn initial_trail_surrogate(&self) -> Option<u16> {
 ///
 /// Panics when `begin` and `end` do not point to code point boundaries,
 /// or point beyond the end of the string.
+#[cfg(stage0)]
 impl ops::Index<ops::Range<usize>> for Wtf8 {
     type Output = Wtf8;
 
@@ -650,12 +651,36 @@ fn index(&self, range: &ops::Range<usize>) -> &Wtf8 {
     }
 }
 
+/// Return a slice of the given string for the byte range [`begin`..`end`).
+///
+/// # Panics
+///
+/// Panics when `begin` and `end` do not point to code point boundaries,
+/// or point beyond the end of the string.
+#[cfg(not(stage0))]
+impl ops::Index<ops::Range<usize>> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
+        // is_code_point_boundary checks that the index is in [0, .len()]
+        if range.start <= range.end &&
+           is_code_point_boundary(self, range.start) &&
+           is_code_point_boundary(self, range.end) {
+            unsafe { slice_unchecked(self, range.start, range.end) }
+        } else {
+            slice_error_fail(self, range.start, range.end)
+        }
+    }
+}
+
 /// Return a slice of the given string from byte `begin` to its end.
 ///
 /// # Panics
 ///
 /// Panics when `begin` is not at a code point boundary,
 /// or is beyond the end of the string.
+#[cfg(stage0)]
 impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
     type Output = Wtf8;
 
@@ -670,12 +695,34 @@ fn index(&self, range: &ops::RangeFrom<usize>) -> &Wtf8 {
     }
 }
 
+/// Return a slice of the given string from byte `begin` to its end.
+///
+/// # Panics
+///
+/// Panics when `begin` is not at a code point boundary,
+/// or is beyond the end of the string.
+#[cfg(not(stage0))]
+impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
+        // is_code_point_boundary checks that the index is in [0, .len()]
+        if is_code_point_boundary(self, range.start) {
+            unsafe { slice_unchecked(self, range.start, self.len()) }
+        } else {
+            slice_error_fail(self, range.start, self.len())
+        }
+    }
+}
+
 /// Return a slice of the given string from its beginning to byte `end`.
 ///
 /// # Panics
 ///
 /// Panics when `end` is not at a code point boundary,
 /// or is beyond the end of the string.
+#[cfg(stage0)]
 impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
     type Output = Wtf8;
 
@@ -690,6 +737,28 @@ fn index(&self, range: &ops::RangeTo<usize>) -> &Wtf8 {
     }
 }
 
+/// Return a slice of the given string from its beginning to byte `end`.
+///
+/// # Panics
+///
+/// Panics when `end` is not at a code point boundary,
+/// or is beyond the end of the string.
+#[cfg(not(stage0))]
+impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
+        // is_code_point_boundary checks that the index is in [0, .len()]
+        if is_code_point_boundary(self, range.end) {
+            unsafe { slice_unchecked(self, 0, range.end) }
+        } else {
+            slice_error_fail(self, 0, range.end)
+        }
+    }
+}
+
+#[cfg(stage0)]
 impl ops::Index<ops::RangeFull> for Wtf8 {
     type Output = Wtf8;
 
@@ -699,6 +768,16 @@ fn index(&self, _range: &ops::RangeFull) -> &Wtf8 {
     }
 }
 
+#[cfg(not(stage0))]
+impl ops::Index<ops::RangeFull> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
+        self
+    }
+}
+
 #[inline]
 fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
     // The first byte is assumed to be 0xED
index 74ab04978cbe264e4685f1e8cc73b9fe8660cbe3..7db64cfb936b5199813f1e9bf8ed84dbc23b6a00 100644 (file)
@@ -454,7 +454,7 @@ fn output(w: &mut Write, idx: int, addr: *mut libc::c_void,
 #[allow(dead_code)]
 fn output_fileline(w: &mut Write, file: &[u8], line: libc::c_int,
                    more: bool) -> io::Result<()> {
-    let file = str::from_utf8(file).ok().unwrap_or("<unknown>");
+    let file = str::from_utf8(file).unwrap_or("<unknown>");
     // prior line: "  ##: {:2$} - func"
     try!(write!(w, "      {:3$}at {}:{}", "", file, line, HEX_WIDTH));
     if more {
index c839ce65298721cea9d8d678f02aff6629d2f153..327ff3953aa32be92a87bb3dba126f177c4d75da 100644 (file)
@@ -20,6 +20,7 @@
 use old_io::{IoResult, FileStat, SeekStyle};
 use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
 use old_io;
+use old_path::{Path, GenericPath};
 use libc::{self, c_int, c_void};
 use mem;
 use ptr;
@@ -391,7 +392,7 @@ fn test_file_desc() {
         let mut reader = FileDesc::new(reader, true);
         let mut writer = FileDesc::new(writer, true);
 
-        writer.write(b"test").ok().unwrap();
+        writer.write(b"test").unwrap();
         let mut buf = [0; 4];
         match reader.read(&mut buf) {
             Ok(4) => {
index ea74aab3331ae5e49c12b76e6f89b999de9ace63..202e5ddaec42bd01c77eda25d11acdba21c902fd 100644 (file)
@@ -338,8 +338,7 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
         }));
         buf.set_len(n as usize);
     }
-    let s: OsString = OsStringExt::from_vec(buf);
-    Ok(PathBuf::new(&s))
+    Ok(PathBuf::from(OsString::from_vec(buf)))
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
index ff29dea254fc42031c0169a1e029de1bfbd3f590..17c8b21f8b3bcf51cc6861253fd19bd7b67fc91c 100644 (file)
@@ -23,7 +23,7 @@ pub fn new() -> (signal, signal) {
 }
 
 pub fn signal(fd: libc::c_int) {
-    FileDesc::new(fd, false).write(&[0]).ok().unwrap();
+    FileDesc::new(fd, false).write(&[0]).unwrap();
 }
 
 pub fn close(fd: libc::c_int) {
index a5a2f71acb7e0db572dd89fee95e1b3df3b5f715..6c191689255bc123ac0517fa676300ef5051f128 100644 (file)
@@ -36,7 +36,7 @@
 const TMPBUF_SZ: usize = 128;
 
 fn bytes2path(b: &[u8]) -> PathBuf {
-    PathBuf::new(<OsStr as OsStrExt>::from_bytes(b))
+    PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
 }
 
 fn os2path(os: OsString) -> PathBuf {
@@ -253,7 +253,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
         let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
         if err != 0 { return Err(io::Error::last_os_error()); }
         v.set_len(sz as uint - 1); // chop off trailing NUL
-        Ok(PathBuf::new(OsString::from_vec(v)))
+        Ok(PathBuf::from(OsString::from_vec(v)))
     }
 }
 
@@ -466,9 +466,9 @@ pub fn page_size() -> usize {
 pub fn temp_dir() -> PathBuf {
     getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| {
         if cfg!(target_os = "android") {
-            PathBuf::new("/data/local/tmp")
+            PathBuf::from("/data/local/tmp")
         } else {
-            PathBuf::new("/tmp")
+            PathBuf::from("/tmp")
         }
     })
 }
index ef175d68fc43fa9966dfa01c7b5cab6c4e690590..b6d2aca9a52365a4eed5a3d66bea8e920f06ad7e 100644 (file)
@@ -204,7 +204,7 @@ fn signal(active: &mut Vec<Box<Inner>>,
 
                 // drain the file descriptor
                 let mut buf = [0];
-                assert_eq!(fd.read(&mut buf).ok().unwrap(), 1);
+                assert_eq!(fd.read(&mut buf).unwrap(), 1);
             }
 
             -1 if os::errno() == libc::EINTR as i32 => {}
index 8935f97ce5d02c0fa2a77df39cb06d9591bd863b..ffa4b37b48794c4a32f31a0a512cd69b241f3999 100644 (file)
 #![allow(deprecated)] // for old path for dynamic lib
 
 use prelude::v1::*;
+use io::prelude::*;
 
 use dynamic_lib::DynamicLibrary;
-use io;
-use io::prelude::*;
 use ffi::CStr;
 use intrinsics;
+use io;
 use libc;
 use mem;
+use old_path::Path;
 use ptr;
 use str;
 use sync::{StaticMutex, MUTEX_INIT};
index a218fb26fda7289552be5e1905c5e15a7f69152f..e7a01478908bcafa22ec5db15e360489f4ad286f 100644 (file)
@@ -22,6 +22,7 @@
 use sys;
 use sys_common::{self, mkerr_libc};
 
+use old_path::{Path, GenericPath};
 use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
 use old_io::{IoResult, IoError, FileStat, SeekStyle};
 use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
index 2b03e9e743172a80f9898473d3844a78936c9ae5..17fdd6755c6d951bc08c34b8fc41a6196f72b8ec 100644 (file)
@@ -757,10 +757,10 @@ pub fn handle(&self) -> libc::HANDLE {
 
 impl Clone for UnixAcceptor {
     fn clone(&self) -> UnixAcceptor {
-        let name = to_utf16(&self.listener.name).ok().unwrap();
+        let name = to_utf16(&self.listener.name).unwrap();
         UnixAcceptor {
             inner: self.inner.clone(),
-            event: Event::new(true, false).ok().unwrap(),
+            event: Event::new(true, false).unwrap(),
             deadline: 0,
             listener: UnixListener {
                 name: self.listener.name.clone(),
index e465ecaa5f67e8f5085c257d1f8f60b25a58779a..e08a6e6b3cd7bfed95efd98fb9d314e275d6a16d 100644 (file)
@@ -24,7 +24,7 @@
 use old_io::{IoResult, IoError};
 use old_io;
 use os;
-use old_path::BytesContainer;
+use old_path::{BytesContainer, GenericPath};
 use ptr;
 use str;
 use sync::{StaticMutex, MUTEX_INIT};
index f542cb2323ebc4839f7747aabd8c0418c6c9da10..52f4cce4aa3bdff763e4d3fb0117589a5257467f 100644 (file)
@@ -29,7 +29,7 @@
 
 use prelude::v1::*;
 
-use old_io::{self, IoError, IoResult, MemReader};
+use old_io::{self, IoError, IoResult, MemReader, Reader};
 use iter::repeat;
 use libc::types::os::arch::extra::LPCVOID;
 use libc::{c_int, HANDLE, LPDWORD, DWORD, LPVOID};
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
deleted file mode 100644 (file)
index d2742d4..0000000
+++ /dev/null
@@ -1,959 +0,0 @@
-// Copyright 2014 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.
-
-//! Native threads
-//!
-//! ## The threading model
-//!
-//! An executing Rust program consists of a collection of native OS threads,
-//! each with their own stack and local state.
-//!
-//! Communication between threads can be done through
-//! [channels](../../std/sync/mpsc/index.html), Rust's message-passing
-//! types, along with [other forms of thread
-//! synchronization](../../std/sync/index.html) and shared-memory data
-//! structures. In particular, types that are guaranteed to be
-//! threadsafe are easily shared between threads using the
-//! atomically-reference-counted container,
-//! [`Arc`](../../std/sync/struct.Arc.html).
-//!
-//! Fatal logic errors in Rust cause *thread panic*, during which
-//! a thread will unwind the stack, running destructors and freeing
-//! owned resources. Thread panic is unrecoverable from within
-//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
-//! the panic may optionally be detected from a different thread. If
-//! the main thread panics, the application will exit with a non-zero
-//! exit code.
-//!
-//! When the main thread of a Rust program terminates, the entire program shuts
-//! down, even if other threads are still running. However, this module provides
-//! convenient facilities for automatically waiting for the termination of a
-//! child thread (i.e., join).
-//!
-//! ## The `Thread` type
-//!
-//! Threads are represented via the `Thread` type, which you can
-//! get in one of two ways:
-//!
-//! * By spawning a new thread, e.g. using the `thread::spawn` function.
-//! * By requesting the current thread, using the `thread::current` function.
-//!
-//! Threads can be named, and provide some built-in support for low-level
-//! synchronization (described below).
-//!
-//! The `thread::current()` function is available even for threads not spawned
-//! by the APIs of this module.
-//!
-//! ## Spawning a thread
-//!
-//! A new thread can be spawned using the `thread::spawn` function:
-//!
-//! ```rust
-//! use std::thread;
-//!
-//! thread::spawn(move || {
-//!     // some work here
-//! });
-//! ```
-//!
-//! In this example, the spawned thread is "detached" from the current
-//! thread. This means that it can outlive its parent (the thread that spawned
-//! it), unless this parent is the main thread.
-//!
-//! ## Scoped threads
-//!
-//! Often a parent thread uses a child thread to perform some particular task,
-//! and at some point must wait for the child to complete before continuing.
-//! For this scenario, use the `thread::scoped` function:
-//!
-//! ```rust
-//! use std::thread;
-//!
-//! let guard = thread::scoped(move || {
-//!     // some work here
-//! });
-//!
-//! // do some other work in the meantime
-//! let output = guard.join();
-//! ```
-//!
-//! The `scoped` function doesn't return a `Thread` directly; instead,
-//! it returns a *join guard*. The join guard is an RAII-style guard
-//! that will automatically join the child thread (block until it
-//! terminates) when it is dropped. You can join the child thread in
-//! advance by calling the `join` method on the guard, which will also
-//! return the result produced by the thread.  A handle to the thread
-//! itself is available via the `thread` method of the join guard.
-//!
-//! ## Configuring threads
-//!
-//! A new thread can be configured before it is spawned via the `Builder` type,
-//! which currently allows you to set the name, stack size, and writers for
-//! `println!` and `panic!` for the child thread:
-//!
-//! ```rust
-//! use std::thread;
-//!
-//! thread::Builder::new().name("child1".to_string()).spawn(move || {
-//!     println!("Hello, world!");
-//! });
-//! ```
-//!
-//! ## Blocking support: park and unpark
-//!
-//! Every thread is equipped with some basic low-level blocking support, via the
-//! `park` and `unpark` functions.
-//!
-//! Conceptually, each `Thread` handle has an associated token, which is
-//! initially not present:
-//!
-//! * The `thread::park()` function blocks the current thread unless or until
-//!   the token is available for its thread handle, at which point it atomically
-//!   consumes the token. It may also return *spuriously*, without consuming the
-//!   token. `thread::park_timeout()` does the same, but allows specifying a
-//!   maximum time to block the thread for.
-//!
-//! * The `unpark()` method on a `Thread` atomically makes the token available
-//!   if it wasn't already.
-//!
-//! In other words, each `Thread` acts a bit like a semaphore with initial count
-//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
-//! and can return spuriously.
-//!
-//! The API is typically used by acquiring a handle to the current thread,
-//! placing that handle in a shared data structure so that other threads can
-//! find it, and then `park`ing. When some desired condition is met, another
-//! thread calls `unpark` on the handle.
-//!
-//! The motivation for this design is twofold:
-//!
-//! * It avoids the need to allocate mutexes and condvars when building new
-//!   synchronization primitives; the threads already provide basic blocking/signaling.
-//!
-//! * It can be implemented very efficiently on many platforms.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use prelude::v1::*;
-
-use any::Any;
-use cell::UnsafeCell;
-use fmt;
-use io;
-use marker::PhantomData;
-use rt::{self, unwind};
-use sync::{Mutex, Condvar, Arc};
-use thunk::Thunk;
-use time::Duration;
-
-use sys::thread as imp;
-use sys_common::{stack, thread_info};
-
-/// Thread configuration. Provides detailed control over the properties
-/// and behavior of new threads.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Builder {
-    // A name for the thread-to-be, for identification in panic messages
-    name: Option<String>,
-    // The size of the stack for the spawned thread
-    stack_size: Option<usize>,
-}
-
-impl Builder {
-    /// Generate the base configuration for spawning a thread, from which
-    /// configuration methods can be chained.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> Builder {
-        Builder {
-            name: None,
-            stack_size: None,
-        }
-    }
-
-    /// Name the thread-to-be. Currently the name is used for identification
-    /// only in panic messages.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn name(mut self, name: String) -> Builder {
-        self.name = Some(name);
-        self
-    }
-
-    /// Set the size of the stack for the new thread.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn stack_size(mut self, size: usize) -> Builder {
-        self.stack_size = Some(size);
-        self
-    }
-
-    /// Redirect thread-local stdout.
-    #[unstable(feature = "std_misc",
-               reason = "Will likely go away after proc removal")]
-    #[deprecated(since = "1.0.0",
-                 reason = "the old I/O module is deprecated and this function \
-                           will be removed with no replacement")]
-    #[allow(deprecated)]
-    pub fn stdout(self, _stdout: Box<Writer + Send + 'static>) -> Builder {
-        self
-    }
-
-    /// Redirect thread-local stderr.
-    #[unstable(feature = "std_misc",
-               reason = "Will likely go away after proc removal")]
-    #[deprecated(since = "1.0.0",
-                 reason = "the old I/O module is deprecated and this function \
-                           will be removed with no replacement")]
-    #[allow(deprecated)]
-    pub fn stderr(self, _stderr: Box<Writer + Send + 'static>) -> Builder {
-        self
-    }
-
-    /// Spawn a new thread, and return a join handle for it.
-    ///
-    /// The child thread may outlive the parent (unless the parent thread
-    /// is the main thread; the whole process is terminated when the main
-    /// thread finishes.) The join handle can be used to block on
-    /// termination of the child thread, including recovering its panics.
-    ///
-    /// # Errors
-    ///
-    /// Unlike the `spawn` free function, this method yields an
-    /// `io::Result` to capture any failure to create the thread at
-    /// the OS level.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
-        F: FnOnce(), F: Send + 'static
-    {
-        self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i))
-    }
-
-    /// Spawn a new child thread that must be joined within a given
-    /// scope, and return a `JoinGuard`.
-    ///
-    /// The join guard can be used to explicitly join the child thread (via
-    /// `join`), returning `Result<T>`, or it will implicitly join the child
-    /// upon being dropped. Because the child thread may refer to data on the
-    /// current thread's stack (hence the "scoped" name), it cannot be detached;
-    /// it *must* be joined before the relevant stack frame is popped. See the
-    /// module documentation for additional details.
-    ///
-    /// # Errors
-    ///
-    /// Unlike the `scoped` free function, this method yields an
-    /// `io::Result` to capture any failure to create the thread at
-    /// the OS level.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
-        T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
-    {
-        self.spawn_inner(Thunk::new(f)).map(|inner| {
-            JoinGuard { inner: inner, _marker: PhantomData }
-        })
-    }
-
-    fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
-        let Builder { name, stack_size } = self;
-
-        let stack_size = stack_size.unwrap_or(rt::min_stack());
-
-        let my_thread = Thread::new(name);
-        let their_thread = my_thread.clone();
-
-        let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
-        let their_packet = Packet(my_packet.0.clone());
-
-        // Spawning a new OS thread guarantees that __morestack will never get
-        // triggered, but we must manually set up the actual stack bounds once
-        // this function starts executing. This raises the lower limit by a bit
-        // because by the time that this function is executing we've already
-        // consumed at least a little bit of stack (we don't know the exact byte
-        // address at which our stack started).
-        let main = move || {
-            let something_around_the_top_of_the_stack = 1;
-            let addr = &something_around_the_top_of_the_stack as *const i32;
-            let my_stack_top = addr as usize;
-            let my_stack_bottom = my_stack_top - stack_size + 1024;
-            unsafe {
-                if let Some(name) = their_thread.name() {
-                    imp::set_name(name);
-                }
-                stack::record_os_managed_stack_bounds(my_stack_bottom,
-                                                      my_stack_top);
-                thread_info::set(imp::guard::current(), their_thread);
-            }
-
-            let mut output = None;
-            let try_result = {
-                let ptr = &mut output;
-
-                // There are two primary reasons that general try/catch is
-                // unsafe. The first is that we do not support nested
-                // try/catch. The fact that this is happening in a newly-spawned
-                // thread suffices. The second is that unwinding while unwinding
-                // is not defined.  We take care of that by having an
-                // 'unwinding' flag in the thread itself. For these reasons,
-                // this unsafety should be ok.
-                unsafe {
-                    unwind::try(move || *ptr = Some(f.invoke(())))
-                }
-            };
-            unsafe {
-                *their_packet.0.get() = Some(match (output, try_result) {
-                    (Some(data), Ok(_)) => Ok(data),
-                    (None, Err(cause)) => Err(cause),
-                    _ => unreachable!()
-                });
-            }
-        };
-
-        Ok(JoinInner {
-            native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }),
-            thread: my_thread,
-            packet: my_packet,
-            joined: false,
-        })
-    }
-}
-
-/// Spawn a new thread, returning a `JoinHandle` for it.
-///
-/// The join handle will implicitly *detach* the child thread upon being
-/// dropped. In this case, the child thread may outlive the parent (unless
-/// the parent thread is the main thread; the whole process is terminated when
-/// the main thread finishes.) Additionally, the join handle provides a `join`
-/// method that can be used to join the child thread. If the child thread
-/// panics, `join` will return an `Err` containing the argument given to
-/// `panic`.
-///
-/// # Panics
-///
-/// Panicks if the OS fails to create a thread; use `Builder::spawn`
-/// to recover from such errors.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn spawn<F>(f: F) -> JoinHandle where F: FnOnce(), F: Send + 'static {
-    Builder::new().spawn(f).unwrap()
-}
-
-/// Spawn a new *scoped* thread, returning a `JoinGuard` for it.
-///
-/// The join guard can be used to explicitly join the child thread (via
-/// `join`), returning `Result<T>`, or it will implicitly join the child
-/// upon being dropped. Because the child thread may refer to data on the
-/// current thread's stack (hence the "scoped" name), it cannot be detached;
-/// it *must* be joined before the relevant stack frame is popped. See the
-/// module documentation for additional details.
-///
-/// # Panics
-///
-/// Panicks if the OS fails to create a thread; use `Builder::scoped`
-/// to recover from such errors.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
-    T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
-{
-    Builder::new().scoped(f).unwrap()
-}
-
-/// Gets a handle to the thread that invokes it.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn current() -> Thread {
-    thread_info::current_thread()
-}
-
-/// Cooperatively give up a timeslice to the OS scheduler.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn yield_now() {
-    unsafe { imp::yield_now() }
-}
-
-/// Determines whether the current thread is unwinding because of panic.
-#[inline]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn panicking() -> bool {
-    unwind::panicking()
-}
-
-/// Put the current thread to sleep for the specified amount of time.
-///
-/// The thread may sleep longer than the duration specified due to scheduling
-/// specifics or platform-dependent functionality. Note that on unix platforms
-/// this function will not return early due to a signal being received or a
-/// spurious wakeup.
-#[unstable(feature = "thread_sleep",
-           reason = "recently added, needs an RFC, and `Duration` itself is \
-                     unstable")]
-pub fn sleep(dur: Duration) {
-    imp::sleep(dur)
-}
-
-/// Block unless or until the current thread's token is made available (may wake spuriously).
-///
-/// See the module doc for more detail.
-//
-// The implementation currently uses the trivial strategy of a Mutex+Condvar
-// with wakeup flag, which does not actually allow spurious wakeups. In the
-// future, this will be implemented in a more efficient way, perhaps along the lines of
-//   http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
-// or futuxes, and in either case may allow spurious wakeups.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn park() {
-    let thread = current();
-    let mut guard = thread.inner.lock.lock().unwrap();
-    while !*guard {
-        guard = thread.inner.cvar.wait(guard).unwrap();
-    }
-    *guard = false;
-}
-
-/// Block unless or until the current thread's token is made available or
-/// the specified duration has been reached (may wake spuriously).
-///
-/// The semantics of this function are equivalent to `park()` except that the
-/// thread will be blocked for roughly no longer than *duration*. This method
-/// should not be used for precise timing due to anomalies such as
-/// preemption or platform differences that may not cause the maximum
-/// amount of time waited to be precisely *duration* long.
-///
-/// See the module doc for more detail.
-#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
-pub fn park_timeout(duration: Duration) {
-    let thread = current();
-    let mut guard = thread.inner.lock.lock().unwrap();
-    if !*guard {
-        let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap();
-        guard = g;
-    }
-    *guard = false;
-}
-
-/// The internal representation of a `Thread` handle
-struct Inner {
-    name: Option<String>,
-    lock: Mutex<bool>,          // true when there is a buffered unpark
-    cvar: Condvar,
-}
-
-unsafe impl Sync for Inner {}
-
-#[derive(Clone)]
-#[stable(feature = "rust1", since = "1.0.0")]
-/// A handle to a thread.
-pub struct Thread {
-    inner: Arc<Inner>,
-}
-
-impl Thread {
-    // Used only internally to construct a thread object without spawning
-    fn new(name: Option<String>) -> Thread {
-        Thread {
-            inner: Arc::new(Inner {
-                name: name,
-                lock: Mutex::new(false),
-                cvar: Condvar::new(),
-            })
-        }
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[unstable(feature = "std_misc",
-               reason = "may change with specifics of new Send semantics")]
-    pub fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static {
-        Builder::new().spawn(f).unwrap().thread().clone()
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[unstable(feature = "std_misc",
-               reason = "may change with specifics of new Send semantics")]
-    pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
-        T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
-    {
-        Builder::new().scoped(f).unwrap()
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn current() -> Thread {
-        thread_info::current_thread()
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[unstable(feature = "std_misc", reason = "name may change")]
-    pub fn yield_now() {
-        unsafe { imp::yield_now() }
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn panicking() -> bool {
-        unwind::panicking()
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[unstable(feature = "std_misc", reason = "recently introduced")]
-    pub fn park() {
-        let thread = current();
-        let mut guard = thread.inner.lock.lock().unwrap();
-        while !*guard {
-            guard = thread.inner.cvar.wait(guard).unwrap();
-        }
-        *guard = false;
-    }
-
-    /// Deprecated: use module-level free function.
-    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
-    #[unstable(feature = "std_misc", reason = "recently introduced")]
-    pub fn park_timeout(duration: Duration) {
-        let thread = current();
-        let mut guard = thread.inner.lock.lock().unwrap();
-        if !*guard {
-            let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap();
-            guard = g;
-        }
-        *guard = false;
-    }
-
-    /// Atomically makes the handle's token available if it is not already.
-    ///
-    /// See the module doc for more detail.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn unpark(&self) {
-        let mut guard = self.inner.lock.lock().unwrap();
-        if !*guard {
-            *guard = true;
-            self.inner.cvar.notify_one();
-        }
-    }
-
-    /// Get the thread's name.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn name(&self) -> Option<&str> {
-        self.inner.name.as_ref().map(|s| &**s)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Thread {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.name(), f)
-    }
-}
-
-// a hack to get around privacy restrictions
-impl thread_info::NewThread for Thread {
-    fn new(name: Option<String>) -> Thread { Thread::new(name) }
-}
-
-/// Indicates the manner in which a thread exited.
-///
-/// A thread that completes without panicking is considered to exit successfully.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
-
-struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
-
-unsafe impl<T:Send> Send for Packet<T> {}
-unsafe impl<T> Sync for Packet<T> {}
-
-/// Inner representation for JoinHandle and JoinGuard
-struct JoinInner<T> {
-    native: imp::rust_thread,
-    thread: Thread,
-    packet: Packet<T>,
-    joined: bool,
-}
-
-impl<T> JoinInner<T> {
-    fn join(&mut self) -> Result<T> {
-        assert!(!self.joined);
-        unsafe { imp::join(self.native) };
-        self.joined = true;
-        unsafe {
-            (*self.packet.0.get()).take().unwrap()
-        }
-    }
-}
-
-/// An owned permission to join on a thread (block on its termination).
-///
-/// Unlike a `JoinGuard`, a `JoinHandle` *detaches* the child thread
-/// when it is dropped, rather than automatically joining on drop.
-///
-/// Due to platform restrictions, it is not possible to `Clone` this
-/// handle: the ability to join a child thread is a uniquely-owned
-/// permission.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct JoinHandle(JoinInner<()>);
-
-impl JoinHandle {
-    /// Extract a handle to the underlying thread
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn thread(&self) -> &Thread {
-        &self.0.thread
-    }
-
-    /// Wait for the associated thread to finish.
-    ///
-    /// If the child thread panics, `Err` is returned with the parameter given
-    /// to `panic`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn join(mut self) -> Result<()> {
-        self.0.join()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Drop for JoinHandle {
-    fn drop(&mut self) {
-        if !self.0.joined {
-            unsafe { imp::detach(self.0.native) }
-        }
-    }
-}
-
-/// An RAII-style guard that will block until thread termination when dropped.
-///
-/// The type `T` is the return type for the thread's main function.
-///
-/// Joining on drop is necessary to ensure memory safety when stack
-/// data is shared between a parent and child thread.
-///
-/// Due to platform restrictions, it is not possible to `Clone` this
-/// handle: the ability to join a child thread is a uniquely-owned
-/// permission.
-#[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct JoinGuard<'a, T: 'a> {
-    inner: JoinInner<T>,
-    _marker: PhantomData<&'a T>,
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {}
-
-impl<'a, T: Send + 'a> JoinGuard<'a, T> {
-    /// Extract a handle to the thread this guard will join on.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn thread(&self) -> &Thread {
-        &self.inner.thread
-    }
-
-    /// Wait for the associated thread to finish, returning the result of the thread's
-    /// calculation.
-    ///
-    /// # Panics
-    ///
-    /// Panics on the child thread are propagated by panicking the parent.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn join(mut self) -> T {
-        match self.inner.join() {
-            Ok(res) => res,
-            Err(_) => panic!("child thread {:?} panicked", self.thread()),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> JoinGuard<'static, T> {
-    /// Detaches the child thread, allowing it to outlive its parent.
-    #[deprecated(since = "1.0.0", reason = "use spawn instead")]
-    #[unstable(feature = "std_misc")]
-    pub fn detach(mut self) {
-        unsafe { imp::detach(self.inner.native) };
-        self.inner.joined = true; // avoid joining in the destructor
-    }
-}
-
-#[unsafe_destructor]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
-    fn drop(&mut self) {
-        if !self.inner.joined {
-            if self.inner.join().is_err() {
-                panic!("child thread {:?} panicked", self.thread());
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::v1::*;
-
-    use any::Any;
-    use sync::mpsc::{channel, Sender};
-    use boxed::BoxAny;
-    use result;
-    use std::old_io::{ChanReader, ChanWriter};
-    use super::{Builder};
-    use thread;
-    use thunk::Thunk;
-    use time::Duration;
-
-    // !!! These tests are dangerous. If something is buggy, they will hang, !!!
-    // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
-
-    #[test]
-    fn test_unnamed_thread() {
-        thread::spawn(move|| {
-            assert!(thread::current().name().is_none());
-        }).join().ok().unwrap();
-    }
-
-    #[test]
-    fn test_named_thread() {
-        Builder::new().name("ada lovelace".to_string()).scoped(move|| {
-            assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
-        }).unwrap().join();
-    }
-
-    #[test]
-    fn test_run_basic() {
-        let (tx, rx) = channel();
-        thread::spawn(move|| {
-            tx.send(()).unwrap();
-        });
-        rx.recv().unwrap();
-    }
-
-    #[test]
-    fn test_join_success() {
-        assert!(thread::scoped(move|| -> String {
-            "Success!".to_string()
-        }).join() == "Success!");
-    }
-
-    #[test]
-    fn test_join_panic() {
-        match thread::spawn(move|| {
-            panic!()
-        }).join() {
-            result::Result::Err(_) => (),
-            result::Result::Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_scoped_success() {
-        let res = thread::scoped(move|| -> String {
-            "Success!".to_string()
-        }).join();
-        assert!(res == "Success!");
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_scoped_panic() {
-        thread::scoped(|| panic!()).join();
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_scoped_implicit_panic() {
-        let _ = thread::scoped(|| panic!());
-    }
-
-    #[test]
-    fn test_spawn_sched() {
-        use clone::Clone;
-
-        let (tx, rx) = channel();
-
-        fn f(i: i32, tx: Sender<()>) {
-            let tx = tx.clone();
-            thread::spawn(move|| {
-                if i == 0 {
-                    tx.send(()).unwrap();
-                } else {
-                    f(i - 1, tx);
-                }
-            });
-
-        }
-        f(10, tx);
-        rx.recv().unwrap();
-    }
-
-    #[test]
-    fn test_spawn_sched_childs_on_default_sched() {
-        let (tx, rx) = channel();
-
-        thread::spawn(move|| {
-            thread::spawn(move|| {
-                tx.send(()).unwrap();
-            });
-        });
-
-        rx.recv().unwrap();
-    }
-
-    fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk<'static>) {
-        let (tx, rx) = channel();
-
-        let x: Box<_> = box 1;
-        let x_in_parent = (&*x) as *const i32 as usize;
-
-        spawnfn(Thunk::new(move|| {
-            let x_in_child = (&*x) as *const i32 as usize;
-            tx.send(x_in_child).unwrap();
-        }));
-
-        let x_in_child = rx.recv().unwrap();
-        assert_eq!(x_in_parent, x_in_child);
-    }
-
-    #[test]
-    fn test_avoid_copying_the_body_spawn() {
-        avoid_copying_the_body(|v| {
-            thread::spawn(move || v.invoke(()));
-        });
-    }
-
-    #[test]
-    fn test_avoid_copying_the_body_thread_spawn() {
-        avoid_copying_the_body(|f| {
-            thread::spawn(move|| {
-                f.invoke(());
-            });
-        })
-    }
-
-    #[test]
-    fn test_avoid_copying_the_body_join() {
-        avoid_copying_the_body(|f| {
-            let _ = thread::spawn(move|| {
-                f.invoke(())
-            }).join();
-        })
-    }
-
-    #[test]
-    fn test_child_doesnt_ref_parent() {
-        // If the child refcounts the parent task, this will stack overflow when
-        // climbing the task tree to dereference each ancestor. (See #1789)
-        // (well, it would if the constant were 8000+ - I lowered it to be more
-        // valgrind-friendly. try this at home, instead..!)
-        const GENERATIONS: u32 = 16;
-        fn child_no(x: u32) -> Thunk<'static> {
-            return Thunk::new(move|| {
-                if x < GENERATIONS {
-                    thread::spawn(move|| child_no(x+1).invoke(()));
-                }
-            });
-        }
-        thread::spawn(|| child_no(0).invoke(()));
-    }
-
-    #[test]
-    fn test_simple_newsched_spawn() {
-        thread::spawn(move || {});
-    }
-
-    #[test]
-    fn test_try_panic_message_static_str() {
-        match thread::spawn(move|| {
-            panic!("static string");
-        }).join() {
-            Err(e) => {
-                type T = &'static str;
-                assert!(e.is::<T>());
-                assert_eq!(*e.downcast::<T>().ok().unwrap(), "static string");
-            }
-            Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic_message_owned_str() {
-        match thread::spawn(move|| {
-            panic!("owned string".to_string());
-        }).join() {
-            Err(e) => {
-                type T = String;
-                assert!(e.is::<T>());
-                assert_eq!(*e.downcast::<T>().ok().unwrap(), "owned string".to_string());
-            }
-            Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic_message_any() {
-        match thread::spawn(move|| {
-            panic!(box 413u16 as Box<Any + Send>);
-        }).join() {
-            Err(e) => {
-                type T = Box<Any + Send>;
-                assert!(e.is::<T>());
-                let any = e.downcast::<T>().ok().unwrap();
-                assert!(any.is::<u16>());
-                assert_eq!(*any.downcast::<u16>().ok().unwrap(), 413);
-            }
-            Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_try_panic_message_unit_struct() {
-        struct Juju;
-
-        match thread::spawn(move|| {
-            panic!(Juju)
-        }).join() {
-            Err(ref e) if e.is::<Juju>() => {}
-            Err(_) | Ok(()) => panic!()
-        }
-    }
-
-    #[test]
-    fn test_park_timeout_unpark_before() {
-        for _ in 0..10 {
-            thread::current().unpark();
-            thread::park_timeout(Duration::seconds(10_000_000));
-        }
-    }
-
-    #[test]
-    fn test_park_timeout_unpark_not_called() {
-        for _ in 0..10 {
-            thread::park_timeout(Duration::milliseconds(10));
-        }
-    }
-
-    #[test]
-    fn test_park_timeout_unpark_called_other_thread() {
-        use std::old_io;
-
-        for _ in 0..10 {
-            let th = thread::current();
-
-            let _guard = thread::spawn(move || {
-                old_io::timer::sleep(Duration::milliseconds(50));
-                th.unpark();
-            });
-
-            thread::park_timeout(Duration::seconds(10_000_000));
-        }
-    }
-
-    #[test]
-    fn sleep_smoke() {
-        thread::sleep(Duration::milliseconds(2));
-        thread::sleep(Duration::milliseconds(-2));
-    }
-
-    // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
-    // to the test harness apparently interfering with stderr configuration.
-}
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
new file mode 100644 (file)
index 0000000..1bf1b09
--- /dev/null
@@ -0,0 +1,733 @@
+// Copyright 2014-2015 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.
+
+//! Thread local storage
+
+#![unstable(feature = "thread_local_internals")]
+
+use prelude::v1::*;
+
+use cell::UnsafeCell;
+
+// Sure wish we had macro hygiene, no?
+#[doc(hidden)]
+#[unstable(feature = "thread_local_internals")]
+pub mod __impl {
+    pub use super::imp::Key as KeyInner;
+    pub use super::imp::destroy_value;
+    pub use sys_common::thread_local::INIT_INNER as OS_INIT_INNER;
+    pub use sys_common::thread_local::StaticKey as OsStaticKey;
+}
+
+/// A thread local storage key which owns its contents.
+///
+/// This key uses the fastest possible implementation available to it for the
+/// target platform. It is instantiated with the `thread_local!` macro and the
+/// primary method is the `with` method.
+///
+/// The `with` method yields a reference to the contained value which cannot be
+/// sent across tasks or escape the given closure.
+///
+/// # Initialization and Destruction
+///
+/// Initialization is dynamically performed on the first call to `with()`
+/// within a thread, and values support destructors which will be run when a
+/// thread exits.
+///
+/// # Examples
+///
+/// ```
+/// use std::cell::RefCell;
+/// use std::thread;
+///
+/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
+///
+/// FOO.with(|f| {
+///     assert_eq!(*f.borrow(), 1);
+///     *f.borrow_mut() = 2;
+/// });
+///
+/// // each thread starts out with the initial value of 1
+/// thread::spawn(move|| {
+///     FOO.with(|f| {
+///         assert_eq!(*f.borrow(), 1);
+///         *f.borrow_mut() = 3;
+///     });
+/// });
+///
+/// // we retain our original value of 2 despite the child thread
+/// FOO.with(|f| {
+///     assert_eq!(*f.borrow(), 2);
+/// });
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct LocalKey<T> {
+    // The key itself may be tagged with #[thread_local], and this `Key` is
+    // stored as a `static`, and it's not valid for a static to reference the
+    // address of another thread_local static. For this reason we kinda wonkily
+    // work around this by generating a shim function which will give us the
+    // address of the inner TLS key at runtime.
+    //
+    // This is trivially devirtualizable by LLVM because we never store anything
+    // to this field and rustc can declare the `static` as constant as well.
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals")]
+    pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>,
+
+    // initialization routine to invoke to create a value
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals")]
+    pub init: fn() -> T,
+}
+
+/// Declare a new thread local storage key of type `std::thread::LocalKey`.
+#[macro_export]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable]
+macro_rules! thread_local {
+    (static $name:ident: $t:ty = $init:expr) => (
+        static $name: ::std::thread::LocalKey<$t> = {
+            use std::cell::UnsafeCell as __UnsafeCell;
+            use std::thread::__local::__impl::KeyInner as __KeyInner;
+            use std::option::Option as __Option;
+            use std::option::Option::None as __None;
+
+            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
+                __UnsafeCell { value: __None }
+            });
+            fn __init() -> $t { $init }
+            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
+                &__KEY
+            }
+            ::std::thread::LocalKey { inner: __getit, init: __init }
+        };
+    );
+    (pub static $name:ident: $t:ty = $init:expr) => (
+        pub static $name: ::std::thread::LocalKey<$t> = {
+            use std::cell::UnsafeCell as __UnsafeCell;
+            use std::thread::__local::__impl::KeyInner as __KeyInner;
+            use std::option::Option as __Option;
+            use std::option::Option::None as __None;
+
+            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
+                __UnsafeCell { value: __None }
+            });
+            fn __init() -> $t { $init }
+            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
+                &__KEY
+            }
+            ::std::thread::LocalKey { inner: __getit, init: __init }
+        };
+    );
+}
+
+// Macro pain #4586:
+//
+// When cross compiling, rustc will load plugins and macros from the *host*
+// platform before search for macros from the target platform. This is primarily
+// done to detect, for example, plugins. Ideally the macro below would be
+// defined once per module below, but unfortunately this means we have the
+// following situation:
+//
+// 1. We compile libstd for x86_64-unknown-linux-gnu, this thread_local!() macro
+//    will inject #[thread_local] statics.
+// 2. We then try to compile a program for arm-linux-androideabi
+// 3. The compiler has a host of linux and a target of android, so it loads
+//    macros from the *linux* libstd.
+// 4. The macro generates a #[thread_local] field, but the android libstd does
+//    not use #[thread_local]
+// 5. Compile error about structs with wrong fields.
+//
+// To get around this, we're forced to inject the #[cfg] logic into the macro
+// itself. Woohoo.
+
+#[macro_export]
+#[doc(hidden)]
+#[allow_internal_unstable]
+macro_rules! __thread_local_inner {
+    (static $name:ident: $t:ty = $init:expr) => (
+        #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
+                       not(target_arch = "aarch64")),
+                   thread_local)]
+        static $name: ::std::thread::__local::__impl::KeyInner<$t> =
+            __thread_local_inner!($init, $t);
+    );
+    (pub static $name:ident: $t:ty = $init:expr) => (
+        #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
+                       not(target_arch = "aarch64")),
+                   thread_local)]
+        pub static $name: ::std::thread::__local::__impl::KeyInner<$t> =
+            __thread_local_inner!($init, $t);
+    );
+    ($init:expr, $t:ty) => ({
+        #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
+        const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
+            ::std::thread::__local::__impl::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: $init },
+                dtor_registered: ::std::cell::UnsafeCell { value: false },
+                dtor_running: ::std::cell::UnsafeCell { value: false },
+            }
+        };
+
+        #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
+        const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
+            ::std::thread::__local::__impl::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: $init },
+                os: ::std::thread::__local::__impl::OsStaticKey {
+                    inner: ::std::thread::__local::__impl::OS_INIT_INNER,
+                    dtor: ::std::option::Option::Some(
+                        ::std::thread::__local::__impl::destroy_value::<$t>
+                    ),
+                },
+            }
+        };
+
+        _INIT
+    });
+}
+
+/// Indicator of the state of a thread local storage key.
+#[unstable(feature = "std_misc",
+           reason = "state querying was recently added")]
+#[derive(Eq, PartialEq, Copy)]
+pub enum LocalKeyState {
+    /// All keys are in this state whenever a thread starts. Keys will
+    /// transition to the `Valid` state once the first call to `with` happens
+    /// and the initialization expression succeeds.
+    ///
+    /// Keys in the `Uninitialized` state will yield a reference to the closure
+    /// passed to `with` so long as the initialization routine does not panic.
+    Uninitialized,
+
+    /// Once a key has been accessed successfully, it will enter the `Valid`
+    /// state. Keys in the `Valid` state will remain so until the thread exits,
+    /// at which point the destructor will be run and the key will enter the
+    /// `Destroyed` state.
+    ///
+    /// Keys in the `Valid` state will be guaranteed to yield a reference to the
+    /// closure passed to `with`.
+    Valid,
+
+    /// When a thread exits, the destructors for keys will be run (if
+    /// necessary). While a destructor is running, and possibly after a
+    /// destructor has run, a key is in the `Destroyed` state.
+    ///
+    /// Keys in the `Destroyed` states will trigger a panic when accessed via
+    /// `with`.
+    Destroyed,
+}
+
+impl<T: 'static> LocalKey<T> {
+    /// Acquire a reference to the value in this TLS key.
+    ///
+    /// This will lazily initialize the value if this thread has not referenced
+    /// this key yet.
+    ///
+    /// # Panics
+    ///
+    /// This function will `panic!()` if the key currently has its
+    /// destructor running, and it **may** panic if the destructor has
+    /// previously been run for this thread.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn with<F, R>(&'static self, f: F) -> R
+                      where F: FnOnce(&T) -> R {
+        let slot = (self.inner)();
+        unsafe {
+            let slot = slot.get().expect("cannot access a TLS value during or \
+                                          after it is destroyed");
+            f(match *slot.get() {
+                Some(ref inner) => inner,
+                None => self.init(slot),
+            })
+        }
+    }
+
+    unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
+        // Execute the initialization up front, *then* move it into our slot,
+        // just in case initialization fails.
+        let value = (self.init)();
+        let ptr = slot.get();
+        *ptr = Some(value);
+        (*ptr).as_ref().unwrap()
+    }
+
+    /// Query the current state of this key.
+    ///
+    /// A key is initially in the `Uninitialized` state whenever a thread
+    /// starts. It will remain in this state up until the first call to `with`
+    /// within a thread has run the initialization expression successfully.
+    ///
+    /// Once the initialization expression succeeds, the key transitions to the
+    /// `Valid` state which will guarantee that future calls to `with` will
+    /// succeed within the thread.
+    ///
+    /// When a thread exits, each key will be destroyed in turn, and as keys are
+    /// destroyed they will enter the `Destroyed` state just before the
+    /// destructor starts to run. Keys may remain in the `Destroyed` state after
+    /// destruction has completed. Keys without destructors (e.g. with types
+    /// that are `Copy`), may never enter the `Destroyed` state.
+    ///
+    /// Keys in the `Uninitialized` can be accessed so long as the
+    /// initialization does not panic. Keys in the `Valid` state are guaranteed
+    /// to be able to be accessed. Keys in the `Destroyed` state will panic on
+    /// any call to `with`.
+    #[unstable(feature = "std_misc",
+               reason = "state querying was recently added")]
+    pub fn state(&'static self) -> LocalKeyState {
+        unsafe {
+            match (self.inner)().get() {
+                Some(cell) => {
+                    match *cell.get() {
+                        Some(..) => LocalKeyState::Valid,
+                        None => LocalKeyState::Uninitialized,
+                    }
+                }
+                None => LocalKeyState::Destroyed,
+            }
+        }
+    }
+
+    /// Deprecated
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0",
+                 reason = "function renamed to state() and returns more info")]
+    pub fn destroyed(&'static self) -> bool { self.state() == LocalKeyState::Destroyed }
+}
+
+#[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
+mod imp {
+    use prelude::v1::*;
+
+    use cell::UnsafeCell;
+    use intrinsics;
+    use ptr;
+
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals")]
+    pub struct Key<T> {
+        // Place the inner bits in an `UnsafeCell` to currently get around the
+        // "only Sync statics" restriction. This allows any type to be placed in
+        // the cell.
+        //
+        // Note that all access requires `T: 'static` so it can't be a type with
+        // any borrowed pointers still.
+        #[unstable(feature = "thread_local_internals")]
+        pub inner: UnsafeCell<T>,
+
+        // Metadata to keep track of the state of the destructor. Remember that
+        // these variables are thread-local, not global.
+        #[unstable(feature = "thread_local_internals")]
+        pub dtor_registered: UnsafeCell<bool>, // should be Cell
+        #[unstable(feature = "thread_local_internals")]
+        pub dtor_running: UnsafeCell<bool>, // should be Cell
+    }
+
+    unsafe impl<T> ::marker::Sync for Key<T> { }
+
+    #[doc(hidden)]
+    impl<T> Key<T> {
+        pub unsafe fn get(&'static self) -> Option<&'static T> {
+            if intrinsics::needs_drop::<T>() && *self.dtor_running.get() {
+                return None
+            }
+            self.register_dtor();
+            Some(&*self.inner.get())
+        }
+
+        unsafe fn register_dtor(&self) {
+            if !intrinsics::needs_drop::<T>() || *self.dtor_registered.get() {
+                return
+            }
+
+            register_dtor(self as *const _ as *mut u8,
+                          destroy_value::<T>);
+            *self.dtor_registered.get() = true;
+        }
+    }
+
+    // Since what appears to be glibc 2.18 this symbol has been shipped which
+    // GCC and clang both use to invoke destructors in thread_local globals, so
+    // let's do the same!
+    //
+    // Note, however, that we run on lots older linuxes, as well as cross
+    // compiling from a newer linux to an older linux, so we also have a
+    // fallback implementation to use as well.
+    //
+    // Due to rust-lang/rust#18804, make sure this is not generic!
+    #[cfg(target_os = "linux")]
+    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+        use boxed;
+        use mem;
+        use libc;
+        use sys_common::thread_local as os;
+
+        extern {
+            static __dso_handle: *mut u8;
+            #[linkage = "extern_weak"]
+            static __cxa_thread_atexit_impl: *const ();
+        }
+        if !__cxa_thread_atexit_impl.is_null() {
+            type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
+                                      arg: *mut u8,
+                                      dso_handle: *mut u8) -> libc::c_int;
+            mem::transmute::<*const (), F>(__cxa_thread_atexit_impl)
+            (dtor, t, __dso_handle);
+            return
+        }
+
+        // The fallback implementation uses a vanilla OS-based TLS key to track
+        // the list of destructors that need to be run for this thread. The key
+        // then has its own destructor which runs all the other destructors.
+        //
+        // The destructor for DTORS is a little special in that it has a `while`
+        // loop to continuously drain the list of registered destructors. It
+        // *should* be the case that this loop always terminates because we
+        // provide the guarantee that a TLS key cannot be set after it is
+        // flagged for destruction.
+        static DTORS: os::StaticKey = os::StaticKey {
+            inner: os::INIT_INNER,
+            dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)),
+        };
+        type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
+        if DTORS.get().is_null() {
+            let v: Box<List> = box Vec::new();
+            DTORS.set(boxed::into_raw(v) as *mut u8);
+        }
+        let list: &mut List = &mut *(DTORS.get() as *mut List);
+        list.push((t, dtor));
+
+        unsafe extern fn run_dtors(mut ptr: *mut u8) {
+            while !ptr.is_null() {
+                let list: Box<List> = Box::from_raw(ptr as *mut List);
+                for &(ptr, dtor) in &*list {
+                    dtor(ptr);
+                }
+                ptr = DTORS.get();
+                DTORS.set(ptr::null_mut());
+            }
+        }
+    }
+
+    // OSX's analog of the above linux function is this _tlv_atexit function.
+    // The disassembly of thread_local globals in C++ (at least produced by
+    // clang) will have this show up in the output.
+    #[cfg(target_os = "macos")]
+    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+        extern {
+            fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
+                           arg: *mut u8);
+        }
+        _tlv_atexit(dtor, t);
+    }
+
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals")]
+    pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
+        let ptr = ptr as *mut Key<T>;
+        // Right before we run the user destructor be sure to flag the
+        // destructor as running for this thread so calls to `get` will return
+        // `None`.
+        *(*ptr).dtor_running.get() = true;
+        ptr::read((*ptr).inner.get());
+    }
+}
+
+#[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
+mod imp {
+    use prelude::v1::*;
+
+    use alloc::boxed;
+    use cell::UnsafeCell;
+    use mem;
+    use ptr;
+    use sys_common::thread_local::StaticKey as OsStaticKey;
+
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals")]
+    pub struct Key<T> {
+        // Statically allocated initialization expression, using an `UnsafeCell`
+        // for the same reasons as above.
+        #[unstable(feature = "thread_local_internals")]
+        pub inner: UnsafeCell<T>,
+
+        // OS-TLS key that we'll use to key off.
+        #[unstable(feature = "thread_local_internals")]
+        pub os: OsStaticKey,
+    }
+
+    unsafe impl<T> ::marker::Sync for Key<T> { }
+
+    struct Value<T: 'static> {
+        key: &'static Key<T>,
+        value: T,
+    }
+
+    #[doc(hidden)]
+    impl<T> Key<T> {
+        pub unsafe fn get(&'static self) -> Option<&'static T> {
+            self.ptr().map(|p| &*p)
+        }
+
+        unsafe fn ptr(&'static self) -> Option<*mut T> {
+            let ptr = self.os.get() as *mut Value<T>;
+            if !ptr.is_null() {
+                if ptr as usize == 1 {
+                    return None
+                }
+                return Some(&mut (*ptr).value as *mut T);
+            }
+
+            // If the lookup returned null, we haven't initialized our own local
+            // copy, so do that now.
+            //
+            // Also note that this transmute_copy should be ok because the value
+            // `inner` is already validated to be a valid `static` value, so we
+            // should be able to freely copy the bits.
+            let ptr: Box<Value<T>> = box Value {
+                key: self,
+                value: mem::transmute_copy(&self.inner),
+            };
+            let ptr: *mut Value<T> = boxed::into_raw(ptr);
+            self.os.set(ptr as *mut u8);
+            Some(&mut (*ptr).value as *mut T)
+        }
+    }
+
+    #[doc(hidden)]
+    #[unstable(feature = "thread_local_internals")]
+    pub unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) {
+        // The OS TLS ensures that this key contains a NULL value when this
+        // destructor starts to run. We set it back to a sentinel value of 1 to
+        // ensure that any future calls to `get` for this thread will return
+        // `None`.
+        //
+        // Note that to prevent an infinite loop we reset it back to null right
+        // before we return from the destructor ourselves.
+        let ptr: Box<Value<T>> = Box::from_raw(ptr as *mut Value<T>);
+        let key = ptr.key;
+        key.os.set(1 as *mut u8);
+        drop(ptr);
+        key.os.set(ptr::null_mut());
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::v1::*;
+
+    use sync::mpsc::{channel, Sender};
+    use cell::UnsafeCell;
+    use super::LocalKeyState;
+    use thread;
+
+    struct Foo(Sender<()>);
+
+    impl Drop for Foo {
+        fn drop(&mut self) {
+            let Foo(ref s) = *self;
+            s.send(()).unwrap();
+        }
+    }
+
+    #[test]
+    fn smoke_no_dtor() {
+        thread_local!(static FOO: UnsafeCell<i32> = UnsafeCell { value: 1 });
+
+        FOO.with(|f| unsafe {
+            assert_eq!(*f.get(), 1);
+            *f.get() = 2;
+        });
+        let (tx, rx) = channel();
+        let _t = thread::spawn(move|| {
+            FOO.with(|f| unsafe {
+                assert_eq!(*f.get(), 1);
+            });
+            tx.send(()).unwrap();
+        });
+        rx.recv().unwrap();
+
+        FOO.with(|f| unsafe {
+            assert_eq!(*f.get(), 2);
+        });
+    }
+
+    #[test]
+    fn states() {
+        struct Foo;
+        impl Drop for Foo {
+            fn drop(&mut self) {
+                assert!(FOO.state() == LocalKeyState::Destroyed);
+            }
+        }
+        fn foo() -> Foo {
+            assert!(FOO.state() == LocalKeyState::Uninitialized);
+            Foo
+        }
+        thread_local!(static FOO: Foo = foo());
+
+        thread::spawn(|| {
+            assert!(FOO.state() == LocalKeyState::Uninitialized);
+            FOO.with(|_| {
+                assert!(FOO.state() == LocalKeyState::Valid);
+            });
+            assert!(FOO.state() == LocalKeyState::Valid);
+        }).join().ok().unwrap();
+    }
+
+    #[test]
+    fn smoke_dtor() {
+        thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell {
+            value: None
+        });
+
+        let (tx, rx) = channel();
+        let _t = thread::spawn(move|| unsafe {
+            let mut tx = Some(tx);
+            FOO.with(|f| {
+                *f.get() = Some(Foo(tx.take().unwrap()));
+            });
+        });
+        rx.recv().unwrap();
+    }
+
+    #[test]
+    fn circular() {
+        struct S1;
+        struct S2;
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
+            value: None
+        });
+        thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
+            value: None
+        });
+        static mut HITS: u32 = 0;
+
+        impl Drop for S1 {
+            fn drop(&mut self) {
+                unsafe {
+                    HITS += 1;
+                    if K2.state() == LocalKeyState::Destroyed {
+                        assert_eq!(HITS, 3);
+                    } else {
+                        if HITS == 1 {
+                            K2.with(|s| *s.get() = Some(S2));
+                        } else {
+                            assert_eq!(HITS, 3);
+                        }
+                    }
+                }
+            }
+        }
+        impl Drop for S2 {
+            fn drop(&mut self) {
+                unsafe {
+                    HITS += 1;
+                    assert!(K1.state() != LocalKeyState::Destroyed);
+                    assert_eq!(HITS, 2);
+                    K1.with(|s| *s.get() = Some(S1));
+                }
+            }
+        }
+
+        thread::spawn(move|| {
+            drop(S1);
+        }).join().ok().unwrap();
+    }
+
+    #[test]
+    fn self_referential() {
+        struct S1;
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
+            value: None
+        });
+
+        impl Drop for S1 {
+            fn drop(&mut self) {
+                assert!(K1.state() == LocalKeyState::Destroyed);
+            }
+        }
+
+        thread::spawn(move|| unsafe {
+            K1.with(|s| *s.get() = Some(S1));
+        }).join().ok().unwrap();
+    }
+
+    #[test]
+    fn dtors_in_dtors_in_dtors() {
+        struct S1(Sender<()>);
+        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
+            value: None
+        });
+        thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell {
+            value: None
+        });
+
+        impl Drop for S1 {
+            fn drop(&mut self) {
+                let S1(ref tx) = *self;
+                unsafe {
+                    if K2.state() != LocalKeyState::Destroyed {
+                        K2.with(|s| *s.get() = Some(Foo(tx.clone())));
+                    }
+                }
+            }
+        }
+
+        let (tx, rx) = channel();
+        let _t = thread::spawn(move|| unsafe {
+            let mut tx = Some(tx);
+            K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
+        });
+        rx.recv().unwrap();
+    }
+}
+
+#[cfg(test)]
+mod dynamic_tests {
+    use prelude::v1::*;
+
+    use cell::RefCell;
+    use collections::HashMap;
+
+    #[test]
+    fn smoke() {
+        fn square(i: i32) -> i32 { i * i }
+        thread_local!(static FOO: i32 = square(3));
+
+        FOO.with(|f| {
+            assert_eq!(*f, 9);
+        });
+    }
+
+    #[test]
+    fn hashmap() {
+        fn map() -> RefCell<HashMap<i32, i32>> {
+            let mut m = HashMap::new();
+            m.insert(1, 2);
+            RefCell::new(m)
+        }
+        thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
+
+        FOO.with(|map| {
+            assert_eq!(map.borrow()[&1], 2);
+        });
+    }
+
+    #[test]
+    fn refcell_vec() {
+        thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
+
+        FOO.with(|vec| {
+            assert_eq!(vec.borrow().len(), 3);
+            vec.borrow_mut().push(4);
+            assert_eq!(vec.borrow()[3], 4);
+        });
+    }
+}
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
new file mode 100644 (file)
index 0000000..57baeb1
--- /dev/null
@@ -0,0 +1,1026 @@
+// Copyright 2014 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.
+
+//! Native threads
+//!
+//! ## The threading model
+//!
+//! An executing Rust program consists of a collection of native OS threads,
+//! each with their own stack and local state.
+//!
+//! Communication between threads can be done through
+//! [channels](../../std/sync/mpsc/index.html), Rust's message-passing
+//! types, along with [other forms of thread
+//! synchronization](../../std/sync/index.html) and shared-memory data
+//! structures. In particular, types that are guaranteed to be
+//! threadsafe are easily shared between threads using the
+//! atomically-reference-counted container,
+//! [`Arc`](../../std/sync/struct.Arc.html).
+//!
+//! Fatal logic errors in Rust cause *thread panic*, during which
+//! a thread will unwind the stack, running destructors and freeing
+//! owned resources. Thread panic is unrecoverable from within
+//! the panicking thread (i.e. there is no 'try/catch' in Rust), but
+//! the panic may optionally be detected from a different thread. If
+//! the main thread panics, the application will exit with a non-zero
+//! exit code.
+//!
+//! When the main thread of a Rust program terminates, the entire program shuts
+//! down, even if other threads are still running. However, this module provides
+//! convenient facilities for automatically waiting for the termination of a
+//! child thread (i.e., join).
+//!
+//! ## The `Thread` type
+//!
+//! Threads are represented via the `Thread` type, which you can
+//! get in one of two ways:
+//!
+//! * By spawning a new thread, e.g. using the `thread::spawn` function.
+//! * By requesting the current thread, using the `thread::current` function.
+//!
+//! Threads can be named, and provide some built-in support for low-level
+//! synchronization (described below).
+//!
+//! The `thread::current()` function is available even for threads not spawned
+//! by the APIs of this module.
+//!
+//! ## Spawning a thread
+//!
+//! A new thread can be spawned using the `thread::spawn` function:
+//!
+//! ```rust
+//! use std::thread;
+//!
+//! thread::spawn(move || {
+//!     // some work here
+//! });
+//! ```
+//!
+//! In this example, the spawned thread is "detached" from the current
+//! thread. This means that it can outlive its parent (the thread that spawned
+//! it), unless this parent is the main thread.
+//!
+//! ## Scoped threads
+//!
+//! Often a parent thread uses a child thread to perform some particular task,
+//! and at some point must wait for the child to complete before continuing.
+//! For this scenario, use the `thread::scoped` function:
+//!
+//! ```rust
+//! use std::thread;
+//!
+//! let guard = thread::scoped(move || {
+//!     // some work here
+//! });
+//!
+//! // do some other work in the meantime
+//! let output = guard.join();
+//! ```
+//!
+//! The `scoped` function doesn't return a `Thread` directly; instead,
+//! it returns a *join guard*. The join guard is an RAII-style guard
+//! that will automatically join the child thread (block until it
+//! terminates) when it is dropped. You can join the child thread in
+//! advance by calling the `join` method on the guard, which will also
+//! return the result produced by the thread.  A handle to the thread
+//! itself is available via the `thread` method of the join guard.
+//!
+//! ## Configuring threads
+//!
+//! A new thread can be configured before it is spawned via the `Builder` type,
+//! which currently allows you to set the name, stack size, and writers for
+//! `println!` and `panic!` for the child thread:
+//!
+//! ```rust
+//! use std::thread;
+//!
+//! thread::Builder::new().name("child1".to_string()).spawn(move || {
+//!     println!("Hello, world!");
+//! });
+//! ```
+//!
+//! ## Blocking support: park and unpark
+//!
+//! Every thread is equipped with some basic low-level blocking support, via the
+//! `park` and `unpark` functions.
+//!
+//! Conceptually, each `Thread` handle has an associated token, which is
+//! initially not present:
+//!
+//! * The `thread::park()` function blocks the current thread unless or until
+//!   the token is available for its thread handle, at which point it atomically
+//!   consumes the token. It may also return *spuriously*, without consuming the
+//!   token. `thread::park_timeout()` does the same, but allows specifying a
+//!   maximum time to block the thread for.
+//!
+//! * The `unpark()` method on a `Thread` atomically makes the token available
+//!   if it wasn't already.
+//!
+//! In other words, each `Thread` acts a bit like a semaphore with initial count
+//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
+//! and can return spuriously.
+//!
+//! The API is typically used by acquiring a handle to the current thread,
+//! placing that handle in a shared data structure so that other threads can
+//! find it, and then `park`ing. When some desired condition is met, another
+//! thread calls `unpark` on the handle.
+//!
+//! The motivation for this design is twofold:
+//!
+//! * It avoids the need to allocate mutexes and condvars when building new
+//!   synchronization primitives; the threads already provide basic blocking/signaling.
+//!
+//! * It can be implemented very efficiently on many platforms.
+//!
+//! ## Thread-local storage
+//!
+//! This module also provides an implementation of thread local storage for Rust
+//! programs. Thread local storage is a method of storing data into a global
+//! variable which each thread in the program will have its own copy of.
+//! Threads do not share this data, so accesses do not need to be synchronized.
+//!
+//! At a high level, this module provides two variants of storage:
+//!
+//! * Owned thread-local storage. This is a type of thread local key which
+//!   owns the value that it contains, and will destroy the value when the
+//!   thread exits. This variant is created with the `thread_local!` macro and
+//!   can contain any value which is `'static` (no borrowed pointers).
+//!
+//! * Scoped thread-local storage. This type of key is used to store a reference
+//!   to a value into local storage temporarily for the scope of a function
+//!   call. There are no restrictions on what types of values can be placed
+//!   into this key.
+//!
+//! Both forms of thread local storage provide an accessor function, `with`,
+//! which will yield a shared reference to the value to the specified
+//! closure. Thread-local keys only allow shared access to values as there is no
+//! way to guarantee uniqueness if a mutable borrow was allowed. Most values
+//! will want to make use of some form of **interior mutability** through the
+//! `Cell` or `RefCell` types.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::__local::{LocalKey, LocalKeyState};
+
+#[unstable(feature = "scoped_tls",
+            reason = "scoped TLS has yet to have wide enough use to fully consider \
+                      stabilizing its interface")]
+pub use self::__scoped::ScopedKey;
+
+use prelude::v1::*;
+
+use any::Any;
+use cell::UnsafeCell;
+use fmt;
+use io;
+use marker::PhantomData;
+use rt::{self, unwind};
+use sync::{Mutex, Condvar, Arc};
+use sys::thread as imp;
+use sys_common::{stack, thread_info};
+use thunk::Thunk;
+use time::Duration;
+
+#[allow(deprecated)] use old_io::Writer;
+
+////////////////////////////////////////////////////////////////////////////////
+// Thread-local storage
+////////////////////////////////////////////////////////////////////////////////
+
+#[macro_use]
+#[doc(hidden)]
+#[path = "local.rs"] pub mod __local;
+
+#[macro_use]
+#[doc(hidden)]
+#[path = "scoped.rs"] pub mod __scoped;
+
+////////////////////////////////////////////////////////////////////////////////
+// Builder
+////////////////////////////////////////////////////////////////////////////////
+
+/// Thread configuration. Provides detailed control over the properties
+/// and behavior of new threads.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Builder {
+    // A name for the thread-to-be, for identification in panic messages
+    name: Option<String>,
+    // The size of the stack for the spawned thread
+    stack_size: Option<usize>,
+}
+
+impl Builder {
+    /// Generate the base configuration for spawning a thread, from which
+    /// configuration methods can be chained.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new() -> Builder {
+        Builder {
+            name: None,
+            stack_size: None,
+        }
+    }
+
+    /// Name the thread-to-be. Currently the name is used for identification
+    /// only in panic messages.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn name(mut self, name: String) -> Builder {
+        self.name = Some(name);
+        self
+    }
+
+    /// Set the size of the stack for the new thread.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn stack_size(mut self, size: usize) -> Builder {
+        self.stack_size = Some(size);
+        self
+    }
+
+    /// Redirect thread-local stdout.
+    #[unstable(feature = "std_misc",
+               reason = "Will likely go away after proc removal")]
+    #[deprecated(since = "1.0.0",
+                 reason = "the old I/O module is deprecated and this function \
+                           will be removed with no replacement")]
+    #[allow(deprecated)]
+    pub fn stdout(self, _stdout: Box<Writer + Send + 'static>) -> Builder {
+        self
+    }
+
+    /// Redirect thread-local stderr.
+    #[unstable(feature = "std_misc",
+               reason = "Will likely go away after proc removal")]
+    #[deprecated(since = "1.0.0",
+                 reason = "the old I/O module is deprecated and this function \
+                           will be removed with no replacement")]
+    #[allow(deprecated)]
+    pub fn stderr(self, _stderr: Box<Writer + Send + 'static>) -> Builder {
+        self
+    }
+
+    /// Spawn a new thread, and return a join handle for it.
+    ///
+    /// The child thread may outlive the parent (unless the parent thread
+    /// is the main thread; the whole process is terminated when the main
+    /// thread finishes.) The join handle can be used to block on
+    /// termination of the child thread, including recovering its panics.
+    ///
+    /// # Errors
+    ///
+    /// Unlike the `spawn` free function, this method yields an
+    /// `io::Result` to capture any failure to create the thread at
+    /// the OS level.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
+        F: FnOnce(), F: Send + 'static
+    {
+        self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i))
+    }
+
+    /// Spawn a new child thread that must be joined within a given
+    /// scope, and return a `JoinGuard`.
+    ///
+    /// The join guard can be used to explicitly join the child thread (via
+    /// `join`), returning `Result<T>`, or it will implicitly join the child
+    /// upon being dropped. Because the child thread may refer to data on the
+    /// current thread's stack (hence the "scoped" name), it cannot be detached;
+    /// it *must* be joined before the relevant stack frame is popped. See the
+    /// module documentation for additional details.
+    ///
+    /// # Errors
+    ///
+    /// Unlike the `scoped` free function, this method yields an
+    /// `io::Result` to capture any failure to create the thread at
+    /// the OS level.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
+        T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
+    {
+        self.spawn_inner(Thunk::new(f)).map(|inner| {
+            JoinGuard { inner: inner, _marker: PhantomData }
+        })
+    }
+
+    fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
+        let Builder { name, stack_size } = self;
+
+        let stack_size = stack_size.unwrap_or(rt::min_stack());
+
+        let my_thread = Thread::new(name);
+        let their_thread = my_thread.clone();
+
+        let my_packet = Packet(Arc::new(UnsafeCell::new(None)));
+        let their_packet = Packet(my_packet.0.clone());
+
+        // Spawning a new OS thread guarantees that __morestack will never get
+        // triggered, but we must manually set up the actual stack bounds once
+        // this function starts executing. This raises the lower limit by a bit
+        // because by the time that this function is executing we've already
+        // consumed at least a little bit of stack (we don't know the exact byte
+        // address at which our stack started).
+        let main = move || {
+            let something_around_the_top_of_the_stack = 1;
+            let addr = &something_around_the_top_of_the_stack as *const i32;
+            let my_stack_top = addr as usize;
+            let my_stack_bottom = my_stack_top - stack_size + 1024;
+            unsafe {
+                if let Some(name) = their_thread.name() {
+                    imp::set_name(name);
+                }
+                stack::record_os_managed_stack_bounds(my_stack_bottom,
+                                                      my_stack_top);
+                thread_info::set(imp::guard::current(), their_thread);
+            }
+
+            let mut output = None;
+            let try_result = {
+                let ptr = &mut output;
+
+                // There are two primary reasons that general try/catch is
+                // unsafe. The first is that we do not support nested
+                // try/catch. The fact that this is happening in a newly-spawned
+                // thread suffices. The second is that unwinding while unwinding
+                // is not defined.  We take care of that by having an
+                // 'unwinding' flag in the thread itself. For these reasons,
+                // this unsafety should be ok.
+                unsafe {
+                    unwind::try(move || *ptr = Some(f.invoke(())))
+                }
+            };
+            unsafe {
+                *their_packet.0.get() = Some(match (output, try_result) {
+                    (Some(data), Ok(_)) => Ok(data),
+                    (None, Err(cause)) => Err(cause),
+                    _ => unreachable!()
+                });
+            }
+        };
+
+        Ok(JoinInner {
+            native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }),
+            thread: my_thread,
+            packet: my_packet,
+            joined: false,
+        })
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Free functions
+////////////////////////////////////////////////////////////////////////////////
+
+/// Spawn a new thread, returning a `JoinHandle` for it.
+///
+/// The join handle will implicitly *detach* the child thread upon being
+/// dropped. In this case, the child thread may outlive the parent (unless
+/// the parent thread is the main thread; the whole process is terminated when
+/// the main thread finishes.) Additionally, the join handle provides a `join`
+/// method that can be used to join the child thread. If the child thread
+/// panics, `join` will return an `Err` containing the argument given to
+/// `panic`.
+///
+/// # Panics
+///
+/// Panicks if the OS fails to create a thread; use `Builder::spawn`
+/// to recover from such errors.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn spawn<F>(f: F) -> JoinHandle where F: FnOnce(), F: Send + 'static {
+    Builder::new().spawn(f).unwrap()
+}
+
+/// Spawn a new *scoped* thread, returning a `JoinGuard` for it.
+///
+/// The join guard can be used to explicitly join the child thread (via
+/// `join`), returning `Result<T>`, or it will implicitly join the child
+/// upon being dropped. Because the child thread may refer to data on the
+/// current thread's stack (hence the "scoped" name), it cannot be detached;
+/// it *must* be joined before the relevant stack frame is popped. See the
+/// module documentation for additional details.
+///
+/// # Panics
+///
+/// Panicks if the OS fails to create a thread; use `Builder::scoped`
+/// to recover from such errors.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
+    T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
+{
+    Builder::new().scoped(f).unwrap()
+}
+
+/// Gets a handle to the thread that invokes it.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn current() -> Thread {
+    thread_info::current_thread()
+}
+
+/// Cooperatively give up a timeslice to the OS scheduler.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn yield_now() {
+    unsafe { imp::yield_now() }
+}
+
+/// Determines whether the current thread is unwinding because of panic.
+#[inline]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn panicking() -> bool {
+    unwind::panicking()
+}
+
+/// Put the current thread to sleep for the specified amount of time.
+///
+/// The thread may sleep longer than the duration specified due to scheduling
+/// specifics or platform-dependent functionality. Note that on unix platforms
+/// this function will not return early due to a signal being received or a
+/// spurious wakeup.
+#[unstable(feature = "thread_sleep",
+           reason = "recently added, needs an RFC, and `Duration` itself is \
+                     unstable")]
+pub fn sleep(dur: Duration) {
+    imp::sleep(dur)
+}
+
+/// Block unless or until the current thread's token is made available (may wake spuriously).
+///
+/// See the module doc for more detail.
+//
+// The implementation currently uses the trivial strategy of a Mutex+Condvar
+// with wakeup flag, which does not actually allow spurious wakeups. In the
+// future, this will be implemented in a more efficient way, perhaps along the lines of
+//   http://cr.openjdk.java.net/~stefank/6989984.1/raw_files/new/src/os/linux/vm/os_linux.cpp
+// or futuxes, and in either case may allow spurious wakeups.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn park() {
+    let thread = current();
+    let mut guard = thread.inner.lock.lock().unwrap();
+    while !*guard {
+        guard = thread.inner.cvar.wait(guard).unwrap();
+    }
+    *guard = false;
+}
+
+/// Block unless or until the current thread's token is made available or
+/// the specified duration has been reached (may wake spuriously).
+///
+/// The semantics of this function are equivalent to `park()` except that the
+/// thread will be blocked for roughly no longer than *duration*. This method
+/// should not be used for precise timing due to anomalies such as
+/// preemption or platform differences that may not cause the maximum
+/// amount of time waited to be precisely *duration* long.
+///
+/// See the module doc for more detail.
+#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
+pub fn park_timeout(duration: Duration) {
+    let thread = current();
+    let mut guard = thread.inner.lock.lock().unwrap();
+    if !*guard {
+        let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap();
+        guard = g;
+    }
+    *guard = false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Thread
+////////////////////////////////////////////////////////////////////////////////
+
+/// The internal representation of a `Thread` handle
+struct Inner {
+    name: Option<String>,
+    lock: Mutex<bool>,          // true when there is a buffered unpark
+    cvar: Condvar,
+}
+
+unsafe impl Sync for Inner {}
+
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+/// A handle to a thread.
+pub struct Thread {
+    inner: Arc<Inner>,
+}
+
+impl Thread {
+    // Used only internally to construct a thread object without spawning
+    fn new(name: Option<String>) -> Thread {
+        Thread {
+            inner: Arc::new(Inner {
+                name: name,
+                lock: Mutex::new(false),
+                cvar: Condvar::new(),
+            })
+        }
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[unstable(feature = "std_misc",
+               reason = "may change with specifics of new Send semantics")]
+    pub fn spawn<F>(f: F) -> Thread where F: FnOnce(), F: Send + 'static {
+        Builder::new().spawn(f).unwrap().thread().clone()
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[unstable(feature = "std_misc",
+               reason = "may change with specifics of new Send semantics")]
+    pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
+        T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
+    {
+        Builder::new().scoped(f).unwrap()
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn current() -> Thread {
+        thread_info::current_thread()
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[unstable(feature = "std_misc", reason = "name may change")]
+    pub fn yield_now() {
+        unsafe { imp::yield_now() }
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn panicking() -> bool {
+        unwind::panicking()
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[unstable(feature = "std_misc", reason = "recently introduced")]
+    pub fn park() {
+        let thread = current();
+        let mut guard = thread.inner.lock.lock().unwrap();
+        while !*guard {
+            guard = thread.inner.cvar.wait(guard).unwrap();
+        }
+        *guard = false;
+    }
+
+    /// Deprecated: use module-level free function.
+    #[deprecated(since = "1.0.0", reason = "use module-level free function")]
+    #[unstable(feature = "std_misc", reason = "recently introduced")]
+    pub fn park_timeout(duration: Duration) {
+        let thread = current();
+        let mut guard = thread.inner.lock.lock().unwrap();
+        if !*guard {
+            let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap();
+            guard = g;
+        }
+        *guard = false;
+    }
+
+    /// Atomically makes the handle's token available if it is not already.
+    ///
+    /// See the module doc for more detail.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn unpark(&self) {
+        let mut guard = self.inner.lock.lock().unwrap();
+        if !*guard {
+            *guard = true;
+            self.inner.cvar.notify_one();
+        }
+    }
+
+    /// Get the thread's name.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn name(&self) -> Option<&str> {
+        self.inner.name.as_ref().map(|s| &**s)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Thread {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.name(), f)
+    }
+}
+
+// a hack to get around privacy restrictions
+impl thread_info::NewThread for Thread {
+    fn new(name: Option<String>) -> Thread { Thread::new(name) }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// JoinHandle and JoinGuard
+////////////////////////////////////////////////////////////////////////////////
+
+/// Indicates the manner in which a thread exited.
+///
+/// A thread that completes without panicking is considered to exit successfully.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub type Result<T> = ::result::Result<T, Box<Any + Send + 'static>>;
+
+struct Packet<T>(Arc<UnsafeCell<Option<Result<T>>>>);
+
+unsafe impl<T:Send> Send for Packet<T> {}
+unsafe impl<T> Sync for Packet<T> {}
+
+/// Inner representation for JoinHandle and JoinGuard
+struct JoinInner<T> {
+    native: imp::rust_thread,
+    thread: Thread,
+    packet: Packet<T>,
+    joined: bool,
+}
+
+impl<T> JoinInner<T> {
+    fn join(&mut self) -> Result<T> {
+        assert!(!self.joined);
+        unsafe { imp::join(self.native) };
+        self.joined = true;
+        unsafe {
+            (*self.packet.0.get()).take().unwrap()
+        }
+    }
+}
+
+/// An owned permission to join on a thread (block on its termination).
+///
+/// Unlike a `JoinGuard`, a `JoinHandle` *detaches* the child thread
+/// when it is dropped, rather than automatically joining on drop.
+///
+/// Due to platform restrictions, it is not possible to `Clone` this
+/// handle: the ability to join a child thread is a uniquely-owned
+/// permission.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct JoinHandle(JoinInner<()>);
+
+impl JoinHandle {
+    /// Extract a handle to the underlying thread
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn thread(&self) -> &Thread {
+        &self.0.thread
+    }
+
+    /// Wait for the associated thread to finish.
+    ///
+    /// If the child thread panics, `Err` is returned with the parameter given
+    /// to `panic`.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn join(mut self) -> Result<()> {
+        self.0.join()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Drop for JoinHandle {
+    fn drop(&mut self) {
+        if !self.0.joined {
+            unsafe { imp::detach(self.0.native) }
+        }
+    }
+}
+
+/// An RAII-style guard that will block until thread termination when dropped.
+///
+/// The type `T` is the return type for the thread's main function.
+///
+/// Joining on drop is necessary to ensure memory safety when stack
+/// data is shared between a parent and child thread.
+///
+/// Due to platform restrictions, it is not possible to `Clone` this
+/// handle: the ability to join a child thread is a uniquely-owned
+/// permission.
+#[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct JoinGuard<'a, T: 'a> {
+    inner: JoinInner<T>,
+    _marker: PhantomData<&'a T>,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<'a, T: Send + 'a> Sync for JoinGuard<'a, T> {}
+
+impl<'a, T: Send + 'a> JoinGuard<'a, T> {
+    /// Extract a handle to the thread this guard will join on.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn thread(&self) -> &Thread {
+        &self.inner.thread
+    }
+
+    /// Wait for the associated thread to finish, returning the result of the thread's
+    /// calculation.
+    ///
+    /// # Panics
+    ///
+    /// Panics on the child thread are propagated by panicking the parent.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn join(mut self) -> T {
+        match self.inner.join() {
+            Ok(res) => res,
+            Err(_) => panic!("child thread {:?} panicked", self.thread()),
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Send> JoinGuard<'static, T> {
+    /// Detaches the child thread, allowing it to outlive its parent.
+    #[deprecated(since = "1.0.0", reason = "use spawn instead")]
+    #[unstable(feature = "std_misc")]
+    pub fn detach(mut self) {
+        unsafe { imp::detach(self.inner.native) };
+        self.inner.joined = true; // avoid joining in the destructor
+    }
+}
+
+#[unsafe_destructor]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
+    fn drop(&mut self) {
+        if !self.inner.joined {
+            if self.inner.join().is_err() {
+                panic!("child thread {:?} panicked", self.thread());
+            }
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests
+////////////////////////////////////////////////////////////////////////////////
+
+#[cfg(test)]
+mod test {
+    use prelude::v1::*;
+
+    use any::Any;
+    use sync::mpsc::{channel, Sender};
+    use boxed::BoxAny;
+    use result;
+    use std::old_io::{ChanReader, ChanWriter};
+    use super::{Builder};
+    use thread;
+    use thunk::Thunk;
+    use time::Duration;
+
+    // !!! These tests are dangerous. If something is buggy, they will hang, !!!
+    // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
+
+    #[test]
+    fn test_unnamed_thread() {
+        thread::spawn(move|| {
+            assert!(thread::current().name().is_none());
+        }).join().ok().unwrap();
+    }
+
+    #[test]
+    fn test_named_thread() {
+        Builder::new().name("ada lovelace".to_string()).scoped(move|| {
+            assert!(thread::current().name().unwrap() == "ada lovelace".to_string());
+        }).unwrap().join();
+    }
+
+    #[test]
+    fn test_run_basic() {
+        let (tx, rx) = channel();
+        thread::spawn(move|| {
+            tx.send(()).unwrap();
+        });
+        rx.recv().unwrap();
+    }
+
+    #[test]
+    fn test_join_success() {
+        assert!(thread::scoped(move|| -> String {
+            "Success!".to_string()
+        }).join() == "Success!");
+    }
+
+    #[test]
+    fn test_join_panic() {
+        match thread::spawn(move|| {
+            panic!()
+        }).join() {
+            result::Result::Err(_) => (),
+            result::Result::Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_scoped_success() {
+        let res = thread::scoped(move|| -> String {
+            "Success!".to_string()
+        }).join();
+        assert!(res == "Success!");
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_scoped_panic() {
+        thread::scoped(|| panic!()).join();
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_scoped_implicit_panic() {
+        let _ = thread::scoped(|| panic!());
+    }
+
+    #[test]
+    fn test_spawn_sched() {
+        use clone::Clone;
+
+        let (tx, rx) = channel();
+
+        fn f(i: i32, tx: Sender<()>) {
+            let tx = tx.clone();
+            thread::spawn(move|| {
+                if i == 0 {
+                    tx.send(()).unwrap();
+                } else {
+                    f(i - 1, tx);
+                }
+            });
+
+        }
+        f(10, tx);
+        rx.recv().unwrap();
+    }
+
+    #[test]
+    fn test_spawn_sched_childs_on_default_sched() {
+        let (tx, rx) = channel();
+
+        thread::spawn(move|| {
+            thread::spawn(move|| {
+                tx.send(()).unwrap();
+            });
+        });
+
+        rx.recv().unwrap();
+    }
+
+    fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk<'static>) {
+        let (tx, rx) = channel();
+
+        let x: Box<_> = box 1;
+        let x_in_parent = (&*x) as *const i32 as usize;
+
+        spawnfn(Thunk::new(move|| {
+            let x_in_child = (&*x) as *const i32 as usize;
+            tx.send(x_in_child).unwrap();
+        }));
+
+        let x_in_child = rx.recv().unwrap();
+        assert_eq!(x_in_parent, x_in_child);
+    }
+
+    #[test]
+    fn test_avoid_copying_the_body_spawn() {
+        avoid_copying_the_body(|v| {
+            thread::spawn(move || v.invoke(()));
+        });
+    }
+
+    #[test]
+    fn test_avoid_copying_the_body_thread_spawn() {
+        avoid_copying_the_body(|f| {
+            thread::spawn(move|| {
+                f.invoke(());
+            });
+        })
+    }
+
+    #[test]
+    fn test_avoid_copying_the_body_join() {
+        avoid_copying_the_body(|f| {
+            let _ = thread::spawn(move|| {
+                f.invoke(())
+            }).join();
+        })
+    }
+
+    #[test]
+    fn test_child_doesnt_ref_parent() {
+        // If the child refcounts the parent task, this will stack overflow when
+        // climbing the task tree to dereference each ancestor. (See #1789)
+        // (well, it would if the constant were 8000+ - I lowered it to be more
+        // valgrind-friendly. try this at home, instead..!)
+        const GENERATIONS: u32 = 16;
+        fn child_no(x: u32) -> Thunk<'static> {
+            return Thunk::new(move|| {
+                if x < GENERATIONS {
+                    thread::spawn(move|| child_no(x+1).invoke(()));
+                }
+            });
+        }
+        thread::spawn(|| child_no(0).invoke(()));
+    }
+
+    #[test]
+    fn test_simple_newsched_spawn() {
+        thread::spawn(move || {});
+    }
+
+    #[test]
+    fn test_try_panic_message_static_str() {
+        match thread::spawn(move|| {
+            panic!("static string");
+        }).join() {
+            Err(e) => {
+                type T = &'static str;
+                assert!(e.is::<T>());
+                assert_eq!(*e.downcast::<T>().unwrap(), "static string");
+            }
+            Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_try_panic_message_owned_str() {
+        match thread::spawn(move|| {
+            panic!("owned string".to_string());
+        }).join() {
+            Err(e) => {
+                type T = String;
+                assert!(e.is::<T>());
+                assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
+            }
+            Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_try_panic_message_any() {
+        match thread::spawn(move|| {
+            panic!(box 413u16 as Box<Any + Send>);
+        }).join() {
+            Err(e) => {
+                type T = Box<Any + Send>;
+                assert!(e.is::<T>());
+                let any = e.downcast::<T>().unwrap();
+                assert!(any.is::<u16>());
+                assert_eq!(*any.downcast::<u16>().unwrap(), 413);
+            }
+            Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_try_panic_message_unit_struct() {
+        struct Juju;
+
+        match thread::spawn(move|| {
+            panic!(Juju)
+        }).join() {
+            Err(ref e) if e.is::<Juju>() => {}
+            Err(_) | Ok(()) => panic!()
+        }
+    }
+
+    #[test]
+    fn test_park_timeout_unpark_before() {
+        for _ in 0..10 {
+            thread::current().unpark();
+            thread::park_timeout(Duration::seconds(10_000_000));
+        }
+    }
+
+    #[test]
+    fn test_park_timeout_unpark_not_called() {
+        for _ in 0..10 {
+            thread::park_timeout(Duration::milliseconds(10));
+        }
+    }
+
+    #[test]
+    fn test_park_timeout_unpark_called_other_thread() {
+        use std::old_io;
+
+        for _ in 0..10 {
+            let th = thread::current();
+
+            let _guard = thread::spawn(move || {
+                old_io::timer::sleep(Duration::milliseconds(50));
+                th.unpark();
+            });
+
+            thread::park_timeout(Duration::seconds(10_000_000));
+        }
+    }
+
+    #[test]
+    fn sleep_smoke() {
+        thread::sleep(Duration::milliseconds(2));
+        thread::sleep(Duration::milliseconds(-2));
+    }
+
+    // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
+    // to the test harness apparently interfering with stderr configuration.
+}
diff --git a/src/libstd/thread/scoped.rs b/src/libstd/thread/scoped.rs
new file mode 100644 (file)
index 0000000..2a8be2a
--- /dev/null
@@ -0,0 +1,317 @@
+// Copyright 2014-2015 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.
+
+//! Scoped thread-local storage
+//!
+//! This module provides the ability to generate *scoped* thread-local
+//! variables. In this sense, scoped indicates that thread local storage
+//! actually stores a reference to a value, and this reference is only placed
+//! in storage for a scoped amount of time.
+//!
+//! There are no restrictions on what types can be placed into a scoped
+//! variable, but all scoped variables are initialized to the equivalent of
+//! null. Scoped thread local storage is useful when a value is present for a known
+//! period of time and it is not required to relinquish ownership of the
+//! contents.
+//!
+//! # Examples
+//!
+//! ```
+//! scoped_thread_local!(static FOO: u32);
+//!
+//! // Initially each scoped slot is empty.
+//! assert!(!FOO.is_set());
+//!
+//! // When inserting a value, the value is only in place for the duration
+//! // of the closure specified.
+//! FOO.set(&1, || {
+//!     FOO.with(|slot| {
+//!         assert_eq!(*slot, 1);
+//!     });
+//! });
+//! ```
+
+#![unstable(feature = "thread_local_internals")]
+
+use prelude::v1::*;
+
+// macro hygiene sure would be nice, wouldn't it?
+#[doc(hidden)]
+pub mod __impl {
+    pub use super::imp::KeyInner;
+    pub use sys_common::thread_local::INIT as OS_INIT;
+}
+
+/// Type representing a thread local storage key corresponding to a reference
+/// to the type parameter `T`.
+///
+/// Keys are statically allocated and can contain a reference to an instance of
+/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
+/// and `with`, both of which currently use closures to control the scope of
+/// their contents.
+#[unstable(feature = "scoped_tls",
+           reason = "scoped TLS has yet to have wide enough use to fully consider \
+                     stabilizing its interface")]
+pub struct ScopedKey<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
+
+/// Declare a new scoped thread local storage key.
+///
+/// This macro declares a `static` item on which methods are used to get and
+/// set the value stored within.
+#[macro_export]
+#[allow_internal_unstable]
+macro_rules! scoped_thread_local {
+    (static $name:ident: $t:ty) => (
+        __scoped_thread_local_inner!(static $name: $t);
+    );
+    (pub static $name:ident: $t:ty) => (
+        __scoped_thread_local_inner!(pub static $name: $t);
+    );
+}
+
+#[macro_export]
+#[doc(hidden)]
+#[allow_internal_unstable]
+macro_rules! __scoped_thread_local_inner {
+    (static $name:ident: $t:ty) => (
+        #[cfg_attr(not(any(windows,
+                           target_os = "android",
+                           target_os = "ios",
+                           target_os = "openbsd",
+                           target_arch = "aarch64")),
+                   thread_local)]
+        static $name: ::std::thread::ScopedKey<$t> =
+            __scoped_thread_local_inner!($t);
+    );
+    (pub static $name:ident: $t:ty) => (
+        #[cfg_attr(not(any(windows,
+                           target_os = "android",
+                           target_os = "ios",
+                           target_os = "openbsd",
+                           target_arch = "aarch64")),
+                   thread_local)]
+        pub static $name: ::std::thread::ScopedKey<$t> =
+            __scoped_thread_local_inner!($t);
+    );
+    ($t:ty) => ({
+        use std::thread::ScopedKey as __Key;
+
+        #[cfg(not(any(windows,
+                      target_os = "android",
+                      target_os = "ios",
+                      target_os = "openbsd",
+                      target_arch = "aarch64")))]
+        const _INIT: __Key<$t> = __Key {
+            inner: ::std::thread::__scoped::__impl::KeyInner {
+                inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
+            }
+        };
+
+        #[cfg(any(windows,
+                  target_os = "android",
+                  target_os = "ios",
+                  target_os = "openbsd",
+                  target_arch = "aarch64"))]
+        const _INIT: __Key<$t> = __Key {
+            inner: ::std::thread::__scoped::__impl::KeyInner {
+                inner: ::std::thread::__scoped::__impl::OS_INIT,
+                marker: ::std::marker::PhantomData::<::std::cell::Cell<$t>>,
+            }
+        };
+
+        _INIT
+    })
+}
+
+#[unstable(feature = "scoped_tls",
+           reason = "scoped TLS has yet to have wide enough use to fully consider \
+                     stabilizing its interface")]
+impl<T> ScopedKey<T> {
+    /// Insert a value into this scoped thread local storage slot for a
+    /// duration of a closure.
+    ///
+    /// While `cb` is running, the value `t` will be returned by `get` unless
+    /// this function is called recursively inside of `cb`.
+    ///
+    /// Upon return, this function will restore the previous value, if any
+    /// was available.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// scoped_thread_local!(static FOO: u32);
+    ///
+    /// FOO.set(&100, || {
+    ///     let val = FOO.with(|v| *v);
+    ///     assert_eq!(val, 100);
+    ///
+    ///     // set can be called recursively
+    ///     FOO.set(&101, || {
+    ///         // ...
+    ///     });
+    ///
+    ///     // Recursive calls restore the previous value.
+    ///     let val = FOO.with(|v| *v);
+    ///     assert_eq!(val, 100);
+    /// });
+    /// ```
+    pub fn set<R, F>(&'static self, t: &T, cb: F) -> R where
+        F: FnOnce() -> R,
+    {
+        struct Reset<'a, T: 'a> {
+            key: &'a __impl::KeyInner<T>,
+            val: *mut T,
+        }
+        #[unsafe_destructor]
+        impl<'a, T> Drop for Reset<'a, T> {
+            fn drop(&mut self) {
+                unsafe { self.key.set(self.val) }
+            }
+        }
+
+        let prev = unsafe {
+            let prev = self.inner.get();
+            self.inner.set(t as *const T as *mut T);
+            prev
+        };
+
+        let _reset = Reset { key: &self.inner, val: prev };
+        cb()
+    }
+
+    /// Get a value out of this scoped variable.
+    ///
+    /// This function takes a closure which receives the value of this
+    /// variable.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `set` has not previously been called.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// scoped_thread_local!(static FOO: u32);
+    ///
+    /// FOO.with(|slot| {
+    ///     // work with `slot`
+    /// });
+    /// ```
+    pub fn with<R, F>(&'static self, cb: F) -> R where
+        F: FnOnce(&T) -> R
+    {
+        unsafe {
+            let ptr = self.inner.get();
+            assert!(!ptr.is_null(), "cannot access a scoped thread local \
+                                     variable without calling `set` first");
+            cb(&*ptr)
+        }
+    }
+
+    /// Test whether this TLS key has been `set` for the current thread.
+    pub fn is_set(&'static self) -> bool {
+        unsafe { !self.inner.get().is_null() }
+    }
+}
+
+#[cfg(not(any(windows,
+              target_os = "android",
+              target_os = "ios",
+              target_os = "openbsd",
+              target_arch = "aarch64")))]
+mod imp {
+    use std::cell::UnsafeCell;
+
+    #[doc(hidden)]
+    pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
+
+    unsafe impl<T> ::marker::Sync for KeyInner<T> { }
+
+    #[doc(hidden)]
+    impl<T> KeyInner<T> {
+        #[doc(hidden)]
+        pub unsafe fn set(&self, ptr: *mut T) { *self.inner.get() = ptr; }
+        #[doc(hidden)]
+        pub unsafe fn get(&self) -> *mut T { *self.inner.get() }
+    }
+}
+
+#[cfg(any(windows,
+          target_os = "android",
+          target_os = "ios",
+          target_os = "openbsd",
+          target_arch = "aarch64"))]
+mod imp {
+    use marker;
+    use std::cell::Cell;
+    use sys_common::thread_local::StaticKey as OsStaticKey;
+
+    #[doc(hidden)]
+    pub struct KeyInner<T> {
+        pub inner: OsStaticKey,
+        pub marker: marker::PhantomData<Cell<T>>,
+    }
+
+    unsafe impl<T> ::marker::Sync for KeyInner<T> { }
+
+    #[doc(hidden)]
+    impl<T> KeyInner<T> {
+        #[doc(hidden)]
+        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
+        #[doc(hidden)]
+        pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
+    }
+}
+
+
+#[cfg(test)]
+mod tests {
+    use cell::Cell;
+    use prelude::v1::*;
+
+    scoped_thread_local!(static FOO: u32);
+
+    #[test]
+    fn smoke() {
+        scoped_thread_local!(static BAR: u32);
+
+        assert!(!BAR.is_set());
+        BAR.set(&1, || {
+            assert!(BAR.is_set());
+            BAR.with(|slot| {
+                assert_eq!(*slot, 1);
+            });
+        });
+        assert!(!BAR.is_set());
+    }
+
+    #[test]
+    fn cell_allowed() {
+        scoped_thread_local!(static BAR: Cell<u32>);
+
+        BAR.set(&Cell::new(1), || {
+            BAR.with(|slot| {
+                assert_eq!(slot.get(), 1);
+            });
+        });
+    }
+
+    #[test]
+    fn scope_item_allowed() {
+        assert!(!FOO.is_set());
+        FOO.set(&1, || {
+            assert!(FOO.is_set());
+            FOO.with(|slot| {
+                assert_eq!(*slot, 1);
+            });
+        });
+        assert!(!FOO.is_set());
+    }
+}
diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs
deleted file mode 100644 (file)
index 0878029..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-// Copyright 2014-2015 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.
-
-//! Thread local storage
-//!
-//! This module provides an implementation of thread local storage for Rust
-//! programs. Thread local storage is a method of storing data into a global
-//! variable which each thread in the program will have its own copy of.
-//! Threads do not share this data, so accesses do not need to be synchronized.
-//!
-//! At a high level, this module provides two variants of storage:
-//!
-//! * Owning thread local storage. This is a type of thread local key which
-//!   owns the value that it contains, and will destroy the value when the
-//!   thread exits. This variant is created with the `thread_local!` macro and
-//!   can contain any value which is `'static` (no borrowed pointers.
-//!
-//! * Scoped thread local storage. This type of key is used to store a reference
-//!   to a value into local storage temporarily for the scope of a function
-//!   call. There are no restrictions on what types of values can be placed
-//!   into this key.
-//!
-//! Both forms of thread local storage provide an accessor function, `with`,
-//! which will yield a shared reference to the value to the specified
-//! closure. Thread local keys only allow shared access to values as there is no
-//! way to guarantee uniqueness if a mutable borrow was allowed. Most values
-//! will want to make use of some form of **interior mutability** through the
-//! `Cell` or `RefCell` types.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use prelude::v1::*;
-
-use cell::UnsafeCell;
-
-#[macro_use]
-pub mod scoped;
-
-// Sure wish we had macro hygiene, no?
-#[doc(hidden)]
-#[unstable(feature = "thread_local_internals")]
-pub mod __impl {
-    pub use super::imp::Key as KeyInner;
-    pub use super::imp::destroy_value;
-    pub use sys_common::thread_local::INIT_INNER as OS_INIT_INNER;
-    pub use sys_common::thread_local::StaticKey as OsStaticKey;
-}
-
-/// A thread local storage key which owns its contents.
-///
-/// This key uses the fastest possible implementation available to it for the
-/// target platform. It is instantiated with the `thread_local!` macro and the
-/// primary method is the `with` method.
-///
-/// The `with` method yields a reference to the contained value which cannot be
-/// sent across tasks or escape the given closure.
-///
-/// # Initialization and Destruction
-///
-/// Initialization is dynamically performed on the first call to `with()`
-/// within a thread, and values support destructors which will be run when a
-/// thread exits.
-///
-/// # Examples
-///
-/// ```
-/// use std::cell::RefCell;
-/// use std::thread;
-///
-/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
-///
-/// FOO.with(|f| {
-///     assert_eq!(*f.borrow(), 1);
-///     *f.borrow_mut() = 2;
-/// });
-///
-/// // each thread starts out with the initial value of 1
-/// thread::spawn(move|| {
-///     FOO.with(|f| {
-///         assert_eq!(*f.borrow(), 1);
-///         *f.borrow_mut() = 3;
-///     });
-/// });
-///
-/// // we retain our original value of 2 despite the child thread
-/// FOO.with(|f| {
-///     assert_eq!(*f.borrow(), 2);
-/// });
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Key<T> {
-    // The key itself may be tagged with #[thread_local], and this `Key` is
-    // stored as a `static`, and it's not valid for a static to reference the
-    // address of another thread_local static. For this reason we kinda wonkily
-    // work around this by generating a shim function which will give us the
-    // address of the inner TLS key at runtime.
-    //
-    // This is trivially devirtualizable by LLVM because we never store anything
-    // to this field and rustc can declare the `static` as constant as well.
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
-    pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>,
-
-    // initialization routine to invoke to create a value
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
-    pub init: fn() -> T,
-}
-
-/// Declare a new thread local storage key of type `std::thread_local::Key`.
-#[macro_export]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[allow_internal_unstable]
-macro_rules! thread_local {
-    (static $name:ident: $t:ty = $init:expr) => (
-        static $name: ::std::thread_local::Key<$t> = {
-            use std::cell::UnsafeCell as __UnsafeCell;
-            use std::thread_local::__impl::KeyInner as __KeyInner;
-            use std::option::Option as __Option;
-            use std::option::Option::None as __None;
-
-            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
-                __UnsafeCell { value: __None }
-            });
-            fn __init() -> $t { $init }
-            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
-                &__KEY
-            }
-            ::std::thread_local::Key { inner: __getit, init: __init }
-        };
-    );
-    (pub static $name:ident: $t:ty = $init:expr) => (
-        pub static $name: ::std::thread_local::Key<$t> = {
-            use std::cell::UnsafeCell as __UnsafeCell;
-            use std::thread_local::__impl::KeyInner as __KeyInner;
-            use std::option::Option as __Option;
-            use std::option::Option::None as __None;
-
-            __thread_local_inner!(static __KEY: __UnsafeCell<__Option<$t>> = {
-                __UnsafeCell { value: __None }
-            });
-            fn __init() -> $t { $init }
-            fn __getit() -> &'static __KeyInner<__UnsafeCell<__Option<$t>>> {
-                &__KEY
-            }
-            ::std::thread_local::Key { inner: __getit, init: __init }
-        };
-    );
-}
-
-// Macro pain #4586:
-//
-// When cross compiling, rustc will load plugins and macros from the *host*
-// platform before search for macros from the target platform. This is primarily
-// done to detect, for example, plugins. Ideally the macro below would be
-// defined once per module below, but unfortunately this means we have the
-// following situation:
-//
-// 1. We compile libstd for x86_64-unknown-linux-gnu, this thread_local!() macro
-//    will inject #[thread_local] statics.
-// 2. We then try to compile a program for arm-linux-androideabi
-// 3. The compiler has a host of linux and a target of android, so it loads
-//    macros from the *linux* libstd.
-// 4. The macro generates a #[thread_local] field, but the android libstd does
-//    not use #[thread_local]
-// 5. Compile error about structs with wrong fields.
-//
-// To get around this, we're forced to inject the #[cfg] logic into the macro
-// itself. Woohoo.
-
-#[macro_export]
-#[doc(hidden)]
-#[allow_internal_unstable]
-macro_rules! __thread_local_inner {
-    (static $name:ident: $t:ty = $init:expr) => (
-        #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                       not(target_arch = "aarch64")),
-                   thread_local)]
-        static $name: ::std::thread_local::__impl::KeyInner<$t> =
-            __thread_local_inner!($init, $t);
-    );
-    (pub static $name:ident: $t:ty = $init:expr) => (
-        #[cfg_attr(all(any(target_os = "macos", target_os = "linux"),
-                       not(target_arch = "aarch64")),
-                   thread_local)]
-        pub static $name: ::std::thread_local::__impl::KeyInner<$t> =
-            __thread_local_inner!($init, $t);
-    );
-    ($init:expr, $t:ty) => ({
-        #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
-        const _INIT: ::std::thread_local::__impl::KeyInner<$t> = {
-            ::std::thread_local::__impl::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: $init },
-                dtor_registered: ::std::cell::UnsafeCell { value: false },
-                dtor_running: ::std::cell::UnsafeCell { value: false },
-            }
-        };
-
-        #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
-        const _INIT: ::std::thread_local::__impl::KeyInner<$t> = {
-            unsafe extern fn __destroy(ptr: *mut u8) {
-                ::std::thread_local::__impl::destroy_value::<$t>(ptr);
-            }
-
-            ::std::thread_local::__impl::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: $init },
-                os: ::std::thread_local::__impl::OsStaticKey {
-                    inner: ::std::thread_local::__impl::OS_INIT_INNER,
-                    dtor: ::std::option::Option::Some(__destroy as unsafe extern fn(*mut u8)),
-                },
-            }
-        };
-
-        _INIT
-    });
-}
-
-/// Indicator of the state of a thread local storage key.
-#[unstable(feature = "std_misc",
-           reason = "state querying was recently added")]
-#[derive(Eq, PartialEq, Copy)]
-pub enum State {
-    /// All keys are in this state whenever a thread starts. Keys will
-    /// transition to the `Valid` state once the first call to `with` happens
-    /// and the initialization expression succeeds.
-    ///
-    /// Keys in the `Uninitialized` state will yield a reference to the closure
-    /// passed to `with` so long as the initialization routine does not panic.
-    Uninitialized,
-
-    /// Once a key has been accessed successfully, it will enter the `Valid`
-    /// state. Keys in the `Valid` state will remain so until the thread exits,
-    /// at which point the destructor will be run and the key will enter the
-    /// `Destroyed` state.
-    ///
-    /// Keys in the `Valid` state will be guaranteed to yield a reference to the
-    /// closure passed to `with`.
-    Valid,
-
-    /// When a thread exits, the destructors for keys will be run (if
-    /// necessary). While a destructor is running, and possibly after a
-    /// destructor has run, a key is in the `Destroyed` state.
-    ///
-    /// Keys in the `Destroyed` states will trigger a panic when accessed via
-    /// `with`.
-    Destroyed,
-}
-
-impl<T: 'static> Key<T> {
-    /// Acquire a reference to the value in this TLS key.
-    ///
-    /// This will lazily initialize the value if this thread has not referenced
-    /// this key yet.
-    ///
-    /// # Panics
-    ///
-    /// This function will `panic!()` if the key currently has its
-    /// destructor running, and it **may** panic if the destructor has
-    /// previously been run for this thread.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with<F, R>(&'static self, f: F) -> R
-                      where F: FnOnce(&T) -> R {
-        let slot = (self.inner)();
-        unsafe {
-            let slot = slot.get().expect("cannot access a TLS value during or \
-                                          after it is destroyed");
-            f(match *slot.get() {
-                Some(ref inner) => inner,
-                None => self.init(slot),
-            })
-        }
-    }
-
-    unsafe fn init(&self, slot: &UnsafeCell<Option<T>>) -> &T {
-        // Execute the initialization up front, *then* move it into our slot,
-        // just in case initialization fails.
-        let value = (self.init)();
-        let ptr = slot.get();
-        *ptr = Some(value);
-        (*ptr).as_ref().unwrap()
-    }
-
-    /// Query the current state of this key.
-    ///
-    /// A key is initially in the `Uninitialized` state whenever a thread
-    /// starts. It will remain in this state up until the first call to `with`
-    /// within a thread has run the initialization expression successfully.
-    ///
-    /// Once the initialization expression succeeds, the key transitions to the
-    /// `Valid` state which will guarantee that future calls to `with` will
-    /// succeed within the thread.
-    ///
-    /// When a thread exits, each key will be destroyed in turn, and as keys are
-    /// destroyed they will enter the `Destroyed` state just before the
-    /// destructor starts to run. Keys may remain in the `Destroyed` state after
-    /// destruction has completed. Keys without destructors (e.g. with types
-    /// that are `Copy`), may never enter the `Destroyed` state.
-    ///
-    /// Keys in the `Uninitialized` can be accessed so long as the
-    /// initialization does not panic. Keys in the `Valid` state are guaranteed
-    /// to be able to be accessed. Keys in the `Destroyed` state will panic on
-    /// any call to `with`.
-    #[unstable(feature = "std_misc",
-               reason = "state querying was recently added")]
-    pub fn state(&'static self) -> State {
-        unsafe {
-            match (self.inner)().get() {
-                Some(cell) => {
-                    match *cell.get() {
-                        Some(..) => State::Valid,
-                        None => State::Uninitialized,
-                    }
-                }
-                None => State::Destroyed,
-            }
-        }
-    }
-
-    /// Deprecated
-    #[unstable(feature = "std_misc")]
-    #[deprecated(since = "1.0.0",
-                 reason = "function renamed to state() and returns more info")]
-    pub fn destroyed(&'static self) -> bool { self.state() == State::Destroyed }
-}
-
-#[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
-mod imp {
-    use prelude::v1::*;
-
-    use cell::UnsafeCell;
-    use intrinsics;
-    use ptr;
-
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
-    pub struct Key<T> {
-        // Place the inner bits in an `UnsafeCell` to currently get around the
-        // "only Sync statics" restriction. This allows any type to be placed in
-        // the cell.
-        //
-        // Note that all access requires `T: 'static` so it can't be a type with
-        // any borrowed pointers still.
-        #[unstable(feature = "thread_local_internals")]
-        pub inner: UnsafeCell<T>,
-
-        // Metadata to keep track of the state of the destructor. Remember that
-        // these variables are thread-local, not global.
-        #[unstable(feature = "thread_local_internals")]
-        pub dtor_registered: UnsafeCell<bool>, // should be Cell
-        #[unstable(feature = "thread_local_internals")]
-        pub dtor_running: UnsafeCell<bool>, // should be Cell
-    }
-
-    unsafe impl<T> ::marker::Sync for Key<T> { }
-
-    #[doc(hidden)]
-    impl<T> Key<T> {
-        pub unsafe fn get(&'static self) -> Option<&'static T> {
-            if intrinsics::needs_drop::<T>() && *self.dtor_running.get() {
-                return None
-            }
-            self.register_dtor();
-            Some(&*self.inner.get())
-        }
-
-        unsafe fn register_dtor(&self) {
-            if !intrinsics::needs_drop::<T>() || *self.dtor_registered.get() {
-                return
-            }
-
-            register_dtor(self as *const _ as *mut u8,
-                          destroy_value::<T>);
-            *self.dtor_registered.get() = true;
-        }
-    }
-
-    // Since what appears to be glibc 2.18 this symbol has been shipped which
-    // GCC and clang both use to invoke destructors in thread_local globals, so
-    // let's do the same!
-    //
-    // Note, however, that we run on lots older linuxes, as well as cross
-    // compiling from a newer linux to an older linux, so we also have a
-    // fallback implementation to use as well.
-    //
-    // Due to rust-lang/rust#18804, make sure this is not generic!
-    #[cfg(target_os = "linux")]
-    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
-        use boxed;
-        use mem;
-        use libc;
-        use sys_common::thread_local as os;
-
-        extern {
-            static __dso_handle: *mut u8;
-            #[linkage = "extern_weak"]
-            static __cxa_thread_atexit_impl: *const ();
-        }
-        if !__cxa_thread_atexit_impl.is_null() {
-            type F = unsafe extern fn(dtor: unsafe extern fn(*mut u8),
-                                      arg: *mut u8,
-                                      dso_handle: *mut u8) -> libc::c_int;
-            mem::transmute::<*const (), F>(__cxa_thread_atexit_impl)
-            (dtor, t, __dso_handle);
-            return
-        }
-
-        // The fallback implementation uses a vanilla OS-based TLS key to track
-        // the list of destructors that need to be run for this thread. The key
-        // then has its own destructor which runs all the other destructors.
-        //
-        // The destructor for DTORS is a little special in that it has a `while`
-        // loop to continuously drain the list of registered destructors. It
-        // *should* be the case that this loop always terminates because we
-        // provide the guarantee that a TLS key cannot be set after it is
-        // flagged for destruction.
-        static DTORS: os::StaticKey = os::StaticKey {
-            inner: os::INIT_INNER,
-            dtor: Some(run_dtors as unsafe extern "C" fn(*mut u8)),
-        };
-        type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
-        if DTORS.get().is_null() {
-            let v: Box<List> = box Vec::new();
-            DTORS.set(boxed::into_raw(v) as *mut u8);
-        }
-        let list: &mut List = &mut *(DTORS.get() as *mut List);
-        list.push((t, dtor));
-
-        unsafe extern fn run_dtors(mut ptr: *mut u8) {
-            while !ptr.is_null() {
-                let list: Box<List> = Box::from_raw(ptr as *mut List);
-                for &(ptr, dtor) in &*list {
-                    dtor(ptr);
-                }
-                ptr = DTORS.get();
-                DTORS.set(ptr::null_mut());
-            }
-        }
-    }
-
-    // OSX's analog of the above linux function is this _tlv_atexit function.
-    // The disassembly of thread_local globals in C++ (at least produced by
-    // clang) will have this show up in the output.
-    #[cfg(target_os = "macos")]
-    unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
-        extern {
-            fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
-                           arg: *mut u8);
-        }
-        _tlv_atexit(dtor, t);
-    }
-
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
-    pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
-        let ptr = ptr as *mut Key<T>;
-        // Right before we run the user destructor be sure to flag the
-        // destructor as running for this thread so calls to `get` will return
-        // `None`.
-        *(*ptr).dtor_running.get() = true;
-        ptr::read((*ptr).inner.get());
-    }
-}
-
-#[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
-mod imp {
-    use prelude::v1::*;
-
-    use alloc::boxed;
-    use cell::UnsafeCell;
-    use mem;
-    use ptr;
-    use sys_common::thread_local::StaticKey as OsStaticKey;
-
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
-    pub struct Key<T> {
-        // Statically allocated initialization expression, using an `UnsafeCell`
-        // for the same reasons as above.
-        #[unstable(feature = "thread_local_internals")]
-        pub inner: UnsafeCell<T>,
-
-        // OS-TLS key that we'll use to key off.
-        #[unstable(feature = "thread_local_internals")]
-        pub os: OsStaticKey,
-    }
-
-    unsafe impl<T> ::marker::Sync for Key<T> { }
-
-    struct Value<T: 'static> {
-        key: &'static Key<T>,
-        value: T,
-    }
-
-    #[doc(hidden)]
-    impl<T> Key<T> {
-        pub unsafe fn get(&'static self) -> Option<&'static T> {
-            self.ptr().map(|p| &*p)
-        }
-
-        unsafe fn ptr(&'static self) -> Option<*mut T> {
-            let ptr = self.os.get() as *mut Value<T>;
-            if !ptr.is_null() {
-                if ptr as usize == 1 {
-                    return None
-                }
-                return Some(&mut (*ptr).value as *mut T);
-            }
-
-            // If the lookup returned null, we haven't initialized our own local
-            // copy, so do that now.
-            //
-            // Also note that this transmute_copy should be ok because the value
-            // `inner` is already validated to be a valid `static` value, so we
-            // should be able to freely copy the bits.
-            let ptr: Box<Value<T>> = box Value {
-                key: self,
-                value: mem::transmute_copy(&self.inner),
-            };
-            let ptr: *mut Value<T> = boxed::into_raw(ptr);
-            self.os.set(ptr as *mut u8);
-            Some(&mut (*ptr).value as *mut T)
-        }
-    }
-
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
-    pub unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) {
-        // The OS TLS ensures that this key contains a NULL value when this
-        // destructor starts to run. We set it back to a sentinel value of 1 to
-        // ensure that any future calls to `get` for this thread will return
-        // `None`.
-        //
-        // Note that to prevent an infinite loop we reset it back to null right
-        // before we return from the destructor ourselves.
-        let ptr: Box<Value<T>> = Box::from_raw(ptr as *mut Value<T>);
-        let key = ptr.key;
-        key.os.set(1 as *mut u8);
-        drop(ptr);
-        key.os.set(ptr::null_mut());
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-
-    use sync::mpsc::{channel, Sender};
-    use cell::UnsafeCell;
-    use super::State;
-    use thread;
-
-    struct Foo(Sender<()>);
-
-    impl Drop for Foo {
-        fn drop(&mut self) {
-            let Foo(ref s) = *self;
-            s.send(()).unwrap();
-        }
-    }
-
-    #[test]
-    fn smoke_no_dtor() {
-        thread_local!(static FOO: UnsafeCell<i32> = UnsafeCell { value: 1 });
-
-        FOO.with(|f| unsafe {
-            assert_eq!(*f.get(), 1);
-            *f.get() = 2;
-        });
-        let (tx, rx) = channel();
-        let _t = thread::spawn(move|| {
-            FOO.with(|f| unsafe {
-                assert_eq!(*f.get(), 1);
-            });
-            tx.send(()).unwrap();
-        });
-        rx.recv().unwrap();
-
-        FOO.with(|f| unsafe {
-            assert_eq!(*f.get(), 2);
-        });
-    }
-
-    #[test]
-    fn states() {
-        struct Foo;
-        impl Drop for Foo {
-            fn drop(&mut self) {
-                assert!(FOO.state() == State::Destroyed);
-            }
-        }
-        fn foo() -> Foo {
-            assert!(FOO.state() == State::Uninitialized);
-            Foo
-        }
-        thread_local!(static FOO: Foo = foo());
-
-        thread::spawn(|| {
-            assert!(FOO.state() == State::Uninitialized);
-            FOO.with(|_| {
-                assert!(FOO.state() == State::Valid);
-            });
-            assert!(FOO.state() == State::Valid);
-        }).join().ok().unwrap();
-    }
-
-    #[test]
-    fn smoke_dtor() {
-        thread_local!(static FOO: UnsafeCell<Option<Foo>> = UnsafeCell {
-            value: None
-        });
-
-        let (tx, rx) = channel();
-        let _t = thread::spawn(move|| unsafe {
-            let mut tx = Some(tx);
-            FOO.with(|f| {
-                *f.get() = Some(Foo(tx.take().unwrap()));
-            });
-        });
-        rx.recv().unwrap();
-    }
-
-    #[test]
-    fn circular() {
-        struct S1;
-        struct S2;
-        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
-            value: None
-        });
-        thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
-            value: None
-        });
-        static mut HITS: u32 = 0;
-
-        impl Drop for S1 {
-            fn drop(&mut self) {
-                unsafe {
-                    HITS += 1;
-                    if K2.state() == State::Destroyed {
-                        assert_eq!(HITS, 3);
-                    } else {
-                        if HITS == 1 {
-                            K2.with(|s| *s.get() = Some(S2));
-                        } else {
-                            assert_eq!(HITS, 3);
-                        }
-                    }
-                }
-            }
-        }
-        impl Drop for S2 {
-            fn drop(&mut self) {
-                unsafe {
-                    HITS += 1;
-                    assert!(K1.state() != State::Destroyed);
-                    assert_eq!(HITS, 2);
-                    K1.with(|s| *s.get() = Some(S1));
-                }
-            }
-        }
-
-        thread::spawn(move|| {
-            drop(S1);
-        }).join().ok().unwrap();
-    }
-
-    #[test]
-    fn self_referential() {
-        struct S1;
-        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
-            value: None
-        });
-
-        impl Drop for S1 {
-            fn drop(&mut self) {
-                assert!(K1.state() == State::Destroyed);
-            }
-        }
-
-        thread::spawn(move|| unsafe {
-            K1.with(|s| *s.get() = Some(S1));
-        }).join().ok().unwrap();
-    }
-
-    #[test]
-    fn dtors_in_dtors_in_dtors() {
-        struct S1(Sender<()>);
-        thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell {
-            value: None
-        });
-        thread_local!(static K2: UnsafeCell<Option<Foo>> = UnsafeCell {
-            value: None
-        });
-
-        impl Drop for S1 {
-            fn drop(&mut self) {
-                let S1(ref tx) = *self;
-                unsafe {
-                    if K2.state() != State::Destroyed {
-                        K2.with(|s| *s.get() = Some(Foo(tx.clone())));
-                    }
-                }
-            }
-        }
-
-        let (tx, rx) = channel();
-        let _t = thread::spawn(move|| unsafe {
-            let mut tx = Some(tx);
-            K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
-        });
-        rx.recv().unwrap();
-    }
-}
-
-#[cfg(test)]
-mod dynamic_tests {
-    use prelude::v1::*;
-
-    use cell::RefCell;
-    use collections::HashMap;
-
-    #[test]
-    fn smoke() {
-        fn square(i: i32) -> i32 { i * i }
-        thread_local!(static FOO: i32 = square(3));
-
-        FOO.with(|f| {
-            assert_eq!(*f, 9);
-        });
-    }
-
-    #[test]
-    fn hashmap() {
-        fn map() -> RefCell<HashMap<i32, i32>> {
-            let mut m = HashMap::new();
-            m.insert(1, 2);
-            RefCell::new(m)
-        }
-        thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
-
-        FOO.with(|map| {
-            assert_eq!(map.borrow()[1], 2);
-        });
-    }
-
-    #[test]
-    fn refcell_vec() {
-        thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
-
-        FOO.with(|vec| {
-            assert_eq!(vec.borrow().len(), 3);
-            vec.borrow_mut().push(4);
-            assert_eq!(vec.borrow()[3], 4);
-        });
-    }
-}
diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs
deleted file mode 100644 (file)
index 86e6c05..0000000
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2014-2015 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.
-
-//! Scoped thread-local storage
-//!
-//! This module provides the ability to generate *scoped* thread-local
-//! variables. In this sense, scoped indicates that thread local storage
-//! actually stores a reference to a value, and this reference is only placed
-//! in storage for a scoped amount of time.
-//!
-//! There are no restrictions on what types can be placed into a scoped
-//! variable, but all scoped variables are initialized to the equivalent of
-//! null. Scoped thread local storage is useful when a value is present for a known
-//! period of time and it is not required to relinquish ownership of the
-//! contents.
-//!
-//! # Examples
-//!
-//! ```
-//! scoped_thread_local!(static FOO: u32);
-//!
-//! // Initially each scoped slot is empty.
-//! assert!(!FOO.is_set());
-//!
-//! // When inserting a value, the value is only in place for the duration
-//! // of the closure specified.
-//! FOO.set(&1, || {
-//!     FOO.with(|slot| {
-//!         assert_eq!(*slot, 1);
-//!     });
-//! });
-//! ```
-
-#![unstable(feature = "std_misc",
-            reason = "scoped TLS has yet to have wide enough use to fully consider \
-                      stabilizing its interface")]
-
-use prelude::v1::*;
-
-// macro hygiene sure would be nice, wouldn't it?
-#[doc(hidden)]
-pub mod __impl {
-    pub use super::imp::KeyInner;
-    pub use sys_common::thread_local::INIT as OS_INIT;
-}
-
-/// Type representing a thread local storage key corresponding to a reference
-/// to the type parameter `T`.
-///
-/// Keys are statically allocated and can contain a reference to an instance of
-/// type `T` scoped to a particular lifetime. Keys provides two methods, `set`
-/// and `with`, both of which currently use closures to control the scope of
-/// their contents.
-pub struct Key<T> { #[doc(hidden)] pub inner: __impl::KeyInner<T> }
-
-/// Declare a new scoped thread local storage key.
-///
-/// This macro declares a `static` item on which methods are used to get and
-/// set the value stored within.
-#[macro_export]
-#[allow_internal_unstable]
-macro_rules! scoped_thread_local {
-    (static $name:ident: $t:ty) => (
-        __scoped_thread_local_inner!(static $name: $t);
-    );
-    (pub static $name:ident: $t:ty) => (
-        __scoped_thread_local_inner!(pub static $name: $t);
-    );
-}
-
-#[macro_export]
-#[doc(hidden)]
-#[allow_internal_unstable]
-macro_rules! __scoped_thread_local_inner {
-    (static $name:ident: $t:ty) => (
-        #[cfg_attr(not(any(windows,
-                           target_os = "android",
-                           target_os = "ios",
-                           target_os = "openbsd",
-                           target_arch = "aarch64")),
-                   thread_local)]
-        static $name: ::std::thread_local::scoped::Key<$t> =
-            __scoped_thread_local_inner!($t);
-    );
-    (pub static $name:ident: $t:ty) => (
-        #[cfg_attr(not(any(windows,
-                           target_os = "android",
-                           target_os = "ios",
-                           target_os = "openbsd",
-                           target_arch = "aarch64")),
-                   thread_local)]
-        pub static $name: ::std::thread_local::scoped::Key<$t> =
-            __scoped_thread_local_inner!($t);
-    );
-    ($t:ty) => ({
-        use std::thread_local::scoped::Key as __Key;
-
-        #[cfg(not(any(windows,
-                      target_os = "android",
-                      target_os = "ios",
-                      target_os = "openbsd",
-                      target_arch = "aarch64")))]
-        const _INIT: __Key<$t> = __Key {
-            inner: ::std::thread_local::scoped::__impl::KeyInner {
-                inner: ::std::cell::UnsafeCell { value: 0 as *mut _ },
-            }
-        };
-
-        #[cfg(any(windows,
-                  target_os = "android",
-                  target_os = "ios",
-                  target_os = "openbsd",
-                  target_arch = "aarch64"))]
-        const _INIT: __Key<$t> = __Key {
-            inner: ::std::thread_local::scoped::__impl::KeyInner {
-                inner: ::std::thread_local::scoped::__impl::OS_INIT,
-                marker: ::std::marker::PhantomData::<::std::cell::Cell<$t>>,
-            }
-        };
-
-        _INIT
-    })
-}
-
-impl<T> Key<T> {
-    /// Insert a value into this scoped thread local storage slot for a
-    /// duration of a closure.
-    ///
-    /// While `cb` is running, the value `t` will be returned by `get` unless
-    /// this function is called recursively inside of `cb`.
-    ///
-    /// Upon return, this function will restore the previous value, if any
-    /// was available.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// scoped_thread_local!(static FOO: u32);
-    ///
-    /// FOO.set(&100, || {
-    ///     let val = FOO.with(|v| *v);
-    ///     assert_eq!(val, 100);
-    ///
-    ///     // set can be called recursively
-    ///     FOO.set(&101, || {
-    ///         // ...
-    ///     });
-    ///
-    ///     // Recursive calls restore the previous value.
-    ///     let val = FOO.with(|v| *v);
-    ///     assert_eq!(val, 100);
-    /// });
-    /// ```
-    pub fn set<R, F>(&'static self, t: &T, cb: F) -> R where
-        F: FnOnce() -> R,
-    {
-        struct Reset<'a, T: 'a> {
-            key: &'a __impl::KeyInner<T>,
-            val: *mut T,
-        }
-        #[unsafe_destructor]
-        impl<'a, T> Drop for Reset<'a, T> {
-            fn drop(&mut self) {
-                unsafe { self.key.set(self.val) }
-            }
-        }
-
-        let prev = unsafe {
-            let prev = self.inner.get();
-            self.inner.set(t as *const T as *mut T);
-            prev
-        };
-
-        let _reset = Reset { key: &self.inner, val: prev };
-        cb()
-    }
-
-    /// Get a value out of this scoped variable.
-    ///
-    /// This function takes a closure which receives the value of this
-    /// variable.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `set` has not previously been called.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// scoped_thread_local!(static FOO: u32);
-    ///
-    /// FOO.with(|slot| {
-    ///     // work with `slot`
-    /// });
-    /// ```
-    pub fn with<R, F>(&'static self, cb: F) -> R where
-        F: FnOnce(&T) -> R
-    {
-        unsafe {
-            let ptr = self.inner.get();
-            assert!(!ptr.is_null(), "cannot access a scoped thread local \
-                                     variable without calling `set` first");
-            cb(&*ptr)
-        }
-    }
-
-    /// Test whether this TLS key has been `set` for the current thread.
-    pub fn is_set(&'static self) -> bool {
-        unsafe { !self.inner.get().is_null() }
-    }
-}
-
-#[cfg(not(any(windows,
-              target_os = "android",
-              target_os = "ios",
-              target_os = "openbsd",
-              target_arch = "aarch64")))]
-mod imp {
-    use std::cell::UnsafeCell;
-
-    #[doc(hidden)]
-    pub struct KeyInner<T> { pub inner: UnsafeCell<*mut T> }
-
-    unsafe impl<T> ::marker::Sync for KeyInner<T> { }
-
-    #[doc(hidden)]
-    impl<T> KeyInner<T> {
-        #[doc(hidden)]
-        pub unsafe fn set(&self, ptr: *mut T) { *self.inner.get() = ptr; }
-        #[doc(hidden)]
-        pub unsafe fn get(&self) -> *mut T { *self.inner.get() }
-    }
-}
-
-#[cfg(any(windows,
-          target_os = "android",
-          target_os = "ios",
-          target_os = "openbsd",
-          target_arch = "aarch64"))]
-mod imp {
-    use marker;
-    use std::cell::Cell;
-    use sys_common::thread_local::StaticKey as OsStaticKey;
-
-    #[doc(hidden)]
-    pub struct KeyInner<T> {
-        pub inner: OsStaticKey,
-        pub marker: marker::PhantomData<Cell<T>>,
-    }
-
-    unsafe impl<T> ::marker::Sync for KeyInner<T> { }
-
-    #[doc(hidden)]
-    impl<T> KeyInner<T> {
-        #[doc(hidden)]
-        pub unsafe fn set(&self, ptr: *mut T) { self.inner.set(ptr as *mut _) }
-        #[doc(hidden)]
-        pub unsafe fn get(&self) -> *mut T { self.inner.get() as *mut _ }
-    }
-}
-
-
-#[cfg(test)]
-mod tests {
-    use cell::Cell;
-    use prelude::v1::*;
-
-    scoped_thread_local!(static FOO: u32);
-
-    #[test]
-    fn smoke() {
-        scoped_thread_local!(static BAR: u32);
-
-        assert!(!BAR.is_set());
-        BAR.set(&1, || {
-            assert!(BAR.is_set());
-            BAR.with(|slot| {
-                assert_eq!(*slot, 1);
-            });
-        });
-        assert!(!BAR.is_set());
-    }
-
-    #[test]
-    fn cell_allowed() {
-        scoped_thread_local!(static BAR: Cell<u32>);
-
-        BAR.set(&Cell::new(1), || {
-            BAR.with(|slot| {
-                assert_eq!(slot.get(), 1);
-            });
-        });
-    }
-
-    #[test]
-    fn scope_item_allowed() {
-        assert!(!FOO.is_set());
-        FOO.set(&1, || {
-            assert!(FOO.is_set());
-            FOO.with(|slot| {
-                assert_eq!(*slot, 1);
-            });
-        });
-        assert!(!FOO.is_set());
-    }
-}
index 70aab26092c440548a082bebf4d1ae230602ac6a..1abe8d0a3c1b1352e77100adb0f246b130981a04 100644 (file)
@@ -351,8 +351,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
                         let max_line_length = if lines.len() == 1 {
                             0
                         } else {
-                            lines.as_slice()
-                                 .windows(2)
+                            lines.windows(2)
                                  .map(|w| w[1] - w[0])
                                  .map(|bp| bp.to_usize())
                                  .max()
index d7961d7da00f1e2e296bfd2e1f04c0a2b4a18398..06255f46779259a67bda3460369cbb3a4e3c0954 100644 (file)
@@ -64,7 +64,7 @@
 //!     fn encode(&self, s: &mut S) -> Result<(), E> {
 //!         s.emit_struct("Spanned", 2, |this| {
 //!             this.emit_struct_field("node", 0, |this| self.node.encode(this))
-//!                 .ok().unwrap();
+//!                 .unwrap();
 //!             this.emit_struct_field("span", 1, |this| self.span.encode(this))
 //!         })
 //!     }
@@ -79,9 +79,9 @@
 //!         d.read_struct("Spanned", 2, |this| {
 //!             Ok(Spanned {
 //!                 node: this.read_struct_field("node", 0, |this| Decodable::decode(this))
-//!                     .ok().unwrap(),
+//!                     .unwrap(),
 //!                 span: this.read_struct_field("span", 1, |this| Decodable::decode(this))
-//!                     .ok().unwrap(),
+//!                     .unwrap(),
 //!             })
 //!         })
 //!     }
index 0eaca9af4f08d41258287ac5c0dc24704b848caa..2fe77bf7a5411cbff2ed0c49a6acfeb769e32491 100644 (file)
@@ -513,7 +513,7 @@ fn into_expr(mut self) -> P<ast::Expr> {
             let lname = self.ecx.ident_of(&format!("__arg{}",
                                                   *name));
             pats.push(self.ecx.pat_ident(e.span, lname));
-            names[self.name_positions[*name]] =
+            names[*self.name_positions.get(name).unwrap()] =
                 Some(Context::format_arg(self.ecx, e.span, arg_ty,
                                          self.ecx.expr_ident(e.span, lname)));
             heads.push(self.ecx.expr_addr_of(e.span, e));
index c61aec0069db255032b059d3bedd105b86305878..31d8b207bb9f080134fcbc582391391b1924c726 100644 (file)
@@ -194,7 +194,7 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 fn res_rel_file(cx: &mut ExtCtxt, sp: codemap::Span, arg: &Path) -> PathBuf {
     // NB: relative paths are resolved relative to the compilation unit
     if !arg.is_absolute() {
-        let mut cu = PathBuf::new(&cx.codemap().span_to_filename(sp));
+        let mut cu = PathBuf::from(&cx.codemap().span_to_filename(sp));
         cu.pop();
         cu.push(arg);
         cu
index 7a2ae55e91494cfad3186ac0122fcbc45c955bd5..5940b791843797cacf97c7225dd9a413e27d74c8 100644 (file)
@@ -236,7 +236,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
                                      argument_gram);
 
     // Extract the arguments:
-    let lhses = match *argument_map[lhs_nm] {
+    let lhses = match **argument_map.get(&lhs_nm).unwrap() {
         MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
         _ => cx.span_bug(def.span, "wrong-structured lhs")
     };
@@ -245,7 +245,7 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt,
         check_lhs_nt_follows(cx, &**lhs, def.span);
     }
 
-    let rhses = match *argument_map[rhs_nm] {
+    let rhses = match **argument_map.get(&rhs_nm).unwrap() {
         MatchedSeq(ref s, _) => /* FIXME (#2543) */ (*s).clone(),
         _ => cx.span_bug(def.span, "wrong-structured rhs")
     };
index 0a9980c892527a9b88bec0fecbb6f1bcf2282f56..f5e891a9dd6439c87a732933ab25b306e0cd693c 100644 (file)
@@ -563,6 +563,13 @@ fn visit_item(&mut self, i: &ast::Item) {
                 }
             }
 
+            ast::ItemDefaultImpl(..) => {
+                self.gate_feature("optin_builtin_traits",
+                                  i.span,
+                                  "default trait implementations are experimental \
+                                   and possibly buggy");
+            }
+
             ast::ItemImpl(_, polarity, _, _, _, _) => {
                 match polarity {
                     ast::ImplPolarity::Negative => {
index 9f217bba00ab6e2b30b280c953a72032aed578a4..9af7b9ab633116619c2e9ff3cc12b4ad28e5ad74 100644 (file)
@@ -39,6 +39,8 @@
 #![feature(unicode)]
 #![feature(path_ext)]
 #![feature(str_char)]
+#![feature(convert)]
+#![feature(into_cow)]
 
 extern crate arena;
 extern crate fmt_macros;
index bb8f9da89171c96c8dea5b39f7de55a071ae2e1a..e0953a8ace68d5c646ee23fa436766fca91b9ad5 100644 (file)
@@ -623,7 +623,7 @@ fn bump_expecting_char<'a,D:fmt::Debug>(r: &mut StringReader<'a>,
         // find the integer representing the name
         self.scan_digits(base);
         let encoded_name : u32 = self.with_str_from(start_bpos, |s| {
-            num::from_str_radix(s, 10).ok().unwrap_or_else(|| {
+            num::from_str_radix(s, 10).unwrap_or_else(|_| {
                 panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]",
                       s, whence, start_bpos, self.last_pos);
             })
@@ -641,7 +641,7 @@ fn bump_expecting_char<'a,D:fmt::Debug>(r: &mut StringReader<'a>,
         let start_bpos = self.last_pos;
         self.scan_digits(base);
         let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| {
-            num::from_str_radix(s, 10).ok().unwrap_or_else(|| {
+            num::from_str_radix(s, 10).unwrap_or_else(|_| {
                 panic!("expected digits representing a ctxt, got {:?}, {}", s, whence);
             })
         });
index 667af642744b9db478dad5ce0fcd12f528599e3b..e77786c134707567abb3bb38f34611ff6de0d0bb 100644 (file)
@@ -5064,8 +5064,8 @@ fn eval_src_mod(&mut self,
                     outer_attrs: &[ast::Attribute],
                     id_sp: Span)
                     -> (ast::Item_, Vec<ast::Attribute> ) {
-        let mut prefix = PathBuf::new(&self.sess.span_diagnostic.cm
-                                           .span_to_filename(self.span));
+        let mut prefix = PathBuf::from(&self.sess.span_diagnostic.cm
+                                            .span_to_filename(self.span));
         prefix.pop();
         let mut dir_path = prefix;
         for part in &self.mod_path_stack {
index f517dca53cdd20366324ceae83dd523a55597220..8e3c00bb805fe30aaefd92ac2ba9f1e3f0d14cd9 100644 (file)
@@ -62,6 +62,7 @@
 #![feature(std_misc)]
 #![feature(str_char)]
 #![feature(path_ext)]
+#![feature(convert)]
 #![cfg_attr(windows, feature(libc))]
 
 #[macro_use] extern crate log;
index 3c269cc485dad908aec4fda4bb09a50625460ad1..309320b52ffe4aa641abdf485537f5452eb7f64a 100644 (file)
@@ -181,21 +181,24 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
             }
         };
 
-        let entry = open(&term[..]);
-        if entry.is_err() {
-            if env::var("MSYSCON").ok().map_or(false, |s| {
-                    "mintty.exe" == s
-                }) {
-                // msys terminal
-                return Some(box TerminfoTerminal {out: out,
-                                                  ti: msys_terminfo(),
-                                                  num_colors: 8} as Box<Terminal<T>+Send>);
-            }
-            debug!("error finding terminfo entry: {:?}", entry.err().unwrap());
-            return None;
-        }
+        let mut file = match open(&term[..]) {
+            Ok(f) => f,
+            Err(err) => return match env::var("MSYSCON") {
+                Ok(ref val) if &val[..] == "mintty.exe" => {
+                    // msys terminal
+                    Some(box TerminfoTerminal{
+                        out: out,
+                        ti: msys_terminfo(),
+                        num_colors: 8,
+                    } as Box<Terminal<T>+Send>)
+                },
+                _ => {
+                    debug!("error finding terminfo entry: {:?}", err);
+                    None
+                },
+            },
+        };
 
-        let mut file = entry.unwrap();
         let ti = parse(&mut file, false);
         if ti.is_err() {
             debug!("error parsing terminfo entry: {:?}", ti.err().unwrap());
index f47921cbf5e6acc3e921dd04ea36b1b373a33b2e..66ee2b1ba87cbee6337302ff195d21093564ae41 100644 (file)
@@ -31,7 +31,7 @@ pub fn get_dbpath_for_term(term: &str) -> Option<Box<PathBuf>> {
 
     // Find search directory
     match env::var_os("TERMINFO") {
-        Some(dir) => dirs_to_search.push(PathBuf::new(&dir)),
+        Some(dir) => dirs_to_search.push(PathBuf::from(dir)),
         None => {
             if homedir.is_some() {
                 // ncurses compatibility;
@@ -40,9 +40,9 @@ pub fn get_dbpath_for_term(term: &str) -> Option<Box<PathBuf>> {
             match env::var("TERMINFO_DIRS") {
                 Ok(dirs) => for i in dirs.split(':') {
                     if i == "" {
-                        dirs_to_search.push(PathBuf::new("/usr/share/terminfo"));
+                        dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
                     } else {
-                        dirs_to_search.push(PathBuf::new(i));
+                        dirs_to_search.push(PathBuf::from(i));
                     }
                 },
                 // Found nothing in TERMINFO_DIRS, use the default paths:
@@ -50,9 +50,9 @@ pub fn get_dbpath_for_term(term: &str) -> Option<Box<PathBuf>> {
                 // ~/.terminfo, ncurses will search /etc/terminfo, then
                 // /lib/terminfo, and eventually /usr/share/terminfo.
                 Err(..) => {
-                    dirs_to_search.push(PathBuf::new("/etc/terminfo"));
-                    dirs_to_search.push(PathBuf::new("/lib/terminfo"));
-                    dirs_to_search.push(PathBuf::new("/usr/share/terminfo"));
+                    dirs_to_search.push(PathBuf::from("/etc/terminfo"));
+                    dirs_to_search.push(PathBuf::from("/lib/terminfo"));
+                    dirs_to_search.push(PathBuf::from("/usr/share/terminfo"));
                 }
             }
         }
index 51decbab8587d1e516279ff98e05dccd3dd6ce91..94944453eda07d50368ccc410060e6189f3d1245 100644 (file)
@@ -45,6 +45,7 @@
 #![feature(libc)]
 #![feature(set_stdio)]
 #![feature(os)]
+#![feature(convert)]
 
 extern crate getopts;
 extern crate serialize;
@@ -382,7 +383,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
     let run_ignored = matches.opt_present("ignored");
 
     let logfile = matches.opt_str("logfile");
-    let logfile = logfile.map(|s| PathBuf::new(&s));
+    let logfile = logfile.map(|s| PathBuf::from(&s));
 
     let run_benchmarks = matches.opt_present("bench");
     let run_tests = ! run_benchmarks ||
@@ -696,7 +697,7 @@ fn len_if_padded(t: &TestDescAndFn) -> uint {
     match tests.iter().max_by(|t|len_if_padded(*t)) {
         Some(t) => {
             let n = t.desc.name.as_slice();
-            st.max_name_len = n.as_slice().len();
+            st.max_name_len = n.len();
         },
         None => {}
     }
index 84d86c5746c0bcfdaa81c9e62b630c5625fbc8fb..e20e6d4f29bfab982cfcd71846711eee6f78cae8 100644 (file)
@@ -333,7 +333,7 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
 mod tests {
     use stats::Stats;
     use stats::Summary;
-    use std::old_io;
+    use std::old_io::{self, Writer};
     use std::f64;
 
     macro_rules! assert_approx_eq {
index ac7f2f824cbbf9ab9c5d3dcab3fb911ad7ea8df0..a08481f8be94e0473c8cfc6b77167bf83d7aa4c1 100644 (file)
@@ -102,8 +102,8 @@ fn collapse(stack: &mut Vec<BookItem>,
     // always include the introduction
     top_items.push(BookItem {
         title: "Introduction".to_string(),
-        path: PathBuf::new("README.md"),
-        path_to_root: PathBuf::new("."),
+        path: PathBuf::from("README.md"),
+        path_to_root: PathBuf::from("."),
         children: vec!(),
     });
 
@@ -133,10 +133,10 @@ fn collapse(stack: &mut Vec<BookItem>,
                 errors.push(format!("paths in SUMMARY.md must be relative, \
                                      but path '{}' for section '{}' is not.",
                                      given_path, title));
-                PathBuf::new("")
+                PathBuf::new()
             }
         };
-        let path_to_root = PathBuf::new(&iter::repeat("../")
+        let path_to_root = PathBuf::from(&iter::repeat("../")
                                          .take(path_from_root.components().count() - 1)
                                          .collect::<String>());
         let item = BookItem {
index 731773917e09118452152504f0df79da09bd10e4..f06290b27cb2809583269f159f4b3313de5745ee 100644 (file)
@@ -87,7 +87,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         if env::args().len() < 3 {
             src = env::current_dir().unwrap().clone();
         } else {
-            src = PathBuf::new(&env::args().nth(2).unwrap());
+            src = PathBuf::from(&env::args().nth(2).unwrap());
         }
         // preprocess the markdown, rerouting markdown references to html references
         let mut markdown_data = String::new();
@@ -164,13 +164,13 @@ fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
         if env::args().len() < 3 {
             src = cwd.clone();
         } else {
-            src = PathBuf::new(&env::args().nth(2).unwrap());
+            src = PathBuf::from(&env::args().nth(2).unwrap());
         }
 
         if env::args().len() < 4 {
             tgt = cwd.join("_book");
         } else {
-            tgt = PathBuf::new(&env::args().nth(3).unwrap());
+            tgt = PathBuf::from(&env::args().nth(3).unwrap());
         }
 
         try!(fs::create_dir(&tgt));
index 294b4e556694ad2be1c935ab5749226a392877bf..e896dee27919e1c4121e2be47b7c5c334e8ffa1f 100644 (file)
@@ -20,6 +20,7 @@
 pub type CommandResult<T> = Result<T, CommandError>;
 
 pub fn err(s: &str) -> CliError {
+    #[derive(Debug)]
     struct E(String);
 
     impl Error for E {
index 09fcd518c1e7e3998f32851738559f36840d845d..4a652f846ed58bd0112c54e609a64737c8dad74f 100644 (file)
@@ -15,6 +15,7 @@
 #![feature(rustdoc)]
 #![feature(rustc_private)]
 #![feature(path_relative_from)]
+#![feature(convert)]
 
 extern crate rustdoc;
 extern crate rustc_back;
index dd1ad413a3d279a873f299ec853c7e03dbf68c1a..604a3e69a21767909233a369c61149385b64a07a 100644 (file)
@@ -19,6 +19,6 @@
 
 // the unused ty param is necessary so this gets monomorphized
 pub fn request<T>(req: &header_map) {
-  let data = req["METHOD".to_string()].clone();
+  let data = req[&"METHOD".to_string()].clone();
   let _x = data.borrow().clone()[0].clone();
 }
index 6cd94ee5602aa5ccf3db96b0b1f3ccda3dcae6ef..03fe2fd94dd527587e50ea7f88f3b480e582f1f4 100644 (file)
@@ -27,8 +27,7 @@ fn bar() { }
 fn baz() { }
 
 pub fn test() {
-    let none: Option<&Path> = None; // appease the typechecker
-    let lib = DynamicLibrary::open(none).unwrap();
+    let lib = DynamicLibrary::open(None).unwrap();
     unsafe {
         assert!(lib.symbol::<int>("foo").is_ok());
         assert!(lib.symbol::<int>("baz").is_err());
index d9a2b06e0393f6f9899af007653ddf0cadc22e4e..18db50a831ca8d5b840168b96550869729573054 100644 (file)
@@ -33,7 +33,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
 
     let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) {
         Success(map) => {
-            match (&*map[str_to_ident("matched")], &*map[str_to_ident("pat")]) {
+            match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) {
                 (&MatchedNonterminal(NtExpr(ref matched_expr)),
                  &MatchedSeq(ref pats, seq_sp)) => {
                     let pats: Vec<P<Pat>> = pats.iter().map(|pat_nt|
index 4c3b3f42acaa9470b77c294bd9525e8adcf878ab..c2ea097ed751f73940981847e20f29821dc8ab8c 100644 (file)
@@ -13,7 +13,8 @@
 
 #![feature(unboxed_closures)]
 
-use std::old_io::File;
+use std::old_io::*;
+use std::old_path::{Path, GenericPath};
 use std::iter::repeat;
 use std::mem::swap;
 use std::env;
index 9cee75757aa1c13a6805e00424a950173ccfa6d2..289f05a299b9942205dd8c763033d1d99ea02a1a 100644 (file)
@@ -39,7 +39,7 @@
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use std::cmp::min;
-use std::old_io::{stdout, IoResult};
+use std::old_io::*;
 use std::iter::repeat;
 use std::env;
 use std::slice::bytes::copy_memory;
index e15f9d99ff691fa4f3f92d49633e7d0cba306541..df839fc27eec8ee6d8495dfd2a5e64f9fa150992 100644 (file)
@@ -39,8 +39,9 @@
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
 use std::cmp::min;
-use std::old_io::{BufferedWriter, File};
+use std::old_io::*;
 use std::old_io;
+use std::old_path::Path;
 use std::num::Float;
 use std::env;
 
index 3ea4a10ea8169f7d148f287b937d599616773f1a..88c9f43f6ec7ca434334ab32cf7e7c8e3592aafb 100644 (file)
@@ -147,7 +147,7 @@ fn make_sequence_processor(sz: uint,
 
 // given a FASTA file on stdin, process sequence THREE
 fn main() {
-    use std::old_io::{stdio, MemReader, BufferedReader};
+    use std::old_io::*;
 
     let rdr = if env::var_os("RUST_BENCH").is_some() {
         let foo = include_bytes!("shootout-k-nucleotide.data");
index bddf615322816d40e1212465d46b01e9d2503be0..128c92921fa8616162c88743baf74f3ee01218a3 100644 (file)
@@ -43,6 +43,7 @@
 // ignore-pretty very bad with line comments
 
 use std::old_io;
+use std::old_io::*;
 use std::env;
 use std::simd::f64x2;
 use std::sync::Arc;
index 33d959dfe93e35f592320a4913dd69d3c7c3a313..93aa5f2571bfbd30a138d928c0c3c0feb87735d0 100644 (file)
@@ -45,7 +45,7 @@
 extern crate libc;
 
 use std::old_io::stdio::{stdin_raw, stdout_raw};
-use std::old_io::{IoResult, EndOfFile};
+use std::old_io::*;
 use std::ptr::{copy_memory, Unique};
 use std::thread;
 
diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs
new file mode 100644 (file)
index 0000000..a88445b
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 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 that macro reexports item are gated by `macro_reexport` feature gate.
+
+// aux-build:macro_reexport_1.rs
+// ignore-stage1
+
+#![crate_type = "dylib"]
+
+#[macro_reexport(reexported)]
+#[macro_use] #[no_link]
+extern crate macro_reexport_1;
+//~^ ERROR macros reexports are experimental and possibly buggy
+//~| HELP add #![feature(macro_reexport)] to the crate attributes to enable
diff --git a/src/test/compile-fail/borrowck-overloaded-index-2.rs b/src/test/compile-fail/borrowck-overloaded-index-2.rs
deleted file mode 100644 (file)
index 58668b7..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 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.
-
-#![feature(box_syntax)]
-
-use std::ops::Index;
-
-struct MyVec<T> {
-    data: Vec<T>,
-}
-
-impl<T> Index<usize> for MyVec<T> {
-    type Output = T;
-
-    fn index(&self, &i: &usize) -> &T {
-        &self.data[i]
-    }
-}
-
-fn main() {
-    let v = MyVec::<Box<_>> { data: vec!(box 1, box 2, box 3) };
-    let good = &v[0]; // Shouldn't fail here
-    let bad = v[0];
-    //~^ ERROR cannot move out of indexed content
-}
index 430f2fcc13a73c0a075cd0ae286739c9bbcb54ea..bee56c9bf390bb17092d20dc86324435decad8e7 100644 (file)
@@ -19,7 +19,7 @@ struct MyVec<T> { x: T }
 
 impl<T> Index<usize> for MyVec<T> {
     type Output = T;
-    fn index(&self, _: &usize) -> &T {
+    fn index(&self, _: usize) -> &T {
         &self.x
     }
 }
index 99f396ef8143213af415dbca2a649d0b4e1cd167..55a6e2ac7b8d6755f8bd2bcac6da1e07105a5d8e 100644 (file)
@@ -18,6 +18,7 @@ struct Foo {
     y: isize,
 }
 
+#[cfg(stage0)]
 impl Index<String> for Foo {
     type Output = isize;
 
@@ -30,8 +31,20 @@ fn index<'a>(&'a self, z: &String) -> &'a isize {
     }
 }
 
-impl IndexMut<String> for Foo {
-    fn index_mut<'a>(&'a mut self, z: &String) -> &'a mut isize {
+impl<'a> Index<&'a String> for Foo {
+    type Output = isize;
+
+    fn index(&self, z: &String) -> &isize {
+        if *z == "x" {
+            &self.x
+        } else {
+            &self.y
+        }
+    }
+}
+
+impl<'a> IndexMut<&'a String> for Foo {
+    fn index_mut(&mut self, z: &String) -> &mut isize {
         if *z == "x" {
             &mut self.x
         } else {
@@ -41,13 +54,13 @@ fn index_mut<'a>(&'a mut self, z: &String) -> &'a mut isize {
 }
 
 fn test1(mut f: Box<Foo>, s: String) {
-    let _p = &mut f[s];
-    let _q = &f[s]; //~ ERROR cannot borrow
+    let _p = &mut f[&s];
+    let _q = &f[&s]; //~ ERROR cannot borrow
 }
 
 fn test2(mut f: Box<Foo>, s: String) {
-    let _p = &mut f[s];
-    let _q = &mut f[s]; //~ ERROR cannot borrow
+    let _p = &mut f[&s];
+    let _q = &mut f[&s]; //~ ERROR cannot borrow
 }
 
 struct Bar {
@@ -55,37 +68,37 @@ struct Bar {
 }
 
 fn test3(mut f: Box<Bar>, s: String) {
-    let _p = &mut f.foo[s];
-    let _q = &mut f.foo[s]; //~ ERROR cannot borrow
+    let _p = &mut f.foo[&s];
+    let _q = &mut f.foo[&s]; //~ ERROR cannot borrow
 }
 
 fn test4(mut f: Box<Bar>, s: String) {
-    let _p = &f.foo[s];
-    let _q = &f.foo[s];
+    let _p = &f.foo[&s];
+    let _q = &f.foo[&s];
 }
 
 fn test5(mut f: Box<Bar>, s: String) {
-    let _p = &f.foo[s];
-    let _q = &mut f.foo[s]; //~ ERROR cannot borrow
+    let _p = &f.foo[&s];
+    let _q = &mut f.foo[&s]; //~ ERROR cannot borrow
 }
 
 fn test6(mut f: Box<Bar>, g: Foo, s: String) {
-    let _p = &f.foo[s];
+    let _p = &f.foo[&s];
     f.foo = g; //~ ERROR cannot assign
 }
 
 fn test7(mut f: Box<Bar>, g: Bar, s: String) {
-    let _p = &f.foo[s];
+    let _p = &f.foo[&s];
     *f = g; //~ ERROR cannot assign
 }
 
 fn test8(mut f: Box<Bar>, g: Foo, s: String) {
-    let _p = &mut f.foo[s];
+    let _p = &mut f.foo[&s];
     f.foo = g; //~ ERROR cannot assign
 }
 
 fn test9(mut f: Box<Bar>, g: Bar, s: String) {
-    let _p = &mut f.foo[s];
+    let _p = &mut f.foo[&s];
     *f = g; //~ ERROR cannot assign
 }
 
diff --git a/src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs b/src/test/compile-fail/borrowck-overloaded-index-move-from-vec.rs
new file mode 100644 (file)
index 0000000..1b62d9c
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2014 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.
+
+#![feature(box_syntax)]
+
+use std::ops::Index;
+
+struct MyVec<T> {
+    data: Vec<T>,
+}
+
+impl<T> Index<usize> for MyVec<T> {
+    type Output = T;
+
+    fn index(&self, i: usize) -> &T {
+        &self.data[i]
+    }
+}
+
+fn main() {
+    let v = MyVec::<Box<_>> { data: vec!(box 1, box 2, box 3) };
+    let good = &v[0]; // Shouldn't fail here
+    let bad = v[0];
+    //~^ ERROR cannot move out of indexed content
+}
diff --git a/src/test/compile-fail/borrowck-overloaded-index-move-index.rs b/src/test/compile-fail/borrowck-overloaded-index-move-index.rs
new file mode 100644 (file)
index 0000000..d8615d1
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright 2014 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 std::ops::{Index, IndexMut};
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+impl Index<String> for Foo {
+    type Output = isize;
+
+    fn index(&self, z: String) -> &isize {
+        if z == "x" {
+            &self.x
+        } else {
+            &self.y
+        }
+    }
+}
+
+impl IndexMut<String> for Foo {
+    fn index_mut(&mut self, z: String) -> &mut isize {
+        if z == "x" {
+            &mut self.x
+        } else {
+            &mut self.y
+        }
+    }
+}
+
+struct Bar {
+    x: isize,
+}
+
+impl Index<isize> for Bar {
+    type Output = isize;
+
+    fn index<'a>(&'a self, z: isize) -> &'a isize {
+        &self.x
+    }
+}
+
+fn main() {
+    let mut f = Foo {
+        x: 1,
+        y: 2,
+    };
+    let mut s = "hello".to_string();
+    let rs = &mut s;
+
+    println!("{}", f[s]);
+    //~^ ERROR cannot move out of `s` because it is borrowed
+
+    f[s] = 10;
+    //~^ ERROR cannot move out of `s` because it is borrowed
+    //~| ERROR use of moved value: `s`
+
+    let s = Bar {
+        x: 1,
+    };
+    let i = 2;
+    let _j = &i;
+    println!("{}", s[i]); // no error, i is copy
+    println!("{}", s[i]);
+}
diff --git a/src/test/compile-fail/borrowck-overloaded-index-ref-index.rs b/src/test/compile-fail/borrowck-overloaded-index-ref-index.rs
new file mode 100644 (file)
index 0000000..4c50caf
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright 2014 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 std::ops::{Index, IndexMut};
+
+struct Foo {
+    x: isize,
+    y: isize,
+}
+
+impl<'a> Index<&'a String> for Foo {
+    type Output = isize;
+
+    fn index(&self, z: &String) -> &isize {
+        if *z == "x" {
+            &self.x
+        } else {
+            &self.y
+        }
+    }
+}
+
+impl<'a> IndexMut<&'a String> for Foo {
+    fn index_mut(&mut self, z: &String) -> &mut isize {
+        if *z == "x" {
+            &mut self.x
+        } else {
+            &mut self.y
+        }
+    }
+}
+
+struct Bar {
+    x: isize,
+}
+
+impl Index<isize> for Bar {
+    type Output = isize;
+
+    fn index<'a>(&'a self, z: isize) -> &'a isize {
+        &self.x
+    }
+}
+
+fn main() {
+    let mut f = Foo {
+        x: 1,
+        y: 2,
+    };
+    let mut s = "hello".to_string();
+    let rs = &mut s;
+    println!("{}", f[&s]);
+    //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    f[&s] = 10;
+    //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+    let s = Bar {
+        x: 1,
+    };
+    s[2] = 20;
+    //~^ ERROR cannot assign to immutable indexed content
+}
diff --git a/src/test/compile-fail/borrowck-overloaded-index.rs b/src/test/compile-fail/borrowck-overloaded-index.rs
deleted file mode 100644 (file)
index 2d752ab..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 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 std::ops::{Index, IndexMut};
-
-struct Foo {
-    x: isize,
-    y: isize,
-}
-
-impl Index<String> for Foo {
-    type Output = isize;
-
-    fn index<'a>(&'a self, z: &String) -> &'a isize {
-        if *z == "x" {
-            &self.x
-        } else {
-            &self.y
-        }
-    }
-}
-
-impl IndexMut<String> for Foo {
-    fn index_mut<'a>(&'a mut self, z: &String) -> &'a mut isize {
-        if *z == "x" {
-            &mut self.x
-        } else {
-            &mut self.y
-        }
-    }
-}
-
-struct Bar {
-    x: isize,
-}
-
-impl Index<isize> for Bar {
-    type Output = isize;
-
-    fn index<'a>(&'a self, z: &isize) -> &'a isize {
-        &self.x
-    }
-}
-
-fn main() {
-    let mut f = Foo {
-        x: 1,
-        y: 2,
-    };
-    let mut s = "hello".to_string();
-    let rs = &mut s;
-    println!("{}", f[s]);
-    //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
-    f[s] = 10;
-    //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
-    let s = Bar {
-        x: 1,
-    };
-    s[2] = 20;
-    //~^ ERROR cannot assign to immutable indexed content
-}
index e59bd62d178549133ae66fe02cd04cc1cb21bbba..5ddde6460b01f9504bf283aa53675e186bb65bf2 100644 (file)
@@ -10,6 +10,8 @@
 
 #![feature(unboxed_closures)]
 
+use std::io::Read;
+
 fn to_fn_once<A,F:FnOnce<A>>(f: F) -> F { f }
 
 fn main() {
@@ -17,7 +19,7 @@ fn main() {
     to_fn_once(move|| { x = 2; });
     //~^ ERROR: cannot assign to immutable captured outer variable
 
-    let s = std::old_io::stdin();
-    to_fn_once(move|| { s.read_to_end(); });
+    let s = std::io::stdin();
+    to_fn_once(move|| { s.read_to_end(&mut Vec::new()); });
     //~^ ERROR: cannot borrow immutable captured outer variable
 }
index 6bcbefb904d9e6a510ec6120a94a40e80aeefa57..a5b317307379e82cfa80d034d4a95e8bca787c6c 100644 (file)
@@ -21,4 +21,14 @@ impl MyTrait for .. {}
 impl MyTrait for .. {}
 //~^ ERROR conflicting implementations for trait `MyTrait`
 
+trait MySafeTrait: MarkerTrait {}
+
+unsafe impl MySafeTrait for .. {}
+//~^ ERROR implementing the trait `MySafeTrait` is not unsafe
+
+unsafe trait MyUnsafeTrait: MarkerTrait {}
+
+impl MyUnsafeTrait for .. {}
+//~^ ERROR the trait `MyUnsafeTrait` requires an `unsafe impl` declaration
+
 fn main() {}
index 91f34320482561aca98a3a707e8405a976579c41..021ef7343cbb4432f028f51e030967d23a98db43 100644 (file)
@@ -20,7 +20,7 @@
 impl Index<usize> for S {
     type Output = str;
 
-    fn index<'a>(&'a self, _: &usize) -> &'a str {
+    fn index(&self, _: usize) -> &str {
         "hello"
     }
 }
@@ -31,7 +31,7 @@ fn index<'a>(&'a self, _: &usize) -> &'a str {
 impl Index<usize> for T {
     type Output = Debug + 'static;
 
-    fn index<'a>(&'a self, idx: &usize) -> &'a (Debug + 'static) {
+    fn index<'a>(&'a self, idx: usize) -> &'a (Debug + 'static) {
         static x: usize = 42;
         &x
     }
diff --git a/src/test/compile-fail/gated-box-patterns.rs b/src/test/compile-fail/gated-box-patterns.rs
new file mode 100644 (file)
index 0000000..abaa256
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 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 that patterns including the box syntax are gated by `box_patterns` feature gate.
+
+fn main() {
+    let x = Box::new(1);
+
+    match x {
+        box 1 => (),
+        //~^ box pattern syntax is experimental
+        //~| add #![feature(box_patterns)] to the crate attributes to enable
+        _     => ()
+    };
+}
diff --git a/src/test/compile-fail/gated-box-syntax.rs b/src/test/compile-fail/gated-box-syntax.rs
new file mode 100644 (file)
index 0000000..3e08c1f
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 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 that the use of the box syntax is gated by `box_syntax` feature gate.
+
+fn main() {
+    let x = box 3;
+    //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
+    //~| HELP add #![feature(box_syntax)] to the crate attributes to enable
+}
diff --git a/src/test/compile-fail/gated-simd-ffi.rs b/src/test/compile-fail/gated-simd-ffi.rs
new file mode 100644 (file)
index 0000000..c0a251e
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2015 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 that the use of smid types in the ffi is gated by `smid_ffi` feature gate.
+
+#![feature(simd)]
+
+#[repr(C)]
+#[derive(Copy)]
+#[simd]
+pub struct f32x4(f32, f32, f32, f32);
+
+#[allow(dead_code)]
+extern {
+    fn foo(x: f32x4);
+    //~^ ERROR use of SIMD type `f32x4` in FFI is highly experimental and may result in invalid code
+    //~| HELP add #![feature(simd_ffi)] to the crate attributes to enable
+}
+
+fn main() {}
index 09d7293a3d0c020202b99da5a11299e531d68e74..f78786a2889dab5df60ce1d813fef94b1f00b6b8 100644 (file)
@@ -8,15 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::old_io;
+use std::io::{self, Read};
 use std::vec;
 
 pub struct Container<'a> {
-    reader: &'a mut Reader
+    reader: &'a mut Read
 }
 
 impl<'a> Container<'a> {
-    pub fn wrap<'s>(reader: &'s mut Reader) -> Container<'s> {
+    pub fn wrap<'s>(reader: &'s mut io::Read) -> Container<'s> {
         Container { reader: reader }
     }
 
@@ -26,8 +26,8 @@ pub fn read_to(&mut self, vec: &mut [u8]) {
 }
 
 pub fn for_stdin<'a>() -> Container<'a> {
-    let mut r = old_io::stdin();
-    Container::wrap(&mut r as &mut Reader)
+    let mut r = io::stdin();
+    Container::wrap(&mut r as &mut io::Read)
 }
 
 fn main() {
index 015f1fa603a2004ae08c5fcae9cff0af5295b7bb..f8d85f939374dabce61c3f7eeaa4f705b2fc0b5a 100644 (file)
@@ -33,7 +33,4 @@ fn main() {
 
     0.contains(bits);
     //~^ ERROR overflow
-    //~| ERROR overflow
-    //~| ERROR overflow
-    //~| ERROR mismatched types
 }
diff --git a/src/test/compile-fail/match-ref-mut-invariance.rs b/src/test/compile-fail/match-ref-mut-invariance.rs
new file mode 100644 (file)
index 0000000..c2b54a9
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 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 when making a ref mut binding with type `&mut T`, the
+// type `T` must match precisely the type `U` of the value being
+// matched, and in particular cannot be some supertype of `U`. Issue
+// #23116. This test focuses on a `match`.
+
+#![allow(dead_code)]
+struct S<'b>(&'b i32);
+impl<'b> S<'b> {
+    fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+        match self.0 { ref mut x => x } //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/match-ref-mut-let-invariance.rs b/src/test/compile-fail/match-ref-mut-let-invariance.rs
new file mode 100644 (file)
index 0000000..ea16c61
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2014 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 when making a ref mut binding with type `&mut T`, the
+// type `T` must match precisely the type `U` of the value being
+// matched, and in particular cannot be some supertype of `U`. Issue
+// #23116. This test focuses on a `let`.
+
+#![allow(dead_code)]
+struct S<'b>(&'b i32);
+impl<'b> S<'b> {
+    fn bar<'a>(&'a mut self) -> &'a mut &'a i32 {
+        let ref mut x = self.0;
+        x //~ ERROR mismatched types
+    }
+}
+
+fn main() {}
index e8bc11317f2aadbd597b1a58228d0a61be3505a1..368269999a296c0008f457a5f7c37f12b63d9e63 100644 (file)
@@ -42,12 +42,5 @@ fn is_send<T:Send>() { }
 fn main() {
     is_send::<A>();
     //~^ ERROR overflow evaluating
-    //~^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
-    //~^^^ NOTE required by `is_send`
-    //~^^^^ ERROR overflow evaluating
-    //~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
-    //~^^^^^^ NOTE required by `is_send`
-    //~^^^^^^^ ERROR overflow evaluating
-    //~^^^^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
-    //~^^^^^^^^^ NOTE required by `is_send`
+    //~| NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
 }
diff --git a/src/test/compile-fail/regions-trait-object-subtyping.rs b/src/test/compile-fail/regions-trait-object-subtyping.rs
new file mode 100644 (file)
index 0000000..8d05cb6
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2014 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 Dummy { fn dummy(&self); }
+
+fn foo1<'a:'b,'b>(x: &'a mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
+    // Here, we are able to coerce
+    x
+}
+
+fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
+    // Here, we are able to coerce
+    x
+}
+
+fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
+    // Without knowing 'a:'b, we can't coerce
+    x //~ ERROR mismatched types
+     //~^ ERROR cannot infer
+}
+
+struct Wrapper<T>(T);
+fn foo4<'a:'b,'b>(x: Wrapper<&'a mut Dummy>) -> Wrapper<&'b mut Dummy> {
+    // We can't coerce because it is packed in `Wrapper`
+    x //~ ERROR mismatched types
+}
+
+fn main() {}
diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs
new file mode 100644 (file)
index 0000000..5415915
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = 1_i32 << id(32);
+}
diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs
new file mode 100644 (file)
index 0000000..fd3e801
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = 1 << id(-1);
+}
diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs
new file mode 100644 (file)
index 0000000..58914ba
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = 1_u64 << id(64);
+}
diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs
new file mode 100644 (file)
index 0000000..ed25876
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// This function is checking that our automatic truncation does not
+// sidestep the overflow checking.
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    // this signals overflow when checking is on
+    let x = 1_i8 << id(17);
+
+    // ... but when checking is off, the fallback will truncate the
+    // input to its lower three bits (= 1). Note that this is *not*
+    // the behavior of the x86 processor for 8- and 16-bit types,
+    // but it is necessary to avoid undefined behavior from LLVM.
+    //
+    // We check that here, by ensuring the result has only been
+    // shifted by one place; if overflow checking is turned off, then
+    // this assertion will pass (and the compiletest driver will
+    // report that the test did not produce the error expected above).
+    assert_eq!(x, 2_i8);
+}
diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs
new file mode 100644 (file)
index 0000000..c36a16f
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = -1_i32 >> id(32);
+}
diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs
new file mode 100644 (file)
index 0000000..f619ebe
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = -1_i32 >> id(-1);
+}
diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs
new file mode 100644 (file)
index 0000000..c261e19
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    let _x = -1_i64 >> id(64);
+}
diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs
new file mode 100644 (file)
index 0000000..6e79a13
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+// error-pattern:thread '<main>' panicked at 'shift operation overflowed'
+// compile-flags: -C debug-assertions
+
+// This function is checking that our (type-based) automatic
+// truncation does not sidestep the overflow checking.
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    // this signals overflow when checking is on
+    let x = 2_i8 >> id(17);
+
+    // ... but when checking is off, the fallback will truncate the
+    // input to its lower three bits (= 1). Note that this is *not*
+    // the behavior of the x86 processor for 8- and 16-bit types,
+    // but it is necessary to avoid undefined behavior from LLVM.
+    //
+    // We check that here, by ensuring the result is not zero; if
+    // overflow checking is turned off, then this assertion will pass
+    // (and the compiletest driver will report that the test did not
+    // produce the error expected above).
+    assert_eq!(x, 1_i8);
+}
index 89352a16d8ba2fe3792b017c9f66bebae9cd9020..fd69d2786b8d0800adb74bc000a7b73b638e1c0f 100644 (file)
@@ -9,7 +9,10 @@
 // except according to those terms.
 
 use std::env;
-use std::old_io::{File, Command};
+use std::fs::File;
+use std::process::Command;
+use std::io::Write;
+use std::path::Path;
 
 // creates broken.rs, which has the Ident \x00name_0,ctxt_0\x00
 // embedded within it, and then attempts to compile broken.rs with the
@@ -22,21 +25,18 @@ fn main() {
 
     let main_file = tmpdir.join("broken.rs");
     let _ = File::create(&main_file).unwrap()
-        .write_str("pub fn main() {
+        .write_all(b"pub fn main() {
                    let \x00name_0,ctxt_0\x00 = 3;
                    println!(\"{}\", \x00name_0,ctxt_0\x00);
-        }");
+        }").unwrap();
 
     // rustc is passed to us with --out-dir and -L etc., so we
     // can't exec it directly
     let result = Command::new("sh")
         .arg("-c")
-        .arg(&format!("{} {}",
-                      rustc,
-                      main_file.as_str()
-                      .unwrap()))
+        .arg(&format!("{} {}", rustc, main_file.display()))
         .output().unwrap();
-    let err = String::from_utf8_lossy(&result.error);
+    let err = String::from_utf8_lossy(&result.stderr);
 
     // positive test so that this test will be updated when the
     // compiler changes.
index 0f759efb02539bc874d624f4511cd767b819f89e..86eed9dbe0a92e1ae9a151d137496261a68ced11 100644 (file)
@@ -10,6 +10,7 @@
 
 use std::dynamic_lib::DynamicLibrary;
 use std::os;
+use std::old_path::Path;
 
 pub fn main() {
     unsafe {
index 08f3bd10e74a716c05b1699be930e7d698b3db0c..4c30c7b22a60dcb62d28bd4511d6a513ef5e1971 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(optin_builtin_traits)]
+
 pub mod bar {
     use std::marker;
 
index ce3e69918ffee927e8c77037456fcc472e6b420c..1826e035e245805964bf7ec8bc91d02ee85d4cb7 100644 (file)
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::{char, env};
-use std::old_io::{File, Command};
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::Path;
+use std::process::Command;
 use std::rand::{thread_rng, Rng};
+use std::{char, env};
 
 // creates unicode_input_multiple_files_{main,chars}.rs, where the
 // former imports the latter. `_chars` just contains an identifier
@@ -40,7 +43,7 @@ fn main() {
     let main_file = tmpdir.join("unicode_input_multiple_files_main.rs");
     {
         let _ = File::create(&main_file).unwrap()
-            .write_str("mod unicode_input_multiple_files_chars;");
+            .write_all(b"mod unicode_input_multiple_files_chars;").unwrap();
     }
 
     for _ in 0..100 {
@@ -48,7 +51,7 @@ fn main() {
             let randoms = tmpdir.join("unicode_input_multiple_files_chars.rs");
             let mut w = File::create(&randoms).unwrap();
             for _ in 0..30 {
-                let _ = w.write_char(random_char());
+                write!(&mut w, "{}", random_char()).unwrap();
             }
         }
 
@@ -58,10 +61,9 @@ fn main() {
                              .arg("-c")
                              .arg(&format!("{} {}",
                                            rustc,
-                                           main_file.as_str()
-                                                    .unwrap()))
+                                           main_file.display()))
                              .output().unwrap();
-        let err = String::from_utf8_lossy(&result.error);
+        let err = String::from_utf8_lossy(&result.stderr);
 
         // positive test so that this test will be updated when the
         // compiler changes.
index a6cb9fe0324d7d7c5cde512aa9ce39506a04a46e..9ed20ccaea5c97c07dffc6abf6a60c2d1f759e5d 100644 (file)
@@ -8,8 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::old_io::{File, Command};
+use std::fs::File;
+use std::io::prelude::*;
 use std::iter::repeat;
+use std::path::Path;
+use std::process::Command;
 use std::rand::{thread_rng, Rng};
 use std::{char, env};
 
@@ -54,11 +57,11 @@ fn main() {
                              .arg("-c")
                              .arg(&format!("{} {}",
                                            rustc,
-                                           main_file.as_str()
+                                           main_file.to_str()
                                                     .unwrap()))
                              .output().unwrap();
 
-        let err = String::from_utf8_lossy(&result.error);
+        let err = String::from_utf8_lossy(&result.stderr);
 
         // the span should end the line (e.g no extra ~'s)
         let expected_span = format!("^{}\n", repeat("~").take(n - 1)
@@ -73,17 +76,16 @@ fn main() {
     }
 
     // Extra characters. Every line is preceded by `filename:lineno <actual code>`
-    let offset = main_file.as_str().unwrap().len() + 3;
+    let offset = main_file.to_str().unwrap().len() + 3;
 
     let result = Command::new("sh")
                          .arg("-c")
                          .arg(format!("{} {}",
                                       rustc,
-                                      main_file.as_str()
-                                               .unwrap()))
+                                      main_file.display()))
                          .output().unwrap();
 
-    let err = String::from_utf8_lossy(result.error.as_slice());
+    let err = String::from_utf8_lossy(&result.stderr);
 
     // Test both the length of the snake and the leading spaces up to it
 
index 088fa19356c4e4a941e05b77dc872640262033b5..2a74e36aff3ddd8f34beb5dd2b8ad0a2b7f33e26 100644 (file)
@@ -11,7 +11,8 @@
 // compile-flags:-g
 // ignore-pretty as this critically relies on line numbers
 
-use std::old_io::stderr;
+use std::io;
+use std::io::prelude::*;
 use std::env;
 
 #[path = "backtrace-debuginfo-aux.rs"] mod aux;
@@ -124,17 +125,18 @@ fn check_trace(output: &str, error: &str) {
 
 fn run_test(me: &str) {
     use std::str;
-    use std::old_io::process::Command;
+    use std::process::Command;
 
     let mut template = Command::new(me);
     template.env("RUST_BACKTRACE", "1");
 
     let mut i = 0;
     loop {
-        let p = template.clone().arg(i.to_string()).spawn().unwrap();
-        let out = p.wait_with_output().unwrap();
-        let output = str::from_utf8(&out.output).unwrap();
-        let error = str::from_utf8(&out.error).unwrap();
+        let out = Command::new(me)
+                          .env("RUST_BACKTRACE", "1")
+                          .arg(i.to_string()).output().unwrap();
+        let output = str::from_utf8(&out.stdout).unwrap();
+        let error = str::from_utf8(&out.stderr).unwrap();
         if out.status.success() {
             assert!(output.contains("done."), "bad output for successful run: {}", output);
             break;
@@ -150,7 +152,7 @@ fn main() {
     let args: Vec<String> = env::args().collect();
     if args.len() >= 2 {
         let case = args[1].parse().unwrap();
-        writeln!(&mut stderr(), "test case {}", case).unwrap();
+        writeln!(&mut io::stderr(), "test case {}", case).unwrap();
         outer(case, pos!());
         println!("done.");
     } else {
index 70cc0463a6e11bd927f153491775d0f9b1d070e3..be5bb628b7294f3e1b43cca2edffabb2043904f7 100644 (file)
@@ -19,7 +19,7 @@
 use log::{set_logger, Logger, LogRecord};
 use std::sync::mpsc::channel;
 use std::fmt;
-use std::old_io::{ChanReader, ChanWriter};
+use std::old_io::{ChanReader, ChanWriter, Reader, Writer};
 use std::thread::Thread;
 
 struct MyWriter(ChanWriter);
index 841aaa94e9b552e9f4de847450136245e7dff80e..35fe447c5e657335dc32faa7ae5f466880770591 100644 (file)
 
 // no-pretty-expanded
 
-#![allow(unused_must_use, dead_code, deprecated)]
-use std::old_io::MemWriter;
+use std::io::Write;
 use std::fmt;
 
 struct Foo<'a> {
-    writer: &'a mut (Writer+'a),
+    writer: &'a mut (Write+'a),
     other: &'a str,
 }
 
@@ -32,8 +31,8 @@ fn borrowing_writer_from_struct_and_formatting_struct_field(foo: Foo) {
 }
 
 fn main() {
-    let mut w = MemWriter::new();
-    write!(&mut w as &mut Writer, "");
+    let mut w = Vec::new();
+    write!(&mut w as &mut Write, "");
     write!(&mut w, ""); // should coerce
     println!("ok");
 
index 0c7ecfcefff34bcdc9bcf3cac4e53fd5eefe9dad..9539486118b812efd53a8c98368ab85b7528ef9d 100644 (file)
@@ -19,7 +19,7 @@
 impl Index<uint> for S {
     type Output = str;
 
-    fn index<'a>(&'a self, _: &uint) -> &'a str {
+    fn index<'a>(&'a self, _: uint) -> &'a str {
         "hello"
     }
 }
@@ -29,7 +29,7 @@ fn index<'a>(&'a self, _: &uint) -> &'a str {
 impl Index<uint> for T {
     type Output = Debug + 'static;
 
-    fn index<'a>(&'a self, idx: &uint) -> &'a (Debug + 'static) {
+    fn index<'a>(&'a self, idx: uint) -> &'a (Debug + 'static) {
         static X: uint = 42;
         &X as &(Debug + 'static)
     }
index 5d68a25a14ada73433012e8a3a13ccdf1c9c04f0..cd6147504512873f74d225b04d3474c0e6b299eb 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(convert)]
+
 use std::env::*;
 use std::path::PathBuf;
 
@@ -16,7 +18,7 @@ fn main() {
     let oldhome = var("HOME");
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
 
     remove_var("HOME");
     if cfg!(target_os = "android") {
@@ -37,14 +39,14 @@ fn main() {
     assert!(home_dir().is_some());
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
 
     remove_var("HOME");
 
     set_var("USERPROFILE", "/home/MountainView");
-    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
 
     set_var("HOME", "/home/MountainView");
     set_var("USERPROFILE", "/home/PaloAlto");
-    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::from("/home/MountainView")));
 }
index 26a0abc76aee2a668fa4d38e4a801e2fdcc2adf2..01e305581f14e6129e7ffb4d23eea60556b58b8a 100644 (file)
@@ -31,7 +31,7 @@ fn into_iter(self) -> I {
 
 fn desugared_for_loop_bad(byte: u8) -> u8 {
     let mut result = 0;
-    let mut x = IntoIterator::into_iter(range(0, u8::BITS));
+    let mut x = IntoIterator::into_iter(0..u8::BITS);
     let mut y = Iterator::next(&mut x);
     let mut z = y.unwrap();
     byte >> z;
index ed0e3bddbe515b8d3a5b6abce07d2528ea72ac61..098fa54207f39d8e592fed0feac8daa076444f0f 100644 (file)
@@ -9,12 +9,13 @@
 // except according to those terms.
 
 use std::env;
-use std::old_io::{stdio, Command};
+use std::process::Command;
+use std::io::{self, Write};
 
 fn main() {
     let mut args = env::args();
     if args.len() > 1 {
-        let mut out = stdio::stdout();
+        let mut out = io::stdout();
         out.write(&['a' as u8; 128 * 1024]).unwrap();
     } else {
         let out = Command::new(&args.next().unwrap()).arg("child").output();
index 18e4190ee459f6b24acccb8d36a18733a6ca28d8..76a5b6488b5a300a69265155008c56d9905b5365 100644 (file)
@@ -29,7 +29,7 @@ fn row<'a>(&'a self, row: uint) -> Row<&'a Mat<T>> {
 impl<T> Index<(uint, uint)> for Mat<T> {
     type Output = T;
 
-    fn index<'a>(&'a self, &(row, col): &(uint, uint)) -> &'a T {
+    fn index<'a>(&'a self, (row, col): (uint, uint)) -> &'a T {
         &self.data[row * self.cols + col]
     }
 }
@@ -37,7 +37,7 @@ fn index<'a>(&'a self, &(row, col): &(uint, uint)) -> &'a T {
 impl<'a, T> Index<(uint, uint)> for &'a Mat<T> {
     type Output = T;
 
-    fn index<'b>(&'b self, index: &(uint, uint)) -> &'b T {
+    fn index<'b>(&'b self, index: (uint, uint)) -> &'b T {
         (*self).index(index)
     }
 }
@@ -47,8 +47,8 @@ struct Row<M> { mat: M, row: uint, }
 impl<T, M: Index<(uint, uint), Output=T>> Index<uint> for Row<M> {
     type Output = T;
 
-    fn index<'a>(&'a self, col: &uint) -> &'a T {
-        &self.mat[(self.row, *col)]
+    fn index<'a>(&'a self, col: uint) -> &'a T {
+        &self.mat[(self.row, col)]
     }
 }
 
@@ -56,7 +56,7 @@ fn main() {
     let m = Mat::new(vec!(1, 2, 3, 4, 5, 6), 3);
     let r = m.row(1);
 
-    assert!(r.index(&2) == &6);
+    assert!(r.index(2) == &6);
     assert!(r[2] == 6);
     assert!(r[2] == 6);
     assert!(6 == r[2]);
index 2f0b8c9f19beb1c0f57ded4062ceb73d33ca23bc..6d32ffd6c43ca31791d0889a54a5ac4172ea7ef1 100644 (file)
@@ -8,31 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::old_io::BufReader;
-use std::old_io::BufferedReader;
-use std::old_io::File;
-use std::old_io::IoResult;
+use std::fs::File;
+use std::io::{self, BufReader, Read};
 
-struct Lexer<R: Reader>
+struct Lexer<R: Read>
 {
-    reader: BufferedReader<R>,
+    reader: BufReader<R>,
 }
 
-impl<R: Reader> Lexer<R>
+impl<R: Read> Lexer<R>
 {
     pub fn new_from_reader(r: R) -> Lexer<R>
     {
-        Lexer{reader: BufferedReader::new(r)}
+        Lexer{reader: BufReader::new(r)}
     }
 
-    pub fn new_from_file(p: Path) -> IoResult<Lexer<File>>
+    pub fn new_from_file(p: &str) -> io::Result<Lexer<File>>
     {
-        Ok(Lexer::new_from_reader(try!(File::open(&p))))
+        Ok(Lexer::new_from_reader(try!(File::open(p))))
     }
 
-    pub fn new_from_str<'a>(s: &'a str) -> Lexer<BufReader<'a>>
+    pub fn new_from_str<'a>(s: &'a str) -> Lexer<&'a [u8]>
     {
-        Lexer::new_from_reader(BufReader::new(s.as_bytes()))
+        Lexer::new_from_reader(s.as_bytes())
     }
 }
 
index 0d482548cc0bf933241d8a6f7407b83e7cba93ec..83b91c93a865f57706d9a81a2b6a55e218bb832a 100644 (file)
 // A reduced version of the rustbook ice. The problem this encountered
 // had to do with trans ignoring binders.
 
-#![feature(associated_types)]
-#![feature(macro_rules)]
-
 use std::iter;
 use std::os;
-use std::old_io::File;
+use std::fs::File;
+use std::io::prelude::*;
+use std::env;
+use std::path::Path;
 
-#[allow(unused)]
-pub fn parse_summary<R: Reader>(_: R, _: &Path) {
+pub fn parse_summary<R: Read>(_: R, _: &Path) {
      let path_from_root = Path::new("");
-     Path::new(iter::repeat("../")
+     Path::new(&iter::repeat("../")
                .take(path_from_root.components().count() - 1)
                .collect::<String>());
  }
 
-fn main() {
-    let cwd = os::getcwd().unwrap();
+fn foo() {
+    let cwd = env::current_dir().unwrap();
     let src = cwd.clone();
-    let summary = File::open(&src.join("SUMMARY.md"));
+    let summary = File::open(&src.join("SUMMARY.md")).unwrap();
     let _ = parse_summary(summary, &src);
 }
+
+fn main() {}
index 049e08d2b94f5b9838a44f8e34c23f8b62e050ab..c5badb614948f4cc738be3a1c6f94127a90e7b31 100644 (file)
@@ -8,24 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android
-// ignore-windows
-
 // Regression test for #20797.
 
 use std::default::Default;
-use std::old_io::IoResult;
-use std::old_io::fs;
-use std::old_io::fs::PathExtensions;
+use std::io;
+use std::fs;
+use std::path::{PathBuf, Path};
+
+pub trait PathExtensions {
+    fn is_dir(&self) -> bool { false }
+}
+
+impl PathExtensions for PathBuf {}
 
 /// A strategy for acquiring more subpaths to walk.
 pub trait Strategy {
-  type P: PathExtensions;
-  /// Get additional subpaths from a given path.
-  fn get_more(&self, item: &Self::P) -> IoResult<Vec<Self::P>>;
-  /// Determine whether a path should be walked further.
-  /// This is run against each item from `get_more()`.
-  fn prune(&self, p: &Self::P) -> bool;
+    type P: PathExtensions;
+    /// Get additional subpaths from a given path.
+    fn get_more(&self, item: &Self::P) -> io::Result<Vec<Self::P>>;
+    /// Determine whether a path should be walked further.
+    /// This is run against each item from `get_more()`.
+    fn prune(&self, p: &Self::P) -> bool;
 }
 
 /// The basic fully-recursive strategy. Nothing is pruned.
@@ -33,10 +36,12 @@ pub trait Strategy {
 pub struct Recursive;
 
 impl Strategy for Recursive {
-  type P = Path;
-  fn get_more(&self, p: &Path) -> IoResult<Vec<Path>> { fs::readdir(p) }
+    type P = PathBuf;
+    fn get_more(&self, p: &PathBuf) -> io::Result<Vec<PathBuf>> {
+        Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect())
+    }
 
-  fn prune(&self, _: &Path) -> bool { false }
+    fn prune(&self, _: &PathBuf) -> bool { false }
 }
 
 /// A directory walker of `P` using strategy `S`.
@@ -46,49 +51,51 @@ pub struct Subpaths<S: Strategy> {
 }
 
 impl<S: Strategy> Subpaths<S> {
-  /// Create a directory walker with a root path and strategy.
-  pub fn new(p: &S::P, strategy: S) -> IoResult<Subpaths<S>> {
-    let stack = try!(strategy.get_more(p));
-    Ok(Subpaths { stack: stack, strategy: strategy })
-  }
+    /// Create a directory walker with a root path and strategy.
+    pub fn new(p: &S::P, strategy: S) -> io::Result<Subpaths<S>> {
+        let stack = try!(strategy.get_more(p));
+        Ok(Subpaths { stack: stack, strategy: strategy })
+    }
 }
 
 impl<S: Default + Strategy> Subpaths<S> {
-  /// Create a directory walker with a root path and a default strategy.
-  pub fn walk(p: &S::P) -> IoResult<Subpaths<S>> {
-      Subpaths::new(p, Default::default())
-  }
+    /// Create a directory walker with a root path and a default strategy.
+    pub fn walk(p: &S::P) -> io::Result<Subpaths<S>> {
+        Subpaths::new(p, Default::default())
+    }
 }
 
 impl<S: Default + Strategy> Default for Subpaths<S> {
-  fn default() -> Subpaths<S> {
-    Subpaths { stack: Vec::new(), strategy: Default::default() }
-  }
+    fn default() -> Subpaths<S> {
+        Subpaths { stack: Vec::new(), strategy: Default::default() }
+    }
 }
 
 impl<S: Strategy> Iterator for Subpaths<S> {
-  type Item = S::P;
-  fn next (&mut self) -> Option<S::P> {
-    let mut opt_path = self.stack.pop();
-    while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) {
-      opt_path = self.stack.pop();
-    }
-    match opt_path {
-      Some(path) => {
-        if PathExtensions::is_dir(&path) {
-          let result = self.strategy.get_more(&path);
-          match result {
-            Ok(dirs) => { self.stack.extend(dirs.into_iter()); },
-            Err(..) => { }
-          }
+    type Item = S::P;
+    fn next (&mut self) -> Option<S::P> {
+        let mut opt_path = self.stack.pop();
+        while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) {
+            opt_path = self.stack.pop();
+        }
+        match opt_path {
+            Some(path) => {
+                if path.is_dir() {
+                    let result = self.strategy.get_more(&path);
+                    match result {
+                        Ok(dirs) => { self.stack.extend(dirs.into_iter()); },
+                        Err(..) => { }
+                    }
+                }
+                Some(path)
+            }
+            None => None,
         }
-        Some(path)
-      }
-      None => None,
     }
-  }
 }
 
-fn main() {
-  let mut walker: Subpaths<Recursive> = Subpaths::walk(&Path::new("/home")).unwrap();
+fn foo() {
+    let mut walker: Subpaths<Recursive> = Subpaths::walk(&PathBuf::new("/home")).unwrap();
 }
+
+fn main() {}
diff --git a/src/test/run-pass/issue-23550.rs b/src/test/run-pass/issue-23550.rs
new file mode 100644 (file)
index 0000000..97357c1
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2015 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.
+
+#![feature(core)]
+#![allow(warnings)]
+
+use std::intrinsics;
+
+#[derive(Copy)]
+struct Wrap(i64);
+
+// These volatile and atomic intrinsics used to cause an ICE
+
+unsafe fn test_bool(p: &mut bool, v: bool) {
+    intrinsics::volatile_load(p);
+    intrinsics::volatile_store(p, v);
+    intrinsics::atomic_load(p);
+    intrinsics::atomic_cxchg(p, v, v);
+    intrinsics::atomic_store(p, v);
+    intrinsics::atomic_xchg(p, v);
+}
+
+unsafe fn test_immediate_fca(p: &mut Wrap, v: Wrap) {
+    intrinsics::volatile_load(p);
+    intrinsics::volatile_store(p, v);
+    intrinsics::atomic_load(p);
+    intrinsics::atomic_cxchg(p, v, v);
+    intrinsics::atomic_store(p, v);
+    intrinsics::atomic_xchg(p, v);
+}
+
+fn main() {}
index 4f89d28332a2349a5a1ff0d3e9636cba60effd41..b04ae0edbed87b20f791ca3bb893652e94c9e250 100644 (file)
@@ -16,7 +16,7 @@
 use std::collections::HashMap;
 
 fn add_interfaces(managed_ip: String, device: HashMap<String, int>)  {
-     println!("{}, {}", managed_ip, device["interfaces".to_string()]);
+     println!("{}, {}", managed_ip, device["interfaces"]);
 }
 
 pub fn main() {}
index b9b5aec62fcdaf1f9725be141732384b08f97680..619bd08141fb62259766fb2d856cfbe96ef340d3 100644 (file)
@@ -56,8 +56,7 @@ fn add_interface(_store: int, managed_ip: String, data: json::Json) -> (String,
 
 fn add_interfaces(store: int, managed_ip: String, device: HashMap<String, json::Json>)
 -> Vec<(String, object)> {
-    match device["interfaces".to_string()]
-    {
+    match device["interfaces"] {
         Json::Array(ref interfaces) =>
         {
           interfaces.iter().map(|interface| {
@@ -67,7 +66,7 @@ fn add_interfaces(store: int, managed_ip: String, device: HashMap<String, json::
         _ =>
         {
             println!("Expected list for {} interfaces, found {}", managed_ip,
-                   device["interfaces".to_string()]);
+                     device["interfaces"]);
             Vec::new()
         }
     }
index fb0e8e599eb2af9477cdbffce70a292b28b7ffd4..7016e28f2ee022800ad3831037e59df33bb6b4df 100644 (file)
@@ -17,7 +17,7 @@ fn bar(a: foo::map) {
     if false {
         panic!();
     } else {
-        let _b = &(*a)[2];
+        let _b = &(*a)[&2];
     }
 }
 
index 9e36b1f5082d03dad3f1a48bc3ed9a38326eb600..78318e083ba404a09b5de94293eb0b0591bd95d3 100644 (file)
@@ -21,6 +21,6 @@ pub fn main() {
     let mut m: HashMap<int, A> = HashMap::new();
     m.insert(1, A(0, 0));
 
-    let A(ref _a, ref _b) = m[1];
-    let (a, b) = match m[1] { A(ref _a, ref _b) => (_a, _b) };
+    let A(ref _a, ref _b) = m[&1];
+    let (a, b) = match m[&1] { A(ref _a, ref _b) => (_a, _b) };
 }
index 3193e5c5fc2477f9005f9ba79580d93c41de4444..d30a0be5feeb5873e89ca062c59e89e1d914ad28 100644 (file)
@@ -10,7 +10,7 @@
 
 // This used to cause an ICE because the retslot for the "return" had the wrong type
 fn testcase<'a>() -> Box<Iterator<Item=usize> + 'a> {
-    return Box::new(range(0, 3).map(|i| { return i; }));
+    return Box::new((0..3).map(|i| { return i; }));
 }
 
 fn main() {
diff --git a/src/test/run-pass/match-ref-unsized.rs b/src/test/run-pass/match-ref-unsized.rs
new file mode 100644 (file)
index 0000000..4de0282
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 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.
+
+// Binding unsized expressions to ref patterns
+
+pub fn main() {
+    let ref a = *"abcdef";
+    assert_eq!(a, "abcdef");
+
+    match *"12345" {
+        ref b => { assert_eq!(b, "12345") }
+    }
+}
index 3ddc666cd384c0ce2c551b5df122201a48992a4a..801e71b3038622f504f7c3c738d9eb5798f84c4b 100644 (file)
@@ -52,8 +52,8 @@ fn not(self) -> Point {
 impl ops::Index<bool> for Point {
     type Output = int;
 
-    fn index(&self, x: &bool) -> &int {
-        if *x {
+    fn index(&self, x: bool) -> &int {
+        if x {
             &self.x
         } else {
             &self.y
index 1118638fe071345d3987346dcd925200c1e261f0..c2b42ac1c8163a5b4667a07ec8898b23bbcd479c 100644 (file)
@@ -11,7 +11,7 @@
 // Regression test for issue #152.
 pub fn main() {
     let mut b: uint = 1_usize;
-    while b <= 32_usize {
+    while b < std::mem::size_of::<usize>() {
         0_usize << b;
         b <<= 1_usize;
         println!("{}", b);
index 0064748e883699dc3968e813eae7c5c389ed89b9..b5c9962fe9c3f4d37ef9ff1c9c9483f41904a89d 100644 (file)
@@ -28,7 +28,7 @@ fn push(&mut self, key: K, value: V) {
     }
 }
 
-impl<K: PartialEq + std::fmt::Debug, V:Clone> Index<K> for AssociationList<K,V> {
+impl<'a, K: PartialEq + std::fmt::Debug, V:Clone> Index<&'a K> for AssociationList<K,V> {
     type Output = V;
 
     fn index<'a>(&'a self, index: &K) -> &'a V {
@@ -49,9 +49,9 @@ pub fn main() {
     list.push(foo.clone(), 22);
     list.push(bar.clone(), 44);
 
-    assert!(list[foo] == 22);
-    assert!(list[bar] == 44);
+    assert!(list[&foo] == 22);
+    assert!(list[&bar] == 44);
 
-    assert!(list[foo] == 22);
-    assert!(list[bar] == 44);
+    assert!(list[&foo] == 22);
+    assert!(list[&bar] == 44);
 }
index 8f655f0517ddf47fe56224d420ba0e0a34992a59..107f0fbc20904b8e4b0fe18d744b5b2040441350 100644 (file)
@@ -23,8 +23,8 @@ struct Foo {
 impl Index<int> for Foo {
     type Output = int;
 
-    fn index(&self, z: &int) -> &int {
-        if *z == 0 {
+    fn index(&self, z: int) -> &int {
+        if z == 0 {
             &self.x
         } else {
             &self.y
@@ -33,8 +33,8 @@ fn index(&self, z: &int) -> &int {
 }
 
 impl IndexMut<int> for Foo {
-    fn index_mut(&mut self, z: &int) -> &mut int {
-        if *z == 0 {
+    fn index_mut(&mut self, z: int) -> &mut int {
+        if z == 0 {
             &mut self.x
         } else {
             &mut self.y
index 487fb93c9fee8f3a09135d7503989ade445b6158..f01e5541c423b11d2034a77f9bbe557533ffe6e5 100644 (file)
@@ -25,8 +25,8 @@ struct Bar {
 impl Index<int> for Foo {
     type Output = int;
 
-    fn index(&self, z: &int) -> &int {
-        if *z == 0 {
+    fn index(&self, z: int) -> &int {
+        if z == 0 {
             &self.x
         } else {
             &self.y
index 10ca3804eaedbc187ab128e619f45d20cd7c41dd..60e0ed9bfdd0f6298b56c26864542da9cd4ecf26 100644 (file)
@@ -18,8 +18,8 @@ struct Foo {
 impl Index<int> for Foo {
     type Output = int;
 
-    fn index(&self, z: &int) -> &int {
-        if *z == 0 {
+    fn index(&self, z: int) -> &int {
+        if z == 0 {
             &self.x
         } else {
             &self.y
@@ -28,8 +28,8 @@ fn index(&self, z: &int) -> &int {
 }
 
 impl IndexMut<int> for Foo {
-    fn index_mut(&mut self, z: &int) -> &mut int {
-        if *z == 0 {
+    fn index_mut(&mut self, z: int) -> &mut int {
+        if z == 0 {
             &mut self.x
         } else {
             &mut self.y
index 466b38e8742339bfdc171bf76f2fa136da6703f7..72998133af19ddecd89565b0b708e0b050854acd 100644 (file)
@@ -28,9 +28,9 @@
 
 fn main() {
     let my_args = env::args().collect::<Vec<_>>();
-    let my_cwd  = PathBuf::new(os::getcwd().unwrap().as_str().unwrap());
+    let my_cwd  = env::current_dir().unwrap();
     let my_env  = env::vars().collect::<Vec<_>>();
-    let my_path = PathBuf::new(os::self_exe_name().unwrap().as_str().unwrap());
+    let my_path = env::current_exe().unwrap();
     let my_dir  = my_path.parent().unwrap();
     let my_ext  = my_path.extension().and_then(|s| s.to_str()).unwrap_or("");
 
index e0810d395558ef38bd686e7bb692c455018e5494..656fe89896932bf159e146b975d7abada6dcb9ee 100644 (file)
 // This test can't be a unit test in std,
 // because it needs TempDir, which is in extra
 
-extern crate libc;
-
 use std::ffi::CString;
-use std::old_io::TempDir;
-use std::old_io::fs::PathExtensions;
-use std::old_io::fs;
-use std::old_io;
-use std::os;
+use std::fs::{self, TempDir, File, PathExt};
 
 fn rename_directory() {
-    unsafe {
-        static U_RWX: i32 = (libc::S_IRUSR | libc::S_IWUSR | libc::S_IXUSR) as i32;
-
-        let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed");
-        let tmpdir = tmpdir.path();
-        let old_path = tmpdir.join_many(&["foo", "bar", "baz"]);
-        fs::mkdir_recursive(&old_path, old_io::USER_RWX);
-        let test_file = &old_path.join("temp.txt");
-
-        /* Write the temp input file */
-        let fromp = CString::new(test_file.as_vec()).unwrap();
-        let modebuf = CString::new(&b"w+b"[..]).unwrap();
-        let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
-        assert!((ostream as uint != 0));
-        let s = "hello".to_string();
-        let buf = CString::new(&b"hello"[..]).unwrap();
-        let write_len = libc::fwrite(buf.as_ptr() as *mut _,
-                                     1_usize as libc::size_t,
-                                     (s.len() + 1_usize) as libc::size_t,
-                                     ostream);
-        assert_eq!(write_len, (s.len() + 1) as libc::size_t);
-        assert_eq!(libc::fclose(ostream), (0_usize as libc::c_int));
-
-        let new_path = tmpdir.join_many(&["quux", "blat"]);
-        fs::mkdir_recursive(&new_path, old_io::USER_RWX);
-        fs::rename(&old_path, &new_path.join("newdir"));
-        assert!(new_path.join("newdir").is_dir());
-        assert!(new_path.join_many(&["newdir", "temp.txt"]).exists());
-    }
+    let tmpdir = TempDir::new("rename_directory").ok().expect("rename_directory failed");
+    let tmpdir = tmpdir.path();
+    let old_path = tmpdir.join("foo/bar/baz");
+    fs::create_dir_all(&old_path).unwrap();
+    let test_file = &old_path.join("temp.txt");
+
+    File::create(test_file).unwrap();
+
+    let new_path = tmpdir.join("quux/blat");
+    fs::create_dir_all(&new_path).unwrap();
+    fs::rename(&old_path, &new_path.join("newdir"));
+    assert!(new_path.join("newdir").is_dir());
+    assert!(new_path.join("newdir/temp.txt").exists());
 }
 
 pub fn main() { rename_directory() }
diff --git a/src/test/run-pass/shift-near-oflo.rs b/src/test/run-pass/shift-near-oflo.rs
new file mode 100644 (file)
index 0000000..4ff058f
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2015 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.
+
+// compile-flags: -C debug-assertions
+
+// Check that we do *not* overflow on a number of edge cases.
+// (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
+
+// (Work around constant-evaluation)
+fn id<T>(x: T) -> T { x }
+
+fn main() {
+    test_left_shift();
+    test_right_shift();
+}
+
+fn test_left_shift() {
+    // negative rhs can panic, but values in [0,N-1] are okay for iN
+
+    macro_rules! tests {
+        ($iN:ty, $uN:ty, $max_rhs:expr, $expect_i:expr, $expect_u:expr) => { {
+            let x = (1 as $iN) << id(0);
+            assert_eq!(x, 1);
+            let x = (1 as $uN) << id(0);
+            assert_eq!(x, 1);
+            let x = (1 as $iN) << id($max_rhs);
+            assert_eq!(x, $expect_i);
+            let x = (1 as $uN) << id($max_rhs);
+            assert_eq!(x, $expect_u);
+            // high-order bits on LHS are silently discarded without panic.
+            let x = (3 as $iN) << id($max_rhs);
+            assert_eq!(x, $expect_i);
+            let x = (3 as $uN) << id($max_rhs);
+            assert_eq!(x, $expect_u);
+        } }
+    }
+
+    let x = 1_i8 << id(0);
+    assert_eq!(x, 1);
+    let x = 1_u8 << id(0);
+    assert_eq!(x, 1);
+    let x = 1_i8 << id(7);
+    assert_eq!(x, std::i8::MIN);
+    let x = 1_u8 << id(7);
+    assert_eq!(x, 0x80);
+    // high-order bits on LHS are silently discarded without panic.
+    let x = 3_i8 << id(7);
+    assert_eq!(x, std::i8::MIN);
+    let x = 3_u8 << id(7);
+    assert_eq!(x, 0x80);
+
+    // above is (approximately) expanded from:
+    tests!(i8, u8, 7, std::i8::MIN, 0x80_u8);
+
+    tests!(i16, u16, 15, std::i16::MIN, 0x8000_u16);
+    tests!(i32, u32, 31, std::i32::MIN, 0x8000_0000_u32);
+    tests!(i64, u64, 63, std::i64::MIN, 0x8000_0000_0000_0000_u64);
+}
+
+fn test_right_shift() {
+    // negative rhs can panic, but values in [0,N-1] are okay for iN
+
+    macro_rules! tests {
+        ($iN:ty, $uN:ty, $max_rhs:expr,
+         $signbit_i:expr, $highbit_i:expr, $highbit_u:expr) =>
+        { {
+            let x = (1 as $iN) >> id(0);
+            assert_eq!(x, 1);
+            let x = (1 as $uN) >> id(0);
+            assert_eq!(x, 1);
+            let x = ($highbit_i) >> id($max_rhs-1);
+            assert_eq!(x, 1);
+            let x = ($highbit_u) >> id($max_rhs);
+            assert_eq!(x, 1);
+            // sign-bit is carried by arithmetic right shift
+            let x = ($signbit_i) >> id($max_rhs);
+            assert_eq!(x, -1);
+            // low-order bits on LHS are silently discarded without panic.
+            let x = ($highbit_i + 1) >> id($max_rhs-1);
+            assert_eq!(x, 1);
+            let x = ($highbit_u + 1) >> id($max_rhs);
+            assert_eq!(x, 1);
+            let x = ($signbit_i + 1) >> id($max_rhs);
+            assert_eq!(x, -1);
+        } }
+    }
+
+    tests!(i8, u8, 7, std::i8::MIN, 0x40_i8, 0x80_u8);
+    tests!(i16, u16, 15, std::i16::MIN, 0x4000_u16, 0x8000_u16);
+    tests!(i32, u32, 31, std::i32::MIN, 0x4000_0000_u32, 0x8000_0000_u32);
+    tests!(i64, u64, 63, std::i64::MIN,
+           0x4000_0000_0000_0000_u64, 0x8000_0000_0000_0000_u64);
+}
index d1428c6be19ef880f06645c74a59908b90dd7b04..665b582581cfb88f42745995fd31e183c76452e0 100644 (file)
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
-use std::os;
 use std::env;
-use std::old_io::PipeStream;
-use std::old_io::Command;
+use std::io::prelude::*;
+use std::io;
+use std::process::{Command, Stdio};
 
 fn test() {
-    let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
-    let reader = PipeStream::open(reader);
-    let mut writer = PipeStream::open(writer);
-    drop(reader);
-
-    let _ = writer.write(&[1]);
+    let _ = io::stdin().read_line(&mut String::new());
+    io::stdout().write(&[1]);
+    assert!(io::stdout().flush().is_err());
 }
 
 fn main() {
@@ -32,6 +29,9 @@ fn main() {
     }
 
     let mut p = Command::new(&args[0])
+                        .stdout(Stdio::piped())
+                        .stdin(Stdio::piped())
                         .arg("test").spawn().unwrap();
+    drop(p.stdout.take());
     assert!(p.wait().unwrap().success());
 }
index 30b53dbb0ad5bea0bdf96b7ddb419345e2749ad6..ee9bb80356164504e1dcee563bbc0478316f863c 100644 (file)
 
 impl Index<Range<Foo>> for Foo {
     type Output = Foo;
-    fn index(&self, index: &Range<Foo>) -> &Foo {
+    fn index(&self, index: Range<Foo>) -> &Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 impl Index<RangeTo<Foo>> for Foo {
     type Output = Foo;
-    fn index(&self, index: &RangeTo<Foo>) -> &Foo {
+    fn index(&self, index: RangeTo<Foo>) -> &Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 impl Index<RangeFrom<Foo>> for Foo {
     type Output = Foo;
-    fn index(&self, index: &RangeFrom<Foo>) -> &Foo {
+    fn index(&self, index: RangeFrom<Foo>) -> &Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 impl Index<RangeFull> for Foo {
     type Output = Foo;
-    fn index(&self, _index: &RangeFull) -> &Foo {
+    fn index(&self, _index: RangeFull) -> &Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 
 impl IndexMut<Range<Foo>> for Foo {
-    fn index_mut(&mut self, index: &Range<Foo>) -> &mut Foo {
+    fn index_mut(&mut self, index: Range<Foo>) -> &mut Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 impl IndexMut<RangeTo<Foo>> for Foo {
-    fn index_mut(&mut self, index: &RangeTo<Foo>) -> &mut Foo {
+    fn index_mut(&mut self, index: RangeTo<Foo>) -> &mut Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 impl IndexMut<RangeFrom<Foo>> for Foo {
-    fn index_mut(&mut self, index: &RangeFrom<Foo>) -> &mut Foo {
+    fn index_mut(&mut self, index: RangeFrom<Foo>) -> &mut Foo {
         unsafe { COUNT += 1; }
         self
     }
 }
 impl IndexMut<RangeFull> for Foo {
-    fn index_mut(&mut self, _index: &RangeFull) -> &mut Foo {
+    fn index_mut(&mut self, _index: RangeFull) -> &mut Foo {
         unsafe { COUNT += 1; }
         self
     }
index 91edb5fd9c1e837e162fd600b7d6e867663b9b0a..b808ea472a28a93b0621662bbacff81727e9c6b2 100644 (file)
@@ -12,7 +12,7 @@
 
 pub fn main() {
     let t = thread::spawn(move|| child((10, 20, 30, 40, 50, 60, 70, 80, 90)) );
-    t.join().ok().unwrap();
+    t.join().ok().unwrap(); // forget Err value, since it doesn't implement Debug
 }
 
 fn child(args: (int, int, int, int, int, int, int, int, int)) {
index 87d7376c243bcd6fa0fcdd0ea099d55b54f32ffb..1ccc189dc81808f7479e5c03d6afab77ab20cf5b 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::old_io::fs::PathExtensions;
-use std::old_io::{File, TempDir};
+use std::fs::{File, TempDir};
+use std::io::prelude::*;
 
 pub fn main() {
-    let dir = TempDir::new_in(&Path::new("."), "").unwrap();
+    let dir = TempDir::new_in(".", "").unwrap();
     let path = dir.path().join("file");
 
     {
@@ -20,7 +20,7 @@ pub fn main() {
             Err(..) => unreachable!(),
             Ok(f) => {
                 let mut f = f;
-                for _ in 0_usize..1000 {
+                for _ in 0..1000 {
                     f.write(&[0]);
                 }
             }
@@ -28,5 +28,5 @@ pub fn main() {
     }
 
     assert!(path.exists());
-    assert_eq!(path.stat().unwrap().size, 1000);
+    assert_eq!(path.metadata().unwrap().len(), 1000);
 }
index 23ea998c026085331ab204c30a17cd5799937c08..e06e6883a75aa4d2e05532280d2c7ed6ca33f9ce 100644 (file)
@@ -19,7 +19,7 @@
 
 use std::sync::mpsc::channel;
 use std::old_io::net::tcp::{TcpListener, TcpStream};
-use std::old_io::{Acceptor, Listener};
+use std::old_io::{Acceptor, Listener, Reader, Writer};
 use std::thread::{Builder, Thread};
 use std::time::Duration;
 
index 053df3a57f329361b33707084f23e329b99dc7b8..bc655837babb9d74a35b9ee73576afacb4fa8106 100644 (file)
@@ -18,6 +18,7 @@
 // they're in a different location than before. Hence, these tests are all run
 // serially here.
 
+use std::old_path::{Path, GenericPath};
 use std::old_io::fs::PathExtensions;
 use std::old_io::{fs, TempDir};
 use std::old_io;
index b02f8eb0aa9d532012522c4f5460e5ba96505b5c..d1af6b746ac421af95a2016adbf4714d226f61c8 100644 (file)
@@ -8,10 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unknown_features)]
 #![feature(box_syntax)]
 
-use std::old_io;
+use std::io::{self, Write};
 
 trait Trait {
     fn f(&self);
@@ -29,9 +28,7 @@ fn f(&self) {
     }
 }
 
-fn foo(mut a: Box<Writer>) {
-    a.write(b"Hello\n");
-}
+fn foo(mut a: Box<Write>) {}
 
 // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
 
@@ -42,6 +39,6 @@ pub fn main() {
     let c: &Trait = &a;
     c.f();
 
-    let out = old_io::stdout();
+    let out = io::stdout();
     foo(Box::new(out));
 }
index ac46187f03a71d90f09c3859a529b235779a52e7..66cc8d658c0a63ac3acdffb8816f39480c4614d8 100644 (file)
@@ -26,6 +26,6 @@ pub fn main() {
         let _b = Foo;
     }).join();
 
-    let s = x.err().unwrap().downcast::<&'static str>().ok().unwrap();
+    let s = x.err().unwrap().downcast::<&'static str>().unwrap();
     assert_eq!(&**s, "This panic should happen.");
 }