]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #23932 - steveklabnik:doc_std_path, r=flaper87
authorManish Goregaokar <manishsmail@gmail.com>
Wed, 1 Apr 2015 19:10:40 +0000 (00:40 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Wed, 1 Apr 2015 19:10:40 +0000 (00:40 +0530)
364 files changed:
src/compiletest/compiletest.rs
src/doc/reference.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/benchmark-tests.md [new file with mode: 0644]
src/doc/trpl/concurrency.md
src/doc/trpl/iterators.md
src/doc/trpl/macros.md
src/doc/trpl/ownership.md
src/doc/trpl/testing.md
src/doc/trpl/traits.md
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/boxed_test.rs
src/liballoc/lib.rs
src/libcollections/bit.rs
src/libcollections/borrow.rs
src/libcollections/btree/map.rs
src/libcollections/lib.rs
src/libcollections/linked_list.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollectionstest/bit/set.rs
src/libcollectionstest/enum_set.rs
src/libcollectionstest/fmt.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/slice.rs
src/libcollectionstest/str.rs
src/libcollectionstest/string.rs
src/libcollectionstest/vec_deque.rs
src/libcore/any.rs
src/libcore/atomic.rs
src/libcore/cell.rs
src/libcore/cmp.rs
src/libcore/cmp_macros.rs
src/libcore/convert.rs
src/libcore/error.rs
src/libcore/finally.rs [deleted file]
src/libcore/fmt/mod.rs
src/libcore/hash/sip.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/num/wrapping.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/prelude.rs
src/libcore/ptr.rs
src/libcore/raw.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs
src/libcoretest/cell.rs
src/libcoretest/finally.rs [deleted file]
src/libcoretest/iter.rs
src/libcoretest/lib.rs
src/libcoretest/mem.rs
src/libcoretest/num/uint_macros.rs
src/libcoretest/str.rs
src/libfmt_macros/lib.rs
src/libgraphviz/lib.rs
src/librand/chacha.rs
src/librand/lib.rs
src/librbml/lib.rs
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/astencode.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/def.rs
src/librustc/middle/infer/bivariate.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/equate.rs
src/librustc/middle/infer/freshen.rs
src/librustc/middle/infer/glb.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/lattice.rs
src/librustc/middle/infer/lub.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/region_inference/README.md
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/infer/sub.rs
src/librustc/middle/infer/unify.rs
src/librustc/middle/privacy.rs
src/librustc/middle/region.rs
src/librustc/middle/traits/coherence.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/middle/ty_fold.rs
src/librustc/middle/ty_match.rs [new file with mode: 0644]
src/librustc/middle/ty_relate/mod.rs [new file with mode: 0644]
src/librustc/middle/ty_walk.rs
src/librustc/util/common.rs
src/librustc/util/ppaux.rs
src/librustc_back/fs.rs
src/librustc_back/lib.rs
src/librustc_back/sha2.rs
src/librustc_back/target/apple_ios_base.rs
src/librustc_back/tempdir.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/lib.rs
src/librustc_resolve/lib.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/controlflow.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/flock.rs
src/librustdoc/lib.rs
src/libserialize/json.rs
src/libserialize/lib.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/table.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/ffi/c_str.rs
src/libstd/ffi/mod.rs
src/libstd/ffi/os_str.rs
src/libstd/fs.rs [new file with mode: 0644]
src/libstd/fs/mod.rs [deleted file]
src/libstd/fs/tempdir.rs [deleted file]
src/libstd/io/buffered.rs
src/libstd/io/cursor.rs
src/libstd/io/error.rs
src/libstd/io/impls.rs
src/libstd/io/mod.rs
src/libstd/io/util.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/addr.rs
src/libstd/net/mod.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/old_io/buffered.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/ip.rs
src/libstd/old_io/pipe.rs
src/libstd/old_io/process.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/rand/os.rs
src/libstd/rt/args.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/poison.rs
src/libstd/sync/task_pool.rs [deleted file]
src/libstd/sys/common/net2.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/ext.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/fs2.rs
src/libstd/sys/unix/helper_signal.rs
src/libstd/sys/unix/net.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/process2.rs
src/libstd/sys/unix/timer.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/ext.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/fs2.rs
src/libstd/sys/windows/net.rs
src/libstd/sys/windows/os.rs
src/libstd/sys/windows/process.rs
src/libstd/sys/windows/process2.rs
src/libstd/sys/windows/stdio.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/print/pprust.rs
src/libsyntax/util/small_vector.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/rustbook/main.rs
src/snapshots.txt
src/test/auxiliary/coherence_copy_like_lib.rs [new file with mode: 0644]
src/test/bench/shootout-binarytrees.rs
src/test/bench/shootout-fannkuch-redux.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-spectralnorm.rs
src/test/compile-fail/coherence-cow-1.rs [new file with mode: 0644]
src/test/compile-fail/coherence-cow-2.rs [new file with mode: 0644]
src/test/compile-fail/coherence-cow-no-cover.rs
src/test/compile-fail/coherence-impls-copy.rs
src/test/compile-fail/coherence-impls-send.rs
src/test/compile-fail/coherence-impls-sized.rs
src/test/compile-fail/coherence-overlap-issue-23516.rs [new file with mode: 0644]
src/test/compile-fail/coherence-vec-local-2.rs [new file with mode: 0644]
src/test/compile-fail/coherence-vec-local.rs [new file with mode: 0644]
src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs [new file with mode: 0644]
src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs [new file with mode: 0644]
src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs [new file with mode: 0644]
src/test/compile-fail/coherence_copy_like_err_struct.rs [new file with mode: 0644]
src/test/compile-fail/coherence_copy_like_err_tuple.rs [new file with mode: 0644]
src/test/compile-fail/coherence_local.rs [new file with mode: 0644]
src/test/compile-fail/coherence_local_err_struct.rs [new file with mode: 0644]
src/test/compile-fail/coherence_local_err_tuple.rs [new file with mode: 0644]
src/test/compile-fail/coherence_local_ref.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow-2.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow-3.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow-3b.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow-4.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow-4b.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow.rs [new file with mode: 0644]
src/test/compile-fail/discrim-ill-typed.rs [new file with mode: 0644]
src/test/compile-fail/discrim-overflow-2.rs [new file with mode: 0644]
src/test/compile-fail/discrim-overflow.rs [new file with mode: 0644]
src/test/compile-fail/dropck_arr_cycle_checked.rs
src/test/compile-fail/dropck_tarena_cycle_checked.rs
src/test/compile-fail/dropck_vec_cycle_checked.rs
src/test/compile-fail/dst-bad-coerce1.rs
src/test/compile-fail/estr-subtyping.rs
src/test/compile-fail/huge-array-simple.rs
src/test/compile-fail/issue-13058.rs
src/test/compile-fail/issue-17651.rs
src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs
src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
src/test/compile-fail/object-lifetime-default-elision.rs
src/test/compile-fail/object-lifetime-default-from-box-error.rs
src/test/compile-fail/regions-close-over-type-parameter-multiple.rs
src/test/compile-fail/regions-trait-object-subtyping.rs
src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs
src/test/compile-fail/variance-deprecated-markers.rs [deleted file]
src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs
src/test/compile-fail/vec_refs_data_with_early_death.rs
src/test/debuginfo/unreachable-locals.rs
src/test/parse-fail/issue-1802-1.rs
src/test/parse-fail/lex-bad-binary-literal.rs [new file with mode: 0644]
src/test/parse-fail/lex-bad-octal-literal.rs [new file with mode: 0644]
src/test/run-fail/assert-eq-macro-panic.rs
src/test/run-fail/rt-set-exit-status-panic.rs
src/test/run-fail/rt-set-exit-status-panic2.rs
src/test/run-fail/rt-set-exit-status.rs
src/test/run-make/link-path-order/main.rs
src/test/run-make/unicode-input/span_length.rs
src/test/run-pass-fulldeps/compiler-calls.rs
src/test/run-pass-fulldeps/create-dir-all-bare.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/rename-directory.rs [new file with mode: 0644]
src/test/run-pass/backtrace.rs
src/test/run-pass/big-literals.rs
src/test/run-pass/capturing-logging.rs
src/test/run-pass/child-outlives-parent.rs
src/test/run-pass/clone-with-exterior.rs
src/test/run-pass/coherence-cow-1.rs [deleted file]
src/test/run-pass/coherence-cow-2.rs [deleted file]
src/test/run-pass/coherence-local-1.rs [deleted file]
src/test/run-pass/coherence-local-2.rs [deleted file]
src/test/run-pass/coherence_copy_like.rs [new file with mode: 0644]
src/test/run-pass/comm.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/create-dir-all-bare.rs [deleted file]
src/test/run-pass/deriving-encodable-decodable-box.rs
src/test/run-pass/deriving-encodable-decodable-cell-refcell.rs
src/test/run-pass/deriving-global.rs
src/test/run-pass/discrim-explicit-23030.rs [new file with mode: 0644]
src/test/run-pass/drop-with-type-ascription-2.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/extern-call-scrub.rs
src/test/run-pass/hashmap-memory.rs
src/test/run-pass/init-large-type.rs
src/test/run-pass/issue-11881.rs
src/test/run-pass/issue-13304.rs
src/test/run-pass/issue-13494.rs
src/test/run-pass/issue-14021.rs
src/test/run-pass/issue-14456.rs
src/test/run-pass/issue-15734.rs
src/test/run-pass/issue-17351.rs
src/test/run-pass/issue-17746.rs [new file with mode: 0644]
src/test/run-pass/issue-20454.rs
src/test/run-pass/issue-20797.rs
src/test/run-pass/issue-22577.rs
src/test/run-pass/issue-2718.rs
src/test/run-pass/issue-3609.rs
src/test/run-pass/issue-3743.rs
src/test/run-pass/issue-8827.rs
src/test/run-pass/issue-9396.rs
src/test/run-pass/ivec-tag.rs
src/test/run-pass/kindck-implicit-close-over-mut-var.rs
src/test/run-pass/macro-with-braces-in-expr-position.rs
src/test/run-pass/method-two-trait-defer-resolution-2.rs
src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs
src/test/run-pass/minmax-stability-issue-23687.rs [new file with mode: 0644]
src/test/run-pass/moves-based-on-type-capture-clause.rs
src/test/run-pass/option-ext.rs
src/test/run-pass/out-of-stack-new-thread-no-split.rs
src/test/run-pass/process-exit.rs [new file with mode: 0644]
src/test/run-pass/regions-refcell.rs
src/test/run-pass/rename-directory.rs [deleted file]
src/test/run-pass/running-with-no-runtime.rs
src/test/run-pass/rust-log-filter.rs
src/test/run-pass/send-is-not-static-par-for.rs
src/test/run-pass/send-resource.rs
src/test/run-pass/simd-binop.rs
src/test/run-pass/small-enum-range-edge.rs
src/test/run-pass/stat.rs [deleted file]
src/test/run-pass/syntax-extension-source-utils.rs
src/test/run-pass/task-comm-0.rs
src/test/run-pass/task-comm-1.rs
src/test/run-pass/task-comm-10.rs
src/test/run-pass/task-comm-11.rs
src/test/run-pass/task-comm-12.rs
src/test/run-pass/task-comm-13.rs
src/test/run-pass/task-comm-14.rs
src/test/run-pass/task-comm-15.rs
src/test/run-pass/task-comm-17.rs
src/test/run-pass/task-comm-3.rs
src/test/run-pass/task-comm-7.rs
src/test/run-pass/task-comm-9.rs
src/test/run-pass/task-life-0.rs
src/test/run-pass/task-spawn-move-and-copy.rs
src/test/run-pass/tcp-accept-stress.rs
src/test/run-pass/tcp-connect-timeouts.rs
src/test/run-pass/tcp-stress.rs
src/test/run-pass/tempfile.rs
src/test/run-pass/threads.rs
src/test/run-pass/trait-bounds-in-arc.rs
src/test/run-pass/traits-conditional-dispatch.rs
src/test/run-pass/unboxed-closures-blanket-fn-mut.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-blanket-fn.rs [new file with mode: 0644]
src/test/run-pass/unit-like-struct-drop-run.rs
src/test/run-pass/variadic-ffi.rs

index f0aacc1460b3fa7b372b6919e632ece9921aea36..7fd09f9e1f5b0b9e0310b26d9efd76c346efc457 100644 (file)
@@ -18,7 +18,6 @@
 #![feature(std_misc)]
 #![feature(test)]
 #![feature(path_ext)]
-#![feature(convert)]
 #![feature(str_char)]
 
 #![deny(warnings)]
index 0bc4414999d74e320e6968e410e3211a39237e01..b3d5ad3b55d0ff8b3d5ce7739a431ff0f5a66742 100644 (file)
@@ -977,7 +977,6 @@ An example of `use` declarations:
 
 ```
 # #![feature(core)]
-use std::iter::range_step;
 use std::option::Option::{Some, None};
 use std::collections::hash_map::{self, HashMap};
 
@@ -985,9 +984,6 @@ fn foo<T>(_: T){}
 fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){}
 
 fn main() {
-    // Equivalent to 'std::iter::range_step(0, 10, 2);'
-    range_step(0, 10, 2);
-
     // Equivalent to 'foo(vec![std::option::Option::Some(1.0f64),
     // std::option::Option::None]);'
     foo(vec![Some(1.0f64), None]);
index d31348d667b57e56e996ca86e2e64e4505f8fdde..136e155b1afe3e6f9f6d00f29b8b9718c12e585a 100644 (file)
@@ -42,5 +42,6 @@
     * [Intrinsics](intrinsics.md)
     * [Lang items](lang-items.md)
     * [Link args](link-args.md)
+    * [Benchmark Tests](benchmark-tests.md)
 * [Conclusion](conclusion.md)
 * [Glossary](glossary.md)
diff --git a/src/doc/trpl/benchmark-tests.md b/src/doc/trpl/benchmark-tests.md
new file mode 100644 (file)
index 0000000..8879653
--- /dev/null
@@ -0,0 +1,152 @@
+% Benchmark tests
+
+Rust supports benchmark tests, which can test the performance of your
+code. Let's make our `src/lib.rs` look like this (comments elided):
+
+```{rust,ignore}
+#![feature(test)]
+
+extern crate test;
+
+pub fn add_two(a: i32) -> i32 {
+    a + 2
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use test::Bencher;
+
+    #[test]
+    fn it_works() {
+        assert_eq!(4, add_two(2));
+    }
+
+    #[bench]
+    fn bench_add_two(b: &mut Bencher) {
+        b.iter(|| add_two(2));
+    }
+}
+```
+
+Note the `test` feature gate, which enables this unstable feature.
+
+We've imported the `test` crate, which contains our benchmarking support.
+We have a new function as well, with the `bench` attribute. Unlike regular
+tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
+`Bencher` provides an `iter` method, which takes a closure. This closure
+contains the code we'd like to benchmark.
+
+We can run benchmark tests with `cargo bench`:
+
+```bash
+$ cargo bench
+   Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
+     Running target/release/adder-91b3e234d4ed382a
+
+running 2 tests
+test tests::it_works ... ignored
+test tests::bench_add_two ... bench:         1 ns/iter (+/- 0)
+
+test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
+```
+
+Our non-benchmark test was ignored. You may have noticed that `cargo bench`
+takes a bit longer than `cargo test`. This is because Rust runs our benchmark
+a number of times, and then takes the average. Because we're doing so little
+work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
+the variance if there was one.
+
+Advice on writing benchmarks:
+
+
+* Move setup code outside the `iter` loop; only put the part you want to measure inside
+* Make the code do "the same thing" on each iteration; do not accumulate or change state
+* Make the outer function idempotent too; the benchmark runner is likely to run
+  it many times
+*  Make the inner `iter` loop short and fast so benchmark runs are fast and the
+   calibrator can adjust the run-length at fine resolution
+* Make the code in the `iter` loop do something simple, to assist in pinpointing
+  performance improvements (or regressions)
+
+## Gotcha: optimizations
+
+There's another tricky part to writing benchmarks: benchmarks compiled with
+optimizations activated can be dramatically changed by the optimizer so that
+the benchmark is no longer benchmarking what one expects. For example, the
+compiler might recognize that some calculation has no external effects and
+remove it entirely.
+
+```{rust,ignore}
+#![feature(test)]
+
+extern crate test;
+use test::Bencher;
+
+#[bench]
+fn bench_xor_1000_ints(b: &mut Bencher) {
+    b.iter(|| {
+        (0..1000).fold(0, |old, new| old ^ new);
+    });
+}
+```
+
+gives the following results
+
+```text
+running 1 test
+test bench_xor_1000_ints ... bench:         0 ns/iter (+/- 0)
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
+```
+
+The benchmarking runner offers two ways to avoid this. Either, the closure that
+the `iter` method receives can return an arbitrary value which forces the
+optimizer to consider the result used and ensures it cannot remove the
+computation entirely. This could be done for the example above by adjusting the
+`b.iter` call to
+
+```rust
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
+b.iter(|| {
+    // note lack of `;` (could also use an explicit `return`).
+    (0..1000).fold(0, |old, new| old ^ new)
+});
+```
+
+Or, the other option is to call the generic `test::black_box` function, which
+is an opaque "black box" to the optimizer and so forces it to consider any
+argument as used.
+
+```rust
+#![feature(test)]
+
+extern crate test;
+
+# fn main() {
+# struct X;
+# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
+b.iter(|| {
+    let n = test::black_box(1000);
+
+    (0..n).fold(0, |a, b| a ^ b)
+})
+# }
+```
+
+Neither of these read or modify the value, and are very cheap for small values.
+Larger values can be passed indirectly to reduce overhead (e.g.
+`black_box(&huge_struct)`).
+
+Performing either of the above changes gives the following benchmarking results
+
+```text
+running 1 test
+test bench_xor_1000_ints ... bench:       131 ns/iter (+/- 3)
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
+```
+
+However, the optimizer can still modify a testcase in an undesirable manner
+even when using either of the above.
index 79cb3117c0ef2ea7c249ca5303f0eadaa1f0a860..6b814a685424ef83220f8ce19f02d036bfe58b70 100644 (file)
@@ -280,13 +280,15 @@ it returns an `Result<T, E>`, and because this is just an example, we `unwrap()`
 it to get a reference to the data. Real code would have more robust error handling
 here. We're then free to mutate it, since we have the lock.
 
-This timer bit is a bit awkward, however. We have picked a reasonable amount of
-time to wait, but it's entirely possible that we've picked too high, and that
-we could be taking less time. It's also possible that we've picked too low,
-and that we aren't actually finishing this computation.
-
-Rust's standard library provides a few more mechanisms for two threads to
-synchronize with each other. Let's talk about one: channels.
+Lastly, while the threads are running, we wait on a short timer. But
+this is not ideal: we may have picked a reasonable amount of time to
+wait but it's more likely we'll either be waiting longer than
+necessary or not long enough, depending on just how much time the
+threads actually take to finish computing when the program runs.
+
+A more precise alternative to the timer would be to use one of the
+mechanisms provided by the Rust standard library for synchronizing
+threads with each other. Let's talk about one of them: channels.
 
 ## Channels
 
index 8d7b1c3bd83932dbaab824ac5752d1ca87f64d1e..55776bee3b585c91e8b0e7bc02b7ca8f5f43571c 100644 (file)
@@ -243,11 +243,12 @@ for num in nums.iter() {
 ```
 
 These two basic iterators should serve you well. There are some more
-advanced iterators, including ones that are infinite. Like `count`:
+advanced iterators, including ones that are infinite. Like using range syntax
+and `step_by`:
 
 ```rust
-# #![feature(core)]
-std::iter::count(1, 5);
+# #![feature(step_by)]
+(1..).step_by(5);
 ```
 
 This iterator counts up from one, adding five each time. It will give
@@ -292,11 +293,11 @@ just use `for` instead.
 There are tons of interesting iterator adapters. `take(n)` will return an
 iterator over the next `n` elements of the original iterator, note that this
 has no side effect on the original iterator. Let's try it out with our infinite
-iterator from before, `count()`:
+iterator from before:
 
 ```rust
-# #![feature(core)]
-for i in std::iter::count(1, 5).take(5) {
+# #![feature(step_by)]
+for i in (1..).step_by(5).take(5) {
     println!("{}", i);
 }
 ```
index 7da36043f6cf17726a3641bab0381564aeb1ada1..7e19ec94ee745160e4fe01ecbcb47e056b43b81d 100644 (file)
@@ -37,7 +37,7 @@ number of elements.
 
 ```rust
 let x: Vec<u32> = vec![1, 2, 3];
-# assert_eq!(&[1,2,3], &x);
+# assert_eq!(x, [1, 2, 3]);
 ```
 
 This can't be an ordinary function, because it takes any number of arguments.
@@ -51,7 +51,7 @@ let x: Vec<u32> = {
     temp_vec.push(3);
     temp_vec
 };
-# assert_eq!(&[1,2,3], &x);
+# assert_eq!(x, [1, 2, 3]);
 ```
 
 We can implement this shorthand, using a macro: [^actual]
@@ -73,7 +73,7 @@ macro_rules! vec {
     };
 }
 # fn main() {
-#     assert_eq!([1,2,3], vec![1,2,3]);
+#     assert_eq!(vec![1,2,3], [1, 2, 3]);
 # }
 ```
 
index f4b5495ba6390d88e50161e7bbb0e212d1324aae..223085cc40b8ee50d04258794276363069d4222c 100644 (file)
@@ -477,7 +477,7 @@ forbidden in item signatures to allow reasoning about the types just based in
 the item signature alone. However, for ergonomic reasons a very restricted
 secondary inference algorithm called “lifetime elision” applies in function
 signatures. It infers only based on the signature components themselves and not
-based on the body of the function, only infers lifetime paramters, and does
+based on the body of the function, only infers lifetime parameters, and does
 this with only three easily memorizable and unambiguous rules. This makes
 lifetime elision a shorthand for writing an item signature, while not hiding
 away the actual types involved as full local inference would if applied to it.
index 8b2c14526cbf0fd91a5611bbfd223fbae6c91125..fddb4c19031726f51f9dfe0930c40dbb4ff538fb 100644 (file)
@@ -430,149 +430,3 @@ documentation tests: the `_0` is generated for the module test, and `add_two_0`
 for the function test. These will auto increment with names like `add_two_1` as
 you add more examples.
 
-# Benchmark tests
-
-Rust also supports benchmark tests, which can test the performance of your
-code. Let's make our `src/lib.rs` look like this (comments elided):
-
-```{rust,ignore}
-extern crate test;
-
-pub fn add_two(a: i32) -> i32 {
-    a + 2
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use test::Bencher;
-
-    #[test]
-    fn it_works() {
-        assert_eq!(4, add_two(2));
-    }
-
-    #[bench]
-    fn bench_add_two(b: &mut Bencher) {
-        b.iter(|| add_two(2));
-    }
-}
-```
-
-We've imported the `test` crate, which contains our benchmarking support.
-We have a new function as well, with the `bench` attribute. Unlike regular
-tests, which take no arguments, benchmark tests take a `&mut Bencher`. This
-`Bencher` provides an `iter` method, which takes a closure. This closure
-contains the code we'd like to benchmark.
-
-We can run benchmark tests with `cargo bench`:
-
-```bash
-$ cargo bench
-   Compiling adder v0.0.1 (file:///home/steve/tmp/adder)
-     Running target/release/adder-91b3e234d4ed382a
-
-running 2 tests
-test tests::it_works ... ignored
-test tests::bench_add_two ... bench:         1 ns/iter (+/- 0)
-
-test result: ok. 0 passed; 0 failed; 1 ignored; 1 measured
-```
-
-Our non-benchmark test was ignored. You may have noticed that `cargo bench`
-takes a bit longer than `cargo test`. This is because Rust runs our benchmark
-a number of times, and then takes the average. Because we're doing so little
-work in this example, we have a `1 ns/iter (+/- 0)`, but this would show
-the variance if there was one.
-
-Advice on writing benchmarks:
-
-
-* Move setup code outside the `iter` loop; only put the part you want to measure inside
-* Make the code do "the same thing" on each iteration; do not accumulate or change state
-* Make the outer function idempotent too; the benchmark runner is likely to run
-  it many times
-*  Make the inner `iter` loop short and fast so benchmark runs are fast and the
-   calibrator can adjust the run-length at fine resolution
-* Make the code in the `iter` loop do something simple, to assist in pinpointing
-  performance improvements (or regressions)
-
-## Gotcha: optimizations
-
-There's another tricky part to writing benchmarks: benchmarks compiled with
-optimizations activated can be dramatically changed by the optimizer so that
-the benchmark is no longer benchmarking what one expects. For example, the
-compiler might recognize that some calculation has no external effects and
-remove it entirely.
-
-```{rust,ignore}
-extern crate test;
-use test::Bencher;
-
-#[bench]
-fn bench_xor_1000_ints(b: &mut Bencher) {
-    b.iter(|| {
-        (0..1000).fold(0, |old, new| old ^ new);
-    });
-}
-```
-
-gives the following results
-
-```text
-running 1 test
-test bench_xor_1000_ints ... bench:         0 ns/iter (+/- 0)
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
-```
-
-The benchmarking runner offers two ways to avoid this. Either, the closure that
-the `iter` method receives can return an arbitrary value which forces the
-optimizer to consider the result used and ensures it cannot remove the
-computation entirely. This could be done for the example above by adjusting the
-`b.iter` call to
-
-```rust
-# struct X;
-# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
-b.iter(|| {
-    // note lack of `;` (could also use an explicit `return`).
-    (0..1000).fold(0, |old, new| old ^ new)
-});
-```
-
-Or, the other option is to call the generic `test::black_box` function, which
-is an opaque "black box" to the optimizer and so forces it to consider any
-argument as used.
-
-```rust
-# #![feature(test)]
-
-extern crate test;
-
-# fn main() {
-# struct X;
-# impl X { fn iter<T, F>(&self, _: F) where F: FnMut() -> T {} } let b = X;
-b.iter(|| {
-    let n = test::black_box(1000);
-
-    (0..n).fold(0, |a, b| a ^ b)
-})
-# }
-```
-
-Neither of these read or modify the value, and are very cheap for small values.
-Larger values can be passed indirectly to reduce overhead (e.g.
-`black_box(&huge_struct)`).
-
-Performing either of the above changes gives the following benchmarking results
-
-```text
-running 1 test
-test bench_xor_1000_ints ... bench:       131 ns/iter (+/- 3)
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 1 measured
-```
-
-However, the optimizer can still modify a testcase in an undesirable manner
-even when using either of the above.
index 1e44076a4305f0d43d5928e47e331bee36e82aee..341c90a70877e7cc485e6ac22b645e9e27c02367 100644 (file)
@@ -277,6 +277,29 @@ One last thing about traits: generic functions with a trait bound use
 dispatched. What's that mean? Check out the chapter on [static and dynamic
 dispatch](static-and-dynamic-dispatch.html) for more.
 
+## Multiple trait bounds
+
+You’ve seen that you can bound a generic type parameter with a trait:
+
+```rust
+fn foo<T: Clone>(x: T) {
+    x.clone();
+}
+```
+
+If you need more than one bound, you can use `+`:
+
+```rust
+use std::fmt::Debug;
+
+fn foo<T: Clone + Debug>(x: T) {
+    x.clone();
+    println!("{:?}", x);
+}
+```
+
+`T` now needs to be both `Clone` as well as `Debug`.
+
 ## Where clause
 
 Writing functions with only a few generic types and a small number of trait
index 9b37ddc7ab53383136d86eee9ef4a44de7288917..73d109f3c8d41c170285852fd94b9d9754c5bfc7 100644 (file)
 ///         let child_numbers = shared_numbers.clone();
 ///
 ///         thread::spawn(move || {
-///             let local_numbers = child_numbers.as_slice();
+///             let local_numbers = &child_numbers[..];
 ///
 ///             // Work with the local numbers
 ///         });
@@ -242,6 +242,38 @@ pub fn weak_count<T>(this: &Arc<T>) -> usize { this.inner().weak.load(SeqCst) -
 #[unstable(feature = "alloc")]
 pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst) }
 
+
+/// Try accessing a mutable reference to the contents behind an unique `Arc<T>`.
+///
+/// The access is granted only if this is the only reference to the object.
+/// Otherwise, `None` is returned.
+///
+/// # Examples
+///
+/// ```
+/// # #![feature(alloc)]
+/// use std::alloc::arc;
+///
+/// let mut four = arc::Arc::new(4);
+///
+/// arc::unique(&mut four).map(|num| *num = 5);
+/// ```
+#[inline]
+#[unstable(feature = "alloc")]
+pub fn unique<T>(this: &mut Arc<T>) -> Option<&mut T> {
+    if strong_count(this) == 1 && weak_count(this) == 0 {
+        // This unsafety is ok because we're guaranteed that the pointer
+        // returned is the *only* pointer that will ever be returned to T. Our
+        // reference count is guaranteed to be 1 at this point, and we required
+        // the Arc itself to be `mut`, so we're returning the only possible
+        // reference to the inner data.
+        let inner = unsafe { &mut **this._ptr };
+        Some(&mut inner.data)
+    }else {
+        None
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Arc<T> {
     /// Makes a clone of the `Arc<T>`.
@@ -312,11 +344,8 @@ pub fn make_unique(&mut self) -> &mut T {
            self.inner().weak.load(SeqCst) != 1 {
             *self = Arc::new((**self).clone())
         }
-        // This unsafety is ok because we're guaranteed that the pointer
-        // returned is the *only* pointer that will ever be returned to T. Our
-        // reference count is guaranteed to be 1 at this point, and we required
-        // the Arc itself to be `mut`, so we're returning the only possible
-        // reference to the inner data.
+        // As with `unique()`, the unsafety is ok because our reference was
+        // either unique to begin with, or became one upon cloning the contents.
         let inner = unsafe { &mut **self._ptr };
         &mut inner.data
     }
@@ -659,7 +688,7 @@ mod tests {
     use std::sync::atomic::Ordering::{Acquire, SeqCst};
     use std::thread;
     use std::vec::Vec;
-    use super::{Arc, Weak, weak_count, strong_count};
+    use super::{Arc, Weak, weak_count, strong_count, unique};
     use std::sync::Mutex;
 
     struct Canary(*mut atomic::AtomicUsize);
@@ -695,6 +724,21 @@ fn manually_share_arc() {
         assert_eq!((*arc_v)[4], 5);
     }
 
+    #[test]
+    fn test_arc_unique() {
+        let mut x = Arc::new(10);
+        assert!(unique(&mut x).is_some());
+        {
+            let y = x.clone();
+            assert!(unique(&mut x).is_none());
+        }
+        {
+            let z = x.downgrade();
+            assert!(unique(&mut x).is_none());
+        }
+        assert!(unique(&mut x).is_some());
+    }
+
     #[test]
     fn test_cowarc_clone_make_unique() {
         let mut cow0 = Arc::new(75);
index f9bd0ab2f1e0fdbe1e3cb88fcb61413d1e21b8b6..c4541e34cdb359189778c55b280456062bd1eaa1 100644 (file)
 use core::any::Any;
 use core::cmp::Ordering;
 use core::default::Default;
-use core::error::{Error, FromError};
+use core::error::Error;
 use core::fmt;
 use core::hash::{self, Hash};
 use core::mem;
 use core::ops::{Deref, DerefMut};
-use core::ptr::Unique;
-use core::raw::TraitObject;
+use core::ptr::{self, Unique};
+use core::raw::{TraitObject, Slice};
+
+use heap;
 
 /// A value that represents the heap. This is the default place that the `box`
 /// keyword allocates into when no place is supplied.
@@ -84,6 +86,7 @@
 /// See the [module-level documentation](../../std/boxed/index.html) for more.
 #[lang = "owned_box"]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[fundamental]
 pub struct Box<T>(Unique<T>);
 
 impl<T> Box<T> {
@@ -233,24 +236,10 @@ fn hash<H: hash::Hasher>(&self, state: &mut H) {
     }
 }
 
-/// Extension methods for an owning `Any` trait object.
-#[unstable(feature = "alloc",
-           reason = "this trait will likely disappear once compiler bugs blocking \
-                     a direct impl on `Box<Any>` have been fixed ")]
-// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
-//                removing this please make sure that you can downcase on
-//                `Box<Any + Send>` as well as `Box<Any>`
-pub trait BoxAny {
-    /// Returns the boxed value if it is of type `T`, or
-    /// `Err(Self)` if it isn't.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl BoxAny for Box<Any> {
+impl Box<Any> {
     #[inline]
-    fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
@@ -267,10 +256,10 @@ fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl BoxAny for Box<Any+Send> {
+impl Box<Any+Send> {
     #[inline]
-    fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
         <Box<Any>>::downcast(self)
     }
 }
@@ -289,13 +278,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Box<Any> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.pad("Box<Any>")
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for Box<T> {
     type Target = T;
@@ -322,8 +304,48 @@ fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
 impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, E: Error + 'a> FromError<E> for Box<Error + 'a> {
-    fn from_error(err: E) -> Box<Error + 'a> {
+impl<'a, E: Error + 'a> From<E> for Box<Error + 'a> {
+    fn from(err: E) -> Box<Error + 'a> {
         Box::new(err)
     }
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, E: Error + Send + 'a> From<E> for Box<Error + Send + 'a> {
+    fn from(err: E) -> Box<Error + Send + 'a> {
+        Box::new(err)
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b> From<&'b str> for Box<Error + Send + 'a> {
+    fn from(err: &'b str) -> Box<Error + Send + 'a> {
+        #[derive(Debug)]
+        struct StringError(Box<str>);
+        impl Error for StringError {
+            fn description(&self) -> &str { &self.0 }
+        }
+        impl fmt::Display for StringError {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                self.0.fmt(f)
+            }
+        }
+
+        // Unfortunately `String` is located in libcollections, so we construct
+        // a `Box<str>` manually here.
+        unsafe {
+            let alloc = if err.len() == 0 {
+                0 as *mut u8
+            } else {
+                let ptr = heap::allocate(err.len(), 1);
+                if ptr.is_null() { ::oom(); }
+                ptr as *mut u8
+            };
+            ptr::copy(err.as_bytes().as_ptr(), alloc, err.len());
+            Box::new(StringError(mem::transmute(Slice {
+                data: alloc,
+                len: err.len(),
+            })))
+        }
+    }
+}
index bb1ff9428a7c01889b89797073a43df8189529bf..fc44ac4eac628b2eba405276caedb542f5d49bff 100644 (file)
@@ -17,7 +17,6 @@
 
 use std::boxed;
 use std::boxed::Box;
-use std::boxed::BoxAny;
 
 #[test]
 fn test_owned_clone() {
@@ -56,17 +55,17 @@ fn test_show() {
     let b = Box::new(Test) as Box<Any>;
     let a_str = format!("{:?}", a);
     let b_str = format!("{:?}", b);
-    assert_eq!(a_str, "Box<Any>");
-    assert_eq!(b_str, "Box<Any>");
+    assert_eq!(a_str, "Any");
+    assert_eq!(b_str, "Any");
 
     static EIGHT: usize = 8;
     static TEST: Test = Test;
     let a = &EIGHT as &Any;
     let b = &TEST as &Any;
     let s = format!("{:?}", a);
-    assert_eq!(s, "&Any");
+    assert_eq!(s, "Any");
     let s = format!("{:?}", b);
-    assert_eq!(s, "&Any");
+    assert_eq!(s, "Any");
 }
 
 #[test]
index b92dfa9117e6beb5745f97c106a758ebfedef1fe..a8be63d637359beff197d7947b43a037023d8b15 100644 (file)
@@ -71,6 +71,8 @@
 #![feature(no_std)]
 #![no_std]
 #![feature(allocator)]
+#![feature(custom_attribute)]
+#![feature(fundamental)]
 #![feature(lang_items, unsafe_destructor)]
 #![feature(box_syntax)]
 #![feature(optin_builtin_traits)]
index 3ed8ca2bea98b1adb197c1654262df769ad138cb..8874ac6eb872f020c1d55de74b835dd454d6cd73 100644 (file)
@@ -38,7 +38,7 @@
 //! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
 //!
 //! ```
-//! # #![feature(collections, core)]
+//! # #![feature(collections, core, step_by)]
 //! use std::collections::{BitSet, BitVec};
 //! use std::num::Float;
 //! use std::iter;
@@ -60,7 +60,7 @@
 //!         if bv[i] {
 //!             // Mark all multiples of i as non-prime (any multiples below i * i
 //!             // will have been marked as non-prime previously)
-//!             for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) }
+//!             for j in (i * i..max_prime).step_by(i) { bv.set(j, false) }
 //!         }
 //!     }
 //!     BitSet::from_bit_vec(bv)
@@ -1264,14 +1264,6 @@ pub fn from_bit_vec(bit_vec: BitVec) -> BitSet {
         BitSet { bit_vec: bit_vec }
     }
 
-    /// Deprecated: use `from_bit_vec`.
-    #[inline]
-    #[deprecated(since = "1.0.0", reason = "renamed to from_bit_vec")]
-    #[unstable(feature = "collections")]
-    pub fn from_bitv(bit_vec: BitVec) -> BitSet {
-        BitSet { bit_vec: bit_vec }
-    }
-
     /// Returns the capacity in bits for this bit vector. Inserting any
     /// element less than this amount will not trigger a resizing.
     ///
index 88d59f699d183030c7c2f665ee3ecd2bd813813a..2fe769b73f5cc00619e11b0d2f771eb3b05bd717 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Borrow<Borrowed: ?Sized> {
     /// Immutably borrow from an owned value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::borrow::Borrow;
+    ///
+    /// fn check<T: Borrow<str>>(s: T) {
+    ///     assert_eq!("Hello", s.borrow());
+    /// }
+    ///
+    /// let s = "Hello".to_string();
+    ///
+    /// check(s);
+    ///
+    /// let s = "Hello";
+    ///
+    /// check(s);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn borrow(&self) -> &Borrowed;
 }
@@ -50,6 +68,20 @@ pub trait Borrow<Borrowed: ?Sized> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
     /// Mutably borrow from an owned value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::borrow::BorrowMut;
+    ///
+    /// fn check<T: BorrowMut<[i32]>>(mut v: T) {
+    ///     assert_eq!(&mut [1, 2, 3], v.borrow_mut());
+    /// }
+    ///
+    /// let v = vec![1, 2, 3];
+    ///
+    /// check(v);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn borrow_mut(&mut self) -> &mut Borrowed;
 }
@@ -171,6 +203,18 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
     /// Acquire a mutable reference to the owned form of the data.
     ///
     /// Copies the data if it is not already owned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::borrow::Cow;
+    ///
+    /// let mut cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
+    ///
+    /// let hello = cow.to_mut();
+    ///
+    /// assert_eq!(hello, &[1, 2, 3]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
         match *self {
@@ -185,6 +229,18 @@ pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
     /// Extract the owned data.
     ///
     /// Copies the data if it is not already owned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::borrow::Cow;
+    ///
+    /// let cow: Cow<[_]> = Cow::Owned(vec![1, 2, 3]);
+    ///
+    /// let hello = cow.into_owned();
+    ///
+    /// assert_eq!(vec![1, 2, 3], hello);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_owned(self) -> <B as ToOwned>::Owned {
         match self {
@@ -192,26 +248,6 @@ pub fn into_owned(self) -> <B as ToOwned>::Owned {
             Owned(owned) => owned
         }
     }
-
-    /// Returns true if this `Cow` wraps a borrowed value
-    #[deprecated(since = "1.0.0", reason = "match on the enum instead")]
-    #[unstable(feature = "std_misc")]
-    pub fn is_borrowed(&self) -> bool {
-        match *self {
-            Borrowed(_) => true,
-            _ => false,
-        }
-    }
-
-    /// Returns true if this `Cow` wraps an owned value
-    #[deprecated(since = "1.0.0", reason = "match on the enum instead")]
-    #[unstable(feature = "std_misc")]
-    pub fn is_owned(&self) -> bool {
-        match *self {
-            Owned(_) => true,
-            _ => false,
-        }
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index e1d007f0ac49739e21a33f60929e5fa0b7f5b19a..adfb284dabea73562a31832c15a098fdfd84d849 100644 (file)
@@ -1134,8 +1134,7 @@ pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
         }
     }
 
-    #[unstable(feature = "collections",
-               reason = "matches entry v3 specification, waiting for dust to settle")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
     pub fn or_insert(self, default: V) -> &'a mut V {
@@ -1145,8 +1144,7 @@ pub fn or_insert(self, default: V) -> &'a mut V {
         }
     }
 
-    #[unstable(feature = "collections",
-               reason = "matches entry v3 specification, waiting for dust to settle")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the result of the default function if empty,
     /// and returns a mutable reference to the value in the entry.
     pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
index c769b3df37f627548150961962c00aa8500c6c39..7658611d809afd6ac23bdd666878c206dc1d3749 100644 (file)
@@ -38,7 +38,6 @@
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(step_by)]
 #![feature(str_char)]
-#![feature(convert)]
 #![feature(slice_patterns)]
 #![feature(debug_builders)]
 #![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))]
 pub use vec::Vec;
 pub use vec_map::VecMap;
 
-#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
-#[unstable(feature = "collections")]
-pub use vec_deque as ring_buf;
-
-#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
-#[unstable(feature = "collections")]
-pub use linked_list as dlist;
-
-#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
-#[unstable(feature = "collections")]
-pub use bit_vec as bitv;
-
-#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
-#[unstable(feature = "collections")]
-pub use bit_set as bitv_set;
-
 // Needed for the vec! macro
 pub use alloc::boxed;
 
            reason = "RFC 509")]
 pub mod bit_vec {
     pub use bit::{BitVec, Iter};
-
-    #[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
-    #[unstable(feature = "collections")]
-    pub use bit::BitVec as Bitv;
 }
 
 #[unstable(feature = "collections",
@@ -119,10 +98,6 @@ pub mod bit_vec {
 pub mod bit_set {
     pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
     pub use bit::SetIter as Iter;
-
-    #[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
-    #[unstable(feature = "collections")]
-    pub use bit::BitSet as BitvSet;
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 52da4902b758cf1c31721072a8c6636ed2ed6a70..dbdb79565736cd16a33a13390f5c67b9ef1f6d81 100644 (file)
 use core::mem;
 use core::ptr;
 
-#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")]
-#[unstable(feature = "collections")]
-pub use LinkedList as DList;
-
 /// A doubly-linked list.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LinkedList<T> {
@@ -252,6 +248,7 @@ pub fn new() -> LinkedList<T> {
     /// }
     /// println!("{}", b.len()); // prints 0
     /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn append(&mut self, other: &mut LinkedList<T>) {
         match self.list_tail.resolve() {
             None => {
@@ -844,7 +841,7 @@ impl<A> ExactSizeIterator for IntoIter<A> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> FromIterator<A> for LinkedList<A> {
     fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> LinkedList<A> {
-        let mut ret = DList::new();
+        let mut ret = LinkedList::new();
         ret.extend(iter);
         ret
     }
@@ -1079,7 +1076,7 @@ fn test_send() {
         thread::spawn(move || {
             check_links(&n);
             let a: &[_] = &[&1,&2,&3];
-            assert_eq!(a, n.iter().collect::<Vec<_>>());
+            assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
         }).join().ok().unwrap();
     }
 
index 050997f2dd3f085459575ea13b65c79725e5c636..4599aff000df5f48e98fa41f08126faad183620b 100644 (file)
@@ -89,8 +89,6 @@
 use core::marker::Sized;
 use core::mem::size_of;
 use core::mem;
-#[cfg(stage0)]
-use core::num::wrapping::WrappingOps;
 use core::ops::FnMut;
 use core::option::Option::{self, Some, None};
 use core::ptr;
 pub use core::slice::{SplitN, RSplitN, SplitNMut, RSplitNMut};
 pub use core::slice::{bytes, mut_ref_slice, ref_slice};
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
-pub use core::slice::{from_raw_buf, from_raw_mut_buf};
 
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
@@ -281,33 +278,6 @@ pub fn move_from(&mut self, mut src: Vec<T>, start: usize, end: usize) -> usize
         cmp::min(self.len(), end-start)
     }
 
-    /// Deprecated: use `&s[start .. end]` notation instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &s[start .. end] instead")]
-    #[inline]
-    pub fn slice(&self, start: usize, end: usize) -> &[T] {
-        &self[start .. end]
-    }
-
-    /// Deprecated: use `&s[start..]` notation instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &s[start..] instead")]
-    #[inline]
-    pub fn slice_from(&self, start: usize) -> &[T] {
-        &self[start ..]
-    }
-
-    /// Deprecated: use `&s[..end]` notation instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &s[..end] instead")]
-    #[inline]
-    pub fn slice_to(&self, end: usize) -> &[T] {
-        &self[.. end]
-    }
-
     /// Divides one slice into two at an index.
     ///
     /// The first will contain all indices from `[0, mid)` (excluding
@@ -557,7 +527,6 @@ pub fn as_ptr(&self) -> *const T {
     /// ```rust
     /// # #![feature(core)]
     /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    /// let s = s.as_slice();
     ///
     /// let seek = 13;
     /// assert_eq!(s.binary_search_by(|probe| probe.cmp(&seek)), Ok(9));
@@ -611,42 +580,6 @@ pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
         core_slice::SliceExt::get_mut(self, index)
     }
 
-    /// Deprecated: use `&mut s[..]` instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
-    #[allow(deprecated)]
-    pub fn as_mut_slice(&mut self) -> &mut [T] {
-        core_slice::SliceExt::as_mut_slice(self)
-    }
-
-    /// Deprecated: use `&mut s[start .. end]` instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[start .. end] instead")]
-    #[inline]
-    pub fn slice_mut(&mut self, start: usize, end: usize) -> &mut [T] {
-        &mut self[start .. end]
-    }
-
-    /// Deprecated: use `&mut s[start ..]` instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[start ..] instead")]
-    #[inline]
-    pub fn slice_from_mut(&mut self, start: usize) -> &mut [T] {
-        &mut self[start ..]
-    }
-
-    /// Deprecated: use `&mut s[.. end]` instead.
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[.. end] instead")]
-    #[inline]
-    pub fn slice_to_mut(&mut self, end: usize) -> &mut [T] {
-        &mut self[.. end]
-    }
-
     /// Returns an iterator that allows modifying each value
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -924,7 +857,6 @@ pub fn sort(&mut self) where T: Ord {
     /// ```rust
     /// # #![feature(core)]
     /// let s = [0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
-    /// let s = s.as_slice();
     ///
     /// assert_eq!(s.binary_search(&13),  Ok(9));
     /// assert_eq!(s.binary_search(&4),   Err(7));
@@ -937,13 +869,6 @@ pub fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord {
         core_slice::SliceExt::binary_search(self, x)
     }
 
-    /// Deprecated: use `binary_search` instead.
-    #[unstable(feature = "collections")]
-    #[deprecated(since = "1.0.0", reason = "use binary_search instead")]
-    pub fn binary_search_elem(&self, x: &T) -> Result<usize, usize> where T: Ord {
-        self.binary_search(x)
-    }
-
     /// Mutates the slice to the next lexicographic permutation.
     ///
     /// Returns `true` if successful and `false` if the slice is at the
index 9ddf8988f1ee7ee643e03b65dcde77b9effa0f53..f8f2909291f3e0402fd70fb5e49972459657e06b 100644 (file)
 //
 // ignore-lexer-test FIXME #15679
 
-//! Unicode string manipulation (the [`str`](../primitive.str.html) type).
+//! Unicode string manipulation (the `str` type).
 //!
-//! Rust's [`str`](../primitive.str.html) type is one of the core primitive
-//! types of the language. `&str` is the borrowed string type. This type of
-//! string can only be created from other strings, unless it is a `&'static str`
-//! (see below). It is not possible to move out of borrowed strings because they
-//! are owned elsewhere.
+//! Rust's `str` type is one of the core primitive types of the language. `&str`
+//! is the borrowed string type. This type of string can only be created from
+//! other strings, unless it is a `&'static str` (see below). It is not possible
+//! to move out of borrowed strings because they are owned elsewhere.
 //!
 //! # Examples
 //!
 use slice::SliceConcatExt;
 
 pub use core::str::{FromStr, Utf8Error, Str};
-pub use core::str::{Lines, LinesAny, MatchIndices, SplitStr, CharRange};
+pub use core::str::{Lines, LinesAny, MatchIndices, CharRange};
 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 core::str::{from_utf8, Chars, CharIndices, Bytes};
+pub use core::str::{from_utf8_unchecked, ParseBoolError};
 pub use unicode::str::{Words, Graphemes, GraphemeIndices};
 pub use core::str::Pattern;
 pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep};
@@ -536,22 +535,6 @@ pub fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
         core_str::StrExt::contains(&self[..], pat)
     }
 
-    /// Returns `true` if `self` contains a `char`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(collections)]
-    /// assert!("hello".contains_char('e'));
-    ///
-    /// assert!(!"hello".contains_char('z'));
-    /// ```
-    #[unstable(feature = "collections")]
-    #[deprecated(since = "1.0.0", reason = "use `contains()` with a char")]
-    pub fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
-        core_str::StrExt::contains_char(&self[..], pat)
-    }
-
     /// An iterator over the codepoints of `self`.
     ///
     /// # Examples
@@ -778,25 +761,6 @@ pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P
         core_str::StrExt::match_indices(&self[..], pat)
     }
 
-    /// An iterator over the substrings of `self` separated by a `&str`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(collections)]
-    /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect();
-    /// assert_eq!(v, ["", "XXX", "YYY", ""]);
-    ///
-    /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
-    /// assert_eq!(v, ["1", "", "2"]);
-    /// ```
-    #[unstable(feature = "collections")]
-    #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")]
-    #[allow(deprecated) /* for SplitStr */]
-    pub fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
-        core_str::StrExt::split_str(&self[..], pat)
-    }
-
     /// An iterator over the lines of a string, separated by `\n`.
     ///
     /// This does not include the empty string after a trailing `\n`.
@@ -848,31 +812,6 @@ pub fn lines(&self) -> Lines {
     pub fn lines_any(&self) -> LinesAny {
         core_str::StrExt::lines_any(&self[..])
     }
-
-    /// Deprecated: use `s[a .. b]` instead.
-    #[unstable(feature = "collections",
-               reason = "use slice notation [a..b] instead")]
-    #[deprecated(since = "1.0.0", reason = "use slice notation [a..b] instead")]
-    pub fn slice(&self, begin: usize, end: usize) -> &str {
-        &self[begin..end]
-    }
-
-    /// Deprecated: use `s[a..]` instead.
-    #[unstable(feature = "collections",
-               reason = "use slice notation [a..b] instead")]
-    #[deprecated(since = "1.0.0", reason = "use slice notation [a..] instead")]
-    pub fn slice_from(&self, begin: usize) -> &str {
-        &self[begin..]
-    }
-
-    /// Deprecated: use `s[..a]` instead.
-    #[unstable(feature = "collections",
-               reason = "use slice notation [a..b] instead")]
-    #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")]
-    pub fn slice_to(&self, end: usize) -> &str {
-        &self[..end]
-    }
-
     /// Returns a slice of the string from the character range [`begin`..`end`).
     ///
     /// That is, start at the `begin`-th code point of the string and continue
@@ -1306,27 +1245,6 @@ pub fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
         core_str::StrExt::rfind(&self[..], pat)
     }
 
-    /// Returns the byte index of the first matching substring if it exists.
-    ///
-    /// Returns `None` if it doesn't exist.
-    ///
-    /// The pattern can be a simple `&str`, or a closure that determines the split.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// # #![feature(collections)]
-    /// let s = "Löwe 老虎 Léopard";
-    ///
-    /// assert_eq!(s.find_str("老虎 L"), Some(6));
-    /// assert_eq!(s.find_str("muffin man"), None);
-    /// ```
-    #[unstable(feature = "collections")]
-    #[deprecated(since = "1.0.0", reason = "use `find()` with a `&str`")]
-    pub fn find_str<'a, P: Pattern<'a>>(&'a self, needle: P) -> Option<usize> {
-        core_str::StrExt::find_str(&self[..], needle)
-    }
-
     /// Retrieves the first character from a `&str` and returns it.
     ///
     /// This does not allocate a new string; instead, it returns a slice that points one character
@@ -1470,12 +1388,12 @@ pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
     /// let gr1 = "a\u{310}e\u{301}o\u{308}\u{332}".graphemes(true).collect::<Vec<&str>>();
     /// let b: &[_] = &["a\u{310}", "e\u{301}", "o\u{308}\u{332}"];
     ///
-    /// assert_eq!(gr1.as_slice(), b);
+    /// assert_eq!(&gr1[..], b);
     ///
     /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>();
     /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
     ///
-    /// assert_eq!(gr2.as_slice(), b);
+    /// assert_eq!(&gr2[..], b);
     /// ```
     #[unstable(feature = "unicode",
                reason = "this functionality may only be provided by libunicode")]
@@ -1493,7 +1411,7 @@ pub fn graphemes(&self, is_extended: bool) -> Graphemes {
     /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::<Vec<(usize, &str)>>();
     /// let b: &[_] = &[(0, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
     ///
-    /// assert_eq!(gr_inds.as_slice(), b);
+    /// assert_eq!(&gr_inds[..], b);
     /// ```
     #[unstable(feature = "unicode",
                reason = "this functionality may only be provided by libunicode")]
index dbf214a712b6528cecc3f57493aed7666ad5538d..d8d7ad9887a8ce92ccf5be1a693fc1bd26a91387 100644 (file)
@@ -93,7 +93,7 @@ pub fn with_capacity(capacity: usize) -> String {
     /// ```
     /// # #![feature(collections, core)]
     /// let s = String::from_str("hello");
-    /// assert_eq!(s.as_slice(), "hello");
+    /// assert_eq!(&s[..], "hello");
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -364,6 +364,14 @@ pub fn into_bytes(self) -> Vec<u8> {
         self.vec
     }
 
+    /// Extract a string slice containing the entire string.
+    #[inline]
+    #[unstable(feature = "convert",
+               reason = "waiting on RFC revision")]
+    pub fn as_str(&self) -> &str {
+        self
+    }
+
     /// Pushes the given string onto this string buffer.
     ///
     /// # Examples
@@ -848,7 +856,6 @@ fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&**self, &**other) }
 #[allow(deprecated)]
 impl Str for String {
     #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_slice(&self) -> &str {
         unsafe { mem::transmute(&*self.vec) }
     }
@@ -1072,11 +1079,6 @@ fn as_slice<'b>(&'b self) -> &'b str {
     }
 }
 
-/// A clone-on-write string
-#[deprecated(since = "1.0.0", reason = "use Cow<'a, str> instead")]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type CowString<'a> = Cow<'a, str>;
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Write for String {
     #[inline]
index 3595288a6c94067d0126c23d74365932dc50913e..087b065031f2badba5d3314a147db426e9af508d 100644 (file)
@@ -389,7 +389,7 @@ pub fn shrink_to_fit(&mut self) {
     /// Note that this will drop any excess capacity. Calling this and
     /// converting back to a vector with `into_vec()` is equivalent to calling
     /// `shrink_to_fit()`.
-    #[unstable(feature = "collections")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_boxed_slice(mut self) -> Box<[T]> {
         self.shrink_to_fit();
         unsafe {
@@ -425,11 +425,18 @@ pub fn truncate(&mut self, len: usize) {
         }
     }
 
+    /// Extract a slice containing the entire vector.
+    #[inline]
+    #[unstable(feature = "convert",
+               reason = "waiting on RFC revision")]
+    pub fn as_slice(&self) -> &[T] {
+        self
+    }
+
     /// Deprecated: use `&mut s[..]` instead.
     #[inline]
-    #[unstable(feature = "collections",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
+    #[unstable(feature = "convert",
+               reason = "waiting on RFC revision")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         &mut self[..]
     }
@@ -823,13 +830,13 @@ pub fn is_empty(&self) -> bool { self.len() == 0 }
     /// # #![feature(collections, core)]
     /// let v = vec![0, 1, 2];
     /// let w = v.map_in_place(|i| i + 3);
-    /// assert_eq!(w.as_slice(), [3, 4, 5].as_slice());
+    /// assert_eq!(&w[..], &[3, 4, 5]);
     ///
     /// #[derive(PartialEq, Debug)]
     /// struct Newtype(u8);
     /// let bytes = vec![0x11, 0x22];
     /// let newtyped_bytes = bytes.map_in_place(|x| Newtype(x));
-    /// assert_eq!(newtyped_bytes.as_slice(), [Newtype(0x11), Newtype(0x22)].as_slice());
+    /// assert_eq!(&newtyped_bytes[..], &[Newtype(0x11), Newtype(0x22)]);
     /// ```
     #[unstable(feature = "collections",
                reason = "API may change to provide stronger guarantees")]
@@ -1533,22 +1540,22 @@ fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
 }
 
 __impl_slice_eq1! { Vec<A>, Vec<B> }
-__impl_slice_eq2! { Vec<A>, &'b [B] }
-__impl_slice_eq2! { Vec<A>, &'b mut [B] }
-__impl_slice_eq2! { Cow<'a, [A]>, &'b [B], Clone }
-__impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B], Clone }
-__impl_slice_eq2! { Cow<'a, [A]>, Vec<B>, Clone }
+__impl_slice_eq1! { Vec<A>, &'b [B] }
+__impl_slice_eq1! { Vec<A>, &'b mut [B] }
+__impl_slice_eq1! { Cow<'a, [A]>, &'b [B], Clone }
+__impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B], Clone }
+__impl_slice_eq1! { Cow<'a, [A]>, Vec<B>, Clone }
 
 macro_rules! array_impls {
     ($($N: expr)+) => {
         $(
             // NOTE: some less important impls are omitted to reduce code bloat
-            __impl_slice_eq2! { Vec<A>, [B; $N] }
-            __impl_slice_eq2! { Vec<A>, &'b [B; $N] }
-            // __impl_slice_eq2! { Vec<A>, &'b mut [B; $N] }
-            // __impl_slice_eq2! { Cow<'a, [A]>, [B; $N], Clone }
-            // __impl_slice_eq2! { Cow<'a, [A]>, &'b [B; $N], Clone }
-            // __impl_slice_eq2! { Cow<'a, [A]>, &'b mut [B; $N], Clone }
+            __impl_slice_eq1! { Vec<A>, [B; $N] }
+            __impl_slice_eq1! { Vec<A>, &'b [B; $N] }
+            // __impl_slice_eq1! { Vec<A>, &'b mut [B; $N] }
+            // __impl_slice_eq1! { Cow<'a, [A]>, [B; $N], Clone }
+            // __impl_slice_eq1! { Cow<'a, [A]>, &'b [B; $N], Clone }
+            // __impl_slice_eq1! { Cow<'a, [A]>, &'b mut [B; $N], Clone }
         )+
     }
 }
@@ -1642,13 +1649,6 @@ fn as_ref(&self) -> &Vec<T> {
     }
 }
 
-#[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] {
@@ -1679,11 +1679,6 @@ fn from(s: &'a str) -> Vec<u8> {
 // Clone-on-write
 ////////////////////////////////////////////////////////////////////////////////
 
-/// A clone-on-write vector
-#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")]
-#[unstable(feature = "collections")]
-pub type CowVec<'a, T> = Cow<'a, [T]>;
-
 #[unstable(feature = "collections")]
 impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
     fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
index 392e5092e3b6a9845b0929e83da10f23ff959c77..49b0c229215bd98ee8842debf19edb21b9d79275 100644 (file)
@@ -25,8 +25,6 @@
 use core::fmt;
 use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
 use core::mem;
-#[cfg(stage0)]
-use core::num::wrapping::WrappingOps;
 use core::ops::{Index, IndexMut};
 use core::ptr::{self, Unique};
 use core::slice;
 
 use alloc::heap;
 
-#[deprecated(since = "1.0.0", reason = "renamed to VecDeque")]
-#[unstable(feature = "collections")]
-pub use VecDeque as RingBuf;
-
 const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
 const MINIMUM_CAPACITY: usize = 1; // 2 - 1
 
@@ -527,7 +521,8 @@ pub fn truncate(&mut self, len: usize) {
     /// buf.push_back(3);
     /// buf.push_back(4);
     /// let b: &[_] = &[&5, &3, &4];
-    /// assert_eq!(buf.iter().collect::<Vec<&i32>>().as_slice(), b);
+    /// let c: Vec<&i32> = buf.iter().collect();
+    /// assert_eq!(&c[..], b);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
@@ -1902,7 +1897,7 @@ fn test_insert() {
         // len is the length *after* insertion
         for len in 1..cap {
             // 0, 1, 2, .., len - 1
-            let expected = iter::count(0, 1).take(len).collect();
+            let expected = (0..).take(len).collect();
             for tail_pos in 0..cap {
                 for to_insert in 0..len {
                     tester.tail = tail_pos;
@@ -1935,7 +1930,7 @@ fn test_remove() {
         // len is the length *after* removal
         for len in 0..cap - 1 {
             // 0, 1, 2, .., len - 1
-            let expected = iter::count(0, 1).take(len).collect();
+            let expected = (0..).take(len).collect();
             for tail_pos in 0..cap {
                 for to_remove in 0..len + 1 {
                     tester.tail = tail_pos;
@@ -1973,7 +1968,7 @@ fn test_shrink_to_fit() {
 
         for len in 0..cap + 1 {
             // 0, 1, 2, .., len - 1
-            let expected = iter::count(0, 1).take(len).collect();
+            let expected = (0..).take(len).collect();
             for tail_pos in 0..max_cap + 1 {
                 tester.tail = tail_pos;
                 tester.head = tail_pos;
@@ -2006,9 +2001,9 @@ fn test_split_off() {
             // index to split at
             for at in 0..len + 1 {
                 // 0, 1, 2, .., at - 1 (may be empty)
-                let expected_self = iter::count(0, 1).take(at).collect();
+                let expected_self = (0..).take(at).collect();
                 // at, at + 1, .., len - 1 (may be empty)
-                let expected_other = iter::count(at, 1).take(len - at).collect();
+                let expected_other = (at..).take(len - at).collect();
 
                 for tail_pos in 0..cap {
                     tester.tail = tail_pos;
index 4b4995d5fa7d9dc0bbfb20960dfdf6252db108af..19ea25ee345fae46e07067f200ab34dc9ad907d2 100644 (file)
@@ -10,7 +10,6 @@
 
 use std::cmp::Ordering::{Equal, Greater, Less};
 use std::collections::{BitSet, BitVec};
-use std::iter::range_step;
 
 #[test]
 fn test_bit_set_show() {
@@ -42,7 +41,7 @@ fn test_bit_set_iterator() {
     assert_eq!(idxs, [0, 2, 3]);
 
     let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
-    let real: Vec<_> = range_step(0, 10000, 2).collect();
+    let real: Vec<_> = (0..10000).step_by(2).collect();
 
     let idxs: Vec<_> = long.iter().collect();
     assert_eq!(idxs, real);
index f04367147cb9d03377fc70bc45c84a0b95c3e2f8..a748541fca5ce9609670271cb38276dd39000c37 100644 (file)
@@ -153,19 +153,19 @@ fn test_iterator() {
 
     e1.insert(A);
     let elems: Vec<_> = e1.iter().collect();
-    assert_eq!([A], elems);
+    assert_eq!(elems, [A]);
 
     e1.insert(C);
     let elems: Vec<_> = e1.iter().collect();
-    assert_eq!([A,C], elems);
+    assert_eq!(elems, [A,C]);
 
     e1.insert(C);
     let elems: Vec<_> = e1.iter().collect();
-    assert_eq!([A,C], elems);
+    assert_eq!(elems, [A,C]);
 
     e1.insert(B);
     let elems: Vec<_> = e1.iter().collect();
-    assert_eq!([A,B,C], elems);
+    assert_eq!(elems, [A,B,C]);
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -183,35 +183,35 @@ fn test_operators() {
 
     let e_union = e1 | e2;
     let elems: Vec<_> = e_union.iter().collect();
-    assert_eq!([A,B,C], elems);
+    assert_eq!(elems, [A,B,C]);
 
     let e_intersection = e1 & e2;
     let elems: Vec<_> = e_intersection.iter().collect();
-    assert_eq!([C], elems);
+    assert_eq!(elems, [C]);
 
     // Another way to express intersection
     let e_intersection = e1 - (e1 - e2);
     let elems: Vec<_> = e_intersection.iter().collect();
-    assert_eq!([C], elems);
+    assert_eq!(elems, [C]);
 
     let e_subtract = e1 - e2;
     let elems: Vec<_> = e_subtract.iter().collect();
-    assert_eq!([A], elems);
+    assert_eq!(elems, [A]);
 
     // Bitwise XOR of two sets, aka symmetric difference
     let e_symmetric_diff = e1 ^ e2;
     let elems: Vec<_> = e_symmetric_diff.iter().collect();
-    assert_eq!([A,B], elems);
+    assert_eq!(elems, [A,B]);
 
     // Another way to express symmetric difference
     let e_symmetric_diff = (e1 - e2) | (e2 - e1);
     let elems: Vec<_> = e_symmetric_diff.iter().collect();
-    assert_eq!([A,B], elems);
+    assert_eq!(elems, [A,B]);
 
     // Yet another way to express symmetric difference
     let e_symmetric_diff = (e1 | e2) - (e1 & e2);
     let elems: Vec<_> = e_symmetric_diff.iter().collect();
-    assert_eq!([A,B], elems);
+    assert_eq!(elems, [A,B]);
 }
 
 #[test]
index 9a9aa71b58bfaa7ac82f845a7fae3898bb235a95..70e21c65a1806549eb10764d5bbb67ddfb616a6e 100644 (file)
@@ -13,5 +13,5 @@
 #[test]
 fn test_format() {
     let s = fmt::format(format_args!("Hello, {}!", "world"));
-    assert_eq!(s.as_slice(), "Hello, world!");
+    assert_eq!(s, "Hello, world!");
 }
index f03a073e274e389712b6f994c74228073dda25b1..456c658a9c6dc82d03b861cd50b8cf51ad6a245b 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(deprecated)]
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(core)]
@@ -21,6 +20,7 @@
 #![feature(unicode)]
 #![feature(unsafe_destructor)]
 #![feature(into_cow)]
+#![feature(step_by)]
 #![cfg_attr(test, feature(str_char))]
 
 #[macro_use] extern crate log;
index 4168fe88a4b562bd7d09e259abba3535a869e355..041d9fba57cc35169b0e4921e7a3af053e69d9ad 100644 (file)
@@ -59,7 +59,7 @@ fn test_from_elem() {
     // Test on-heap from_elem.
     v = vec![20; 6];
     {
-        let v = v.as_slice();
+        let v = &v[..];
         assert_eq!(v[0], 20);
         assert_eq!(v[1], 20);
         assert_eq!(v[2], 20);
@@ -685,7 +685,7 @@ fn test_capacity() {
 #[test]
 fn test_slice_2() {
     let v = vec![1, 2, 3, 4, 5];
-    let v = v.slice(1, 3);
+    let v = &v[1..3];
     assert_eq!(v.len(), 2);
     assert_eq!(v[0], 2);
     assert_eq!(v[1], 3);
index 5cfa800905415dd855554be725c97731ac513448..ed9ee0206b74f1f724fc434a8ff379694ebdcd5c 100644 (file)
@@ -83,38 +83,38 @@ fn test_collect() {
 fn test_into_bytes() {
     let data = String::from_str("asdf");
     let buf = data.into_bytes();
-    assert_eq!(b"asdf", buf);
+    assert_eq!(buf, b"asdf");
 }
 
 #[test]
 fn test_find_str() {
     // byte positions
-    assert_eq!("".find_str(""), Some(0));
-    assert!("banana".find_str("apple pie").is_none());
+    assert_eq!("".find(""), Some(0));
+    assert!("banana".find("apple pie").is_none());
 
     let data = "abcabc";
-    assert_eq!(data[0..6].find_str("ab"), Some(0));
-    assert_eq!(data[2..6].find_str("ab"), Some(3 - 2));
-    assert!(data[2..4].find_str("ab").is_none());
+    assert_eq!(data[0..6].find("ab"), Some(0));
+    assert_eq!(data[2..6].find("ab"), Some(3 - 2));
+    assert!(data[2..4].find("ab").is_none());
 
     let string = "ประเทศไทย中华Việt Nam";
     let mut data = String::from_str(string);
     data.push_str(string);
-    assert!(data.find_str("ไท华").is_none());
-    assert_eq!(data[0..43].find_str(""), Some(0));
-    assert_eq!(data[6..43].find_str(""), Some(6 - 6));
+    assert!(data.find("ไท华").is_none());
+    assert_eq!(data[0..43].find(""), Some(0));
+    assert_eq!(data[6..43].find(""), Some(6 - 6));
 
-    assert_eq!(data[0..43].find_str("ประ"), Some( 0));
-    assert_eq!(data[0..43].find_str("ทศไ"), Some(12));
-    assert_eq!(data[0..43].find_str("ย中"), Some(24));
-    assert_eq!(data[0..43].find_str("iệt"), Some(34));
-    assert_eq!(data[0..43].find_str("Nam"), Some(40));
+    assert_eq!(data[0..43].find("ประ"), Some( 0));
+    assert_eq!(data[0..43].find("ทศไ"), Some(12));
+    assert_eq!(data[0..43].find("ย中"), Some(24));
+    assert_eq!(data[0..43].find("iệt"), Some(34));
+    assert_eq!(data[0..43].find("Nam"), Some(40));
 
-    assert_eq!(data[43..86].find_str("ประ"), Some(43 - 43));
-    assert_eq!(data[43..86].find_str("ทศไ"), Some(55 - 43));
-    assert_eq!(data[43..86].find_str("ย中"), Some(67 - 43));
-    assert_eq!(data[43..86].find_str("iệt"), Some(77 - 43));
-    assert_eq!(data[43..86].find_str("Nam"), Some(83 - 43));
+    assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
+    assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
+    assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
+    assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
+    assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
 }
 
 #[test]
@@ -297,16 +297,16 @@ fn test_replace_2d() {
 
 #[test]
 fn test_slice() {
-    assert_eq!("ab", "abc".slice(0, 2));
-    assert_eq!("bc", "abc".slice(1, 3));
-    assert_eq!("", "abc".slice(1, 1));
-    assert_eq!("\u{65e5}", "\u{65e5}\u{672c}".slice(0, 3));
+    assert_eq!("ab", &"abc"[0..2]);
+    assert_eq!("bc", &"abc"[1..3]);
+    assert_eq!("", &"abc"[1..1]);
+    assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
 
     let data = "ประเทศไทย中华";
-    assert_eq!("ป", data.slice(0, 3));
-    assert_eq!("ร", data.slice(3, 6));
-    assert_eq!("", data.slice(3, 3));
-    assert_eq!("华", data.slice(30, 33));
+    assert_eq!("ป", &data[0..3]);
+    assert_eq!("ร", &data[3..6]);
+    assert_eq!("", &data[3..3]);
+    assert_eq!("华", &data[30..33]);
 
     fn a_million_letter_x() -> String {
         let mut i = 0;
@@ -328,23 +328,23 @@ fn half_a_million_letter_x() -> String {
     }
     let letters = a_million_letter_x();
     assert!(half_a_million_letter_x() ==
-        String::from_str(letters.slice(0, 3 * 500000)));
+        String::from_str(&letters[0..3 * 500000]));
 }
 
 #[test]
 fn test_slice_2() {
     let ss = "中华Việt Nam";
 
-    assert_eq!("华", ss.slice(3, 6));
-    assert_eq!("Việt Nam", ss.slice(6, 16));
+    assert_eq!("华", &ss[3..6]);
+    assert_eq!("Việt Nam", &ss[6..16]);
 
-    assert_eq!("ab", "abc".slice(0, 2));
-    assert_eq!("bc", "abc".slice(1, 3));
-    assert_eq!("", "abc".slice(1, 1));
+    assert_eq!("ab", &"abc"[0..2]);
+    assert_eq!("bc", &"abc"[1..3]);
+    assert_eq!("", &"abc"[1..1]);
 
-    assert_eq!("中", ss.slice(0, 3));
-    assert_eq!("华V", ss.slice(3, 7));
-    assert_eq!("", ss.slice(3, 3));
+    assert_eq!("中", &ss[0..3]);
+    assert_eq!("华V", &ss[3..7]);
+    assert_eq!("", &ss[3..3]);
     /*0: 中
       3: 华
       6: V
@@ -360,20 +360,20 @@ fn test_slice_2() {
 #[test]
 #[should_panic]
 fn test_slice_fail() {
-    "中华Việt Nam".slice(0, 2);
+    &"中华Việt Nam"[0..2];
 }
 
 #[test]
 fn test_slice_from() {
-    assert_eq!("abcd".slice_from(0), "abcd");
-    assert_eq!("abcd".slice_from(2), "cd");
-    assert_eq!("abcd".slice_from(4), "");
+    assert_eq!(&"abcd"[0..], "abcd");
+    assert_eq!(&"abcd"[2..], "cd");
+    assert_eq!(&"abcd"[4..], "");
 }
 #[test]
 fn test_slice_to() {
-    assert_eq!("abcd".slice_to(0), "");
-    assert_eq!("abcd".slice_to(2), "ab");
-    assert_eq!("abcd".slice_to(4), "abcd");
+    assert_eq!(&"abcd"[..0], "");
+    assert_eq!(&"abcd"[..2], "ab");
+    assert_eq!(&"abcd"[..4], "abcd");
 }
 
 #[test]
@@ -660,10 +660,10 @@ fn test_contains() {
 
 #[test]
 fn test_contains_char() {
-    assert!("abc".contains_char('b'));
-    assert!("a".contains_char('a'));
-    assert!(!"abc".contains_char('d'));
-    assert!(!"".contains_char('a'));
+    assert!("abc".contains('b'));
+    assert!("a".contains('a'));
+    assert!(!"abc".contains('d'));
+    assert!(!"".contains('a'));
 }
 
 #[test]
@@ -1445,9 +1445,9 @@ fn test_graphemes() {
 }
 
 #[test]
-fn test_split_strator() {
+fn test_splitator() {
     fn t(s: &str, sep: &str, u: &[&str]) {
-        let v: Vec<&str> = s.split_str(sep).collect();
+        let v: Vec<&str> = s.split(sep).collect();
         assert_eq!(v, u);
     }
     t("--1233345--", "12345", &["--1233345--"]);
@@ -1470,9 +1470,9 @@ fn t(s: &str, sep: &str, u: &[&str]) {
 fn test_str_default() {
     use std::default::Default;
 
-    fn t<S: Default + Str>() {
+    fn t<S: Default + AsRef<str>>() {
         let s: S = Default::default();
-        assert_eq!(s.as_slice(), "");
+        assert_eq!(s.as_ref(), "");
     }
 
     t::<&str>();
index 4768d5e92ac30057643b6b680edd322e05f6beff..5d6aa8ac0dcc37aa181ad829c2e0ee0e97d6e803 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::borrow::IntoCow;
+use std::borrow::{IntoCow, Cow};
 use std::iter::repeat;
 use std::str::Utf8Error;
-use std::string::{CowString, as_string};
+use std::string::as_string;
 
 use test::Bencher;
 
@@ -52,11 +52,11 @@ fn test_from_utf8() {
 #[test]
 fn test_from_utf8_lossy() {
     let xs = b"hello";
-    let ys: CowString = "hello".into_cow();
+    let ys: Cow<str> = "hello".into_cow();
     assert_eq!(String::from_utf8_lossy(xs), ys);
 
     let xs = "ศไทย中华Việt Nam".as_bytes();
-    let ys: CowString = "ศไทย中华Việt Nam".into_cow();
+    let ys: Cow<str> = "ศไทย中华Việt Nam".into_cow();
     assert_eq!(String::from_utf8_lossy(xs), ys);
 
     let xs = b"Hello\xC2 There\xFF Goodbye";
index fe752d5a7e1904d0741f50d3ad056e4f5ea21f08..12323286f6b4bae103ecaca8e012da9632d63916 100644 (file)
@@ -18,7 +18,6 @@
 use self::Taggypar::*;
 
 #[test]
-#[allow(deprecated)]
 fn test_simple() {
     let mut d = VecDeque::new();
     assert_eq!(d.len(), 0);
@@ -545,7 +544,7 @@ fn test_from_iter() {
     let u: Vec<_> = deq.iter().cloned().collect();
     assert_eq!(u, v);
 
-    let seq = iter::count(0, 2).take(256);
+    let seq = (0..).step_by(2).take(256);
     let deq: VecDeque<_> = seq.collect();
     for (i, &x) in deq.iter().enumerate() {
         assert_eq!(2*i, x);
@@ -821,7 +820,7 @@ fn test_as_slices() {
 
         let (left, right) = ring.as_slices();
         let expected: Vec<_> = (0..i+1).collect();
-        assert_eq!(left, expected);
+        assert_eq!(left, &expected[..]);
         assert_eq!(right, []);
     }
 
@@ -830,8 +829,8 @@ fn test_as_slices() {
         let (left, right) = ring.as_slices();
         let expected_left: Vec<_> = (-last..j+1).rev().collect();
         let expected_right: Vec<_> = (0..first).collect();
-        assert_eq!(left, expected_left);
-        assert_eq!(right, expected_right);
+        assert_eq!(left, &expected_left[..]);
+        assert_eq!(right, &expected_right[..]);
     }
 
     assert_eq!(ring.len() as i32, cap);
@@ -849,7 +848,7 @@ fn test_as_mut_slices() {
 
         let (left, right) = ring.as_mut_slices();
         let expected: Vec<_> = (0..i+1).collect();
-        assert_eq!(left, expected);
+        assert_eq!(left, &expected[..]);
         assert_eq!(right, []);
     }
 
@@ -858,8 +857,8 @@ fn test_as_mut_slices() {
         let (left, right) = ring.as_mut_slices();
         let expected_left: Vec<_> = (-last..j+1).rev().collect();
         let expected_right: Vec<_> = (0..first).collect();
-        assert_eq!(left, expected_left);
-        assert_eq!(right, expected_right);
+        assert_eq!(left, &expected_left[..]);
+        assert_eq!(right, &expected_right[..]);
     }
 
     assert_eq!(ring.len() as i32, cap);
index d3bc07b173ac8e963f5541204ab68e3fded38731..320fdd50b3510bd41df790ca167bb72857839f85 100644 (file)
@@ -71,6 +71,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use fmt;
 use marker::Send;
 use mem::transmute;
 use option::Option::{self, Some, None};
@@ -105,6 +106,13 @@ fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
 // Extension methods for Any trait objects.
 ///////////////////////////////////////////////////////////////////////////////
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Debug for Any {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Any")
+    }
+}
+
 impl Any {
     /// Returns true if the boxed type is the same as `T`
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -202,8 +210,7 @@ pub struct TypeId {
 impl TypeId {
     /// Returns the `TypeId` of the type this generic function has been
     /// instantiated with
-    #[unstable(feature = "core",
-               reason = "may grow a `Reflect` bound soon via marker traits")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn of<T: ?Sized + Any>() -> TypeId {
         TypeId {
             t: unsafe { intrinsics::type_id::<T>() },
index 91b4b46ac3979ec954968f7cda23b6475bb36d11..8c396a4e7fbcb1768e74efb576fbb4d33b163040 100644 (file)
@@ -1062,144 +1062,3 @@ pub fn fence(order: Ordering) {
         }
     }
 }
-
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "renamed to AtomicIsize")]
-#[allow(missing_docs)]
-pub struct AtomicInt {
-    v: UnsafeCell<isize>,
-}
-
-#[allow(deprecated)]
-unsafe impl Sync for AtomicInt {}
-
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "renamed to AtomicUsize")]
-#[allow(missing_docs)]
-pub struct AtomicUint {
-    v: UnsafeCell<usize>,
-}
-
-#[allow(deprecated)]
-unsafe impl Sync for AtomicUint {}
-
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "use ATOMIC_ISIZE_INIT instead")]
-#[allow(missing_docs, deprecated)]
-pub const ATOMIC_INT_INIT: AtomicInt =
-        AtomicInt { v: UnsafeCell { value: 0 } };
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "use ATOMIC_USIZE_INIT instead")]
-#[allow(missing_docs, deprecated)]
-pub const ATOMIC_UINT_INIT: AtomicUint =
-        AtomicUint { v: UnsafeCell { value: 0, } };
-
-#[allow(missing_docs, deprecated)]
-impl AtomicInt {
-    #[inline]
-    pub fn new(v: isize) -> AtomicInt {
-        AtomicInt {v: UnsafeCell::new(v)}
-    }
-
-    #[inline]
-    pub fn load(&self, order: Ordering) -> isize {
-        unsafe { atomic_load(self.v.get(), order) }
-    }
-
-    #[inline]
-    pub fn store(&self, val: isize, order: Ordering) {
-        unsafe { atomic_store(self.v.get(), val, order); }
-    }
-
-    #[inline]
-    pub fn swap(&self, val: isize, order: Ordering) -> isize {
-        unsafe { atomic_swap(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize {
-        unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
-    }
-
-    #[inline]
-    pub fn fetch_add(&self, val: isize, order: Ordering) -> isize {
-        unsafe { atomic_add(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize {
-        unsafe { atomic_sub(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_and(&self, val: isize, order: Ordering) -> isize {
-        unsafe { atomic_and(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_or(&self, val: isize, order: Ordering) -> isize {
-        unsafe { atomic_or(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize {
-        unsafe { atomic_xor(self.v.get(), val, order) }
-    }
-}
-
-#[allow(missing_docs, deprecated)]
-impl AtomicUint {
-    #[inline]
-    pub fn new(v: usize) -> AtomicUint {
-        AtomicUint { v: UnsafeCell::new(v) }
-    }
-
-    #[inline]
-    pub fn load(&self, order: Ordering) -> usize {
-        unsafe { atomic_load(self.v.get(), order) }
-    }
-
-    #[inline]
-    pub fn store(&self, val: usize, order: Ordering) {
-        unsafe { atomic_store(self.v.get(), val, order); }
-    }
-
-    #[inline]
-    pub fn swap(&self, val: usize, order: Ordering) -> usize {
-        unsafe { atomic_swap(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize {
-        unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
-    }
-
-    #[inline]
-    pub fn fetch_add(&self, val: usize, order: Ordering) -> usize {
-        unsafe { atomic_add(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize {
-        unsafe { atomic_sub(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_and(&self, val: usize, order: Ordering) -> usize {
-        unsafe { atomic_and(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_or(&self, val: usize, order: Ordering) -> usize {
-        unsafe { atomic_or(self.v.get(), val, order) }
-    }
-
-    #[inline]
-    pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize {
-        unsafe { atomic_xor(self.v.get(), val, order) }
-    }
-}
index 9e6dbce0325935da3737fe1c10cbf511c7afaa68..906c87f3ffda63132a2a7cce73e71447bf26016e 100644 (file)
@@ -343,23 +343,6 @@ pub fn borrow_state(&self) -> BorrowState {
         }
     }
 
-    /// Attempts to immutably borrow the wrapped value.
-    ///
-    /// The borrow lasts until the returned `Ref` exits scope. Multiple
-    /// immutable borrows can be taken out at the same time.
-    ///
-    /// Returns `None` if the value is currently mutably borrowed.
-    #[unstable(feature = "core", reason = "may be renamed or removed")]
-    #[deprecated(since = "1.0.0",
-                 reason = "dispatch on `cell.borrow_state()` instead")]
-    #[inline]
-    pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
-        match BorrowRef::new(&self.borrow) {
-            Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
-            None => None,
-        }
-    }
-
     /// Immutably borrows the wrapped value.
     ///
     /// The borrow lasts until the returned `Ref` exits scope. Multiple
@@ -407,23 +390,6 @@ pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
         }
     }
 
-    /// Mutably borrows the wrapped value.
-    ///
-    /// The borrow lasts until the returned `RefMut` exits scope. The value
-    /// cannot be borrowed while this borrow is active.
-    ///
-    /// Returns `None` if the value is currently borrowed.
-    #[unstable(feature = "core", reason = "may be renamed or removed")]
-    #[deprecated(since = "1.0.0",
-                 reason = "dispatch on `cell.borrow_state()` instead")]
-    #[inline]
-    pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
-        match BorrowRefMut::new(&self.borrow) {
-            Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
-            None => None,
-        }
-    }
-
     /// Mutably borrows the wrapped value.
     ///
     /// The borrow lasts until the returned `RefMut` exits scope. The value
index 9b8b59ec8ce6e0ffe3758e99ee3150fcf2fb9839..efe1179621de5efde5843896c2aabea9faba2e99 100644 (file)
@@ -64,7 +64,6 @@
 /// inverse of `ne`; that is, `!(a == b)` if and only if `a != b`.
 #[lang="eq"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[old_orphan_check]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used by `==`.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -360,6 +359,8 @@ fn ge(&self, other: &Rhs) -> bool {
 
 /// Compare and return the minimum of two values.
 ///
+/// Returns the first argument if the comparison determines them to be equal.
+///
 /// # Examples
 ///
 /// ```
@@ -371,11 +372,13 @@ fn ge(&self, other: &Rhs) -> bool {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn min<T: Ord>(v1: T, v2: T) -> T {
-    if v1 < v2 { v1 } else { v2 }
+    if v1 <= v2 { v1 } else { v2 }
 }
 
 /// Compare and return the maximum of two values.
 ///
+/// Returns the second argument if the comparison determines them to be equal.
+///
 /// # Examples
 ///
 /// ```
@@ -387,7 +390,7 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn max<T: Ord>(v1: T, v2: T) -> T {
-    if v1 > v2 { v1 } else { v2 }
+    if v2 >= v1 { v2 } else { v1 }
 }
 
 /// Compare and return the minimum of two values if there is one.
@@ -425,7 +428,7 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
 
 /// Compare and return the maximum of two values if there is one.
 ///
-/// Returns the first argument if the comparison determines them to be equal.
+/// Returns the second argument if the comparison determines them to be equal.
 ///
 /// # Examples
 ///
@@ -450,8 +453,8 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
 #[unstable(feature = "core")]
 pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
     match v1.partial_cmp(&v2) {
-        Some(Less) => Some(v2),
-        Some(Equal) | Some(Greater) => Some(v1),
+        Some(Equal) | Some(Less) => Some(v2),
+        Some(Greater) => Some(v1),
         None => None
     }
 }
index 18357bac9e6f685bf7739ce91e4c223917ba1500..95dab3d165ad3f99cfa4db8034afa5cc492b0d7d 100644 (file)
 #[macro_export]
 macro_rules! __impl_slice_eq1 {
     ($Lhs: ty, $Rhs: ty) => {
+        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
+    };
+    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, 'b, A, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
+        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
             #[inline]
             fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
             #[inline]
@@ -31,13 +34,7 @@ macro_rules! __impl_slice_eq2 {
         __impl_slice_eq2! { $Lhs, $Rhs, Sized }
     };
     ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
-        #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
-            #[inline]
-            fn eq(&self, other: &$Rhs) -> bool { &self[..] == &other[..] }
-            #[inline]
-            fn ne(&self, other: &$Rhs) -> bool { &self[..] != &other[..] }
-        }
+        __impl_slice_eq1!($Lhs, $Rhs, $Bound);
 
         #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
index 21f9b1f5513aaaf7f7c8d5184616c3f3552371b8..4a99f1a756a7c3e8ac31317a0a2eee8374fc06d3 100644 (file)
 //! 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")]
+#![stable(feature = "rust1", since = "1.0.0")]
 
 use marker::Sized;
 
 /// A cheap, reference-to-reference conversion.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsRef<T: ?Sized> {
     /// Perform the conversion.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_ref(&self) -> &T;
 }
 
 /// A cheap, mutable reference-to-mutable reference conversion.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsMut<T: ?Sized> {
     /// Perform the conversion.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn as_mut(&mut self) -> &mut T;
 }
 
 /// A conversion that consumes `self`, which may or may not be
 /// expensive.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Into<T>: Sized {
     /// Perform the conversion.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn into(self) -> T;
 }
 
 /// Construct `Self` via a conversion.
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait From<T> {
     /// Perform the conversion.
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn from(T) -> Self;
 }
 
@@ -48,14 +55,8 @@ pub trait From<T> {
 // 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 &
+#[stable(feature = "rust1", since = "1.0.0")]
 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)
@@ -63,6 +64,7 @@ fn as_ref(&self) -> &U {
 }
 
 // As lifts over &mut
+#[stable(feature = "rust1", since = "1.0.0")]
 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)
@@ -77,14 +79,8 @@ fn as_ref(&self) -> &U {
 //     }
 // }
 
-// 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
+#[stable(feature = "rust1", since = "1.0.0")]
 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()
@@ -100,28 +96,38 @@ fn as_mut(&mut self) -> &mut U {
 // }
 
 // From implies Into
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T, U> Into<U> for T where U: From<T> {
     fn into(self) -> U {
         U::from(self)
     }
 }
 
+// From (and thus Into) is reflexive
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> From<T> for T {
+    fn from(t: T) -> T { t }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // CONCRETE IMPLS
 ////////////////////////////////////////////////////////////////////////////////
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsRef<[T]> for [T] {
     fn as_ref(&self) -> &[T] {
         self
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsMut<[T]> for [T] {
     fn as_mut(&mut self) -> &mut [T] {
         self
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<str> for str {
     fn as_ref(&self) -> &str {
         self
index 9430aa0066871326399b577f02d72884cf3eae68..24035b7d9a83bdc8ff23a6c687ee58de29461a90 100644 (file)
 //! high-level module to provide its own errors that do not commit to any
 //! particular implementation, but also reveal some of its implementation for
 //! debugging via `cause` chains.
-//!
-//! # The `FromError` trait
-//!
-//! `FromError` is a simple trait that expresses conversions between different
-//! error types. To provide maximum flexibility, it does not require either of
-//! the types to actually implement the `Error` trait, although this will be the
-//! common case.
-//!
-//! The main use of this trait is in the `try!` macro, which uses it to
-//! automatically convert a given error to the error specified in a function's
-//! return type.
-//!
-//! For example,
-//!
-//! ```
-//! #![feature(core)]
-//! use std::error::FromError;
-//! use std::{io, str};
-//! use std::fs::File;
-//!
-//! enum MyError {
-//!     Io(io::Error),
-//!     Utf8(str::Utf8Error),
-//! }
-//!
-//! impl FromError<io::Error> for MyError {
-//!     fn from_error(err: io::Error) -> MyError { MyError::Io(err) }
-//! }
-//!
-//! impl FromError<str::Utf8Error> for MyError {
-//!     fn from_error(err: str::Utf8Error) -> MyError { MyError::Utf8(err) }
-//! }
-//!
-//! #[allow(unused_variables)]
-//! fn open_and_map() -> Result<(), MyError> {
-//!     let b = b"foo.txt";
-//!     let s = try!(str::from_utf8(b));
-//!     let f = try!(File::open(s));
-//!
-//!     // do something interesting here...
-//!     Ok(())
-//! }
-//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -97,19 +54,3 @@ pub trait Error: Debug + Display {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn cause(&self) -> Option<&Error> { None }
 }
-
-/// A trait for types that can be converted from a given error type `E`.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait FromError<E> {
-    /// Perform the conversion.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn from_error(err: E) -> Self;
-}
-
-// Any type is convertable from itself
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<E> FromError<E> for E {
-    fn from_error(err: E) -> E {
-        err
-    }
-}
diff --git a/src/libcore/finally.rs b/src/libcore/finally.rs
deleted file mode 100644 (file)
index 93a7d2b..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! The Finally trait provides a method, `finally` on
-//! stack closures that emulates Java-style try/finally blocks.
-//!
-//! Using the `finally` method is sometimes convenient, but the type rules
-//! prohibit any shared, mutable state between the "try" case and the
-//! "finally" case. For advanced cases, the `try_finally` function can
-//! also be used. See that function for more details.
-//!
-//! # Examples
-//!
-//! ```
-//! # #![feature(core)]
-//! # #![feature(unboxed_closures)]
-//!
-//! use std::finally::Finally;
-//!
-//! (|| {
-//!     // ...
-//! }).finally(|| {
-//!     // this code is always run
-//! })
-//! ```
-
-#![unstable(feature = "core")]
-#![deprecated(since = "1.0.0",
-              reason = "It is unclear if this module is more robust than implementing \
-                        Drop on a custom type, and this module is being removed with no \
-                        replacement. Use a custom Drop implementation to regain existing \
-                        functionality.")]
-#![allow(deprecated)]
-
-use ops::{Drop, FnMut, FnOnce};
-
-/// A trait for executing a destructor unconditionally after a block of code,
-/// regardless of whether the blocked fails.
-pub trait Finally<T> {
-    /// Executes this object, unconditionally running `dtor` after this block of
-    /// code has run.
-    fn finally<F>(&mut self, dtor: F) -> T where F: FnMut();
-}
-
-impl<T, F> Finally<T> for F where F: FnMut() -> T {
-    fn finally<G>(&mut self, mut dtor: G) -> T where G: FnMut() {
-        try_finally(&mut (), self, |_, f| (*f)(), |_| dtor())
-    }
-}
-
-/// The most general form of the `finally` functions. The function
-/// `try_fn` will be invoked first; whether or not it panics, the
-/// function `finally_fn` will be invoked next. The two parameters
-/// `mutate` and `drop` are used to thread state through the two
-/// closures. `mutate` is used for any shared, mutable state that both
-/// closures require access to; `drop` is used for any state that the
-/// `try_fn` requires ownership of.
-///
-/// **WARNING:** While shared, mutable state between the try and finally
-/// function is often necessary, one must be very careful; the `try`
-/// function could have panicked at any point, so the values of the shared
-/// state may be inconsistent.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(core)]
-/// use std::finally::try_finally;
-///
-/// struct State<'a> { buffer: &'a mut [u8], len: usize }
-/// # let mut buf = [];
-/// let mut state = State { buffer: &mut buf, len: 0 };
-/// try_finally(
-///     &mut state, (),
-///     |state, ()| {
-///         // use state.buffer, state.len
-///     },
-///     |state| {
-///         // use state.buffer, state.len to cleanup
-///     })
-/// ```
-pub fn try_finally<T, U, R, F, G>(mutate: &mut T, drop: U, try_fn: F, finally_fn: G) -> R where
-    F: FnOnce(&mut T, U) -> R,
-    G: FnMut(&mut T),
-{
-    let f = Finallyalizer {
-        mutate: mutate,
-        dtor: finally_fn,
-    };
-    try_fn(&mut *f.mutate, drop)
-}
-
-struct Finallyalizer<'a, A:'a, F> where F: FnMut(&mut A) {
-    mutate: &'a mut A,
-    dtor: F,
-}
-
-#[unsafe_destructor]
-impl<'a, A, F> Drop for Finallyalizer<'a, A, F> where F: FnMut(&mut A) {
-    #[inline]
-    fn drop(&mut self) {
-        (self.dtor)(self.mutate);
-    }
-}
index ffb358cdac84d90854623e1dc969473269edeb09..3f8bbeb1feb88eb35126a9f16b3efd061141d240 100644 (file)
@@ -12,7 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use any;
 use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
 use char::CharExt;
 use iter::Iterator;
@@ -997,11 +996,6 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 
 tuple! { T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Debug for &'a (any::Any+'a) {
-    fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for [T] {
     fn fmt(&self, f: &mut Formatter) -> Result {
index e65fbac926bd91e854a12023b093f90412215896..6820a7025fca6f171cda155752bf60d6e258bf2d 100644 (file)
@@ -114,11 +114,6 @@ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
         state
     }
 
-    /// Returns the computed hash.
-    #[unstable(feature = "hash")]
-    #[deprecated(since = "1.0.0", reason = "renamed to finish")]
-    pub fn result(&self) -> u64 { self.finish() }
-
     fn reset(&mut self) {
         self.length = 0;
         self.v0 = self.k0 ^ 0x736f6d6570736575;
index 43cf64bf3ad9dfbe2af6ec10269dd70c06aa7d94..0e91eafce187f7b0ed2dd8160c7c4fe365669043 100644 (file)
     /// Rust moves to non-zeroing dynamic drop (and thus removes the
     /// embedded drop flags that are being established by this
     /// intrinsic).
-    #[cfg(not(stage0))]
     pub fn init_dropped<T>() -> T;
 
     /// Create a value initialized to zero.
index 44d48f9f4bf9d18d3ff023c3f9840b5a98dc99e5..42e90ec34db7ce97853ff8a734997604d7f439f4 100644 (file)
 //!
 //! # The `Iterator` trait
 //!
-//! This module defines Rust's core iteration trait. The `Iterator` trait has one
-//! unimplemented method, `next`. All other methods are derived through default
-//! methods to perform operations such as `zip`, `chain`, `enumerate`, and `fold`.
+//! This module defines Rust's core iteration trait. The `Iterator` trait has
+//! one unimplemented method, `next`. All other methods are derived through
+//! default methods to perform operations such as `zip`, `chain`, `enumerate`,
+//! and `fold`.
 //!
 //! The goal of this module is to unify iteration across all containers in Rust.
-//! An iterator can be considered as a state machine which is used to track which
-//! element will be yielded next.
+//! An iterator can be considered as a state machine which is used to track
+//! which element will be yielded next.
 //!
-//! There are various extensions also defined in this module to assist with various
-//! types of iteration, such as the `DoubleEndedIterator` for iterating in reverse,
-//! the `FromIterator` trait for creating a container from an iterator, and much
-//! more.
+//! There are various extensions also defined in this module to assist with
+//! various types of iteration, such as the `DoubleEndedIterator` for iterating
+//! in reverse, the `FromIterator` trait for creating a container from an
+//! iterator, and much more.
 //!
-//! ## Rust's `for` loop
+//! # Rust's `for` loop
 //!
-//! The special syntax used by rust's `for` loop is based around the `Iterator`
-//! trait defined in this module. For loops can be viewed as a syntactical expansion
-//! into a `loop`, for example, the `for` loop in this example is essentially
-//! translated to the `loop` below.
+//! The special syntax used by rust's `for` loop is based around the
+//! `IntoIterator` trait defined in this module. `for` loops can be viewed as a
+//! syntactical expansion into a `loop`, for example, the `for` loop in this
+//! example is essentially translated to the `loop` below.
 //!
 //! ```
 //! let values = vec![1, 2, 3];
 //!
-//! // "Syntactical sugar" taking advantage of an iterator
-//! for &x in values.iter() {
+//! for x in values {
 //!     println!("{}", x);
 //! }
 //!
 //! // Rough translation of the iteration without a `for` iterator.
-//! let mut it = values.iter();
+//! # let values = vec![1, 2, 3];
+//! let mut it = values.into_iter();
 //! loop {
 //!     match it.next() {
-//!         Some(&x) => {
-//!             println!("{}", x);
-//!         }
-//!         None => { break }
+//!         Some(x) => println!("{}", x),
+//!         None => break,
 //!     }
 //! }
 //! ```
 //!
-//! This `for` loop syntax can be applied to any iterator over any type.
+//! Because `Iterator`s implement `IntoIterator`, this `for` loop syntax can be applied to any
+//! iterator over any type.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use default::Default;
 use marker;
 use mem;
-use num::{Int, Zero, One, ToPrimitive};
-use ops::{Add, Sub, FnMut, RangeFrom};
-use option::Option;
-use option::Option::{Some, None};
+use num::{Int, Zero, One};
+use ops::{self, Add, Sub, FnMut, RangeFrom};
+use option::Option::{self, Some, None};
 use marker::Sized;
 use usize;
 
@@ -85,21 +84,22 @@ fn _assert_is_object_safe(_: &Iterator) {}
 /// else.
 #[lang="iterator"]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
-                            method"]
+#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling \
+                            `.iter()` or a similar method"]
 pub trait Iterator {
     /// The type of the elements being iterated
     #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
-    /// Advance the iterator and return the next value. Return `None` when the end is reached.
+    /// Advance the iterator and return the next value. Return `None` when the
+    /// end is reached.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn next(&mut self) -> Option<Self::Item>;
 
     /// Returns a lower and upper bound on the remaining length of the iterator.
     ///
-    /// An upper bound of `None` means either there is no known upper bound, or the upper bound
-    /// does not fit within a `usize`.
+    /// An upper bound of `None` means either there is no known upper bound, or
+    /// the upper bound does not fit within a `usize`.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn size_hint(&self) -> (usize, Option<usize>) { (0, None) }
@@ -275,7 +275,8 @@ fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> where
     /// iterator plus the current index of iteration.
     ///
     /// `enumerate` keeps its count as a `usize`. If you want to count by a
-    /// different sized integer, the `zip` function provides similar functionality.
+    /// different sized integer, the `zip` function provides similar
+    /// functionality.
     ///
     /// # Examples
     ///
@@ -433,7 +434,7 @@ fn scan<St, B, F>(self, initial_state: St, f: F) -> Scan<Self, St, F>
     /// # #![feature(core)]
     /// let xs = [2, 3];
     /// let ys = [0, 1, 0, 1, 2];
-    /// let it = xs.iter().flat_map(|&x| std::iter::count(0, 1).take(x));
+    /// let it = xs.iter().flat_map(|&x| (0..).take(x));
     /// // Check that `it` has the same elements as `ys`
     /// for (i, x) in it.enumerate() {
     ///     assert_eq!(x, ys[i]);
@@ -530,10 +531,9 @@ fn by_ref(&mut self) -> &mut Self where Self: Sized { self }
     /// # Examples
     ///
     /// ```
-    /// # #![feature(core)]
-    /// let a = [1, 2, 3, 4, 5];
-    /// let b: Vec<_> = a.iter().cloned().collect();
-    /// assert_eq!(a, b);
+    /// let expected = [1, 2, 3, 4, 5];
+    /// let actual: Vec<_> = expected.iter().cloned().collect();
+    /// assert_eq!(actual, expected);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -553,8 +553,7 @@ fn collect<B: FromIterator<Self::Item>>(self) -> B where Self: Sized {
     /// assert_eq!(even, [2, 4]);
     /// assert_eq!(odd, [1, 3]);
     /// ```
-    #[unstable(feature = "core",
-               reason = "recently added as part of collections reform")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn partition<B, F>(self, mut f: F) -> (B, B) where
         Self: Sized,
         B: Default + Extend<Self::Item>,
@@ -613,7 +612,8 @@ fn all<F>(&mut self, mut f: F) -> bool where
         true
     }
 
-    /// Tests whether any element of an iterator satisfies the specified predicate.
+    /// Tests whether any element of an iterator satisfies the specified
+    /// predicate.
     ///
     /// Does not consume the iterator past the first found element.
     ///
@@ -624,7 +624,7 @@ fn all<F>(&mut self, mut f: F) -> bool where
     /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
     /// assert!(it.any(|x| *x == 3));
-    /// assert_eq!(it.as_slice(), [4, 5]);
+    /// assert_eq!(&it[..], [4, 5]);
     ///
     /// ```
     #[inline]
@@ -648,7 +648,7 @@ fn any<F>(&mut self, mut f: F) -> bool where
     /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
     /// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3);
-    /// assert_eq!(it.as_slice(), [4, 5]);
+    /// assert_eq!(&it[..], [4, 5]);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
@@ -672,7 +672,7 @@ fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
     /// let a = [1, 2, 3, 4, 5];
     /// let mut it = a.iter();
     /// assert_eq!(it.position(|x| *x == 3).unwrap(), 2);
-    /// assert_eq!(it.as_slice(), [4, 5]);
+    /// assert_eq!(&it[..], [4, 5]);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
@@ -702,7 +702,7 @@ fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
     /// let a = [1, 2, 2, 4, 5];
     /// let mut it = a.iter();
     /// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2);
-    /// assert_eq!(it.as_slice(), [1, 2]);
+    /// assert_eq!(&it[..], [1, 2]);
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
@@ -722,6 +722,9 @@ fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
 
     /// Consumes the entire iterator to return the maximum element.
     ///
+    /// Returns the rightmost element if the comparison determines two elements
+    /// to be equally maximum.
+    ///
     /// # Examples
     ///
     /// ```
@@ -732,16 +735,19 @@ fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
     #[stable(feature = "rust1", since = "1.0.0")]
     fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
     {
-        self.fold(None, |max, x| {
+        self.fold(None, |max, y| {
             match max {
-                None    => Some(x),
-                Some(y) => Some(cmp::max(x, y))
+                None    => Some(y),
+                Some(x) => Some(cmp::max(x, y))
             }
         })
     }
 
     /// Consumes the entire iterator to return the minimum element.
     ///
+    /// Returns the leftmost element if the comparison determines two elements
+    /// to be equally minimum.
+    ///
     /// # Examples
     ///
     /// ```
@@ -752,10 +758,10 @@ fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
     #[stable(feature = "rust1", since = "1.0.0")]
     fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
     {
-        self.fold(None, |min, x| {
+        self.fold(None, |min, y| {
             match min {
-                None    => Some(x),
-                Some(y) => Some(cmp::min(x, y))
+                None    => Some(y),
+                Some(x) => Some(cmp::min(x, y))
             }
         })
     }
@@ -771,7 +777,8 @@ fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
     ///    element in the iterator and all elements are equal.
     ///
     /// On an iterator of length `n`, `min_max` does `1.5 * n` comparisons,
-    /// and so is faster than calling `min` and `max` separately which does `2 * n` comparisons.
+    /// and so is faster than calling `min` and `max` separately which does `2 *
+    /// n` comparisons.
     ///
     /// # Examples
     ///
@@ -799,16 +806,17 @@ fn min_max(mut self) -> MinMaxResult<Self::Item> where Self: Sized, Self::Item:
             Some(x) => {
                 match self.next() {
                     None => return OneElement(x),
-                    Some(y) => if x < y {(x, y)} else {(y,x)}
+                    Some(y) => if x <= y {(x, y)} else {(y, x)}
                 }
             }
         };
 
         loop {
-            // `first` and `second` are the two next elements we want to look at.
-            // We first compare `first` and `second` (#1). The smaller one is then compared to
-            // current minimum (#2). The larger one is compared to current maximum (#3). This
-            // way we do 3 comparisons for 2 elements.
+            // `first` and `second` are the two next elements we want to look
+            // at.  We first compare `first` and `second` (#1). The smaller one
+            // is then compared to current minimum (#2). The larger one is
+            // compared to current maximum (#3). This way we do 3 comparisons
+            // for 2 elements.
             let first = match self.next() {
                 None => break,
                 Some(x) => x
@@ -817,19 +825,19 @@ fn min_max(mut self) -> MinMaxResult<Self::Item> where Self: Sized, Self::Item:
                 None => {
                     if first < min {
                         min = first;
-                    } else if first > max {
+                    } else if first >= max {
                         max = first;
                     }
                     break;
                 }
                 Some(x) => x
             };
-            if first < second {
-                if first < min {min = first;}
-                if max < second {max = second;}
+            if first <= second {
+                if first < min { min = first }
+                if second >= max { max = second }
             } else {
-                if second < min {min = second;}
-                if max < first {max = first;}
+                if second < min { min = second }
+                if first >= max { max = first }
             }
         }
 
@@ -839,6 +847,9 @@ fn min_max(mut self) -> MinMaxResult<Self::Item> where Self: Sized, Self::Item:
     /// Return the element that gives the maximum value from the
     /// specified function.
     ///
+    /// Returns the rightmost element if the comparison determines two elements
+    /// to be equally maximum.
+    ///
     /// # Examples
     ///
     /// ```
@@ -854,14 +865,14 @@ fn max_by<B: Ord, F>(self, mut f: F) -> Option<Self::Item> where
         Self: Sized,
         F: FnMut(&Self::Item) -> B,
     {
-        self.fold(None, |max: Option<(Self::Item, B)>, x| {
-            let x_val = f(&x);
+        self.fold(None, |max: Option<(Self::Item, B)>, y| {
+            let y_val = f(&y);
             match max {
-                None             => Some((x, x_val)),
-                Some((y, y_val)) => if x_val > y_val {
-                    Some((x, x_val))
-                } else {
+                None             => Some((y, y_val)),
+                Some((x, x_val)) => if y_val >= x_val {
                     Some((y, y_val))
+                } else {
+                    Some((x, x_val))
                 }
             }
         }).map(|(x, _)| x)
@@ -870,6 +881,9 @@ fn max_by<B: Ord, F>(self, mut f: F) -> Option<Self::Item> where
     /// Return the element that gives the minimum value from the
     /// specified function.
     ///
+    /// Returns the leftmost element if the comparison determines two elements
+    /// to be equally minimum.
+    ///
     /// # Examples
     ///
     /// ```
@@ -885,11 +899,11 @@ fn min_by<B: Ord, F>(self, mut f: F) -> Option<Self::Item> where
         Self: Sized,
         F: FnMut(&Self::Item) -> B,
     {
-        self.fold(None, |min: Option<(Self::Item, B)>, x| {
-            let x_val = f(&x);
+        self.fold(None, |min: Option<(Self::Item, B)>, y| {
+            let y_val = f(&y);
             match min {
-                None             => Some((x, x_val)),
-                Some((y, y_val)) => if x_val < y_val {
+                None             => Some((y, y_val)),
+                Some((x, x_val)) => if x_val <= y_val {
                     Some((x, x_val))
                 } else {
                     Some((y, y_val))
@@ -927,10 +941,10 @@ fn rev(self) -> Rev<Self> where Self: Sized {
     /// # #![feature(core)]
     /// let a = [(1, 2), (3, 4)];
     /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
-    /// assert_eq!([1, 3], left);
-    /// assert_eq!([2, 4], right);
+    /// assert_eq!(left, [1, 3]);
+    /// assert_eq!(right, [2, 4]);
     /// ```
-    #[unstable(feature = "core", reason = "recent addition")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn unzip<A, B, FromA, FromB>(self) -> (FromA, FromB) where
         FromA: Default + Extend<A>,
         FromB: Default + Extend<B>,
@@ -1027,7 +1041,8 @@ pub trait FromIterator<A> {
     /// assert_eq!(colors_set.len(), 3);
     /// ```
     ///
-    /// `FromIterator` is more commonly used implicitly via the `Iterator::collect` method:
+    /// `FromIterator` is more commonly used implicitly via the
+    /// `Iterator::collect` method:
     ///
     /// ```
     /// use std::collections::HashSet;
@@ -1041,6 +1056,9 @@ pub trait FromIterator<A> {
 }
 
 /// Conversion into an `Iterator`
+///
+/// Implementing this trait allows you to use your type with Rust's `for` loop. See
+/// the [module level documentation](../index.html) for more details.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
     /// The type of the elements being iterated
@@ -1094,12 +1112,13 @@ fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
 
 /// An object implementing random access indexing by `usize`
 ///
-/// A `RandomAccessIterator` should be either infinite or a `DoubleEndedIterator`.
-/// Calling `next()` or `next_back()` on a `RandomAccessIterator`
-/// reduces the indexable range accordingly. That is, `it.idx(1)` will become `it.idx(0)`
-/// after `it.next()` is called.
+/// A `RandomAccessIterator` should be either infinite or a
+/// `DoubleEndedIterator`.  Calling `next()` or `next_back()` on a
+/// `RandomAccessIterator` reduces the indexable range accordingly. That is,
+/// `it.idx(1)` will become `it.idx(0)` after `it.next()` is called.
 #[unstable(feature = "core",
-           reason = "not widely used, may be better decomposed into Index and ExactSizeIterator")]
+           reason = "not widely used, may be better decomposed into Index \
+                     and ExactSizeIterator")]
 pub trait RandomAccessIterator: Iterator {
     /// Return the number of indexable elements. At most `std::usize::MAX`
     /// elements are indexable, even if the iterator represents a longer range.
@@ -1144,13 +1163,15 @@ impl<I: ExactSizeIterator, F> ExactSizeIterator for Inspect<I, F> where
     F: FnMut(&I::Item),
 {}
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<I> ExactSizeIterator for Rev<I> where I: ExactSizeIterator + DoubleEndedIterator {}
+impl<I> ExactSizeIterator for Rev<I>
+    where I: ExactSizeIterator + DoubleEndedIterator {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> where
     F: FnMut(I::Item) -> B,
 {}
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A, B> ExactSizeIterator for Zip<A, B> where A: ExactSizeIterator, B: ExactSizeIterator {}
+impl<A, B> ExactSizeIterator for Zip<A, B>
+    where A: ExactSizeIterator, B: ExactSizeIterator {}
 
 /// An double-ended iterator with the direction inverted
 #[derive(Clone)]
@@ -1177,7 +1198,9 @@ fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() }
 }
 
 #[unstable(feature = "core", reason = "trait is experimental")]
-impl<I> RandomAccessIterator for Rev<I> where I: DoubleEndedIterator + RandomAccessIterator {
+impl<I> RandomAccessIterator for Rev<I>
+    where I: DoubleEndedIterator + RandomAccessIterator
+{
     #[inline]
     fn indexable(&self) -> usize { self.iter.indexable() }
     #[inline]
@@ -1244,10 +1267,10 @@ pub trait MultiplicativeIterator<A> {
     ///
     /// ```
     /// # #![feature(core)]
-    /// use std::iter::{count, MultiplicativeIterator};
+    /// use std::iter::MultiplicativeIterator;
     ///
     /// fn factorial(n: usize) -> usize {
-    ///     count(1, 1).take_while(|&i| i <= n).product()
+    ///     (1..).take_while(|&i| i <= n).product()
     /// }
     /// assert!(factorial(0) == 1);
     /// assert!(factorial(1) == 1);
@@ -1280,7 +1303,8 @@ fn product(self) -> $A {
 impl_multiplicative! { f32,  1.0 }
 impl_multiplicative! { f64,  1.0 }
 
-/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for more detail.
+/// `MinMaxResult` is an enum returned by `min_max`. See `Iterator::min_max` for
+/// more detail.
 #[derive(Clone, PartialEq, Debug)]
 #[unstable(feature = "core",
            reason = "unclear whether such a fine-grained result is widely useful")]
@@ -1291,15 +1315,17 @@ pub enum MinMaxResult<T> {
     /// Iterator with one element, so the minimum and maximum are the same
     OneElement(T),
 
-    /// More than one element in the iterator, the first element is not larger than the second
+    /// More than one element in the iterator, the first element is not larger
+    /// than the second
     MinMax(T, T)
 }
 
 impl<T: Clone> MinMaxResult<T> {
-    /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option` has variant
-    /// `None` if and only if the `MinMaxResult` has variant `NoElements`. Otherwise variant
-    /// `Some(x,y)` is returned where `x <= y`. If `MinMaxResult` has variant `OneElement(x)`,
-    /// performing this operation will make one clone of `x`.
+    /// `into_option` creates an `Option` of type `(T,T)`. The returned `Option`
+    /// has variant `None` if and only if the `MinMaxResult` has variant
+    /// `NoElements`. Otherwise variant `Some(x,y)` is returned where `x <= y`.
+    /// If `MinMaxResult` has variant `OneElement(x)`, performing this operation
+    /// will make one clone of `x`.
     ///
     /// # Examples
     ///
@@ -2511,7 +2537,7 @@ pub fn step_by(self, by: A) -> StepBy<A, Self> {
 }
 
 #[allow(deprecated)]
-impl<A: Step> ::ops::Range<A> {
+impl<A: Step> ops::Range<A> {
     /// Creates an iterator with the same range, but stepping by the
     /// given amount at each iteration.
     ///
@@ -2544,26 +2570,6 @@ pub fn step_by(self, by: A) -> StepBy<A, Self> {
     }
 }
 
-/// An infinite iterator starting at `start` and advancing by `step` with each
-/// iteration
-#[unstable(feature = "core",
-           reason = "may be renamed or replaced by range notation adapters")]
-#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")]
-pub type Counter<A> = StepBy<A, RangeFrom<A>>;
-
-/// Deprecated: use `(start..).step_by(step)` instead.
-#[inline]
-#[unstable(feature = "core",
-           reason = "may be renamed or replaced by range notation adapters")]
-#[deprecated(since = "1.0.0-beta", reason = "use (start..).step_by(step) instead")]
-#[allow(deprecated)]
-pub fn count<A>(start: A, step: A) -> Counter<A> {
-    StepBy {
-        range: RangeFrom { start: start },
-        step_by: step,
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A> Iterator for StepBy<A, RangeFrom<A>> where
     A: Clone,
@@ -2584,108 +2590,12 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-/// An iterator over the range [start, stop)
-#[allow(deprecated)]
-#[derive(Clone)]
-#[unstable(feature = "core",
-           reason = "will be replaced by range notation")]
-#[deprecated(since = "1.0.0-beta", reason = "use range notation")]
-pub struct Range<A> {
-    state: A,
-    stop: A,
-    one: A,
-}
-
-/// Deprecated: use `(start..stop)` instead.
-#[inline]
-#[unstable(feature = "core", reason = "will be replaced by range notation")]
-#[deprecated(since = "1.0.0-beta", reason = "use (start..stop) instead")]
-#[allow(deprecated)]
-pub fn range<A: Int>(start: A, stop: A) -> Range<A> {
-    Range {
-        state: start,
-        stop: stop,
-        one: Int::one(),
-    }
-}
-
-// FIXME: #10414: Unfortunate type bound
-#[unstable(feature = "core",
-           reason = "will be replaced by range notation")]
-#[deprecated(since = "1.0.0-beta", reason = "use range notation")]
-#[allow(deprecated)]
-impl<A: Int + ToPrimitive> Iterator for Range<A> {
-    type Item = A;
-
-    #[inline]
-    fn next(&mut self) -> Option<A> {
-        if self.state < self.stop {
-            let result = self.state.clone();
-            self.state = self.state + self.one;
-            Some(result)
-        } else {
-            None
-        }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        // This first checks if the elements are representable as i64. If they aren't, try u64 (to
-        // handle cases like range(huge, huger)). We don't use usize/isize because the difference of
-        // the i64/u64 might lie within their range.
-        let bound = match self.state.to_i64() {
-            Some(a) => {
-                let sz = self.stop.to_i64().map(|b| b.checked_sub(a));
-                match sz {
-                    Some(Some(bound)) => bound.to_usize(),
-                    _ => None,
-                }
-            },
-            None => match self.state.to_u64() {
-                Some(a) => {
-                    let sz = self.stop.to_u64().map(|b| b.checked_sub(a));
-                    match sz {
-                        Some(Some(bound)) => bound.to_usize(),
-                        _ => None
-                    }
-                },
-                None => None
-            }
-        };
-
-        match bound {
-            Some(b) => (b, Some(b)),
-            // Standard fallback for unbounded/unrepresentable bounds
-            None => (0, None)
-        }
-    }
-}
-
-/// `Int` is required to ensure the range will be the same regardless of
-/// the direction it is consumed.
-#[unstable(feature = "core",
-           reason = "will be replaced by range notation")]
-#[deprecated(since = "1.0.0-beta", reason = "use range notation")]
-#[allow(deprecated)]
-impl<A: Int + ToPrimitive> DoubleEndedIterator for Range<A> {
-    #[inline]
-    fn next_back(&mut self) -> Option<A> {
-        if self.stop > self.state {
-            self.stop = self.stop - self.one;
-            Some(self.stop.clone())
-        } else {
-            None
-        }
-    }
-}
-
 /// An iterator over the range [start, stop]
 #[derive(Clone)]
 #[unstable(feature = "core",
            reason = "likely to be replaced by range notation and adapters")]
-#[allow(deprecated)]
 pub struct RangeInclusive<A> {
-    range: Range<A>,
+    range: ops::Range<A>,
     done: bool,
 }
 
@@ -2693,18 +2603,18 @@ pub struct RangeInclusive<A> {
 #[inline]
 #[unstable(feature = "core",
            reason = "likely to be replaced by range notation and adapters")]
-#[allow(deprecated)]
-pub fn range_inclusive<A: Int>(start: A, stop: A) -> RangeInclusive<A> {
+pub fn range_inclusive<A>(start: A, stop: A) -> RangeInclusive<A>
+    where A: Step + One + Clone
+{
     RangeInclusive {
-        range: range(start, stop),
+        range: start..stop,
         done: false,
     }
 }
 
 #[unstable(feature = "core",
            reason = "likely to be replaced by range notation and adapters")]
-#[allow(deprecated)]
-impl<A: Int + ToPrimitive> Iterator for RangeInclusive<A> {
+impl<A: Step + One + Clone> Iterator for RangeInclusive<A> {
     type Item = A;
 
     #[inline]
@@ -2712,9 +2622,9 @@ fn next(&mut self) -> Option<A> {
         match self.range.next() {
             Some(x) => Some(x),
             None => {
-                if !self.done && self.range.state == self.range.stop {
+                if !self.done && self.range.start == self.range.end {
                     self.done = true;
-                    Some(self.range.stop.clone())
+                    Some(self.range.end.clone())
                 } else {
                     None
                 }
@@ -2740,46 +2650,28 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 
 #[unstable(feature = "core",
            reason = "likely to be replaced by range notation and adapters")]
-#[allow(deprecated)]
-impl<A: Int + ToPrimitive> DoubleEndedIterator for RangeInclusive<A> {
+impl<A> DoubleEndedIterator for RangeInclusive<A>
+    where A: Step + One + Clone,
+          for<'a> &'a A: Sub<Output=A>
+{
     #[inline]
     fn next_back(&mut self) -> Option<A> {
-        if self.range.stop > self.range.state {
-            let result = self.range.stop.clone();
-            self.range.stop = self.range.stop - self.range.one;
+        if self.range.end > self.range.start {
+            let result = self.range.end.clone();
+            self.range.end = &self.range.end - &A::one();
             Some(result)
-        } else if !self.done && self.range.state == self.range.stop {
+        } else if !self.done && self.range.start == self.range.end {
             self.done = true;
-            Some(self.range.stop.clone())
+            Some(self.range.end.clone())
         } else {
             None
         }
     }
 }
 
-/// An iterator over the range [start, stop) by `step`. It handles overflow by stopping.
-#[unstable(feature = "core",
-           reason = "likely to be replaced by range notation and adapters")]
-#[deprecated(since = "1.0.0-beta", reason = "use range notation and step_by")]
-pub type RangeStep<A> = StepBy<A, ::ops::Range<A>>;
-
-/// Deprecated: use `(start..stop).step_by(step)` instead.
-#[inline]
-#[unstable(feature = "core",
-           reason = "likely to be replaced by range notation and adapters")]
-#[deprecated(since = "1.0.0-beta",
-             reason = "use `(start..stop).step_by(step)` instead")]
-#[allow(deprecated)]
-pub fn range_step<A: Int>(start: A, stop: A, step: A) -> RangeStep<A> {
-    StepBy {
-        step_by: step,
-        range: ::ops::Range { start: start, end: stop },
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
-impl<A: Step + Zero + Clone> Iterator for StepBy<A, ::ops::Range<A>> {
+impl<A: Step + Zero + Clone> Iterator for StepBy<A, ops::Range<A>> {
     type Item = A;
 
     #[inline]
@@ -2882,13 +2774,13 @@ fn next(&mut self) -> Option<A> {
 macro_rules! range_exact_iter_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl ExactSizeIterator for ::ops::Range<$t> { }
+        impl ExactSizeIterator for ops::Range<$t> { }
     )*)
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
-impl<A: Step + One + Clone> Iterator for ::ops::Range<A> {
+impl<A: Step + One + Clone> Iterator for ops::Range<A> {
     type Item = A;
 
     #[inline]
@@ -2927,7 +2819,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
-impl<A: Step + One + Clone> DoubleEndedIterator for ::ops::Range<A> where
+impl<A: Step + One + Clone> DoubleEndedIterator for ops::Range<A> where
     for<'a> &'a A: Sub<&'a A, Output = A>
 {
     #[inline]
@@ -2943,7 +2835,7 @@ fn next_back(&mut self) -> Option<A> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
-impl<A: Step + One> Iterator for ::ops::RangeFrom<A> {
+impl<A: Step + One> Iterator for ops::RangeFrom<A> {
     type Item = A;
 
     #[inline]
index cf5cb0c2f5e3927cc4d247b0dda4b1099996e723..3a9af50fefbc78c29f2453144563bfb506c1dc86 100644 (file)
 #![feature(unboxed_closures)]
 #![feature(rustc_attrs)]
 #![feature(optin_builtin_traits)]
+#![feature(fundamental)]
 #![feature(concat_idents)]
 #![feature(reflect)]
+#![feature(custom_attribute)]
 
 #[macro_use]
 mod macros;
 pub mod cell;
 pub mod char;
 pub mod panicking;
-pub mod finally;
 pub mod iter;
 pub mod option;
 pub mod raw;
index d5a7c1d6b26472ac3fb49cadc6e0c764252593c8..751bd7353e4cbba9d861b22c98c10419239997a4 100644 (file)
@@ -66,10 +66,10 @@ macro_rules! assert {
     );
 }
 
-/// Asserts that two expressions are equal to each other, testing equality in
-/// both directions.
+/// Asserts that two expressions are equal to each other.
 ///
-/// On panic, this macro will print the values of the expressions.
+/// On panic, this macro will print the values of the expressions with their
+/// debug representations.
 ///
 /// # Examples
 ///
@@ -84,10 +84,8 @@ macro_rules! assert_eq {
     ($left:expr , $right:expr) => ({
         match (&($left), &($right)) {
             (left_val, right_val) => {
-                // check both directions of equality....
-                if !((*left_val == *right_val) &&
-                     (*right_val == *left_val)) {
-                    panic!("assertion failed: `(left == right) && (right == left)` \
+                if !(*left_val == *right_val) {
+                    panic!("assertion failed: `(left == right)` \
                            (left: `{:?}`, right: `{:?}`)", *left_val, *right_val)
                 }
             }
@@ -156,7 +154,7 @@ macro_rules! debug_assert_eq {
 
 /// Short circuiting evaluation on Err
 ///
-/// `libstd` contains a more general `try!` macro that uses `FromError`.
+/// `libstd` contains a more general `try!` macro that uses `From<E>`.
 #[macro_export]
 macro_rules! try {
     ($e:expr) => ({
@@ -233,7 +231,7 @@ macro_rules! writeln {
 /// ```
 /// # #![feature(core)]
 /// fn divide_by_three(x: u32) -> u32 { // one of the poorest implementations of x/3
-///     for i in std::iter::count(0, 1) {
+///     for i in 0.. {
 ///         if 3*i < i { panic!("u32 overflow"); }
 ///         if x < 3*i { return i-1; }
 ///     }
index 3f4b39da4b3bb1e888cec84aaee71358644b7b0b..d1d9c3899427b04e21d29e8dd4f53372dc0ee87b 100644 (file)
@@ -49,6 +49,7 @@ impl !Send for Managed { }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang="sized"]
 #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
+#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
 pub trait Sized : MarkerTrait {
     // Empty.
 }
@@ -346,17 +347,16 @@ impl<T:?Sized> MarkerTrait for T { }
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
 
-/// `PhantomData` is a way to tell the compiler about fake fields.
-/// Phantom data is required whenever type parameters are not used.
-/// The idea is that if the compiler encounters a `PhantomData<T>`
-/// instance, it will behave *as if* an instance of the type `T` were
-/// present for the purpose of various automatic analyses.
+/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
+/// even though it does not. This allows you to inform the compiler about certain safety properties
+/// of your code.
+///
+/// Though they both have scary names, `PhantomData<T>` and "phantom types" are unrelated. 👻👻👻
 ///
 /// # Examples
 ///
 /// When handling external resources over a foreign function interface, `PhantomData<T>` can
-/// prevent mismatches by enforcing types in the method implementations, although the struct
-/// doesn't actually contain values of the resource type.
+/// prevent mismatches by enforcing types in the method implementations:
 ///
 /// ```
 /// # trait ResType { fn foo(&self); };
@@ -397,11 +397,6 @@ pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
 /// commonly necessary if the structure is using an unsafe pointer
 /// like `*mut T` whose referent may be dropped when the type is
 /// dropped, as a `*mut T` is otherwise not treated as owned.
-///
-/// FIXME. Better documentation and examples of common patterns needed
-/// here! For now, please see [RFC 738][738] for more information.
-///
-/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
 #[lang="phantom_data"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct PhantomData<T:?Sized>;
@@ -415,42 +410,6 @@ unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
     unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 }
 
-/// Old-style marker trait. Deprecated.
-#[unstable(feature = "core", reason = "deprecated")]
-#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")]
-#[lang="contravariant_lifetime"]
-pub struct ContravariantLifetime<'a>;
-
-/// Old-style marker trait. Deprecated.
-#[unstable(feature = "core", reason = "deprecated")]
-#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(&'a ())>`")]
-#[lang="covariant_lifetime"]
-pub struct CovariantLifetime<'a>;
-
-/// Old-style marker trait. Deprecated.
-#[unstable(feature = "core", reason = "deprecated")]
-#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<&'a ()>>`")]
-#[lang="invariant_lifetime"]
-pub struct InvariantLifetime<'a>;
-
-/// Old-style marker trait. Deprecated.
-#[unstable(feature = "core", reason = "deprecated")]
-#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(T)>`")]
-#[lang="contravariant_type"]
-pub struct ContravariantType<T>;
-
-/// Old-style marker trait. Deprecated.
-#[unstable(feature = "core", reason = "deprecated")]
-#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
-#[lang="covariant_type"]
-pub struct CovariantType<T>;
-
-/// Old-style marker trait. Deprecated.
-#[unstable(feature = "core", reason = "deprecated")]
-#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<T>>`")]
-#[lang="invariant_type"]
-pub struct InvariantType<T>;
-
 /// A marker trait indicates a type that can be reflected over. This
 /// trait is implemented for all types. Its purpose is to ensure that
 /// when you write a generic function that will employ reflection,
@@ -487,9 +446,5 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 pub trait Reflect : MarkerTrait {
 }
 
-#[cfg(stage0)]
-impl<T> Reflect for T { }
-
-#[cfg(not(stage0))]
 impl Reflect for .. { }
 
index 98e8668239bb8ee67e9aed5fcd3cce856c291838..249beb6295c0733be70e4f74806ee1fbe3c2ea90 100644 (file)
@@ -173,11 +173,6 @@ pub unsafe fn zeroed<T>() -> T {
 #[inline]
 #[unstable(feature = "filling_drop")]
 pub unsafe fn dropped<T>() -> T {
-    #[cfg(stage0)]
-    #[inline(always)]
-    unsafe fn dropped_impl<T>() -> T { zeroed() }
-
-    #[cfg(not(stage0))]
     #[inline(always)]
     unsafe fn dropped_impl<T>() -> T { intrinsics::init_dropped() }
 
@@ -337,38 +332,32 @@ macro_rules! repeat_u8_as_u64 {
 // But having the sign bit set is a pain, so 0x1d is probably better.
 //
 // And of course, 0x00 brings back the old world of zero'ing on drop.
-#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
+#[unstable(feature = "filling_drop")]
 pub const POST_DROP_U8: u8 = 0x1d;
-#[cfg(not(stage0))] #[unstable(feature = "filling_drop")]
+#[unstable(feature = "filling_drop")]
 pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8);
-#[cfg(not(stage0))]  #[unstable(feature = "filling_drop")]
+#[unstable(feature = "filling_drop")]
 pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8);
 
 #[cfg(target_pointer_width = "32")]
-#[cfg(not(stage0))]  #[unstable(feature = "filling_drop")]
+#[unstable(feature = "filling_drop")]
 pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize;
 #[cfg(target_pointer_width = "64")]
-#[cfg(not(stage0))]  #[unstable(feature = "filling_drop")]
+#[unstable(feature = "filling_drop")]
 pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize;
 
-#[cfg(stage0)]  #[unstable(feature = "filling_drop")]
-pub const POST_DROP_U8: u8 = 0;
-#[cfg(stage0)]  #[unstable(feature = "filling_drop")]
-pub const POST_DROP_U32: u32 = 0;
-#[cfg(stage0)]  #[unstable(feature = "filling_drop")]
-pub const POST_DROP_U64: u64 = 0;
-#[cfg(stage0)]  #[unstable(feature = "filling_drop")]
-pub const POST_DROP_USIZE: usize = 0;
-
-/// Interprets `src` as `&U`, and then reads `src` without moving the contained value.
-///
-/// This function will unsafely assume the pointer `src` is valid for `sizeof(U)` bytes by
-/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the
-/// contained value instead of moving out of `src`.
-///
-/// It is not a compile-time error if `T` and `U` have different sizes, but it is highly encouraged
-/// to only invoke this function where `T` and `U` have the same size. This function triggers
-/// undefined behavior if `U` is larger than `T`.
+/// Interprets `src` as `&U`, and then reads `src` without moving the contained
+/// value.
+///
+/// This function will unsafely assume the pointer `src` is valid for
+/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
+/// will also unsafely create a copy of the contained value instead of moving
+/// out of `src`.
+///
+/// It is not a compile-time error if `T` and `U` have different sizes, but it
+/// is highly encouraged to only invoke this function where `T` and `U` have the
+/// same size. This function triggers undefined behavior if `U` is larger than
+/// `T`.
 ///
 /// # Examples
 ///
index 64f8e7055a57ae57b0ab0cbe93812b6fcf1859e4..a4829ed96b3530d6e81096d6f59594eed1a45381 100644 (file)
@@ -46,7 +46,7 @@
 /// intended to have wrapping semantics.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)]
-pub struct Wrapping<T>(pub T);
+pub struct Wrapping<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
 
 #[unstable(feature = "core", reason = "may be removed or relocated")]
 pub mod wrapping;
index bda05a3d9e885aff66f7929816cbe13a360ac0d3..a78eed8ae5fa843c65007fc8bb097cc9328d81d7 100644 (file)
@@ -30,6 +30,8 @@
 use intrinsics::{i32_mul_with_overflow, u32_mul_with_overflow};
 use intrinsics::{i64_mul_with_overflow, u64_mul_with_overflow};
 
+use ::{i8,i16,i32,i64,u8,u16,u32,u64};
+
 #[unstable(feature = "core", reason = "may be removed, renamed, or relocated")]
 #[deprecated(since = "1.0.0", reason = "moved to inherent methods")]
 pub trait WrappingOps {
@@ -43,6 +45,12 @@ pub trait OverflowingOps {
     fn overflowing_add(self, rhs: Self) -> (Self, bool);
     fn overflowing_sub(self, rhs: Self) -> (Self, bool);
     fn overflowing_mul(self, rhs: Self) -> (Self, bool);
+
+    fn overflowing_div(self, rhs: Self) -> (Self, bool);
+    fn overflowing_rem(self, rhs: Self) -> (Self, bool);
+
+    fn overflowing_shl(self, rhs: u32) -> (Self, bool);
+    fn overflowing_shr(self, rhs: u32) -> (Self, bool);
 }
 
 macro_rules! sh_impl {
@@ -184,6 +192,20 @@ fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
 
 wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 
+mod shift_max {
+    #![allow(non_upper_case_globals)]
+
+    pub const  i8: u32 = (1 << 3) - 1;
+    pub const i16: u32 = (1 << 4) - 1;
+    pub const i32: u32 = (1 << 5) - 1;
+    pub const i64: u32 = (1 << 6) - 1;
+
+    pub const  u8: u32 = i8;
+    pub const u16: u32 = i16;
+    pub const u32: u32 = i32;
+    pub const u64: u32 = i64;
+}
+
 macro_rules! overflowing_impl {
     ($($t:ident)*) => ($(
         impl OverflowingOps for $t {
@@ -205,6 +227,34 @@ fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
                     concat_idents!($t, _mul_with_overflow)(self, rhs)
                 }
             }
+
+            #[inline(always)]
+            fn overflowing_div(self, rhs: $t) -> ($t, bool) {
+                if self == $t::MIN && rhs == -1 {
+                    (1, true)
+                } else {
+                    (self/rhs, false)
+                }
+            }
+            #[inline(always)]
+            fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
+                if self == $t::MIN && rhs == -1 {
+                    (0, true)
+                } else {
+                    (self % rhs, false)
+                }
+            }
+
+            #[inline(always)]
+            fn overflowing_shl(self, rhs: u32) -> ($t, bool) {
+                (self << (rhs & self::shift_max::$t),
+                 (rhs > self::shift_max::$t))
+            }
+            #[inline(always)]
+            fn overflowing_shr(self, rhs: u32) -> ($t, bool) {
+                (self >> (rhs & self::shift_max::$t),
+                 (rhs > self::shift_max::$t))
+            }
         }
     )*)
 }
@@ -234,6 +284,26 @@ fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
             (res.0 as usize, res.1)
         }
     }
+    #[inline(always)]
+    fn overflowing_div(self, rhs: usize) -> (usize, bool) {
+        let (r, f) = (self as u64).overflowing_div(rhs as u64);
+        (r as usize, f)
+    }
+    #[inline(always)]
+    fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
+        let (r, f) = (self as u64).overflowing_rem(rhs as u64);
+        (r as usize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
+        let (r, f) = (self as u64).overflowing_shl(rhs);
+        (r as usize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
+        let (r, f) = (self as u64).overflowing_shr(rhs);
+        (r as usize, f)
+    }
 }
 
 #[cfg(target_pointer_width = "32")]
@@ -259,6 +329,26 @@ fn overflowing_mul(self, rhs: usize) -> (usize, bool) {
             (res.0 as usize, res.1)
         }
     }
+    #[inline(always)]
+    fn overflowing_div(self, rhs: usize) -> (usize, bool) {
+        let (r, f) = (self as u32).overflowing_div(rhs as u32);
+        (r as usize, f)
+    }
+    #[inline(always)]
+    fn overflowing_rem(self, rhs: usize) -> (usize, bool) {
+        let (r, f) = (self as u32).overflowing_rem(rhs as u32);
+        (r as usize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shl(self, rhs: u32) -> (usize, bool) {
+        let (r, f) = (self as u32).overflowing_shl(rhs);
+        (r as usize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shr(self, rhs: u32) -> (usize, bool) {
+        let (r, f) = (self as u32).overflowing_shr(rhs);
+        (r as usize, f)
+    }
 }
 
 #[cfg(target_pointer_width = "64")]
@@ -284,6 +374,26 @@ fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
             (res.0 as isize, res.1)
         }
     }
+    #[inline(always)]
+    fn overflowing_div(self, rhs: isize) -> (isize, bool) {
+        let (r, f) = (self as i64).overflowing_div(rhs as i64);
+        (r as isize, f)
+    }
+    #[inline(always)]
+    fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
+        let (r, f) = (self as i64).overflowing_rem(rhs as i64);
+        (r as isize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
+        let (r, f) = (self as i64).overflowing_shl(rhs);
+        (r as isize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
+        let (r, f) = (self as i64).overflowing_shr(rhs);
+        (r as isize, f)
+    }
 }
 
 #[cfg(target_pointer_width = "32")]
@@ -309,4 +419,24 @@ fn overflowing_mul(self, rhs: isize) -> (isize, bool) {
             (res.0 as isize, res.1)
         }
     }
+    #[inline(always)]
+    fn overflowing_div(self, rhs: isize) -> (isize, bool) {
+        let (r, f) = (self as i32).overflowing_div(rhs as i32);
+        (r as isize, f)
+    }
+    #[inline(always)]
+    fn overflowing_rem(self, rhs: isize) -> (isize, bool) {
+        let (r, f) = (self as i32).overflowing_rem(rhs as i32);
+        (r as isize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shl(self, rhs: u32) -> (isize, bool) {
+        let (r, f) = (self as i32).overflowing_shl(rhs);
+        (r as isize, f)
+    }
+    #[inline(always)]
+    fn overflowing_shr(self, rhs: u32) -> (isize, bool) {
+        let (r, f) = (self as i32).overflowing_shr(rhs);
+        (r as isize, f)
+    }
 }
index 862eb16d0bfb3fcb26c5f7a11008e5b142d867b1..21af342b1bf788ca448a08e8eecc50905ed4342b 100644 (file)
@@ -1117,6 +1117,7 @@ fn deref_mut(&mut self) -> &mut T { *self }
 #[lang="fn"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait Fn<Args> : FnMut<Args> {
     /// This is called when the call operator is used.
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
@@ -1126,6 +1127,7 @@ pub trait Fn<Args> : FnMut<Args> {
 #[lang="fn_mut"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait FnMut<Args> : FnOnce<Args> {
     /// This is called when the call operator is used.
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
@@ -1135,6 +1137,7 @@ pub trait FnMut<Args> : FnOnce<Args> {
 #[lang="fn_once"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[fundamental] // so that regex can rely that `&str: !FnMut`
 pub trait FnOnce<Args> {
     /// The returned type after the call operator is used.
     type Output;
@@ -1142,3 +1145,52 @@ pub trait FnOnce<Args> {
     /// This is called when the call operator is used.
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
+
+#[cfg(not(stage0))]
+mod impls {
+    use marker::Sized;
+    use super::{Fn, FnMut, FnOnce};
+
+    impl<'a,A,F:?Sized> Fn<A> for &'a F
+        where F : Fn<A>
+    {
+        extern "rust-call" fn call(&self, args: A) -> F::Output {
+            (**self).call(args)
+        }
+    }
+
+    impl<'a,A,F:?Sized> FnMut<A> for &'a F
+        where F : Fn<A>
+    {
+        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
+            (**self).call(args)
+        }
+    }
+
+    impl<'a,A,F:?Sized> FnOnce<A> for &'a F
+        where F : Fn<A>
+    {
+        type Output = F::Output;
+
+        extern "rust-call" fn call_once(self, args: A) -> F::Output {
+            (*self).call(args)
+        }
+    }
+
+    impl<'a,A,F:?Sized> FnMut<A> for &'a mut F
+        where F : FnMut<A>
+    {
+        extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
+            (*self).call_mut(args)
+        }
+    }
+
+    impl<'a,A,F:?Sized> FnOnce<A> for &'a mut F
+        where F : FnMut<A>
+    {
+        type Output = F::Output;
+        extern "rust-call" fn call_once(mut self, args: A) -> F::Output {
+            (*self).call_mut(args)
+        }
+    }
+}
index c5102ede29fcf82f0ab37905e444f973d492ba98..6db7c9bd99d9b08cb02fa3e12ca5d79e84bd695a 100644 (file)
 use ops::FnOnce;
 use result::Result::{Ok, Err};
 use result::Result;
-#[allow(deprecated)]
-use slice::AsSlice;
 use slice;
 
 // Note that this is not a lang item per se, but it has a hidden dependency on
@@ -765,25 +763,6 @@ pub fn unwrap_or_default(self) -> T {
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
 
-#[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]
-    fn as_slice<'a>(&'a self) -> &'a [T] {
-        match *self {
-            Some(ref x) => slice::ref_slice(x),
-            None => {
-                let result: &[_] = &[];
-                result
-            }
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Default for Option<T> {
     #[inline]
index 448b90c0dbdaf5af2074f9df5ef6fc1e0290bd48..e60bc49408195644c331d56e35926db606000bb0 100644 (file)
 pub use clone::Clone;
 pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
 pub use convert::{AsRef, AsMut, Into, From};
-pub use iter::Extend;
-pub use iter::{Iterator, DoubleEndedIterator};
-pub use iter::{ExactSizeIterator};
+pub use iter::{Iterator, DoubleEndedIterator, Extend, ExactSizeIterator};
 pub use option::Option::{self, Some, None};
 pub use result::Result::{self, Ok, Err};
-pub use slice::{AsSlice, SliceExt};
-pub use str::{Str, StrExt};
+pub use slice::SliceExt;
+pub use str::StrExt;
+
+#[allow(deprecated)] pub use slice::AsSlice;
+#[allow(deprecated)] pub use str::Str;
index 41a70ef708f30d85a5a49ff63c175cad0ccdb826..ff51e25fcbf2535f9cf81a3d0129c7dc7aa556c3 100644 (file)
@@ -157,21 +157,6 @@ pub fn null<T>() -> *const T { 0 as *const T }
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn null_mut<T>() -> *mut T { 0 as *mut T }
 
-/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be
-/// `0`.
-///
-/// # Safety
-///
-/// Beyond accepting a raw pointer, this is unsafe because it will not drop the
-/// contents of `dst`, and may be used to create invalid instances of `T`.
-#[inline]
-#[unstable(feature = "core",
-           reason = "may play a larger role in std::ptr future extensions")]
-#[deprecated(since = "1.0.0", reason = "use `write_bytes` instead")]
-pub unsafe fn zero_memory<T>(dst: *mut T, count: usize) {
-    write_bytes(dst, 0, count);
-}
-
 /// Swaps the values at two mutable locations of the same type, without
 /// deinitialising either. They may overlap, unlike `mem::swap` which is
 /// otherwise equivalent.
index 8502a9c53c4a88cc4a0b24fd3dc0d98e08eeca35..47d1f3a1a3ccf1ab40ef385c921bd0c8e2f8b41c 100644 (file)
@@ -64,19 +64,6 @@ pub struct Slice<T> {
 
 impl<T> Copy for Slice<T> {}
 
-/// The representation of an old closure.
-#[repr(C)]
-#[derive(Copy)]
-#[unstable(feature = "core")]
-#[deprecated(reason = "unboxed new closures do not have a universal representation; \
-                       `&Fn` (etc) trait objects should use `TraitObject` instead",
-             since= "1.0.0")]
-#[allow(deprecated) /* for deriving Copy impl */]
-pub struct Closure {
-    pub code: *mut (),
-    pub env: *mut (),
-}
-
 /// The representation of a trait object like `&SomeTrait`.
 ///
 /// This struct has the same layout as types like `&SomeTrait` and
index 223a0bdae36cd8c3cebe763a4192e2950732c4e6..d8856130fab33b1d794ede0a0a6f966f73196701 100644 (file)
@@ -88,10 +88,6 @@ fn binary_search_by<F>(&self, f: F) -> Result<usize, usize> where
     fn len(&self) -> usize;
     fn is_empty(&self) -> bool { self.len() == 0 }
     fn get_mut<'a>(&'a mut self, index: usize) -> Option<&'a mut Self::Item>;
-    #[unstable(feature = "core",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
-    fn as_mut_slice<'a>(&'a mut self) -> &'a mut [Self::Item];
     fn iter_mut<'a>(&'a mut self) -> IterMut<'a, Self::Item>;
     fn first_mut<'a>(&'a mut self) -> Option<&'a mut Self::Item>;
     fn tail_mut<'a>(&'a mut self) -> &'a mut [Self::Item];
@@ -263,12 +259,6 @@ fn get_mut(&mut self, index: usize) -> Option<&mut T> {
         if index < self.len() { Some(&mut self[index]) } else { None }
     }
 
-    #[inline]
-    #[unstable(feature = "core",
-               reason = "will be replaced by slice syntax")]
-    #[deprecated(since = "1.0.0", reason = "use &mut s[..] instead")]
-    fn as_mut_slice(&mut self) -> &mut [T] { self }
-
     #[inline]
     fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
         unsafe {
@@ -1502,54 +1492,6 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] {
     transmute(RawSlice { data: p, len: len })
 }
 
-/// Forms a slice from a pointer and a length.
-///
-/// The pointer given is actually a reference to the base of the slice. This
-/// reference is used to give a concrete lifetime to tie the returned slice to.
-/// Typically this should indicate that the slice is valid for as long as the
-/// pointer itself is valid.
-///
-/// The `len` argument is the number of **elements**, not the number of bytes.
-///
-/// This function is unsafe as there is no guarantee that the given pointer is
-/// valid for `len` elements, nor whether the lifetime provided is a suitable
-/// lifetime for the returned slice.
-///
-/// # Examples
-///
-/// ```
-/// #![feature(core)]
-/// use std::slice;
-///
-/// // manifest a slice out of thin air!
-/// let ptr = 0x1234 as *const usize;
-/// let amt = 10;
-/// unsafe {
-///     let slice = slice::from_raw_buf(&ptr, amt);
-/// }
-/// ```
-#[inline]
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "use from_raw_parts")]
-pub unsafe fn from_raw_buf<'a, T>(p: &'a *const T, len: usize) -> &'a [T] {
-    transmute(RawSlice { data: *p, len: len })
-}
-
-/// Performs the same functionality as `from_raw_buf`, except that a mutable
-/// slice is returned.
-///
-/// This function is unsafe for the same reasons as `from_raw_buf`, as well as
-/// not being able to provide a non-aliasing guarantee of the returned mutable
-/// slice.
-#[inline]
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "use from_raw_parts_mut")]
-pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: usize) -> &'a mut [T] {
-    transmute(RawSlice { data: *p, len: len })
-}
-
 //
 // Submodules
 //
index f9e2b47d9b63428ab8bb4c87a610ebb548ebc31d..934c4515614efc52dc97d3890c60908c5f98e391 100644 (file)
@@ -28,8 +28,6 @@
 use iter::{Map, Iterator, DoubleEndedIterator};
 use marker::Sized;
 use mem;
-#[allow(deprecated)]
-use num::Int;
 use ops::{Fn, FnMut, FnOnce};
 use option::Option::{self, None, Some};
 use raw::{Repr, Slice};
@@ -243,78 +241,6 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
     mem::transmute(v)
 }
 
-/// Constructs a static string slice from a given raw pointer.
-///
-/// This function will read memory starting at `s` until it finds a 0, and then
-/// transmute the memory up to that point as a string slice, returning the
-/// corresponding `&'static str` value.
-///
-/// This function is unsafe because the caller must ensure the C string itself
-/// has the static lifetime and that the memory `s` is valid up to and including
-/// the first null byte.
-///
-/// # Panics
-///
-/// This function will panic if the string pointed to by `s` is not valid UTF-8.
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
-pub unsafe fn from_c_str(s: *const i8) -> &'static str {
-    let s = s as *const u8;
-    let mut len: usize = 0;
-    while *s.offset(len as isize) != 0 {
-        len += 1;
-    }
-    let v: &'static [u8] = ::mem::transmute(Slice { data: s, len: len });
-    from_utf8(v).ok().expect("from_c_str passed invalid utf-8 data")
-}
-
-/// Something that can be used to compare against a character
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0",
-             reason = "use `Pattern` instead")]
-// NB: Rather than removing it, make it private and move it into self::pattern
-pub trait CharEq {
-    /// Determine if the splitter should split at the given character
-    fn matches(&mut self, char) -> bool;
-    /// Indicate if this is only concerned about ASCII characters,
-    /// which can allow for a faster implementation.
-    fn only_ascii(&self) -> bool;
-}
-
-#[allow(deprecated) /* for CharEq */ ]
-impl CharEq for char {
-    #[inline]
-    fn matches(&mut self, c: char) -> bool { *self == c }
-
-    #[inline]
-    fn only_ascii(&self) -> bool { (*self as u32) < 128 }
-}
-
-#[allow(deprecated) /* for CharEq */ ]
-impl<F> CharEq for F where F: FnMut(char) -> bool {
-    #[inline]
-    fn matches(&mut self, c: char) -> bool { (*self)(c) }
-
-    #[inline]
-    fn only_ascii(&self) -> bool { false }
-}
-
-#[allow(deprecated) /* for CharEq */ ]
-impl<'a> CharEq for &'a [char] {
-    #[inline]
-    #[allow(deprecated) /* for CharEq */ ]
-    fn matches(&mut self, c: char) -> bool {
-        self.iter().any(|&m| { let mut m = m; m.matches(c) })
-    }
-
-    #[inline]
-    #[allow(deprecated) /* for CharEq */ ]
-    fn only_ascii(&self) -> bool {
-        self.iter().all(|m| m.only_ascii())
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Error for Utf8Error {
     fn description(&self) -> &str {
@@ -1047,22 +973,6 @@ fn next(&mut self) -> Option<(usize, usize)> {
     }
 }
 
-/// An iterator over the substrings of a string separated by a given
-/// search string
-#[unstable(feature = "core")]
-#[deprecated(since = "1.0.0", reason = "use `Split` with a `&str`")]
-pub struct SplitStr<'a, P: Pattern<'a>>(Split<'a, P>);
-#[allow(deprecated)]
-impl<'a, P: Pattern<'a>> Iterator for SplitStr<'a, P> {
-    type Item = &'a str;
-
-    #[inline]
-    #[allow(deprecated)]
-    fn next(&mut self) -> Option<&'a str> {
-        Iterator::next(&mut self.0)
-    }
-}
-
 impl<'a, 'b>  OldMatchIndices<'a, 'b> {
     #[inline]
     #[allow(dead_code)]
@@ -1444,8 +1354,6 @@ fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
     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>;
     fn lines<'a>(&'a self) -> Lines<'a>;
     fn lines_any<'a>(&'a self) -> LinesAny<'a>;
     fn char_len(&self) -> usize;
@@ -1565,12 +1473,6 @@ fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
         MatchIndices(pat.into_searcher(self))
     }
 
-    #[inline]
-    #[allow(deprecated) /* for SplitStr */ ]
-    fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
-        SplitStr(self.split(pat))
-    }
-
     #[inline]
     fn lines(&self) -> Lines {
         Lines { inner: self.split_terminator('\n').0 }
index 98b6533980dd913728ff45724e01793ee26d1122..922ab2c14a6b71d9b19980267af365f06e204f5b 100644 (file)
@@ -8,10 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(deprecated) /* for CharEq */ ]
-
 use prelude::*;
-use super::CharEq;
 
 // Pattern
 
@@ -228,6 +225,40 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
 
 // Impl for a CharEq wrapper
 
+#[doc(hidden)]
+trait CharEq {
+    fn matches(&mut self, char) -> bool;
+    fn only_ascii(&self) -> bool;
+}
+
+impl CharEq for char {
+    #[inline]
+    fn matches(&mut self, c: char) -> bool { *self == c }
+
+    #[inline]
+    fn only_ascii(&self) -> bool { (*self as u32) < 128 }
+}
+
+impl<F> CharEq for F where F: FnMut(char) -> bool {
+    #[inline]
+    fn matches(&mut self, c: char) -> bool { (*self)(c) }
+
+    #[inline]
+    fn only_ascii(&self) -> bool { false }
+}
+
+impl<'a> CharEq for &'a [char] {
+    #[inline]
+    fn matches(&mut self, c: char) -> bool {
+        self.iter().any(|&m| { let mut m = m; m.matches(c) })
+    }
+
+    #[inline]
+    fn only_ascii(&self) -> bool {
+        self.iter().all(|m| m.only_ascii())
+    }
+}
+
 struct CharEqPattern<C: CharEq>(C);
 
 struct CharEqSearcher<'a, C: CharEq> {
@@ -425,65 +456,116 @@ fn str_search_step<F, G>(mut m: &mut StrSearcher,
     }
 }
 
-macro_rules! associated_items {
-    ($t:ty, $s:ident, $e:expr) => {
-        // FIXME: #22463
-        //type Searcher = $t;
-
-        fn into_searcher(self, haystack: &'a str) -> $t {
-            let $s = self;
-            $e.into_searcher(haystack)
+macro_rules! char_eq_pattern_impl {
+    ($wrapper:ty, $wrapper_ident:ident) => {
+        fn into_searcher(self, haystack: &'a str) -> $wrapper {
+            $wrapper_ident(CharEqPattern(self).into_searcher(haystack))
         }
-
         #[inline]
         fn is_contained_in(self, haystack: &'a str) -> bool {
-            let $s = self;
-            $e.is_contained_in(haystack)
+            CharEqPattern(self).is_contained_in(haystack)
         }
-
         #[inline]
         fn is_prefix_of(self, haystack: &'a str) -> bool {
-            let $s = self;
-            $e.is_prefix_of(haystack)
+            CharEqPattern(self).is_prefix_of(haystack)
         }
-
-        // FIXME: #21750
-        /*#[inline]
+        #[inline]
         fn is_suffix_of(self, haystack: &'a str) -> bool
-            where $t: ReverseSearcher<'a>
+            where $wrapper: ReverseSearcher<'a>
         {
-            let $s = self;
-            $e.is_suffix_of(haystack)
-        }*/
+            CharEqPattern(self).is_suffix_of(haystack)
+        }
     }
 }
 
-// CharEq delegation impls
+// Pattern for char
 
-/// Searches for chars that are equal to a given char
 impl<'a> Pattern<'a> for char {
-    type Searcher =   <CharEqPattern<Self> as Pattern<'a>>::Searcher;
-    associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
-                      s, CharEqPattern(s));
+    type Searcher = CharSearcher<'a>;
+    char_eq_pattern_impl!(CharSearcher<'a>, CharSearcher);
+}
+
+pub struct CharSearcher<'a>(CharEqSearcher<'a, char>);
+
+unsafe impl<'a> Searcher<'a> for CharSearcher<'a> {
+    #[inline]
+    fn haystack(&self) -> &'a str { self.0.haystack() }
+    #[inline]
+    fn next(&mut self) -> SearchStep { self.0.next() }
+}
+unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> {
+    #[inline]
+    fn next_back(&mut self) -> SearchStep { self.0.next_back() }
 }
+impl<'a> DoubleEndedSearcher<'a> for CharSearcher<'a> {}
+
+// Pattern for &[char]
 
-/// Searches for chars that are equal to any of the chars in the array
 impl<'a, 'b> Pattern<'a> for &'b [char] {
-    type Searcher =   <CharEqPattern<Self> as Pattern<'a>>::Searcher;
-    associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
-                      s, CharEqPattern(s));
+    type Searcher = CharSliceSearcher<'a, 'b>;
+    char_eq_pattern_impl!(CharSliceSearcher<'a, 'b>, CharSliceSearcher);
 }
 
-/// 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));
+pub struct CharSliceSearcher<'a, 'b>(CharEqSearcher<'a, &'b [char]>);
+
+unsafe impl<'a, 'b> Searcher<'a> for CharSliceSearcher<'a, 'b> {
+    #[inline]
+    fn haystack(&self) -> &'a str { self.0.haystack() }
+    #[inline]
+    fn next(&mut self) -> SearchStep { self.0.next() }
+}
+unsafe impl<'a, 'b> ReverseSearcher<'a> for CharSliceSearcher<'a, 'b> {
+    #[inline]
+    fn next_back(&mut self) -> SearchStep { self.0.next_back() }
+}
+impl<'a, 'b> DoubleEndedSearcher<'a> for CharSliceSearcher<'a, 'b> {}
+
+// Pattern for predicates
+
+impl<'a, F: FnMut(char) -> bool> Pattern<'a> for F {
+    type Searcher = CharPredSearcher<'a, F>;
+    char_eq_pattern_impl!(CharPredSearcher<'a, F>, CharPredSearcher);
+}
+
+pub struct CharPredSearcher<'a, F: FnMut(char) -> bool>(CharEqSearcher<'a, F>);
+
+unsafe impl<'a, F> Searcher<'a> for CharPredSearcher<'a, F>
+    where F: FnMut(char) -> bool
+{
+    #[inline]
+    fn haystack(&self) -> &'a str { self.0.haystack() }
+    #[inline]
+    fn next(&mut self) -> SearchStep { self.0.next() }
+}
+unsafe impl<'a, F> ReverseSearcher<'a> for CharPredSearcher<'a, F>
+    where F: FnMut(char) -> bool
+{
+    #[inline]
+    fn next_back(&mut self) -> SearchStep { self.0.next_back() }
 }
+impl<'a, F> DoubleEndedSearcher<'a> for CharPredSearcher<'a, F>
+    where F: FnMut(char) -> bool
+{}
 
-/// 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));
+// Pattern for &&str
+
+impl<'a, 'b> Pattern<'a> for &'b &'b str {
+    type Searcher = <&'b str as Pattern<'a>>::Searcher;
+    #[inline]
+    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)
+    }
+    #[inline]
+    fn is_suffix_of(self, haystack: &'a str) -> bool {
+        (*self).is_suffix_of(haystack)
+    }
 }
index fff3cc14eadfd45fb4127f3ea800c7a4ad39fae6..85dd10390038fadc92ac4e3faf3d260d029497d3 100644 (file)
@@ -59,7 +59,6 @@ fn double_imm_borrow() {
 fn no_mut_then_imm_borrow() {
     let x = RefCell::new(0);
     let _b1 = x.borrow_mut();
-    assert!(x.try_borrow().is_none());
     assert_eq!(x.borrow_state(), BorrowState::Writing);
 }
 
@@ -67,7 +66,6 @@ fn no_mut_then_imm_borrow() {
 fn no_imm_then_borrow_mut() {
     let x = RefCell::new(0);
     let _b1 = x.borrow();
-    assert!(x.try_borrow_mut().is_none());
     assert_eq!(x.borrow_state(), BorrowState::Reading);
 }
 
@@ -76,7 +74,6 @@ fn no_double_borrow_mut() {
     let x = RefCell::new(0);
     assert_eq!(x.borrow_state(), BorrowState::Unused);
     let _b1 = x.borrow_mut();
-    assert!(x.try_borrow_mut().is_none());
     assert_eq!(x.borrow_state(), BorrowState::Writing);
 }
 
@@ -105,7 +102,7 @@ fn double_borrow_single_release_no_borrow_mut() {
     {
         let _b2 = x.borrow();
     }
-    assert!(x.try_borrow_mut().is_none());
+    assert_eq!(x.borrow_state(), BorrowState::Reading);
 }
 
 #[test]
@@ -122,14 +119,14 @@ fn clone_ref_updates_flag() {
     let x = RefCell::new(0);
     {
         let b1 = x.borrow();
-        assert!(x.try_borrow_mut().is_none());
+        assert_eq!(x.borrow_state(), BorrowState::Reading);
         {
             let _b2 = clone_ref(&b1);
-            assert!(x.try_borrow_mut().is_none());
+            assert_eq!(x.borrow_state(), BorrowState::Reading);
         }
-        assert!(x.try_borrow_mut().is_none());
+        assert_eq!(x.borrow_state(), BorrowState::Reading);
     }
-    assert!(x.try_borrow_mut().is_some());
+    assert_eq!(x.borrow_state(), BorrowState::Unused);
 }
 
 #[test]
diff --git a/src/libcoretest/finally.rs b/src/libcoretest/finally.rs
deleted file mode 100644 (file)
index 2a48395..0000000
+++ /dev/null
@@ -1,62 +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.
-
-#![allow(deprecated)]
-
-use core::finally::{try_finally, Finally};
-use std::thread;
-
-#[test]
-fn test_success() {
-    let mut i = 0;
-    try_finally(
-        &mut i, (),
-        |i, ()| {
-            *i = 10;
-        },
-        |i| {
-            assert!(!thread::panicking());
-            assert_eq!(*i, 10);
-            *i = 20;
-        });
-    assert_eq!(i, 20);
-}
-
-#[test]
-#[should_panic]
-fn test_fail() {
-    let mut i = 0;
-    try_finally(
-        &mut i, (),
-        |i, ()| {
-            *i = 10;
-            panic!();
-        },
-        |i| {
-            assert!(thread::panicking());
-            assert_eq!(*i, 10);
-        })
-}
-
-#[test]
-fn test_retval() {
-    let mut closure = || 10;
-    // FIXME(#16640) `: i32` annotation shouldn't be necessary
-    let i: i32 = closure.finally(|| { });
-    assert_eq!(i, 10);
-}
-
-#[test]
-fn test_compact() {
-    fn do_some_fallible_work() {}
-    fn but_always_run_this_function() { }
-    let mut f = do_some_fallible_work;
-    f.finally(but_always_run_this_function);
-}
index 15938a5dcb4770bdac1d5b59c2856db5dc580ff5..af80d347f028e02b66d4b8c572993c9b4d5edda4 100644 (file)
@@ -72,7 +72,7 @@ fn test_multi_iter() {
 
 #[test]
 fn test_counter_from_iter() {
-    let it = count(0, 5).take(10);
+    let it = (0..).step_by(5).take(10);
     let xs: Vec<isize> = FromIterator::from_iter(it);
     assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
 }
@@ -90,7 +90,7 @@ fn test_iterator_chain() {
     }
     assert_eq!(i, expected.len());
 
-    let ys = count(30, 10).take(4);
+    let ys = (30..).step_by(10).take(4);
     let it = xs.iter().cloned().chain(ys);
     let mut i = 0;
     for x in it {
@@ -102,7 +102,7 @@ fn test_iterator_chain() {
 
 #[test]
 fn test_filter_map() {
-    let it = count(0, 1).take(10)
+    let it = (0..).step_by(1).take(10)
         .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
     assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
 }
@@ -244,7 +244,7 @@ fn add(old: &mut isize, new: &usize) -> Option<f64> {
 fn test_iterator_flat_map() {
     let xs = [0, 3, 6];
     let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
-    let it = xs.iter().flat_map(|&x| count(x, 1).take(3));
+    let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
     let mut i = 0;
     for x in it {
         assert_eq!(x, ys[i]);
@@ -291,13 +291,13 @@ fn count(st: &mut usize) -> Option<usize> {
 #[test]
 fn test_cycle() {
     let cycle_len = 3;
-    let it = count(0, 1).take(cycle_len).cycle();
+    let it = (0..).step_by(1).take(cycle_len).cycle();
     assert_eq!(it.size_hint(), (usize::MAX, None));
     for (i, x) in it.take(100).enumerate() {
         assert_eq!(i % cycle_len, x);
     }
 
-    let mut it = count(0, 1).take(0).cycle();
+    let mut it = (0..).step_by(1).take(0).cycle();
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert_eq!(it.next(), None);
 }
@@ -360,7 +360,7 @@ fn test_iterator_min() {
 
 #[test]
 fn test_iterator_size_hint() {
-    let c = count(0, 1);
+    let c = (0..).step_by(1);
     let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
     let v2 = &[10, 11, 12];
     let vi = v.iter();
index 9cc3063dee678eece513b665e98ebc0b9a7af015..7ae0dcbb5f9d4b7cae3fda5196908395db025ead 100644 (file)
@@ -39,7 +39,6 @@
 mod cell;
 mod char;
 mod cmp;
-mod finally;
 mod fmt;
 mod hash;
 mod iter;
index fae36787c3dadf66df71995ae64b02ea9ad584c7..5bc08376d257c5ceff5a7e2b1a722bbcdbc15d45 100644 (file)
@@ -103,7 +103,7 @@ impl Foo for isize {}
     }
 
     unsafe {
-        assert_eq!([76], transmute::<_, Vec<u8>>("L".to_string()));
+        assert_eq!(transmute::<_, Vec<u8>>("L".to_string()), [76]);
     }
 }
 
index 39e41a4fad3b7d5092c834aa43c69a443b1018b7..e3eff6e7512ecf6d3c08167ac809fd5e49ea6552 100644 (file)
@@ -20,7 +20,7 @@ mod tests {
     fn test_overflows() {
         assert!(MAX > 0);
         assert!(MIN <= 0);
-        assert!(MIN + MAX + 1 == 0);
+        assert!((MIN + MAX).wrapping_add(1) == 0);
     }
 
     #[test]
index 38cab4f0e0942440063c16e0bd3b1a3813fd9451..c935b5545740c6d8c6b8b8ba438fb069f93ede75 100644 (file)
@@ -163,9 +163,9 @@ fn starts_short_long() {
 
 #[test]
 fn contains_weird_cases() {
-    assert!("* \t".contains_char(' '));
-    assert!(!"* \t".contains_char('?'));
-    assert!(!"* \t".contains_char('\u{1F4A9}'));
+    assert!("* \t".contains(' '));
+    assert!(!"* \t".contains('?'));
+    assert!(!"* \t".contains('\u{1F4A9}'));
 }
 
 #[test]
@@ -347,11 +347,11 @@ mod $name {
     make_test!(chars_count, s, s.chars().count());
 
     make_test!(contains_bang_str, s, s.contains("!"));
-    make_test!(contains_bang_char, s, s.contains_char('!'));
+    make_test!(contains_bang_char, s, s.contains('!'));
 
     make_test!(match_indices_a_str, s, s.match_indices("a").count());
 
-    make_test!(split_str_a_str, s, s.split_str("a").count());
+    make_test!(split_a_str, s, s.split("a").count());
 
     make_test!(trim_ascii_char, s, {
         use std::ascii::AsciiExt;
@@ -368,11 +368,11 @@ mod $name {
 
     make_test!(find_underscore_char, s, s.find('_'));
     make_test!(rfind_underscore_char, s, s.rfind('_'));
-    make_test!(find_underscore_str, s, s.find_str("_"));
+    make_test!(find_underscore_str, s, s.find("_"));
 
     make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
     make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
-    make_test!(find_zzz_str, s, s.find_str("\u{1F4A4}"));
+    make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
 
     make_test!(split_space_char, s, s.split(' ').count());
     make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
@@ -380,6 +380,6 @@ mod $name {
     make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
     make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
 
-    make_test!(split_str_space_str, s, s.split_str(" ").count());
-    make_test!(split_str_ad_str, s, s.split_str("ad").count());
+    make_test!(split_space_str, s, s.split(" ").count());
+    make_test!(split_ad_str, s, s.split("ad").count());
 }
index 9b220409ef59789b162b2ce380ade3d05624e39b..a7be6a7fcf07a8550e31481b47fe8cb7049a5e40 100644 (file)
@@ -446,7 +446,7 @@ mod tests {
 
     fn same(fmt: &'static str, p: &[Piece<'static>]) {
         let parser = Parser::new(fmt);
-        assert!(p == parser.collect::<Vec<Piece<'static>>>());
+        assert!(parser.collect::<Vec<Piece<'static>>>() == p);
     }
 
     fn fmtdflt() -> FormatSpec<'static> {
index b3a3f266a5ef33449a76658aeba5a9c4d77c6bd9..74be96235d2d767918f2a3b91bcf5ad7e780eec2 100644 (file)
@@ -84,7 +84,7 @@
 //!
 //!     fn edges(&'a self) -> dot::Edges<'a,Ed> {
 //!         let &Edges(ref edges) = self;
-//!         edges.as_slice().into_cow()
+//!         (&edges[..]).into_cow()
 //!     }
 //!
 //!     fn source(&self, e: &Ed) -> Nd { let &(s,_) = e; s }
index 91abb548d2ee18520b13feabec69cc7a7fb60d89..44187a4fc99429002d292e679fb4af77bc5260d7 100644 (file)
@@ -198,7 +198,7 @@ fn rand<R: Rng>(other: &mut R) -> ChaChaRng {
         for word in &mut key {
             *word = other.gen();
         }
-        SeedableRng::from_seed(key.as_slice())
+        SeedableRng::from_seed(&key[..])
     }
 }
 
index 85f3c621c7e88b9412c95600b1c6f379c0b381fd..15d3d981eb5c0c79fd565e7e33ecbcc3aea19c8c 100644 (file)
@@ -154,7 +154,7 @@ fn next_f64(&mut self) -> f64 {
     ///
     /// let mut v = [0; 13579];
     /// thread_rng().fill_bytes(&mut v);
-    /// println!("{:?}", v.as_slice());
+    /// println!("{:?}", &v[..]);
     /// ```
     fn fill_bytes(&mut self, dest: &mut [u8]) {
         // this could, in theory, be done by transmuting dest to a
@@ -310,9 +310,9 @@ fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
     /// let mut rng = thread_rng();
     /// let mut y = [1, 2, 3];
     /// rng.shuffle(&mut y);
-    /// println!("{:?}", y.as_slice());
+    /// println!("{:?}", y);
     /// rng.shuffle(&mut y);
-    /// println!("{:?}", y.as_slice());
+    /// println!("{:?}", y);
     /// ```
     fn shuffle<T>(&mut self, values: &mut [T]) {
         let mut i = values.len();
index 092cd780ec7c7cfb02efc8e16e996c3f8d5ae1d7..3e91b98877062cc5f83a3288774f69c22527460e 100644 (file)
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
-#![feature(io)]
 #![feature(core)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
@@ -862,8 +861,8 @@ fn write_tag<W: Write>(w: &mut W, n: usize) -> EncodeResult {
         } else if 0x100 <= n && n < NUM_TAGS {
             w.write_all(&[0xf0 | (n >> 8) as u8, n as u8])
         } else {
-            Err(io::Error::new(io::ErrorKind::Other, "invalid tag",
-                               Some(n.to_string())))
+            Err(io::Error::new(io::ErrorKind::Other,
+                               &format!("invalid tag: {}", n)[..]))
         }
     }
 
@@ -876,7 +875,7 @@ fn write_sized_vuint<W: Write>(w: &mut W, n: usize, size: usize) -> EncodeResult
             4 => w.write_all(&[0x10 | ((n >> 24) as u8), (n >> 16) as u8,
                             (n >> 8) as u8, n as u8]),
             _ => Err(io::Error::new(io::ErrorKind::Other,
-                                    "isize too big", Some(n.to_string())))
+                                    &format!("isize too big: {}", n)[..]))
         }
     }
 
@@ -885,8 +884,8 @@ fn write_vuint<W: Write>(w: &mut W, n: usize) -> EncodeResult {
         if n < 0x4000 { return write_sized_vuint(w, n, 2); }
         if n < 0x200000 { return write_sized_vuint(w, n, 3); }
         if n < 0x10000000 { return write_sized_vuint(w, n, 4); }
-        Err(io::Error::new(io::ErrorKind::Other, "isize too big",
-                           Some(n.to_string())))
+        Err(io::Error::new(io::ErrorKind::Other,
+                           &format!("isize too big: {}", n)[..]))
     }
 
     impl<'a> Encoder<'a> {
@@ -1077,8 +1076,8 @@ fn _emit_tagged_sub(&mut self, v: usize) -> EncodeResult {
                 self.wr_tagged_raw_u32(EsSub32 as usize, v)
             } else {
                 Err(io::Error::new(io::ErrorKind::Other,
-                                   "length or variant id too big",
-                                   Some(v.to_string())))
+                                   &format!("length or variant id too big: {}",
+                                            v)[..]))
             }
         }
 
index 70303bb3410b71cbdbc61c19d4a76cd8eeb8e38b..0a29ed90ad46100d863d69a2e799c34000632a69 100644 (file)
@@ -68,6 +68,8 @@
     E0019,
     E0020,
     E0022,
+    E0079, // enum variant: expected signed integer constant
+    E0080, // enum variant: constant evaluation error
     E0109,
     E0110,
     E0133,
     E0313, // lifetime of borrowed pointer outlives lifetime of captured variable
     E0314, // closure outlives stack frame
     E0315, // cannot invoke closure outside of its lifetime
-    E0316 // nested quantification of lifetimes
+    E0316, // nested quantification of lifetimes
+    E0370  // discriminant overflow
 }
 
 __build_diagnostic_array! { DIAGNOSTICS }
index f31f8e8d4ce2708894ccf804ffaac8c1aee544a7..a4bb17bc354769d18a2253b7b9a0eb19421aa0f5 100644 (file)
 #![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(std_misc)]
-#![feature(io)]
 #![feature(path_ext)]
 #![feature(str_words)]
 #![feature(str_char)]
-#![feature(convert)]
 #![feature(into_cow)]
 #![feature(slice_patterns)]
 #![cfg_attr(test, feature(test))]
@@ -122,6 +120,8 @@ pub mod middle {
     pub mod traits;
     pub mod ty;
     pub mod ty_fold;
+    pub mod ty_match;
+    pub mod ty_relate;
     pub mod ty_walk;
     pub mod weak_lang_items;
 }
index a8f83bee7f6824a1accd17dca0dda02f87fa2aea..862ced78c082c5056322e6ec8db9e6f4c2777e9f 100644 (file)
@@ -34,8 +34,7 @@
 use std::io::{Cursor, SeekFrom};
 use syntax::abi;
 use syntax::ast::{self, DefId, NodeId};
-use syntax::ast_map::{PathElem, PathElems};
-use syntax::ast_map;
+use syntax::ast_map::{self, LinkedPath, PathElem, PathElems};
 use syntax::ast_util::*;
 use syntax::ast_util;
 use syntax::attr;
@@ -1513,7 +1512,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
                         &krate.module,
                         &[],
                         ast::CRATE_NODE_ID,
-                        [].iter().cloned().chain(None),
+                        [].iter().cloned().chain(LinkedPath::empty()),
                         syntax::parse::token::special_idents::invalid,
                         ast::Public);
 
@@ -1874,7 +1873,7 @@ fn encode_misc_info(ecx: &EncodeContext,
     }
 
     // Encode reexports for the root module.
-    encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(None));
+    encode_reexports(ecx, rbml_w, 0, [].iter().cloned().chain(LinkedPath::empty()));
 
     rbml_w.end_tag();
     rbml_w.end_tag();
index 1ea632d9618fc709fc969c813600fd00f3d38ad3..b6061f39233d20b26d2f7a11535223310f67c192 100644 (file)
@@ -1197,7 +1197,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    if let Some(ty) = tcx.node_types.borrow().get(&id) {
+    if let Some(ty) = tcx.node_types().get(&id) {
         rbml_w.tag(c::tag_table_node_type, |rbml_w| {
             rbml_w.id(id);
             rbml_w.emit_ty(ecx, *ty);
@@ -1884,7 +1884,7 @@ fn decode_side_tables(dcx: &DecodeContext,
                         let ty = val_dsr.read_ty(dcx);
                         debug!("inserting ty for node {}: {}",
                                id, ty_to_string(dcx.tcx, ty));
-                        dcx.tcx.node_types.borrow_mut().insert(id, ty);
+                        dcx.tcx.node_type_insert(id, ty);
                     }
                     c::tag_table_item_subst => {
                         let item_substs = ty::ItemSubsts {
index 0d9e0d14def645ced90898ae7b5c300def44859e..e3e5efc53c7decdca8253aab72db0ada53beea16 100644 (file)
@@ -13,6 +13,8 @@
 
 pub use self::const_val::*;
 
+use self::ErrKind::*;
+
 use metadata::csearch;
 use middle::{astencode, def};
 use middle::pat_util::def_to_path;
@@ -27,6 +29,7 @@
 
 use std::borrow::{Cow, IntoCow};
 use std::num::wrapping::OverflowingOps;
+use std::num::ToPrimitive;
 use std::cmp::Ordering;
 use std::collections::hash_map::Entry::Vacant;
 use std::{i8, i16, i32, i64};
@@ -234,6 +237,7 @@ pub enum ErrKind {
     NotOnStruct,
     NotOnTuple,
 
+    NegateWithOverflow(i64),
     AddiWithOverflow(i64, i64),
     SubiWithOverflow(i64, i64),
     MuliWithOverflow(i64, i64),
@@ -244,6 +248,8 @@ pub enum ErrKind {
     DivideWithOverflow,
     ModuloByZero,
     ModuloWithOverflow,
+    ShiftLeftWithOverflow,
+    ShiftRightWithOverflow,
     MissingStructField,
     NonConstPath,
     ExpectedConstTuple,
@@ -257,6 +263,7 @@ pub enum ErrKind {
 impl ConstEvalErr {
     pub fn description(&self) -> Cow<str> {
         use self::ErrKind::*;
+
         match self.kind {
             CannotCast => "can't cast this type".into_cow(),
             CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(),
@@ -275,6 +282,7 @@ pub fn description(&self) -> Cow<str> {
             NotOnStruct => "not on struct".into_cow(),
             NotOnTuple => "not on tuple".into_cow(),
 
+            NegateWithOverflow(..) => "attempted to negate with overflow".into_cow(),
             AddiWithOverflow(..) => "attempted to add with overflow".into_cow(),
             SubiWithOverflow(..) => "attempted to sub with overflow".into_cow(),
             MuliWithOverflow(..) => "attempted to mul with overflow".into_cow(),
@@ -285,6 +293,8 @@ pub fn description(&self) -> Cow<str> {
             DivideWithOverflow   => "attempted to divide with overflow".into_cow(),
             ModuloByZero         => "attempted remainder with a divisor of zero".into_cow(),
             ModuloWithOverflow   => "attempted remainder with overflow".into_cow(),
+            ShiftLeftWithOverflow => "attempted left shift with overflow".into_cow(),
+            ShiftRightWithOverflow => "attempted right shift with overflow".into_cow(),
             MissingStructField  => "nonexistent struct field".into_cow(),
             NonConstPath        => "non-constant path in constant expr".into_cow(),
             ExpectedConstTuple => "expected constant tuple".into_cow(),
@@ -297,57 +307,294 @@ pub fn description(&self) -> Cow<str> {
     }
 }
 
+pub type EvalResult = Result<const_val, ConstEvalErr>;
+pub type CastResult = Result<const_val, ErrKind>;
+
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum IntTy { I8, I16, I32, I64 }
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum UintTy { U8, U16, U32, U64 }
+
+impl IntTy {
+    pub fn from(tcx: &ty::ctxt, t: ast::IntTy) -> IntTy {
+        let t = if let ast::TyIs = t {
+            tcx.sess.target.int_type
+        } else {
+            t
+        };
+        match t {
+            ast::TyIs => unreachable!(),
+            ast::TyI8  => IntTy::I8,
+            ast::TyI16 => IntTy::I16,
+            ast::TyI32 => IntTy::I32,
+            ast::TyI64 => IntTy::I64,
+        }
+    }
+}
+
+impl UintTy {
+    pub fn from(tcx: &ty::ctxt, t: ast::UintTy) -> UintTy {
+        let t = if let ast::TyUs = t {
+            tcx.sess.target.uint_type
+        } else {
+            t
+        };
+        match t {
+            ast::TyUs => unreachable!(),
+            ast::TyU8  => UintTy::U8,
+            ast::TyU16 => UintTy::U16,
+            ast::TyU32 => UintTy::U32,
+            ast::TyU64 => UintTy::U64,
+        }
+    }
+}
+
 macro_rules! signal {
-    ($e:expr, $ctor:ident) => {
-        return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor })
+    ($e:expr, $exn:expr) => {
+        return Err(ConstEvalErr { span: $e.span, kind: $exn })
+    }
+}
+
+// The const_{int,uint}_checked_{neg,add,sub,mul,div,shl,shr} family
+// of functions catch and signal overflow errors during constant
+// evaluation.
+//
+// They all take the operator's arguments (`a` and `b` if binary), the
+// overall expression (`e`) and, if available, whole expression's
+// concrete type (`opt_ety`).
+//
+// If the whole expression's concrete type is None, then this is a
+// constant evaluation happening before type check (e.g. in the check
+// to confirm that a pattern range's left-side is not greater than its
+// right-side). We do not do arithmetic modulo the type's bitwidth in
+// such a case; we just do 64-bit arithmetic and assume that later
+// passes will do it again with the type information, and thus do the
+// overflow checks then.
+
+pub fn const_int_checked_neg<'a>(
+    a: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
+
+    let (min,max) = match opt_ety {
+        // (-i8::MIN is itself not an i8, etc, but this is an easy way
+        // to allow literals to pass the check. Of course that does
+        // not work for i64::MIN.)
+        Some(IntTy::I8) =>  (-(i8::MAX as i64), -(i8::MIN as i64)),
+        Some(IntTy::I16) => (-(i16::MAX as i64), -(i16::MIN as i64)),
+        Some(IntTy::I32) => (-(i32::MAX as i64), -(i32::MIN as i64)),
+        None | Some(IntTy::I64) => (-i64::MAX, -(i64::MIN+1)),
     };
 
-    ($e:expr, $ctor:ident($($arg:expr),*)) => {
-        return Err(ConstEvalErr { span: $e.span, kind: ErrKind::$ctor($($arg),*) })
+    let oflo = a < min || a > max;
+    if oflo {
+        signal!(e, NegateWithOverflow(a));
+    } else {
+        Ok(const_int(-a))
+    }
+}
+
+pub fn const_uint_checked_neg<'a>(
+    a: u64, _e: &'a Expr, _opt_ety: Option<UintTy>) -> EvalResult {
+    // This always succeeds, and by definition, returns `(!a)+1`.
+    Ok(const_uint(-a))
+}
+
+macro_rules! overflow_checking_body {
+    ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident,
+     lhs: $to_8_lhs:ident $to_16_lhs:ident $to_32_lhs:ident,
+     rhs: $to_8_rhs:ident $to_16_rhs:ident $to_32_rhs:ident $to_64_rhs:ident,
+     $EnumTy:ident $T8: ident $T16: ident $T32: ident $T64: ident,
+     $result_type: ident) => { {
+        let (a,b,opt_ety) = ($a,$b,$ety);
+        match opt_ety {
+            Some($EnumTy::$T8) => match (a.$to_8_lhs(), b.$to_8_rhs()) {
+                (Some(a), Some(b)) => {
+                    let (a, oflo) = a.$overflowing_op(b);
+                    (a as $result_type, oflo)
+                }
+                (None, _) | (_, None) => (0, true)
+            },
+            Some($EnumTy::$T16) => match (a.$to_16_lhs(), b.$to_16_rhs()) {
+                (Some(a), Some(b)) => {
+                    let (a, oflo) = a.$overflowing_op(b);
+                    (a as $result_type, oflo)
+                }
+                (None, _) | (_, None) => (0, true)
+            },
+            Some($EnumTy::$T32) => match (a.$to_32_lhs(), b.$to_32_rhs()) {
+                (Some(a), Some(b)) => {
+                    let (a, oflo) = a.$overflowing_op(b);
+                    (a as $result_type, oflo)
+                }
+                (None, _) | (_, None) => (0, true)
+            },
+            None | Some($EnumTy::$T64) => match b.$to_64_rhs() {
+                Some(b) => a.$overflowing_op(b),
+                None => (0, true),
+            }
+        }
+    } }
+}
+
+macro_rules! int_arith_body {
+    ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
+        overflow_checking_body!(
+            $a, $b, $ety, $overflowing_op,
+            lhs: to_i8 to_i16 to_i32,
+            rhs: to_i8 to_i16 to_i32 to_i64, IntTy I8 I16 I32 I64, i64)
+    }
+}
+
+macro_rules! uint_arith_body {
+    ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
+        overflow_checking_body!(
+            $a, $b, $ety, $overflowing_op,
+            lhs: to_u8 to_u16 to_u32,
+            rhs: to_u8 to_u16 to_u32 to_u64, UintTy U8 U16 U32 U64, u64)
+    }
+}
+
+macro_rules! int_shift_body {
+    ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
+        overflow_checking_body!(
+            $a, $b, $ety, $overflowing_op,
+            lhs: to_i8 to_i16 to_i32,
+            rhs: to_u32 to_u32 to_u32 to_u32, IntTy I8 I16 I32 I64, i64)
     }
 }
 
-fn checked_add_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
-    let (ret, oflo) = a.overflowing_add(b);
-    if !oflo { Ok(const_int(ret)) } else { signal!(e, AddiWithOverflow(a, b)) }
+macro_rules! uint_shift_body {
+    ($a:ident, $b:ident, $ety:ident, $overflowing_op:ident) => {
+        overflow_checking_body!(
+            $a, $b, $ety, $overflowing_op,
+            lhs: to_u8 to_u16 to_u32,
+            rhs: to_u32 to_u32 to_u32 to_u32, UintTy U8 U16 U32 U64, u64)
+    }
 }
-fn checked_sub_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
-    let (ret, oflo) = a.overflowing_sub(b);
-    if !oflo { Ok(const_int(ret)) } else { signal!(e, SubiWithOverflow(a, b)) }
+
+macro_rules! pub_fn_checked_op {
+    {$fn_name:ident ($a:ident : $a_ty:ty, $b:ident : $b_ty:ty,.. $WhichTy:ident) {
+        $ret_oflo_body:ident $overflowing_op:ident
+            $const_ty:ident $signal_exn:expr
+    }} => {
+        pub fn $fn_name<'a>($a: $a_ty,
+                            $b: $b_ty,
+                            e: &'a Expr,
+                            opt_ety: Option<$WhichTy>) -> EvalResult {
+            let (ret, oflo) = $ret_oflo_body!($a, $b, opt_ety, $overflowing_op);
+            if !oflo { Ok($const_ty(ret)) } else { signal!(e, $signal_exn) }
+        }
+    }
 }
-fn checked_mul_int(e: &Expr, a: i64, b: i64) -> Result<const_val, ConstEvalErr> {
-    let (ret, oflo) = a.overflowing_mul(b);
-    if !oflo { Ok(const_int(ret)) } else { signal!(e, MuliWithOverflow(a, b)) }
+
+pub_fn_checked_op!{ const_int_checked_add(a: i64, b: i64,.. IntTy) {
+           int_arith_body overflowing_add const_int AddiWithOverflow(a, b)
+}}
+
+pub_fn_checked_op!{ const_int_checked_sub(a: i64, b: i64,.. IntTy) {
+           int_arith_body overflowing_sub const_int SubiWithOverflow(a, b)
+}}
+
+pub_fn_checked_op!{ const_int_checked_mul(a: i64, b: i64,.. IntTy) {
+           int_arith_body overflowing_mul const_int MuliWithOverflow(a, b)
+}}
+
+pub fn const_int_checked_div<'a>(
+    a: i64, b: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
+    if b == 0 { signal!(e, DivideByZero); }
+    let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_div);
+    if !oflo { Ok(const_int(ret)) } else { signal!(e, DivideWithOverflow) }
 }
 
-fn checked_add_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
-    let (ret, oflo) = a.overflowing_add(b);
-    if !oflo { Ok(const_uint(ret)) } else { signal!(e, AdduWithOverflow(a, b)) }
+pub fn const_int_checked_rem<'a>(
+    a: i64, b: i64, e: &'a Expr, opt_ety: Option<IntTy>) -> EvalResult {
+    if b == 0 { signal!(e, ModuloByZero); }
+    let (ret, oflo) = int_arith_body!(a, b, opt_ety, overflowing_rem);
+    if !oflo { Ok(const_int(ret)) } else { signal!(e, ModuloWithOverflow) }
 }
-fn checked_sub_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
-    let (ret, oflo) = a.overflowing_sub(b);
-    if !oflo { Ok(const_uint(ret)) } else { signal!(e, SubuWithOverflow(a, b)) }
+
+pub_fn_checked_op!{ const_int_checked_shl(a: i64, b: i64,.. IntTy) {
+           int_shift_body overflowing_shl const_int ShiftLeftWithOverflow
+}}
+
+pub_fn_checked_op!{ const_int_checked_shl_via_uint(a: i64, b: u64,.. IntTy) {
+           int_shift_body overflowing_shl const_int ShiftLeftWithOverflow
+}}
+
+pub_fn_checked_op!{ const_int_checked_shr(a: i64, b: i64,.. IntTy) {
+           int_shift_body overflowing_shr const_int ShiftRightWithOverflow
+}}
+
+pub_fn_checked_op!{ const_int_checked_shr_via_uint(a: i64, b: u64,.. IntTy) {
+           int_shift_body overflowing_shr const_int ShiftRightWithOverflow
+}}
+
+pub_fn_checked_op!{ const_uint_checked_add(a: u64, b: u64,.. UintTy) {
+           uint_arith_body overflowing_add const_uint AdduWithOverflow(a, b)
+}}
+
+pub_fn_checked_op!{ const_uint_checked_sub(a: u64, b: u64,.. UintTy) {
+           uint_arith_body overflowing_sub const_uint SubuWithOverflow(a, b)
+}}
+
+pub_fn_checked_op!{ const_uint_checked_mul(a: u64, b: u64,.. UintTy) {
+           uint_arith_body overflowing_mul const_uint MuluWithOverflow(a, b)
+}}
+
+pub fn const_uint_checked_div<'a>(
+    a: u64, b: u64, e: &'a Expr, opt_ety: Option<UintTy>) -> EvalResult {
+    if b == 0 { signal!(e, DivideByZero); }
+    let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_div);
+    if !oflo { Ok(const_uint(ret)) } else { signal!(e, DivideWithOverflow) }
 }
-fn checked_mul_uint(e: &Expr, a: u64, b: u64) -> Result<const_val, ConstEvalErr> {
-    let (ret, oflo) = a.overflowing_mul(b);
-    if !oflo { Ok(const_uint(ret)) } else { signal!(e, MuluWithOverflow(a, b)) }
+
+pub fn const_uint_checked_rem<'a>(
+    a: u64, b: u64, e: &'a Expr, opt_ety: Option<UintTy>) -> EvalResult {
+    if b == 0 { signal!(e, ModuloByZero); }
+    let (ret, oflo) = uint_arith_body!(a, b, opt_ety, overflowing_rem);
+    if !oflo { Ok(const_uint(ret)) } else { signal!(e, ModuloWithOverflow) }
 }
 
+pub_fn_checked_op!{ const_uint_checked_shl(a: u64, b: u64,.. UintTy) {
+           uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow
+}}
+
+pub_fn_checked_op!{ const_uint_checked_shl_via_int(a: u64, b: i64,.. UintTy) {
+           uint_shift_body overflowing_shl const_uint ShiftLeftWithOverflow
+}}
+
+pub_fn_checked_op!{ const_uint_checked_shr(a: u64, b: u64,.. UintTy) {
+           uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow
+}}
+
+pub_fn_checked_op!{ const_uint_checked_shr_via_int(a: u64, b: i64,.. UintTy) {
+           uint_shift_body overflowing_shr const_uint ShiftRightWithOverflow
+}}
 
 pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      e: &Expr,
-                                     ty_hint: Option<Ty<'tcx>>)
-                                     -> Result<const_val, ConstEvalErr> {
+                                     ty_hint: Option<Ty<'tcx>>) -> EvalResult {
     fn fromb(b: bool) -> const_val { const_int(b as i64) }
 
     let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e));
 
+    // If type of expression itself is int or uint, normalize in these
+    // bindings so that isize/usize is mapped to a type with an
+    // inherently known bitwidth.
+    let expr_int_type = ety.and_then(|ty| {
+        if let ty::ty_int(t) = ty.sty {
+            Some(IntTy::from(tcx, t)) } else { None }
+    });
+    let expr_uint_type = ety.and_then(|ty| {
+        if let ty::ty_uint(t) = ty.sty {
+            Some(UintTy::from(tcx, t)) } else { None }
+    });
+
     let result = match e.node {
       ast::ExprUnary(ast::UnNeg, ref inner) => {
         match try!(eval_const_expr_partial(tcx, &**inner, ety)) {
           const_float(f) => const_float(-f),
-          const_int(i) => const_int(-i),
-          const_uint(i) => const_uint(-i),
+          const_int(n) =>  try!(const_int_checked_neg(n, e, expr_int_type)),
+          const_uint(n) => try!(const_uint_checked_neg(n, e, expr_uint_type)),
           const_str(_) => signal!(e, NegateOnString),
           const_bool(_) => signal!(e, NegateOnBoolean),
           const_binary(_) => signal!(e, NegateOnBinary),
@@ -391,51 +638,17 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
             }
           }
           (const_int(a), const_int(b)) => {
-            let is_a_min_value = || {
-                let int_ty = match ty::expr_ty_opt(tcx, e).map(|ty| &ty.sty) {
-                    Some(&ty::ty_int(int_ty)) => int_ty,
-                    _ => return false
-                };
-                let int_ty = if let ast::TyIs = int_ty {
-                    tcx.sess.target.int_type
-                } else {
-                    int_ty
-                };
-                match int_ty {
-                    ast::TyI8 => (a as i8) == i8::MIN,
-                    ast::TyI16 =>  (a as i16) == i16::MIN,
-                    ast::TyI32 =>  (a as i32) == i32::MIN,
-                    ast::TyI64 =>  (a as i64) == i64::MIN,
-                    ast::TyIs => unreachable!()
-                }
-            };
             match op.node {
-              ast::BiAdd => try!(checked_add_int(e, a, b)),
-              ast::BiSub => try!(checked_sub_int(e, a, b)),
-              ast::BiMul => try!(checked_mul_int(e, a, b)),
-              ast::BiDiv => {
-                  if b == 0 {
-                      signal!(e, DivideByZero);
-                  } else if b == -1 && is_a_min_value() {
-                      signal!(e, DivideWithOverflow);
-                  } else {
-                      const_int(a / b)
-                  }
-              }
-              ast::BiRem => {
-                  if b == 0 {
-                      signal!(e, ModuloByZero)
-                  } else if b == -1 && is_a_min_value() {
-                      signal!(e, ModuloWithOverflow)
-                  } else {
-                      const_int(a % b)
-                  }
-              }
+              ast::BiAdd => try!(const_int_checked_add(a,b,e,expr_int_type)),
+              ast::BiSub => try!(const_int_checked_sub(a,b,e,expr_int_type)),
+              ast::BiMul => try!(const_int_checked_mul(a,b,e,expr_int_type)),
+              ast::BiDiv => try!(const_int_checked_div(a,b,e,expr_int_type)),
+              ast::BiRem => try!(const_int_checked_rem(a,b,e,expr_int_type)),
               ast::BiAnd | ast::BiBitAnd => const_int(a & b),
               ast::BiOr | ast::BiBitOr => const_int(a | b),
               ast::BiBitXor => const_int(a ^ b),
-              ast::BiShl => const_int(a << b as usize),
-              ast::BiShr => const_int(a >> b as usize),
+              ast::BiShl => try!(const_int_checked_shl(a,b,e,expr_int_type)),
+              ast::BiShr => try!(const_int_checked_shr(a,b,e,expr_int_type)),
               ast::BiEq => fromb(a == b),
               ast::BiLt => fromb(a < b),
               ast::BiLe => fromb(a <= b),
@@ -446,18 +659,16 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
           }
           (const_uint(a), const_uint(b)) => {
             match op.node {
-              ast::BiAdd => try!(checked_add_uint(e, a, b)),
-              ast::BiSub => try!(checked_sub_uint(e, a, b)),
-              ast::BiMul => try!(checked_mul_uint(e, a, b)),
-              ast::BiDiv if b == 0 => signal!(e, DivideByZero),
-              ast::BiDiv => const_uint(a / b),
-              ast::BiRem if b == 0 => signal!(e, ModuloByZero),
-              ast::BiRem => const_uint(a % b),
+              ast::BiAdd => try!(const_uint_checked_add(a,b,e,expr_uint_type)),
+              ast::BiSub => try!(const_uint_checked_sub(a,b,e,expr_uint_type)),
+              ast::BiMul => try!(const_uint_checked_mul(a,b,e,expr_uint_type)),
+              ast::BiDiv => try!(const_uint_checked_div(a,b,e,expr_uint_type)),
+              ast::BiRem => try!(const_uint_checked_rem(a,b,e,expr_uint_type)),
               ast::BiAnd | ast::BiBitAnd => const_uint(a & b),
               ast::BiOr | ast::BiBitOr => const_uint(a | b),
               ast::BiBitXor => const_uint(a ^ b),
-              ast::BiShl => const_uint(a << b as usize),
-              ast::BiShr => const_uint(a >> b as usize),
+              ast::BiShl => try!(const_uint_checked_shl(a,b,e,expr_uint_type)),
+              ast::BiShr => try!(const_uint_checked_shr(a,b,e,expr_uint_type)),
               ast::BiEq => fromb(a == b),
               ast::BiLt => fromb(a < b),
               ast::BiLe => fromb(a <= b),
@@ -469,15 +680,15 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
           // shifts can have any integral type as their rhs
           (const_int(a), const_uint(b)) => {
             match op.node {
-              ast::BiShl => const_int(a << b as usize),
-              ast::BiShr => const_int(a >> b as usize),
+              ast::BiShl => try!(const_int_checked_shl_via_uint(a,b,e,expr_int_type)),
+              ast::BiShr => try!(const_int_checked_shr_via_uint(a,b,e,expr_int_type)),
               _ => signal!(e, InvalidOpForIntUint(op.node)),
             }
           }
           (const_uint(a), const_int(b)) => {
             match op.node {
-              ast::BiShl => const_uint(a << b as usize),
-              ast::BiShr => const_uint(a >> b as usize),
+              ast::BiShl => try!(const_uint_checked_shl_via_int(a,b,e,expr_uint_type)),
+              ast::BiShr => try!(const_uint_checked_shr_via_int(a,b,e,expr_uint_type)),
               _ => signal!(e, InvalidOpForUintInt(op.node)),
             }
           }
@@ -506,10 +717,15 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
                     tcx.sess.span_fatal(target_ty.span,
                                         "target type not found for const cast")
                 });
+
         // Prefer known type to noop, but always have a type hint.
+        //
+        // FIXME (#23833): the type-hint can cause problems,
+        // e.g. `(i8::MAX + 1_i8) as u32` feeds in `u32` as result
+        // type to the sum, and thus no overflow is signaled.
         let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety);
         let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
-        match cast_const(val, ety) {
+        match cast_const(tcx, val, ety) {
             Ok(val) => val,
             Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
         }
@@ -607,39 +823,49 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
     Ok(result)
 }
 
-fn cast_const(val: const_val, ty: Ty) -> Result<const_val, ErrKind> {
-    macro_rules! define_casts {
-        ($($ty_pat:pat => (
-            $intermediate_ty:ty,
-            $const_type:ident,
-            $target_ty:ty
-        )),*) => (match ty.sty {
-            $($ty_pat => {
-                match val {
-                    const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
-                    const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
-                    const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
-                    const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
-                    _ => Err(ErrKind::CannotCastTo(stringify!($const_type))),
-                }
-            },)*
-            _ => Err(ErrKind::CannotCast),
-        })
+fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult {
+    macro_rules! convert_val {
+        ($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
+            match val {
+                const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
+                const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
+                const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
+                const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
+                _ => Err(ErrKind::CannotCastTo(stringify!($const_type))),
+            }
+        }
+    }
+
+    // Issue #23890: If isize/usize, then dispatch to appropriate target representation type
+    match (&ty.sty, tcx.sess.target.int_type, tcx.sess.target.uint_type) {
+        (&ty::ty_int(ast::TyIs), ast::TyI32, _) => return convert_val!(i32, const_int, i64),
+        (&ty::ty_int(ast::TyIs), ast::TyI64, _) => return convert_val!(i64, const_int, i64),
+        (&ty::ty_int(ast::TyIs), _, _) => panic!("unexpected target.int_type"),
+
+        (&ty::ty_uint(ast::TyUs), _, ast::TyU32) => return convert_val!(u32, const_uint, u64),
+        (&ty::ty_uint(ast::TyUs), _, ast::TyU64) => return convert_val!(u64, const_uint, u64),
+        (&ty::ty_uint(ast::TyUs), _, _) => panic!("unexpected target.uint_type"),
+
+        _ => {}
     }
 
-    define_casts!{
-        ty::ty_int(ast::TyIs) => (isize, const_int, i64),
-        ty::ty_int(ast::TyI8) => (i8, const_int, i64),
-        ty::ty_int(ast::TyI16) => (i16, const_int, i64),
-        ty::ty_int(ast::TyI32) => (i32, const_int, i64),
-        ty::ty_int(ast::TyI64) => (i64, const_int, i64),
-        ty::ty_uint(ast::TyUs) => (usize, const_uint, u64),
-        ty::ty_uint(ast::TyU8) => (u8, const_uint, u64),
-        ty::ty_uint(ast::TyU16) => (u16, const_uint, u64),
-        ty::ty_uint(ast::TyU32) => (u32, const_uint, u64),
-        ty::ty_uint(ast::TyU64) => (u64, const_uint, u64),
-        ty::ty_float(ast::TyF32) => (f32, const_float, f64),
-        ty::ty_float(ast::TyF64) => (f64, const_float, f64)
+    match ty.sty {
+        ty::ty_int(ast::TyIs) => unreachable!(),
+        ty::ty_uint(ast::TyUs) => unreachable!(),
+
+        ty::ty_int(ast::TyI8) => convert_val!(i8, const_int, i64),
+        ty::ty_int(ast::TyI16) => convert_val!(i16, const_int, i64),
+        ty::ty_int(ast::TyI32) => convert_val!(i32, const_int, i64),
+        ty::ty_int(ast::TyI64) => convert_val!(i64, const_int, i64),
+
+        ty::ty_uint(ast::TyU8) => convert_val!(u8, const_uint, u64),
+        ty::ty_uint(ast::TyU16) => convert_val!(u16, const_uint, u64),
+        ty::ty_uint(ast::TyU32) => convert_val!(u32, const_uint, u64),
+        ty::ty_uint(ast::TyU64) => convert_val!(u64, const_uint, u64),
+
+        ty::ty_float(ast::TyF32) => convert_val!(f32, const_float, f64),
+        ty::ty_float(ast::TyF64) => convert_val!(f64, const_float, f64),
+        _ => Err(ErrKind::CannotCast),
     }
 }
 
index a112ce6bd287c6053b6d2d82684ee8f9287321b0..7e436d95192f5da4b12c9965d3513cac86e5872e 100644 (file)
@@ -108,7 +108,7 @@ fn pre(&self,
             pprust::NodeIdent(_) | pprust::NodeName(_) => 0,
             pprust::NodeExpr(expr) => expr.id,
             pprust::NodeBlock(blk) => blk.id,
-            pprust::NodeItem(_) => 0,
+            pprust::NodeItem(_) | pprust::NodeSubItem(_) => 0,
             pprust::NodePat(pat) => pat.id
         };
 
index 1a054c0f464aac9afb5a91adb6f007490a8969da..c60bb229be142aba8a94353ea6dac1ce6efde82c 100644 (file)
@@ -65,7 +65,7 @@ pub enum Def {
 ///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
 ///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
 ///           base_def        depth = 2
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct PathResolution {
     pub base_def: Def,
     pub last_private: LastPrivate,
@@ -85,6 +85,17 @@ pub fn full_def(&self) -> Def {
     pub fn def_id(&self) -> ast::DefId {
         self.full_def().def_id()
     }
+
+    pub fn new(base_def: Def,
+               last_private: LastPrivate,
+               depth: usize)
+               -> PathResolution {
+        PathResolution {
+            base_def: base_def,
+            last_private: last_private,
+            depth: depth,
+        }
+    }
 }
 
 // Definition mapping
index 17b0d788590c4c18a41a33ac61a068dbc8741bf0..940dc75271c22f0a33d1585ab2af2a0eee1aede9 100644 (file)
 //! In particular, it might be enough to say (A,B) are bivariant for
 //! all (A,B).
 
-use middle::ty::BuiltinBounds;
+use super::combine::{self, CombineFields};
+use super::type_variable::{BiTo};
+
 use middle::ty::{self, Ty};
 use middle::ty::TyVar;
-use middle::infer::combine::*;
-use middle::infer::cres;
-use middle::infer::type_variable::BiTo;
-use util::ppaux::Repr;
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
+use util::ppaux::{Repr};
 
-pub struct Bivariate<'f, 'tcx: 'f> {
-    fields: CombineFields<'f, 'tcx>
+pub struct Bivariate<'a, 'tcx: 'a> {
+    fields: CombineFields<'a, 'tcx>
 }
 
-#[allow(non_snake_case)]
-pub fn Bivariate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Bivariate<'f, 'tcx> {
-    Bivariate { fields: cf }
+impl<'a, 'tcx> Bivariate<'a, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx>) -> Bivariate<'a, 'tcx> {
+        Bivariate { fields: fields }
+    }
 }
 
-impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> {
-    fn tag(&self) -> String { "Bivariate".to_string() }
-    fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
+    fn tag(&self) -> &'static str { "Bivariate" }
 
-    fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-                         -> cres<'tcx, Ty<'tcx>>
-    {
-        match v {
-            ty::Invariant => self.equate().tys(a, b),
-            ty::Covariant => self.tys(a, b),
-            ty::Contravariant => self.tys(a, b),
-            ty::Bivariant => self.tys(a, b),
-        }
-    }
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
 
-    fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-                             -> cres<'tcx, ty::Region>
-    {
-        match v {
-            ty::Invariant => self.equate().regions(a, b),
-            ty::Covariant => self.regions(a, b),
-            ty::Contravariant => self.regions(a, b),
-            ty::Bivariant => self.regions(a, b),
-        }
-    }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
-    fn regions(&self, a: ty::Region, _: ty::Region) -> cres<'tcx, ty::Region> {
-        Ok(a)
-    }
-
-    fn builtin_bounds(&self,
-                      a: BuiltinBounds,
-                      b: BuiltinBounds)
-                      -> cres<'tcx, BuiltinBounds>
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               variance: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>
     {
-        if a != b {
-            Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
-        } else {
-            Ok(a)
+        match variance {
+            // If we have Foo<A> and Foo is invariant w/r/t A,
+            // and we want to assert that
+            //
+            //     Foo<A> <: Foo<B> ||
+            //     Foo<B> <: Foo<A>
+            //
+            // then still A must equal B.
+            ty::Invariant => self.relate(a, b),
+
+            ty::Covariant => self.relate(a, b),
+            ty::Bivariant => self.relate(a, b),
+            ty::Contravariant => self.relate(a, b),
         }
     }
 
-    fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         debug!("{}.tys({}, {})", self.tag(),
                a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
         if a == b { return Ok(a); }
@@ -109,17 +97,22 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
             }
 
             _ => {
-                super_tys(self, a, b)
+                combine::super_combine_tys(self.fields.infcx, self, a, b)
             }
         }
     }
 
-    fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
-        where T : Combineable<'tcx>
+    fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> {
+        Ok(a)
+    }
+
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a,'tcx>
     {
         let a1 = ty::erase_late_bound_regions(self.tcx(), a);
         let b1 = ty::erase_late_bound_regions(self.tcx(), b);
-        let c = try!(Combineable::combine(self, &a1, &b1));
+        let c = try!(self.relate(&a1, &b1));
         Ok(ty::Binder(c))
     }
 }
index 9aa17b2b1d9fe2f6a4c6e33e0f90f14181e26515..86f12b669b35ebe42f714835d26cb2c5cb7a74dd 100644 (file)
 use super::glb::Glb;
 use super::lub::Lub;
 use super::sub::Sub;
-use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
-use super::{InferCtxt, cres};
+use super::{InferCtxt};
 use super::{MiscVariable, TypeTrace};
 use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf};
 
-use middle::subst;
-use middle::subst::{ErasedRegions, NonerasedRegions, Substs};
-use middle::ty::{FloatVar, FnSig, IntVar, TyVar};
+use middle::ty::{TyVar};
 use middle::ty::{IntType, UintType};
-use middle::ty::BuiltinBounds;
 use middle::ty::{self, Ty};
 use middle::ty_fold;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
+use middle::ty_relate::{self, Relate, RelateResult, TypeRelation};
 use util::ppaux::Repr;
 
-use std::rc::Rc;
-use syntax::ast::Unsafety;
 use syntax::ast;
-use syntax::abi;
 use syntax::codemap::Span;
 
-pub trait Combine<'tcx> : Sized {
-    fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx }
-    fn tag(&self) -> String;
-
-    fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx>;
-
-    fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields().infcx }
-    fn a_is_expected(&self) -> bool { self.fields().a_is_expected }
-    fn trace(&self) -> TypeTrace<'tcx> { self.fields().trace.clone() }
-    fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { self.fields().equate() }
-    fn bivariate<'a>(&'a self) -> Bivariate<'a, 'tcx> { self.fields().bivariate() }
-
-    fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { self.fields().sub() }
-    fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields().clone()) }
-    fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields().clone()) }
-
-    fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
-        debug!("{}.mts({}, {})",
-               self.tag(),
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
-
-        if a.mutbl != b.mutbl {
-            Err(ty::terr_mutability)
-        } else {
-            let mutbl = a.mutbl;
-            let variance = match mutbl {
-                ast::MutImmutable => ty::Covariant,
-                ast::MutMutable => ty::Invariant,
-            };
-            let ty = try!(self.tys_with_variance(variance, a.ty, b.ty));
-            Ok(ty::mt {ty: ty, mutbl: mutbl})
-        }
-    }
-
-    fn tys_with_variance(&self, variance: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-                         -> cres<'tcx, Ty<'tcx>>;
-
-    fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>;
-
-    fn regions_with_variance(&self, variance: ty::Variance, a: ty::Region, b: ty::Region)
-                             -> cres<'tcx, ty::Region>;
-
-    fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>;
-
-    fn substs(&self,
-              item_def_id: ast::DefId,
-              a_subst: &subst::Substs<'tcx>,
-              b_subst: &subst::Substs<'tcx>)
-              -> cres<'tcx, subst::Substs<'tcx>>
-    {
-        debug!("substs: item_def_id={} a_subst={} b_subst={}",
-               item_def_id.repr(self.infcx().tcx),
-               a_subst.repr(self.infcx().tcx),
-               b_subst.repr(self.infcx().tcx));
-
-        let variances = if self.infcx().tcx.variance_computed.get() {
-            Some(ty::item_variances(self.infcx().tcx, item_def_id))
-        } else {
-            None
-        };
-        self.substs_variances(variances.as_ref().map(|v| &**v), a_subst, b_subst)
-    }
-
-    fn substs_variances(&self,
-                        variances: Option<&ty::ItemVariances>,
-                        a_subst: &subst::Substs<'tcx>,
-                        b_subst: &subst::Substs<'tcx>)
-                        -> cres<'tcx, subst::Substs<'tcx>>
-    {
-        let mut substs = subst::Substs::empty();
-
-        for &space in &subst::ParamSpace::all() {
-            let a_tps = a_subst.types.get_slice(space);
-            let b_tps = b_subst.types.get_slice(space);
-            let t_variances = variances.map(|v| v.types.get_slice(space));
-            let tps = try!(relate_type_params(self, t_variances, a_tps, b_tps));
-            substs.types.replace(space, tps);
-        }
-
-        match (&a_subst.regions, &b_subst.regions) {
-            (&ErasedRegions, _) | (_, &ErasedRegions) => {
-                substs.regions = ErasedRegions;
-            }
-
-            (&NonerasedRegions(ref a), &NonerasedRegions(ref b)) => {
-                for &space in &subst::ParamSpace::all() {
-                    let a_regions = a.get_slice(space);
-                    let b_regions = b.get_slice(space);
-                    let r_variances = variances.map(|v| v.regions.get_slice(space));
-                    let regions = try!(relate_region_params(self,
-                                                            r_variances,
-                                                            a_regions,
-                                                            b_regions));
-                    substs.mut_regions().replace(space, regions);
-                }
-            }
-        }
-
-        return Ok(substs);
-
-        fn relate_type_params<'tcx, C: Combine<'tcx>>(this: &C,
-                                                      variances: Option<&[ty::Variance]>,
-                                                      a_tys: &[Ty<'tcx>],
-                                                      b_tys: &[Ty<'tcx>])
-                                                      -> cres<'tcx, Vec<Ty<'tcx>>>
-        {
-            if a_tys.len() != b_tys.len() {
-                return Err(ty::terr_ty_param_size(expected_found(this,
-                                                                 a_tys.len(),
-                                                                 b_tys.len())));
-            }
-
-            (0.. a_tys.len()).map(|i| {
-                let a_ty = a_tys[i];
-                let b_ty = b_tys[i];
-                let v = variances.map_or(ty::Invariant, |v| v[i]);
-                this.tys_with_variance(v, a_ty, b_ty)
-            }).collect()
-        }
-
-        fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C,
-                                                        variances: Option<&[ty::Variance]>,
-                                                        a_rs: &[ty::Region],
-                                                        b_rs: &[ty::Region])
-                                                        -> cres<'tcx, Vec<ty::Region>>
-        {
-            let tcx = this.infcx().tcx;
-            let num_region_params = a_rs.len();
-
-            debug!("relate_region_params(\
-                   a_rs={}, \
-                   b_rs={},
-                   variances={})",
-                   a_rs.repr(tcx),
-                   b_rs.repr(tcx),
-                   variances.repr(tcx));
-
-            assert_eq!(num_region_params,
-                       variances.map_or(num_region_params,
-                                        |v| v.len()));
-
-            assert_eq!(num_region_params, b_rs.len());
-
-            (0..a_rs.len()).map(|i| {
-                let a_r = a_rs[i];
-                let b_r = b_rs[i];
-                let variance = variances.map_or(ty::Invariant, |v| v[i]);
-                this.regions_with_variance(variance, a_r, b_r)
-            }).collect()
-        }
-    }
-
-    fn bare_fn_tys(&self, a: &ty::BareFnTy<'tcx>,
-                   b: &ty::BareFnTy<'tcx>) -> cres<'tcx, ty::BareFnTy<'tcx>> {
-        let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
-        let abi = try!(self.abi(a.abi, b.abi));
-        let sig = try!(self.binders(&a.sig, &b.sig));
-        Ok(ty::BareFnTy {unsafety: unsafety,
-                         abi: abi,
-                         sig: sig})
-    }
-
-    fn fn_sigs(&self, a: &ty::FnSig<'tcx>, b: &ty::FnSig<'tcx>) -> cres<'tcx, ty::FnSig<'tcx>> {
-        if a.variadic != b.variadic {
-            return Err(ty::terr_variadic_mismatch(expected_found(self, a.variadic, b.variadic)));
-        }
-
-        let inputs = try!(argvecs(self,
-                                  &a.inputs,
-                                  &b.inputs));
-
-        let output = try!(match (a.output, b.output) {
-            (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) =>
-                Ok(ty::FnConverging(try!(self.tys(a_ty, b_ty)))),
-            (ty::FnDiverging, ty::FnDiverging) =>
-                Ok(ty::FnDiverging),
-            (a, b) =>
-                Err(ty::terr_convergence_mismatch(
-                    expected_found(self, a != ty::FnDiverging, b != ty::FnDiverging))),
-        });
-
-        return Ok(ty::FnSig {inputs: inputs,
-                             output: output,
-                             variadic: a.variadic});
-
-
-        fn argvecs<'tcx, C>(combiner: &C,
-                            a_args: &[Ty<'tcx>],
-                            b_args: &[Ty<'tcx>])
-                            -> cres<'tcx, Vec<Ty<'tcx>>>
-                            where C: Combine<'tcx> {
-            if a_args.len() == b_args.len() {
-                a_args.iter().zip(b_args.iter())
-                    .map(|(a, b)| combiner.args(*a, *b)).collect()
-            } else {
-                Err(ty::terr_arg_count)
-            }
-        }
-    }
-
-    fn args(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
-        self.tys_with_variance(ty::Contravariant, a, b).and_then(|t| Ok(t))
-    }
-
-    fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
-        if a != b {
-            Err(ty::terr_unsafety_mismatch(expected_found(self, a, b)))
-        } else {
-            Ok(a)
-        }
-    }
-
-    fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<'tcx, abi::Abi> {
-        if a == b {
-            Ok(a)
-        } else {
-            Err(ty::terr_abi_mismatch(expected_found(self, a, b)))
-        }
-    }
-
-    fn projection_tys(&self,
-                      a: &ty::ProjectionTy<'tcx>,
-                      b: &ty::ProjectionTy<'tcx>)
-                      -> cres<'tcx, ty::ProjectionTy<'tcx>>
-    {
-        if a.item_name != b.item_name {
-            Err(ty::terr_projection_name_mismatched(
-                expected_found(self, a.item_name, b.item_name)))
-        } else {
-            let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref));
-            Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
-        }
-    }
-
-    fn projection_predicates(&self,
-                             a: &ty::ProjectionPredicate<'tcx>,
-                             b: &ty::ProjectionPredicate<'tcx>)
-                             -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
-    {
-        let projection_ty = try!(self.projection_tys(&a.projection_ty, &b.projection_ty));
-        let ty = try!(self.tys(a.ty, b.ty));
-        Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
-    }
-
-    fn projection_bounds(&self,
-                         a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
-                         b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
-                         -> cres<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
-    {
-        // To be compatible, `a` and `b` must be for precisely the
-        // same set of traits and item names. We always require that
-        // projection bounds lists are sorted by trait-def-id and item-name,
-        // so we can just iterate through the lists pairwise, so long as they are the
-        // same length.
-        if a.len() != b.len() {
-            Err(ty::terr_projection_bounds_length(expected_found(self, a.len(), b.len())))
-        } else {
-            a.iter()
-                .zip(b.iter())
-                .map(|(a, b)| self.binders(a, b))
-                .collect()
-        }
-    }
-
-    fn existential_bounds(&self,
-                          a: &ty::ExistentialBounds<'tcx>,
-                          b: &ty::ExistentialBounds<'tcx>)
-                          -> cres<'tcx, ty::ExistentialBounds<'tcx>>
-    {
-        let r = try!(self.regions_with_variance(ty::Contravariant, a.region_bound, b.region_bound));
-        let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds));
-        let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
-        Ok(ty::ExistentialBounds { region_bound: r,
-                                   builtin_bounds: nb,
-                                   projection_bounds: pb })
-    }
-
-    fn builtin_bounds(&self,
-                      a: BuiltinBounds,
-                      b: BuiltinBounds)
-                      -> cres<'tcx, BuiltinBounds>
-    {
-        // Two sets of builtin bounds are only relatable if they are
-        // precisely the same (but see the coercion code).
-        if a != b {
-            Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
-        } else {
-            Ok(a)
-        }
-    }
-
-    fn trait_refs(&self,
-                  a: &ty::TraitRef<'tcx>,
-                  b: &ty::TraitRef<'tcx>)
-                  -> cres<'tcx, ty::TraitRef<'tcx>>
-    {
-        // Different traits cannot be related
-        if a.def_id != b.def_id {
-            Err(ty::terr_traits(expected_found(self, a.def_id, b.def_id)))
-        } else {
-            let substs = try!(self.substs(a.def_id, a.substs, b.substs));
-            Ok(ty::TraitRef { def_id: a.def_id, substs: self.tcx().mk_substs(substs) })
-        }
-    }
-
-    fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
-        where T : Combineable<'tcx>;
-    // this must be overridden to do correctly, so as to account for higher-ranked
-    // behavior
-}
-
-pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> {
-    fn combine<C:Combine<'tcx>>(combiner: &C, a: &Self, b: &Self) -> cres<'tcx, Self>;
-}
-
-impl<'tcx,T> Combineable<'tcx> for Rc<T>
-    where T : Combineable<'tcx>
-{
-    fn combine<C>(combiner: &C,
-                  a: &Rc<T>,
-                  b: &Rc<T>)
-                  -> cres<'tcx, Rc<T>>
-                  where C: Combine<'tcx> {
-        Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b))))
-    }
-}
-
-impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
-    fn combine<C>(combiner: &C,
-                  a: &ty::TraitRef<'tcx>,
-                  b: &ty::TraitRef<'tcx>)
-                  -> cres<'tcx, ty::TraitRef<'tcx>>
-                  where C: Combine<'tcx> {
-        combiner.trait_refs(a, b)
-    }
-}
-
-impl<'tcx> Combineable<'tcx> for Ty<'tcx> {
-    fn combine<C>(combiner: &C,
-                  a: &Ty<'tcx>,
-                  b: &Ty<'tcx>)
-                  -> cres<'tcx, Ty<'tcx>>
-                  where C: Combine<'tcx> {
-        combiner.tys(*a, *b)
-    }
-}
-
-impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
-    fn combine<C>(combiner: &C,
-                  a: &ty::ProjectionPredicate<'tcx>,
-                  b: &ty::ProjectionPredicate<'tcx>)
-                  -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
-                  where C: Combine<'tcx> {
-        combiner.projection_predicates(a, b)
-    }
-}
-
-impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> {
-    fn combine<C>(combiner: &C,
-                  a: &ty::FnSig<'tcx>,
-                  b: &ty::FnSig<'tcx>)
-                  -> cres<'tcx, ty::FnSig<'tcx>>
-                  where C: Combine<'tcx> {
-        combiner.fn_sigs(a, b)
-    }
-}
-
 #[derive(Clone)]
 pub struct CombineFields<'a, 'tcx: 'a> {
     pub infcx: &'a InferCtxt<'a, 'tcx>,
@@ -433,234 +59,133 @@ pub struct CombineFields<'a, 'tcx: 'a> {
     pub trace: TypeTrace<'tcx>,
 }
 
-pub fn expected_found<'tcx, C, T>(this: &C,
-                                  a: T,
-                                  b: T)
-                                  -> ty::expected_found<T>
-                                  where C: Combine<'tcx> {
-    if this.a_is_expected() {
-        ty::expected_found {expected: a, found: b}
-    } else {
-        ty::expected_found {expected: b, found: a}
-    }
-}
-
-pub fn super_tys<'tcx, C>(this: &C,
-                          a: Ty<'tcx>,
-                          b: Ty<'tcx>)
-                          -> cres<'tcx, Ty<'tcx>>
-                          where C: Combine<'tcx> {
-    let tcx = this.infcx().tcx;
-    let a_sty = &a.sty;
-    let b_sty = &b.sty;
-    debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
-    return match (a_sty, b_sty) {
-        // The "subtype" ought to be handling cases involving var:
-        (&ty::ty_infer(TyVar(_)), _)
-        | (_, &ty::ty_infer(TyVar(_))) =>
-            tcx.sess.bug(
-                &format!("{}: bot and var types should have been handled ({},{})",
-                this.tag(),
-                a.repr(this.infcx().tcx),
-                b.repr(this.infcx().tcx))),
-
-        (&ty::ty_err, _) | (_, &ty::ty_err) => Ok(tcx.types.err),
+pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
+                                       relation: &mut R,
+                                       a: Ty<'tcx>,
+                                       b: Ty<'tcx>)
+                                       -> RelateResult<'tcx, Ty<'tcx>>
+    where R: TypeRelation<'a,'tcx>
+{
+    let a_is_expected = relation.a_is_expected();
 
+    match (&a.sty, &b.sty) {
         // Relate integral variables to other types
-        (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
-            try!(this.infcx().simple_vars(this.a_is_expected(),
-                                            a_id, b_id));
+        (&ty::ty_infer(ty::IntVar(a_id)), &ty::ty_infer(ty::IntVar(b_id))) => {
+            try!(infcx.int_unification_table
+                      .borrow_mut()
+                      .unify_var_var(a_id, b_id)
+                      .map_err(|e| int_unification_error(a_is_expected, e)));
             Ok(a)
         }
-        (&ty::ty_infer(IntVar(v_id)), &ty::ty_int(v)) => {
-            unify_integral_variable(this, this.a_is_expected(),
-                                    v_id, IntType(v))
+        (&ty::ty_infer(ty::IntVar(v_id)), &ty::ty_int(v)) => {
+            unify_integral_variable(infcx, a_is_expected, v_id, IntType(v))
         }
-        (&ty::ty_int(v), &ty::ty_infer(IntVar(v_id))) => {
-            unify_integral_variable(this, !this.a_is_expected(),
-                                    v_id, IntType(v))
+        (&ty::ty_int(v), &ty::ty_infer(ty::IntVar(v_id))) => {
+            unify_integral_variable(infcx, !a_is_expected, v_id, IntType(v))
         }
-        (&ty::ty_infer(IntVar(v_id)), &ty::ty_uint(v)) => {
-            unify_integral_variable(this, this.a_is_expected(),
-                                    v_id, UintType(v))
+        (&ty::ty_infer(ty::IntVar(v_id)), &ty::ty_uint(v)) => {
+            unify_integral_variable(infcx, a_is_expected, v_id, UintType(v))
         }
-        (&ty::ty_uint(v), &ty::ty_infer(IntVar(v_id))) => {
-            unify_integral_variable(this, !this.a_is_expected(),
-                                    v_id, UintType(v))
+        (&ty::ty_uint(v), &ty::ty_infer(ty::IntVar(v_id))) => {
+            unify_integral_variable(infcx, !a_is_expected, v_id, UintType(v))
         }
 
         // Relate floating-point variables to other types
-        (&ty::ty_infer(FloatVar(a_id)), &ty::ty_infer(FloatVar(b_id))) => {
-            try!(this.infcx().simple_vars(this.a_is_expected(), a_id, b_id));
+        (&ty::ty_infer(ty::FloatVar(a_id)), &ty::ty_infer(ty::FloatVar(b_id))) => {
+            try!(infcx.float_unification_table
+                      .borrow_mut()
+                      .unify_var_var(a_id, b_id)
+                      .map_err(|e| float_unification_error(relation.a_is_expected(), e)));
             Ok(a)
         }
-        (&ty::ty_infer(FloatVar(v_id)), &ty::ty_float(v)) => {
-            unify_float_variable(this, this.a_is_expected(), v_id, v)
-        }
-        (&ty::ty_float(v), &ty::ty_infer(FloatVar(v_id))) => {
-            unify_float_variable(this, !this.a_is_expected(), v_id, v)
+        (&ty::ty_infer(ty::FloatVar(v_id)), &ty::ty_float(v)) => {
+            unify_float_variable(infcx, a_is_expected, v_id, v)
         }
-
-        (&ty::ty_char, _)
-        | (&ty::ty_bool, _)
-        | (&ty::ty_int(_), _)
-        | (&ty::ty_uint(_), _)
-        | (&ty::ty_float(_), _) => {
-            if a == b {
-                Ok(a)
-            } else {
-                Err(ty::terr_sorts(expected_found(this, a, b)))
-            }
+        (&ty::ty_float(v), &ty::ty_infer(ty::FloatVar(v_id))) => {
+            unify_float_variable(infcx, !a_is_expected, v_id, v)
         }
 
-        (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if
-          a_p.idx == b_p.idx && a_p.space == b_p.space => Ok(a),
-
-        (&ty::ty_enum(a_id, a_substs), &ty::ty_enum(b_id, b_substs))
-          if a_id == b_id => {
-            let substs = try!(this.substs(a_id, a_substs, b_substs));
-            Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
+        // All other cases of inference are errors
+        (&ty::ty_infer(_), _) |
+        (_, &ty::ty_infer(_)) => {
+            Err(ty::terr_sorts(ty_relate::expected_found(relation, &a, &b)))
         }
 
-        (&ty::ty_trait(ref a_), &ty::ty_trait(ref b_)) => {
-            debug!("Trying to match traits {:?} and {:?}", a, b);
-            let principal = try!(this.binders(&a_.principal, &b_.principal));
-            let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
-            Ok(ty::mk_trait(tcx, principal, bounds))
-        }
-
-        (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
-          if a_id == b_id => {
-            let substs = try!(this.substs(a_id, a_substs, b_substs));
-            Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs)))
-        }
-
-        (&ty::ty_closure(a_id, a_substs),
-         &ty::ty_closure(b_id, b_substs))
-          if a_id == b_id => {
-            // All ty_closure types with the same id represent
-            // the (anonymous) type of the same closure expression. So
-            // all of their regions should be equated.
-            let substs = try!(this.substs_variances(None, a_substs, b_substs));
-            Ok(ty::mk_closure(tcx, a_id, tcx.mk_substs(substs)))
-        }
 
-        (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
-            let typ = try!(this.tys(a_inner, b_inner));
-            Ok(ty::mk_uniq(tcx, typ))
-        }
-
-        (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
-            let mt = try!(this.mts(a_mt, b_mt));
-            Ok(ty::mk_ptr(tcx, mt))
-        }
-
-        (&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));
-            let mt = try!(this.mts(a_mt, b_mt));
-            Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
-        }
-
-        (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => {
-            this.tys(a_t, b_t).and_then(|t| {
-                if sz_a == sz_b {
-                    Ok(ty::mk_vec(tcx, t, Some(sz_a)))
-                } else {
-                    Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b)))
-                }
-            })
-        }
-
-        (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
-            this.tys(a_t, b_t).and_then(|t| {
-                if sz_a == sz_b {
-                    Ok(ty::mk_vec(tcx, t, sz_a))
-                } else {
-                    Err(ty::terr_sorts(expected_found(this, a, b)))
-                }
-            })
-        }
-
-        (&ty::ty_str, &ty::ty_str) => Ok(ty::mk_str(tcx)),
-
-        (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
-            if as_.len() == bs.len() {
-                as_.iter().zip(bs.iter())
-                   .map(|(a, b)| this.tys(*a, *b))
-                   .collect::<Result<_, _>>()
-                   .map(|ts| ty::mk_tup(tcx, ts))
-            } else if as_.len() != 0 && bs.len() != 0 {
-                Err(ty::terr_tuple_size(
-                    expected_found(this, as_.len(), bs.len())))
-            } else {
-                Err(ty::terr_sorts(expected_found(this, a, b)))
-            }
-        }
-
-        (&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty))
-            if a_opt_def_id == b_opt_def_id =>
-        {
-            let fty = try!(this.bare_fn_tys(a_fty, b_fty));
-            Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
-        }
-
-        (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
-            let projection_ty = try!(this.projection_tys(a_data, b_data));
-            Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
-        }
-
-        _ => Err(ty::terr_sorts(expected_found(this, a, b))),
-    };
-
-    fn unify_integral_variable<'tcx, C>(this: &C,
-                                        vid_is_expected: bool,
-                                        vid: ty::IntVid,
-                                        val: ty::IntVarValue)
-                                        -> cres<'tcx, Ty<'tcx>>
-                                        where C: Combine<'tcx> {
-        try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
-        match val {
-            IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
-            UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)),
+        _ => {
+            ty_relate::super_relate_tys(relation, a, b)
         }
     }
+}
 
-    fn unify_float_variable<'tcx, C>(this: &C,
-                                     vid_is_expected: bool,
-                                     vid: ty::FloatVid,
-                                     val: ast::FloatTy)
-                                     -> cres<'tcx, Ty<'tcx>>
-                                     where C: Combine<'tcx> {
-        try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
-        Ok(ty::mk_mach_float(this.tcx(), val))
+fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+                                    vid_is_expected: bool,
+                                    vid: ty::IntVid,
+                                    val: ty::IntVarValue)
+                                    -> RelateResult<'tcx, Ty<'tcx>>
+{
+    try!(infcx
+         .int_unification_table
+         .borrow_mut()
+         .unify_var_value(vid, val)
+         .map_err(|e| int_unification_error(vid_is_expected, e)));
+    match val {
+        IntType(v) => Ok(ty::mk_mach_int(infcx.tcx, v)),
+        UintType(v) => Ok(ty::mk_mach_uint(infcx.tcx, v)),
     }
 }
 
-impl<'f, 'tcx> CombineFields<'f, 'tcx> {
-    pub fn switch_expected(&self) -> CombineFields<'f, 'tcx> {
+fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+                                 vid_is_expected: bool,
+                                 vid: ty::FloatVid,
+                                 val: ast::FloatTy)
+                                 -> RelateResult<'tcx, Ty<'tcx>>
+{
+    try!(infcx
+         .float_unification_table
+         .borrow_mut()
+         .unify_var_value(vid, val)
+         .map_err(|e| float_unification_error(vid_is_expected, e)));
+    Ok(ty::mk_mach_float(infcx.tcx, val))
+}
+
+impl<'a, 'tcx> CombineFields<'a, 'tcx> {
+    pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
+        self.infcx.tcx
+    }
+
+    pub fn switch_expected(&self) -> CombineFields<'a, 'tcx> {
         CombineFields {
             a_is_expected: !self.a_is_expected,
             ..(*self).clone()
         }
     }
 
-    fn equate(&self) -> Equate<'f, 'tcx> {
-        Equate((*self).clone())
+    pub fn equate(&self) -> Equate<'a, 'tcx> {
+        Equate::new(self.clone())
+    }
+
+    pub fn bivariate(&self) -> Bivariate<'a, 'tcx> {
+        Bivariate::new(self.clone())
+    }
+
+    pub fn sub(&self) -> Sub<'a, 'tcx> {
+        Sub::new(self.clone())
     }
 
-    fn bivariate(&self) -> Bivariate<'f, 'tcx> {
-        Bivariate((*self).clone())
+    pub fn lub(&self) -> Lub<'a, 'tcx> {
+        Lub::new(self.clone())
     }
 
-    fn sub(&self) -> Sub<'f, 'tcx> {
-        Sub((*self).clone())
+    pub fn glb(&self) -> Glb<'a, 'tcx> {
+        Glb::new(self.clone())
     }
 
     pub fn instantiate(&self,
                        a_ty: Ty<'tcx>,
                        dir: RelationDir,
                        b_vid: ty::TyVid)
-                       -> cres<'tcx, ()>
+                       -> RelateResult<'tcx, ()>
     {
         let tcx = self.infcx.tcx;
         let mut stack = Vec::new();
@@ -724,15 +249,12 @@ pub fn instantiate(&self,
             // relations wind up attributed to the same spans. We need
             // to associate causes/spans with each of the relations in
             // the stack to get this right.
-            match dir {
-                BiTo => try!(self.bivariate().tys(a_ty, b_ty)),
-
-                EqTo => try!(self.equate().tys(a_ty, b_ty)),
-
-                SubtypeOf => try!(self.sub().tys(a_ty, b_ty)),
-
-                SupertypeOf => try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)),
-            };
+            try!(match dir {
+                BiTo => self.bivariate().relate(&a_ty, &b_ty),
+                EqTo => self.equate().relate(&a_ty, &b_ty),
+                SubtypeOf => self.sub().relate(&a_ty, &b_ty),
+                SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty),
+            });
         }
 
         Ok(())
@@ -746,7 +268,7 @@ fn generalize(&self,
                   ty: Ty<'tcx>,
                   for_vid: ty::TyVid,
                   make_region_vars: bool)
-                  -> cres<'tcx, Ty<'tcx>>
+                  -> RelateResult<'tcx, Ty<'tcx>>
     {
         let mut generalize = Generalizer {
             infcx: self.infcx,
@@ -839,3 +361,37 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
         self.infcx.next_region_var(MiscVariable(self.span))
     }
 }
+
+pub trait RelateResultCompare<'tcx, T> {
+    fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
+        F: FnOnce() -> ty::type_err<'tcx>;
+}
+
+impl<'tcx, T:Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'tcx, T> {
+    fn compare<F>(&self, t: T, f: F) -> RelateResult<'tcx, T> where
+        F: FnOnce() -> ty::type_err<'tcx>,
+    {
+        self.clone().and_then(|s| {
+            if s == t {
+                self.clone()
+            } else {
+                Err(f())
+            }
+        })
+    }
+}
+
+fn int_unification_error<'tcx>(a_is_expected: bool, v: (ty::IntVarValue, ty::IntVarValue))
+                               -> ty::type_err<'tcx>
+{
+    let (a, b) = v;
+    ty::terr_int_mismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b))
+}
+
+fn float_unification_error<'tcx>(a_is_expected: bool,
+                                 v: (ast::FloatTy, ast::FloatTy))
+                                 -> ty::type_err<'tcx>
+{
+    let (a, b) = v;
+    ty::terr_float_mismatch(ty_relate::expected_found_bool(a_is_expected, &a, &b))
+}
index 59ed2dfd24f258f8b33aa76cc8fe34fa56abf8dc..2003f459d89b42cb895625da636b8d3e74ecb04f 100644 (file)
@@ -8,51 +8,43 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use super::combine::{self, CombineFields};
+use super::higher_ranked::HigherRankedRelations;
+use super::{Subtype};
+use super::type_variable::{EqTo};
+
 use middle::ty::{self, Ty};
 use middle::ty::TyVar;
-use middle::infer::combine::*;
-use middle::infer::cres;
-use middle::infer::Subtype;
-use middle::infer::type_variable::EqTo;
-use util::ppaux::Repr;
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
+use util::ppaux::{Repr};
 
-pub struct Equate<'f, 'tcx: 'f> {
-    fields: CombineFields<'f, 'tcx>
+pub struct Equate<'a, 'tcx: 'a> {
+    fields: CombineFields<'a, 'tcx>
 }
 
-#[allow(non_snake_case)]
-pub fn Equate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Equate<'f, 'tcx> {
-    Equate { fields: cf }
+impl<'a, 'tcx> Equate<'a, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx>) -> Equate<'a, 'tcx> {
+        Equate { fields: fields }
+    }
 }
 
-impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> {
-    fn tag(&self) -> String { "Equate".to_string() }
-    fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
+impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
+    fn tag(&self) -> &'static str { "Equate" }
 
-    fn tys_with_variance(&self, _: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-                         -> cres<'tcx, Ty<'tcx>>
-    {
-        // Once we're equating, it doesn't matter what the variance is.
-        self.tys(a, b)
-    }
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
 
-    fn regions_with_variance(&self, _: ty::Variance, a: ty::Region, b: ty::Region)
-                             -> cres<'tcx, ty::Region>
-    {
-        // Once we're equating, it doesn't matter what the variance is.
-        self.regions(a, b)
-    }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
-    fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
-               self.tag(),
-               a.repr(self.fields.infcx.tcx),
-               b.repr(self.fields.infcx.tcx));
-        self.infcx().region_vars.make_eqregion(Subtype(self.trace()), a, b);
-        Ok(a)
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               _: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>
+    {
+        self.relate(a, b)
     }
 
-    fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
         debug!("{}.tys({}, {})", self.tag(),
                a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
         if a == b { return Ok(a); }
@@ -77,15 +69,26 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
             }
 
             _ => {
-                super_tys(self, a, b)
+                combine::super_combine_tys(self.fields.infcx, self, a, b)
             }
         }
     }
 
-    fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
-        where T : Combineable<'tcx>
+    fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
+        debug!("{}.regions({}, {})",
+               self.tag(),
+               a.repr(self.fields.infcx.tcx),
+               b.repr(self.fields.infcx.tcx));
+        let origin = Subtype(self.fields.trace.clone());
+        self.fields.infcx.region_vars.make_eqregion(origin, a, b);
+        Ok(a)
+    }
+
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a, 'tcx>
     {
-        try!(self.sub().binders(a, b));
-        self.sub().binders(b, a)
+        try!(self.fields.higher_ranked_sub(a, b));
+        self.fields.higher_ranked_sub(b, a)
     }
 }
index e41b949d5df1d75cb98d80b57fccc83bb79a76eb..29f74d12ea3e814bb82c3030687b78d9eb7bd534 100644 (file)
@@ -37,7 +37,7 @@
 use std::collections::hash_map::{self, Entry};
 
 use super::InferCtxt;
-use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
+use super::unify::ToType;
 
 pub struct TypeFreshener<'a, 'tcx:'a> {
     infcx: &'a InferCtxt<'a, 'tcx>,
@@ -104,29 +104,38 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+        let tcx = self.infcx.tcx;
+
         match t.sty {
             ty::ty_infer(ty::TyVar(v)) => {
-                self.freshen(self.infcx.type_variables.borrow().probe(v),
-                               ty::TyVar(v),
-                               ty::FreshTy)
+                self.freshen(
+                    self.infcx.type_variables.borrow().probe(v),
+                    ty::TyVar(v),
+                    ty::FreshTy)
             }
 
             ty::ty_infer(ty::IntVar(v)) => {
-                self.freshen(self.infcx.probe_var(v),
-                             ty::IntVar(v),
-                             ty::FreshIntTy)
+                self.freshen(
+                    self.infcx.int_unification_table.borrow_mut()
+                                                    .probe(v)
+                                                    .map(|v| v.to_type(tcx)),
+                    ty::IntVar(v),
+                    ty::FreshIntTy)
             }
 
             ty::ty_infer(ty::FloatVar(v)) => {
-                self.freshen(self.infcx.probe_var(v),
-                             ty::FloatVar(v),
-                             ty::FreshIntTy)
+                self.freshen(
+                    self.infcx.float_unification_table.borrow_mut()
+                                                      .probe(v)
+                                                      .map(|v| v.to_type(tcx)),
+                    ty::FloatVar(v),
+                    ty::FreshIntTy)
             }
 
             ty::ty_infer(ty::FreshTy(c)) |
             ty::ty_infer(ty::FreshIntTy(c)) => {
                 if c >= self.freshen_count {
-                    self.tcx().sess.bug(
+                    tcx.sess.bug(
                         &format!("Encountered a freshend type with id {} \
                                   but our counter is only at {}",
                                  c,
index 3b83d37f58234a6f046cffdadaff8fe209470867..5822fb0f2d432fba8d7c3fe10959268c158d3fc4 100644 (file)
@@ -8,67 +8,79 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::*;
-use super::lattice::*;
+use super::combine::CombineFields;
 use super::higher_ranked::HigherRankedRelations;
-use super::cres;
+use super::InferCtxt;
+use super::lattice::{self, LatticeDir};
 use super::Subtype;
 
 use middle::ty::{self, Ty};
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use util::ppaux::Repr;
 
 /// "Greatest lower bound" (common subtype)
-pub struct Glb<'f, 'tcx: 'f> {
-    fields: CombineFields<'f, 'tcx>
+pub struct Glb<'a, 'tcx: 'a> {
+    fields: CombineFields<'a, 'tcx>
 }
 
-#[allow(non_snake_case)]
-pub fn Glb<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Glb<'f, 'tcx> {
-    Glb { fields: cf }
+impl<'a, 'tcx> Glb<'a, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx>) -> Glb<'a, 'tcx> {
+        Glb { fields: fields }
+    }
 }
 
-impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
-    fn tag(&self) -> String { "Glb".to_string() }
-    fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
+    fn tag(&self) -> &'static str { "Glb" }
+
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
+
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
-    fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-                         -> cres<'tcx, Ty<'tcx>>
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               variance: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>
     {
-        match v {
-            ty::Invariant => self.equate().tys(a, b),
-            ty::Covariant => self.tys(a, b),
-            ty::Bivariant => self.bivariate().tys(a, b),
-            ty::Contravariant => self.lub().tys(a, b),
+        match variance {
+            ty::Invariant => self.fields.equate().relate(a, b),
+            ty::Covariant => self.relate(a, b),
+            ty::Bivariant => self.fields.bivariate().relate(a, b),
+            ty::Contravariant => self.fields.lub().relate(a, b),
         }
     }
 
-    fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-                             -> cres<'tcx, ty::Region>
-    {
-        match v {
-            ty::Invariant => self.equate().regions(a, b),
-            ty::Covariant => self.regions(a, b),
-            ty::Bivariant => self.bivariate().regions(a, b),
-            ty::Contravariant => self.lub().regions(a, b),
-        }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        lattice::super_lattice_tys(self, a, b)
     }
 
-    fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
+    fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
         debug!("{}.regions({}, {})",
                self.tag(),
                a.repr(self.fields.infcx.tcx),
                b.repr(self.fields.infcx.tcx));
 
-        Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
+        let origin = Subtype(self.fields.trace.clone());
+        Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b))
     }
 
-    fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
-        super_lattice_tys(self, a, b)
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a, 'tcx>
+    {
+        self.fields.higher_ranked_glb(a, b)
     }
+}
 
-    fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
-        where T : Combineable<'tcx>
-    {
-        self.higher_ranked_glb(a, b)
+impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
+        self.fields.infcx
+    }
+
+    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+        let mut sub = self.fields.sub();
+        try!(sub.relate(&v, &a));
+        try!(sub.relate(&v, &b));
+        Ok(())
     }
 }
index 16b387330b9efea402867d39e78c64e76cbeefeb..f347d28b93c2b0aa06f41e6e4dd00abedc938ae1 100644 (file)
 //! Helper routines for higher-ranked things. See the `doc` module at
 //! the end of the file for details.
 
-use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType, SkolemizationMap};
-use super::combine::{Combine, Combineable};
+use super::{CombinedSnapshot, InferCtxt, HigherRankedType, SkolemizationMap};
+use super::combine::CombineFields;
 
 use middle::subst;
 use middle::ty::{self, Binder};
 use middle::ty_fold::{self, TypeFoldable};
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use syntax::codemap::Span;
 use util::nodemap::{FnvHashMap, FnvHashSet};
 use util::ppaux::Repr;
 
-pub trait HigherRankedRelations<'tcx> {
-    fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binder<T>>
-        where T : Combineable<'tcx>;
+pub trait HigherRankedRelations<'a,'tcx> {
+    fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
+        where T: Relate<'a,'tcx>;
 
-    fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binder<T>>
-        where T : Combineable<'tcx>;
+    fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
+        where T: Relate<'a,'tcx>;
 
-    fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binder<T>>
-        where T : Combineable<'tcx>;
+    fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
+        where T: Relate<'a,'tcx>;
 }
 
 trait InferCtxtExt {
@@ -40,15 +41,15 @@ fn region_vars_confined_to_snapshot(&self,
                                         -> Vec<ty::RegionVid>;
 }
 
-impl<'tcx,C> HigherRankedRelations<'tcx> for C
-    where C : Combine<'tcx>
-{
+impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
     fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
-                            -> cres<'tcx, Binder<T>>
-        where T : Combineable<'tcx>
+                            -> RelateResult<'tcx, Binder<T>>
+        where T: Relate<'a,'tcx>
     {
+        let tcx = self.infcx.tcx;
+
         debug!("higher_ranked_sub(a={}, b={})",
-               a.repr(self.tcx()), b.repr(self.tcx()));
+               a.repr(tcx), b.repr(tcx));
 
         // Rather than checking the subtype relationship between `a` and `b`
         // as-is, we need to do some extra work here in order to make sure
@@ -60,32 +61,32 @@ fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
 
         // Start a snapshot so we can examine "all bindings that were
         // created as part of this type comparison".
-        return self.infcx().try(|snapshot| {
+        return self.infcx.commit_if_ok(|snapshot| {
             // First, we instantiate each bound region in the subtype with a fresh
             // region variable.
             let (a_prime, _) =
-                self.infcx().replace_late_bound_regions_with_fresh_var(
-                    self.trace().origin.span(),
+                self.infcx.replace_late_bound_regions_with_fresh_var(
+                    self.trace.origin.span(),
                     HigherRankedType,
                     a);
 
             // Second, we instantiate each bound region in the supertype with a
             // fresh concrete region.
             let (b_prime, skol_map) =
-                self.infcx().skolemize_late_bound_regions(b, snapshot);
+                self.infcx.skolemize_late_bound_regions(b, snapshot);
 
-            debug!("a_prime={}", a_prime.repr(self.tcx()));
-            debug!("b_prime={}", b_prime.repr(self.tcx()));
+            debug!("a_prime={}", a_prime.repr(tcx));
+            debug!("b_prime={}", b_prime.repr(tcx));
 
             // Compare types now that bound regions have been replaced.
-            let result = try!(Combineable::combine(self, &a_prime, &b_prime));
+            let result = try!(self.sub().relate(&a_prime, &b_prime));
 
             // Presuming type comparison succeeds, we need to check
             // that the skolemized regions do not "leak".
-            match leak_check(self.infcx(), &skol_map, snapshot) {
+            match leak_check(self.infcx, &skol_map, snapshot) {
                 Ok(()) => { }
                 Err((skol_br, tainted_region)) => {
-                    if self.a_is_expected() {
+                    if self.a_is_expected {
                         debug!("Not as polymorphic!");
                         return Err(ty::terr_regions_insufficiently_polymorphic(skol_br,
                                                                                tainted_region));
@@ -98,42 +99,42 @@ fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
             }
 
             debug!("higher_ranked_sub: OK result={}",
-                   result.repr(self.tcx()));
+                   result.repr(tcx));
 
             Ok(ty::Binder(result))
         });
     }
 
-    fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binder<T>>
-        where T : Combineable<'tcx>
+    fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
+        where T: Relate<'a,'tcx>
     {
         // Start a snapshot so we can examine "all bindings that were
         // created as part of this type comparison".
-        return self.infcx().try(|snapshot| {
+        return self.infcx.commit_if_ok(|snapshot| {
             // Instantiate each bound region with a fresh region variable.
-            let span = self.trace().origin.span();
+            let span = self.trace.origin.span();
             let (a_with_fresh, a_map) =
-                self.infcx().replace_late_bound_regions_with_fresh_var(
+                self.infcx.replace_late_bound_regions_with_fresh_var(
                     span, HigherRankedType, a);
             let (b_with_fresh, _) =
-                self.infcx().replace_late_bound_regions_with_fresh_var(
+                self.infcx.replace_late_bound_regions_with_fresh_var(
                     span, HigherRankedType, b);
 
             // Collect constraints.
             let result0 =
-                try!(Combineable::combine(self, &a_with_fresh, &b_with_fresh));
+                try!(self.lub().relate(&a_with_fresh, &b_with_fresh));
             let result0 =
-                self.infcx().resolve_type_vars_if_possible(&result0);
+                self.infcx.resolve_type_vars_if_possible(&result0);
             debug!("lub result0 = {}", result0.repr(self.tcx()));
 
             // Generalize the regions appearing in result0 if possible
-            let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot);
-            let span = self.trace().origin.span();
+            let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
+            let span = self.trace.origin.span();
             let result1 =
                 fold_regions_in(
                     self.tcx(),
                     &result0,
-                    |r, debruijn| generalize_region(self.infcx(), span, snapshot, debruijn,
+                    |r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
                                                     &new_vars, &a_map, r));
 
             debug!("lub({},{}) = {}",
@@ -194,40 +195,40 @@ fn generalize_region(infcx: &InferCtxt,
         }
     }
 
-    fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> cres<'tcx, Binder<T>>
-        where T : Combineable<'tcx>
+    fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
+        where T: Relate<'a,'tcx>
     {
-        debug!("{}.higher_ranked_glb({}, {})",
-               self.tag(), a.repr(self.tcx()), b.repr(self.tcx()));
+        debug!("higher_ranked_glb({}, {})",
+               a.repr(self.tcx()), b.repr(self.tcx()));
 
         // Make a snapshot so we can examine "all bindings that were
         // created as part of this type comparison".
-        return self.infcx().try(|snapshot| {
+        return self.infcx.commit_if_ok(|snapshot| {
             // Instantiate each bound region with a fresh region variable.
             let (a_with_fresh, a_map) =
-                self.infcx().replace_late_bound_regions_with_fresh_var(
-                    self.trace().origin.span(), HigherRankedType, a);
+                self.infcx.replace_late_bound_regions_with_fresh_var(
+                    self.trace.origin.span(), HigherRankedType, a);
             let (b_with_fresh, b_map) =
-                self.infcx().replace_late_bound_regions_with_fresh_var(
-                    self.trace().origin.span(), HigherRankedType, b);
+                self.infcx.replace_late_bound_regions_with_fresh_var(
+                    self.trace.origin.span(), HigherRankedType, b);
             let a_vars = var_ids(self, &a_map);
             let b_vars = var_ids(self, &b_map);
 
             // Collect constraints.
             let result0 =
-                try!(Combineable::combine(self, &a_with_fresh, &b_with_fresh));
+                try!(self.glb().relate(&a_with_fresh, &b_with_fresh));
             let result0 =
-                self.infcx().resolve_type_vars_if_possible(&result0);
+                self.infcx.resolve_type_vars_if_possible(&result0);
             debug!("glb result0 = {}", result0.repr(self.tcx()));
 
             // Generalize the regions appearing in result0 if possible
-            let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot);
-            let span = self.trace().origin.span();
+            let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
+            let span = self.trace.origin.span();
             let result1 =
                 fold_regions_in(
                     self.tcx(),
                     &result0,
-                    |r, debruijn| generalize_region(self.infcx(), span, snapshot, debruijn,
+                    |r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
                                                     &new_vars,
                                                     &a_map, &a_vars, &b_vars,
                                                     r));
@@ -332,17 +333,19 @@ fn fresh_bound_variable(infcx: &InferCtxt, debruijn: ty::DebruijnIndex) -> ty::R
     }
 }
 
-fn var_ids<'tcx, T: Combine<'tcx>>(combiner: &T,
-                                   map: &FnvHashMap<ty::BoundRegion, ty::Region>)
-                                   -> Vec<ty::RegionVid> {
-    map.iter().map(|(_, r)| match *r {
-            ty::ReInfer(ty::ReVar(r)) => { r }
-            r => {
-                combiner.infcx().tcx.sess.span_bug(
-                    combiner.trace().origin.span(),
-                    &format!("found non-region-vid: {:?}", r));
-            }
-        }).collect()
+fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx>,
+                      map: &FnvHashMap<ty::BoundRegion, ty::Region>)
+                     -> Vec<ty::RegionVid> {
+    map.iter()
+       .map(|(_, r)| match *r {
+           ty::ReInfer(ty::ReVar(r)) => { r }
+           r => {
+               fields.tcx().sess.span_bug(
+                   fields.trace.origin.span(),
+                   &format!("found non-region-vid: {:?}", r));
+           }
+       })
+       .collect()
 }
 
 fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region) -> bool {
@@ -356,8 +359,8 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
                                unbound_value: &T,
                                mut fldr: F)
                                -> T
-    where T : Combineable<'tcx>,
-          F : FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
+    where T: TypeFoldable<'tcx>,
+          F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
 {
     unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, &mut |region, current_depth| {
         // we should only be encountering "escaping" late-bound regions here,
index 9c764628c14f8602599658392514c6c62abdb76b..57001083b03e200e410d7fa0e9de3a76854a09a4 100644 (file)
 //! over a `LatticeValue`, which is a value defined with respect to
 //! a lattice.
 
-use super::*;
-use super::combine::*;
-use super::glb::Glb;
-use super::lub::Lub;
+use super::combine;
+use super::InferCtxt;
 
 use middle::ty::TyVar;
 use middle::ty::{self, Ty};
+use middle::ty_relate::{RelateResult, TypeRelation};
 use util::ppaux::Repr;
 
-pub trait LatticeDir<'tcx> {
+pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> {
+    fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
+
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
-    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()>;
-}
-
-impl<'a, 'tcx> LatticeDir<'tcx> for Lub<'a, 'tcx> {
-    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()> {
-        let sub = self.sub();
-        try!(sub.tys(a, v));
-        try!(sub.tys(b, v));
-        Ok(())
-    }
-}
-
-impl<'a, 'tcx> LatticeDir<'tcx> for Glb<'a, 'tcx> {
-    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, ()> {
-        let sub = self.sub();
-        try!(sub.tys(v, a));
-        try!(sub.tys(v, b));
-        Ok(())
-    }
+    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
 }
 
-pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L,
-                                                                 a: Ty<'tcx>,
-                                                                 b: Ty<'tcx>)
-                                                                 -> cres<'tcx, Ty<'tcx>>
+pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
+                                                        a: Ty<'tcx>,
+                                                        b: Ty<'tcx>)
+                                                        -> RelateResult<'tcx, Ty<'tcx>>
+    where 'tcx: 'a
 {
     debug!("{}.lattice_tys({}, {})",
            this.tag(),
-           a.repr(this.infcx().tcx),
-           b.repr(this.infcx().tcx));
+           a.repr(this.tcx()),
+           b.repr(this.tcx()));
 
     if a == b {
         return Ok(a);
@@ -95,7 +79,7 @@ pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L,
         }
 
         _ => {
-            super_tys(this, a, b)
+            combine::super_combine_tys(this.infcx(), this, a, b)
         }
     }
 }
index 5000ab32ff671a3af264176b55375375e61f4c47..f456687be13ac49567537768bfdc0c72f4a4a6a5 100644 (file)
@@ -8,67 +8,80 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::*;
+use super::combine::CombineFields;
 use super::higher_ranked::HigherRankedRelations;
-use super::lattice::*;
-use super::cres;
+use super::InferCtxt;
+use super::lattice::{self, LatticeDir};
 use super::Subtype;
 
 use middle::ty::{self, Ty};
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use util::ppaux::Repr;
 
 /// "Least upper bound" (common supertype)
-pub struct Lub<'f, 'tcx: 'f> {
-    fields: CombineFields<'f, 'tcx>
+pub struct Lub<'a, 'tcx: 'a> {
+    fields: CombineFields<'a, 'tcx>
 }
 
-#[allow(non_snake_case)]
-pub fn Lub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Lub<'f, 'tcx> {
-    Lub { fields: cf }
+impl<'a, 'tcx> Lub<'a, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx>) -> Lub<'a, 'tcx> {
+        Lub { fields: fields }
+    }
 }
 
-impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> {
-    fn tag(&self) -> String { "Lub".to_string() }
-    fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
+    fn tag(&self) -> &'static str { "Lub" }
+
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
+
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
-    fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-                         -> cres<'tcx, Ty<'tcx>>
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               variance: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>
     {
-        match v {
-            ty::Invariant => self.equate().tys(a, b),
-            ty::Covariant => self.tys(a, b),
-            ty::Bivariant => self.bivariate().tys(a, b),
-            ty::Contravariant => self.glb().tys(a, b),
+        match variance {
+            ty::Invariant => self.fields.equate().relate(a, b),
+            ty::Covariant => self.relate(a, b),
+            ty::Bivariant => self.fields.bivariate().relate(a, b),
+            ty::Contravariant => self.fields.glb().relate(a, b),
         }
     }
 
-    fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-                             -> cres<'tcx, ty::Region>
-    {
-        match v {
-            ty::Invariant => self.equate().regions(a, b),
-            ty::Covariant => self.regions(a, b),
-            ty::Bivariant => self.bivariate().regions(a, b),
-            ty::Contravariant => self.glb().regions(a, b),
-        }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        lattice::super_lattice_tys(self, a, b)
     }
 
-    fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
+    fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
         debug!("{}.regions({}, {})",
                self.tag(),
                a.repr(self.tcx()),
                b.repr(self.tcx()));
 
-        Ok(self.infcx().region_vars.lub_regions(Subtype(self.trace()), a, b))
+        let origin = Subtype(self.fields.trace.clone());
+        Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b))
     }
 
-    fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
-        super_lattice_tys(self, a, b)
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a, 'tcx>
+    {
+        self.fields.higher_ranked_lub(a, b)
     }
+}
 
-    fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
-        where T : Combineable<'tcx>
-    {
-        self.higher_ranked_lub(a, b)
+impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
+        self.fields.infcx
+    }
+
+    fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
+        let mut sub = self.fields.sub();
+        try!(sub.relate(&a, &v));
+        try!(sub.relate(&b, &v));
+        Ok(())
     }
 }
+
index 4cc9b65c2dab300d14e8b6b637422380c66d8ef6..da811c354578de5bbc4747c3439fe9f8efa74a5c 100644 (file)
@@ -28,7 +28,8 @@
 use middle::ty::replace_late_bound_regions;
 use middle::ty::{self, Ty};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
-use std::cell::RefCell;
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
+use std::cell::{RefCell};
 use std::fmt;
 use std::rc::Rc;
 use syntax::ast;
 use util::ppaux::ty_to_string;
 use util::ppaux::{Repr, UserString};
 
-use self::combine::{Combine, Combineable, CombineFields};
+use self::combine::CombineFields;
 use self::region_inference::{RegionVarBindings, RegionSnapshot};
-use self::equate::Equate;
-use self::sub::Sub;
-use self::lub::Lub;
-use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes};
+use self::unify::{ToType, UnificationTable};
 use self::error_reporting::ErrorReporting;
 
 pub mod bivariate;
@@ -62,9 +60,7 @@
 pub mod unify;
 
 pub type Bound<T> = Option<T>;
-
-pub type cres<'tcx, T> = Result<T,ty::type_err<'tcx>>; // "combine result"
-pub type ures<'tcx> = cres<'tcx, ()>; // "unify result"
+pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
 pub type fres<T> = Result<T, fixup_err>; // "fixup result"
 
 pub struct InferCtxt<'a, 'tcx: 'a> {
@@ -265,7 +261,7 @@ pub enum LateBoundRegionConversionTime {
 ///
 /// See `error_reporting.rs` for more details
 #[derive(Clone, Debug)]
-pub enum RegionVariableOrigin<'tcx> {
+pub enum RegionVariableOrigin {
     // Region variables created for ill-categorized reasons,
     // mostly indicates places in need of refactoring
     MiscVariable(Span),
@@ -280,7 +276,7 @@ pub enum RegionVariableOrigin<'tcx> {
     Autoref(Span),
 
     // Regions created as part of an automatic coercion
-    Coercion(TypeTrace<'tcx>),
+    Coercion(Span),
 
     // Region variables created as the values for early-bound regions
     EarlyBoundRegion(Span, ast::Name),
@@ -343,8 +339,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
         values: Types(expected_found(a_is_expected, a, b))
     };
 
-    let result =
-        cx.commit_if_ok(|| cx.lub(a_is_expected, trace.clone()).tys(a, b));
+    let result = cx.commit_if_ok(|_| cx.lub(a_is_expected, trace.clone()).relate(&a, &b));
     match result {
         Ok(t) => t,
         Err(ref err) => {
@@ -359,29 +354,28 @@ pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                           origin: TypeOrigin,
                           a: Ty<'tcx>,
                           b: Ty<'tcx>)
-                          -> ures<'tcx>
+                          -> UnitResult<'tcx>
 {
     debug!("mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
-    cx.commit_if_ok(|| {
-        cx.sub_types(a_is_expected, origin, a, b)
-    })
+    cx.sub_types(a_is_expected, origin, a, b)
 }
 
 pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                               a: Ty<'tcx>,
                               b: Ty<'tcx>)
-                              -> ures<'tcx> {
+                              -> UnitResult<'tcx> {
     debug!("can_mk_subty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
     cx.probe(|_| {
         let trace = TypeTrace {
             origin: Misc(codemap::DUMMY_SP),
             values: Types(expected_found(true, a, b))
         };
-        cx.sub(true, trace).tys(a, b).to_ures()
+        cx.sub(true, trace).relate(&a, &b).map(|_| ())
     })
 }
 
-pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> ures<'tcx>
+pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
+                             -> UnitResult<'tcx>
 {
     cx.can_equate(&a, &b)
 }
@@ -401,11 +395,10 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                          origin: TypeOrigin,
                          a: Ty<'tcx>,
                          b: Ty<'tcx>)
-                         -> ures<'tcx>
+                         -> UnitResult<'tcx>
 {
     debug!("mk_eqty({} <: {})", a.repr(cx.tcx), b.repr(cx.tcx));
-    cx.commit_if_ok(
-        || cx.eq_types(a_is_expected, origin, a, b))
+    cx.commit_if_ok(|_| cx.eq_types(a_is_expected, origin, a, b))
 }
 
 pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
@@ -413,12 +406,11 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
                                    origin: TypeOrigin,
                                    a: ty::PolyTraitRef<'tcx>,
                                    b: ty::PolyTraitRef<'tcx>)
-                                   -> ures<'tcx>
+                                   -> UnitResult<'tcx>
 {
     debug!("mk_sub_trait_refs({} <: {})",
            a.repr(cx.tcx), b.repr(cx.tcx));
-    cx.commit_if_ok(
-        || cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone()))
+    cx.commit_if_ok(|_| cx.sub_poly_trait_refs(a_is_expected, origin, a.clone(), b.clone()))
 }
 
 fn expected_found<T>(a_is_expected: bool,
@@ -433,57 +425,6 @@ fn expected_found<T>(a_is_expected: bool,
     }
 }
 
-trait then<'tcx> {
-    fn then<T, F>(&self, f: F) -> Result<T, ty::type_err<'tcx>> where
-        T: Clone,
-        F: FnOnce() -> Result<T, ty::type_err<'tcx>>;
-}
-
-impl<'tcx> then<'tcx> for ures<'tcx> {
-    fn then<T, F>(&self, f: F) -> Result<T, ty::type_err<'tcx>> where
-        T: Clone,
-        F: FnOnce() -> Result<T, ty::type_err<'tcx>>,
-    {
-        self.and_then(move |_| f())
-    }
-}
-
-trait ToUres<'tcx> {
-    fn to_ures(&self) -> ures<'tcx>;
-}
-
-impl<'tcx, T> ToUres<'tcx> for cres<'tcx, T> {
-    fn to_ures(&self) -> ures<'tcx> {
-        match *self {
-          Ok(ref _v) => Ok(()),
-          Err(ref e) => Err((*e))
-        }
-    }
-}
-
-trait CresCompare<'tcx, T> {
-    fn compare<F>(&self, t: T, f: F) -> cres<'tcx, T> where
-        F: FnOnce() -> ty::type_err<'tcx>;
-}
-
-impl<'tcx, T:Clone + PartialEq> CresCompare<'tcx, T> for cres<'tcx, T> {
-    fn compare<F>(&self, t: T, f: F) -> cres<'tcx, T> where
-        F: FnOnce() -> ty::type_err<'tcx>,
-    {
-        (*self).clone().and_then(move |s| {
-            if s == t {
-                (*self).clone()
-            } else {
-                Err(f())
-            }
-        })
-    }
-}
-
-pub fn uok<'tcx>() -> ures<'tcx> {
-    Ok(())
-}
-
 #[must_use = "once you start a snapshot, you should always consume it"]
 pub struct CombinedSnapshot {
     type_snapshot: type_variable::Snapshot,
@@ -512,41 +453,56 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
         use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat};
         match ty.sty {
             ty::ty_infer(ty::IntVar(vid)) => {
-                match self.int_unification_table.borrow_mut().get(self.tcx, vid).value {
-                    None => UnconstrainedInt,
-                    _ => Neither,
+                if self.int_unification_table.borrow_mut().has_value(vid) {
+                    Neither
+                } else {
+                    UnconstrainedInt
                 }
             },
             ty::ty_infer(ty::FloatVar(vid)) => {
-                match self.float_unification_table.borrow_mut().get(self.tcx, vid).value {
-                    None => return UnconstrainedFloat,
-                    _ => Neither,
+                if self.float_unification_table.borrow_mut().has_value(vid) {
+                    Neither
+                } else {
+                    UnconstrainedFloat
                 }
             },
             _ => Neither,
         }
     }
 
-    pub fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-                              -> CombineFields<'b, 'tcx> {
+    fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+                      -> CombineFields<'a, 'tcx> {
         CombineFields {infcx: self,
                        a_is_expected: a_is_expected,
                        trace: trace}
     }
 
-    pub fn equate<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-                      -> Equate<'b, 'tcx> {
-        Equate(self.combine_fields(a_is_expected, trace))
+    // public so that it can be used from the rustc_driver unit tests
+    pub fn equate(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+              -> equate::Equate<'a, 'tcx>
+    {
+        self.combine_fields(a_is_expected, trace).equate()
     }
 
-    pub fn sub<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-                   -> Sub<'b, 'tcx> {
-        Sub(self.combine_fields(a_is_expected, trace))
+    // public so that it can be used from the rustc_driver unit tests
+    pub fn sub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+               -> sub::Sub<'a, 'tcx>
+    {
+        self.combine_fields(a_is_expected, trace).sub()
     }
 
-    pub fn lub<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-                   -> Lub<'b, 'tcx> {
-        Lub(self.combine_fields(a_is_expected, trace))
+    // public so that it can be used from the rustc_driver unit tests
+    pub fn lub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+               -> lub::Lub<'a, 'tcx>
+    {
+        self.combine_fields(a_is_expected, trace).lub()
+    }
+
+    // public so that it can be used from the rustc_driver unit tests
+    pub fn glb(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
+               -> glb::Glb<'a, 'tcx>
+    {
+        self.combine_fields(a_is_expected, trace).glb()
     }
 
     fn start_snapshot(&self) -> CombinedSnapshot {
@@ -609,11 +565,19 @@ pub fn commit_unconditionally<R, F>(&self, f: F) -> R where
         r
     }
 
-    /// Execute `f` and commit the bindings if successful
+    /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`
     pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
-        F: FnOnce() -> Result<T, E>
+        F: FnOnce(&CombinedSnapshot) -> Result<T, E>
     {
-        self.commit_unconditionally(move || self.try(move |_| f()))
+        debug!("commit_if_ok()");
+        let snapshot = self.start_snapshot();
+        let r = f(&snapshot);
+        debug!("commit_if_ok() -- r.is_ok() = {}", r.is_ok());
+        match r {
+            Ok(_) => { self.commit_from(snapshot); }
+            Err(_) => { self.rollback_to(snapshot); }
+        }
+        r
     }
 
     /// Execute `f` and commit only the region bindings if successful.
@@ -628,7 +592,7 @@ pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
                                float_snapshot,
                                region_vars_snapshot } = self.start_snapshot();
 
-        let r = self.try(move |_| f());
+        let r = self.commit_if_ok(|_| f());
 
         // Roll back any non-region bindings - they should be resolved
         // inside `f`, with, e.g. `resolve_type_vars_if_possible`.
@@ -649,25 +613,6 @@ pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
         r
     }
 
-    /// Execute `f`, unroll bindings on panic
-    pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
-        F: FnOnce(&CombinedSnapshot) -> Result<T, E>
-    {
-        debug!("try()");
-        let snapshot = self.start_snapshot();
-        let r = f(&snapshot);
-        debug!("try() -- r.is_ok() = {}", r.is_ok());
-        match r {
-            Ok(_) => {
-                self.commit_from(snapshot);
-            }
-            Err(_) => {
-                self.rollback_to(snapshot);
-            }
-        }
-        r
-    }
-
     /// Execute `f` then unroll any bindings it creates
     pub fn probe<R, F>(&self, f: F) -> R where
         F: FnOnce(&CombinedSnapshot) -> R,
@@ -691,12 +636,12 @@ pub fn sub_types(&self,
                      origin: TypeOrigin,
                      a: Ty<'tcx>,
                      b: Ty<'tcx>)
-                     -> ures<'tcx>
+                     -> UnitResult<'tcx>
     {
         debug!("sub_types({} <: {})", a.repr(self.tcx), b.repr(self.tcx));
-        self.commit_if_ok(|| {
+        self.commit_if_ok(|_| {
             let trace = TypeTrace::types(origin, a_is_expected, a, b);
-            self.sub(a_is_expected, trace).tys(a, b).to_ures()
+            self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ())
         })
     }
 
@@ -705,11 +650,11 @@ pub fn eq_types(&self,
                     origin: TypeOrigin,
                     a: Ty<'tcx>,
                     b: Ty<'tcx>)
-                    -> ures<'tcx>
+                    -> UnitResult<'tcx>
     {
-        self.commit_if_ok(|| {
+        self.commit_if_ok(|_| {
             let trace = TypeTrace::types(origin, a_is_expected, a, b);
-            self.equate(a_is_expected, trace).tys(a, b).to_ures()
+            self.equate(a_is_expected, trace).relate(&a, &b).map(|_| ())
         })
     }
 
@@ -718,17 +663,17 @@ pub fn sub_trait_refs(&self,
                           origin: TypeOrigin,
                           a: Rc<ty::TraitRef<'tcx>>,
                           b: Rc<ty::TraitRef<'tcx>>)
-                          -> ures<'tcx>
+                          -> UnitResult<'tcx>
     {
         debug!("sub_trait_refs({} <: {})",
                a.repr(self.tcx),
                b.repr(self.tcx));
-        self.commit_if_ok(|| {
+        self.commit_if_ok(|_| {
             let trace = TypeTrace {
                 origin: origin,
                 values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
             };
-            self.sub(a_is_expected, trace).trait_refs(&*a, &*b).to_ures()
+            self.sub(a_is_expected, trace).relate(&*a, &*b).map(|_| ())
         })
     }
 
@@ -737,17 +682,17 @@ pub fn sub_poly_trait_refs(&self,
                                origin: TypeOrigin,
                                a: ty::PolyTraitRef<'tcx>,
                                b: ty::PolyTraitRef<'tcx>)
-                               -> ures<'tcx>
+                               -> UnitResult<'tcx>
     {
         debug!("sub_poly_trait_refs({} <: {})",
                a.repr(self.tcx),
                b.repr(self.tcx));
-        self.commit_if_ok(|| {
+        self.commit_if_ok(|_| {
             let trace = TypeTrace {
                 origin: origin,
                 values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
             };
-            self.sub(a_is_expected, trace).binders(&a, &b).to_ures()
+            self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ())
         })
     }
 
@@ -774,7 +719,7 @@ pub fn skolemize_late_bound_regions<T>(&self,
     pub fn leak_check(&self,
                       skol_map: &SkolemizationMap,
                       snapshot: &CombinedSnapshot)
-                      -> ures<'tcx>
+                      -> UnitResult<'tcx>
     {
         /*! See `higher_ranked::leak_check` */
 
@@ -799,8 +744,8 @@ pub fn plug_leaks<T>(&self,
     pub fn equality_predicate(&self,
                               span: Span,
                               predicate: &ty::PolyEquatePredicate<'tcx>)
-                              -> ures<'tcx> {
-        self.try(|snapshot| {
+                              -> UnitResult<'tcx> {
+        self.commit_if_ok(|snapshot| {
             let (ty::EquatePredicate(a, b), skol_map) =
                 self.skolemize_late_bound_regions(predicate, snapshot);
             let origin = EquatePredicate(span);
@@ -812,8 +757,8 @@ pub fn equality_predicate(&self,
     pub fn region_outlives_predicate(&self,
                                      span: Span,
                                      predicate: &ty::PolyRegionOutlivesPredicate)
-                                     -> ures<'tcx> {
-        self.try(|snapshot| {
+                                     -> UnitResult<'tcx> {
+        self.commit_if_ok(|snapshot| {
             let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
                 self.skolemize_late_bound_regions(predicate, snapshot);
             let origin = RelateRegionParamBound(span);
@@ -852,7 +797,7 @@ pub fn next_float_var_id(&self) -> FloatVid {
             .new_key(None)
     }
 
-    pub fn next_region_var(&self, origin: RegionVariableOrigin<'tcx>) -> ty::Region {
+    pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region {
         ty::ReInfer(ty::ReVar(self.region_vars.new_region_var(origin)))
     }
 
@@ -948,12 +893,18 @@ pub fn shallow_resolve(&self, typ: Ty<'tcx>) -> Ty<'tcx> {
             }
 
             ty::ty_infer(ty::IntVar(v)) => {
-                self.probe_var(v)
+                self.int_unification_table
+                    .borrow_mut()
+                    .probe(v)
+                    .map(|v| v.to_type(self.tcx))
                     .unwrap_or(typ)
             }
 
             ty::ty_infer(ty::FloatVar(v)) => {
-                self.probe_var(v)
+                self.float_unification_table
+                    .borrow_mut()
+                    .probe(v)
+                    .map(|v| v.to_type(self.tcx))
                     .unwrap_or(typ)
             }
 
@@ -1104,8 +1055,8 @@ pub fn verify_generic_bound(&self,
         self.region_vars.verify_generic_bound(origin, kind, a, bs);
     }
 
-    pub fn can_equate<T>(&self, a: &T, b: &T) -> ures<'tcx>
-        where T : Combineable<'tcx> + Repr<'tcx>
+    pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx>
+        where T: Relate<'b,'tcx> + Repr<'tcx>
     {
         debug!("can_equate({}, {})", a.repr(self.tcx), b.repr(self.tcx));
         self.probe(|_| {
@@ -1116,9 +1067,8 @@ pub fn can_equate<T>(&self, a: &T, b: &T) -> ures<'tcx>
             let e = self.tcx.types.err;
             let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP),
                                     values: Types(expected_found(true, e, e)) };
-            let eq = self.equate(true, trace);
-            Combineable::combine(&eq, a, b)
-        }).to_ures()
+            self.equate(true, trace).relate(a, b)
+        }).map(|_| ())
     }
 }
 
@@ -1304,14 +1254,14 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
     }
 }
 
-impl<'tcx> RegionVariableOrigin<'tcx> {
+impl RegionVariableOrigin {
     pub fn span(&self) -> Span {
         match *self {
             MiscVariable(a) => a,
             PatternRegion(a) => a,
             AddrOfRegion(a) => a,
             Autoref(a) => a,
-            Coercion(ref a) => a.span(),
+            Coercion(a) => a,
             EarlyBoundRegion(a, _) => a,
             LateBoundRegion(a, _, _) => a,
             BoundRegionInCoherence(_) => codemap::DUMMY_SP,
@@ -1320,7 +1270,7 @@ pub fn span(&self) -> Span {
     }
 }
 
-impl<'tcx> Repr<'tcx> for RegionVariableOrigin<'tcx> {
+impl<'tcx> Repr<'tcx> for RegionVariableOrigin {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
             MiscVariable(a) => {
@@ -1333,7 +1283,7 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
                 format!("AddrOfRegion({})", a.repr(tcx))
             }
             Autoref(a) => format!("Autoref({})", a.repr(tcx)),
-            Coercion(ref a) => format!("Coercion({})", a.repr(tcx)),
+            Coercion(a) => format!("Coercion({})", a.repr(tcx)),
             EarlyBoundRegion(a, b) => {
                 format!("EarlyBoundRegion({},{})", a.repr(tcx), b.repr(tcx))
             }
index a009e0a8234b990008f7ca2304cf8400ac84d51c..e44211da4a7bb4cafc94ea5c93cecfe3d55f54f1 100644 (file)
@@ -249,114 +249,61 @@ there is a reference created whose lifetime does not enclose
 the borrow expression, we must issue sufficient restrictions to ensure
 that the pointee remains valid.
 
-## Adding closures
-
-The other significant complication to the region hierarchy is
-closures. I will describe here how closures should work, though some
-of the work to implement this model is ongoing at the time of this
-writing.
-
-The body of closures are type-checked along with the function that
-creates them. However, unlike other expressions that appear within the
-function body, it is not entirely obvious when a closure body executes
-with respect to the other expressions. This is because the closure
-body will execute whenever the closure is called; however, we can
-never know precisely when the closure will be called, especially
-without some sort of alias analysis.
-
-However, we can place some sort of limits on when the closure
-executes.  In particular, the type of every closure `fn:'r K` includes
-a region bound `'r`. This bound indicates the maximum lifetime of that
-closure; once we exit that region, the closure cannot be called
-anymore. Therefore, we say that the lifetime of the closure body is a
-sublifetime of the closure bound, but the closure body itself is unordered
-with respect to other parts of the code.
-
-For example, consider the following fragment of code:
-
-    'a: {
-         let closure: fn:'a() = || 'b: {
-             'c: ...
-         };
-         'd: ...
-    }
-
-Here we have four lifetimes, `'a`, `'b`, `'c`, and `'d`. The closure
-`closure` is bounded by the lifetime `'a`. The lifetime `'b` is the
-lifetime of the closure body, and `'c` is some statement within the
-closure body. Finally, `'d` is a statement within the outer block that
-created the closure.
-
-We can say that the closure body `'b` is a sublifetime of `'a` due to
-the closure bound. By the usual lexical scoping conventions, the
-statement `'c` is clearly a sublifetime of `'b`, and `'d` is a
-sublifetime of `'d`. However, there is no ordering between `'c` and
-`'d` per se (this kind of ordering between statements is actually only
-an issue for dataflow; passes like the borrow checker must assume that
-closures could execute at any time from the moment they are created
-until they go out of scope).
-
-### Complications due to closure bound inference
-
-There is only one problem with the above model: in general, we do not
-actually *know* the closure bounds during region inference! In fact,
-closure bounds are almost always region variables! This is very tricky
-because the inference system implicitly assumes that we can do things
-like compute the LUB of two scoped lifetimes without needing to know
-the values of any variables.
-
-Here is an example to illustrate the problem:
-
-    fn identify<T>(x: T) -> T { x }
-
-    fn foo() { // 'foo is the function body
-      'a: {
-           let closure = identity(|| 'b: {
-               'c: ...
-           });
-           'd: closure();
-      }
-      'e: ...;
-    }
-
-In this example, the closure bound is not explicit. At compile time,
-we will create a region variable (let's call it `V0`) to represent the
-closure bound.
-
-The primary difficulty arises during the constraint propagation phase.
-Imagine there is some variable with incoming edges from `'c` and `'d`.
-This means that the value of the variable must be `LUB('c,
-'d)`. However, without knowing what the closure bound `V0` is, we
-can't compute the LUB of `'c` and `'d`! Any we don't know the closure
-bound until inference is done.
-
-The solution is to rely on the fixed point nature of inference.
-Basically, when we must compute `LUB('c, 'd)`, we just use the current
-value for `V0` as the closure's bound. If `V0`'s binding should
-change, then we will do another round of inference, and the result of
-`LUB('c, 'd)` will change.
-
-One minor implication of this is that the graph does not in fact track
-the full set of dependencies between edges. We cannot easily know
-whether the result of a LUB computation will change, since there may
-be indirect dependencies on other variables that are not reflected on
-the graph. Therefore, we must *always* iterate over all edges when
-doing the fixed point calculation, not just those adjacent to nodes
-whose values have changed.
-
-Were it not for this requirement, we could in fact avoid fixed-point
-iteration altogether. In that universe, we could instead first
-identify and remove strongly connected components (SCC) in the graph.
-Note that such components must consist solely of region variables; all
-of these variables can effectively be unified into a single variable.
-Once SCCs are removed, we are left with a DAG.  At this point, we
-could walk the DAG in topological order once to compute the expanding
-nodes, and again in reverse topological order to compute the
-contracting nodes. However, as I said, this does not work given the
-current treatment of closure bounds, but perhaps in the future we can
-address this problem somehow and make region inference somewhat more
-efficient. Note that this is solely a matter of performance, not
-expressiveness.
+## Modeling closures
+
+Integrating closures properly into the model is a bit of
+work-in-progress. In an ideal world, we would model closures as
+closely as possible after their desugared equivalents. That is, a
+closure type would be modeled as a struct, and the region hierarchy of
+different closure bodies would be completely distinct from all other
+fns. We are generally moving in that direction but there are
+complications in terms of the implementation.
+
+In practice what we currently do is somewhat different. The basis for
+the current approach is the observation that the only time that
+regions from distinct fn bodies interact with one another is through
+an upvar or the type of a fn parameter (since closures live in the fn
+body namespace, they can in fact have fn parameters whose types
+include regions from the surrounding fn body). For these cases, there
+are separate mechanisms which ensure that the regions that appear in
+upvars/parameters outlive the dynamic extent of each call to the
+closure:
+
+1. Types must outlive the region of any expression where they are used.
+   For a closure type `C` to outlive a region `'r`, that implies that the
+   types of all its upvars must outlive `'r`.
+2. Parameters must outlive the region of any fn that they are passed to.
+
+Therefore, we can -- sort of -- assume that any region from an
+enclosing fns is larger than any region from one of its enclosed
+fn. And that is precisely what we do: when building the region
+hierarchy, each region lives in its own distinct subtree, but if we
+are asked to compute the `LUB(r1, r2)` of two regions, and those
+regions are in disjoint subtrees, we compare the lexical nesting of
+the two regions.
+
+*Ideas for improving the situation:* (FIXME #3696) The correctness
+argument here is subtle and a bit hand-wavy. The ideal, as stated
+earlier, would be to model things in such a way that it corresponds
+more closely to the desugared code. The best approach for doing this
+is a bit unclear: it may in fact be possible to *actually* desugar
+before we start, but I don't think so. The main option that I've been
+thinking through is imposing a "view shift" as we enter the fn body,
+so that regions appearing in the types of fn parameters and upvars are
+translated from being regions in the outer fn into free region
+parameters, just as they would be if we applied the desugaring. The
+challenge here is that type inference may not have fully run, so the
+types may not be fully known: we could probably do this translation
+lazilly, as type variables are instantiated. We would also have to
+apply a kind of inverse translation to the return value. This would be
+a good idea anyway, as right now it is possible for free regions
+instantiated within the closure to leak into the parent: this
+currently leads to type errors, since those regions cannot outlive any
+expressions within the parent hierarchy. Much like the current
+handling of closures, there are no known cases where this leads to a
+type-checking accepting incorrect code (though it sometimes rejects
+what might be considered correct code; see rust-lang/rust#22557), but
+it still doesn't feel like the right approach.
 
 ### Skolemization
 
index c432d114b6eed5cbe38d42c5dc5c4baeefb1f9a3..98347e97e09c3cb498a7692c76b7f59533a7564b 100644 (file)
@@ -18,7 +18,6 @@
 pub use self::VarValue::*;
 use self::Classification::*;
 
-use super::cres;
 use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
 
 use middle::region;
@@ -26,6 +25,7 @@
 use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
 use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
 use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
+use middle::ty_relate::RelateResult;
 use middle::graph;
 use middle::graph::{Direction, NodeIndex};
 use util::common::indenter;
@@ -115,7 +115,7 @@ pub enum RegionResolutionError<'tcx> {
     /// Could not infer a value for `v` because `sub_r <= v` (due to
     /// `sub_origin`) but `v <= sup_r` (due to `sup_origin`) and
     /// `sub_r <= sup_r` does not hold.
-    SubSupConflict(RegionVariableOrigin<'tcx>,
+    SubSupConflict(RegionVariableOrigin,
                    SubregionOrigin<'tcx>, Region,
                    SubregionOrigin<'tcx>, Region),
 
@@ -124,7 +124,7 @@ pub enum RegionResolutionError<'tcx> {
     /// Could not infer a value for `v` because `v <= r1` (due to
     /// `origin1`) and `v <= r2` (due to `origin2`) and
     /// `r1` and `r2` have no intersection.
-    SupSupConflict(RegionVariableOrigin<'tcx>,
+    SupSupConflict(RegionVariableOrigin,
                    SubregionOrigin<'tcx>, Region,
                    SubregionOrigin<'tcx>, Region),
 
@@ -132,7 +132,7 @@ pub enum RegionResolutionError<'tcx> {
     /// more specific errors message by suggesting to the user where they
     /// should put a lifetime. In those cases we process and put those errors
     /// into `ProcessedErrors` before we do any reporting.
-    ProcessedErrors(Vec<RegionVariableOrigin<'tcx>>,
+    ProcessedErrors(Vec<RegionVariableOrigin>,
                     Vec<(TypeTrace<'tcx>, ty::type_err<'tcx>)>,
                     Vec<SameRegions>),
 }
@@ -168,7 +168,7 @@ pub fn push(&mut self, other: BoundRegion) {
 
 pub struct RegionVarBindings<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    var_origins: RefCell<Vec<RegionVariableOrigin<'tcx>>>,
+    var_origins: RefCell<Vec<RegionVariableOrigin>>,
 
     // Constraints of the form `A <= B` introduced by the region
     // checker.  Here at least one of `A` and `B` must be a region
@@ -316,7 +316,7 @@ pub fn num_vars(&self) -> u32 {
         len as u32
     }
 
-    pub fn new_region_var(&self, origin: RegionVariableOrigin<'tcx>) -> RegionVid {
+    pub fn new_region_var(&self, origin: RegionVariableOrigin) -> RegionVid {
         let id = self.num_vars();
         self.var_origins.borrow_mut().push(origin.clone());
         let vid = RegionVid { index: id };
@@ -760,15 +760,17 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
             // at least as big as the block fr.scope_id".  So, we can
             // reasonably compare free regions and scopes:
             let fr_scope = fr.scope.to_code_extent();
-            match self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) {
+            let r_id = self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id);
+
+            if r_id == fr_scope {
               // if the free region's scope `fr.scope_id` is bigger than
               // the scope region `s_id`, then the LUB is the free
               // region itself:
-              Some(r_id) if r_id == fr_scope => f,
-
+              f
+            } else {
               // otherwise, we don't know what the free region is,
               // so we must conservatively say the LUB is static:
-              _ => ReStatic
+              ReStatic
             }
           }
 
@@ -776,10 +778,7 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
             // The region corresponding to an outer block is a
             // subtype of the region corresponding to an inner
             // block.
-            match self.tcx.region_maps.nearest_common_ancestor(a_id, b_id) {
-              Some(r_id) => ReScope(r_id),
-              _ => ReStatic
-            }
+            ReScope(self.tcx.region_maps.nearest_common_ancestor(a_id, b_id))
           }
 
           (ReFree(ref a_fr), ReFree(ref b_fr)) => {
@@ -799,7 +798,8 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
     /// regions are given as argument, in any order, a consistent result is returned.
     fn lub_free_regions(&self,
                         a: &FreeRegion,
-                        b: &FreeRegion) -> ty::Region
+                        b: &FreeRegion)
+                        -> ty::Region
     {
         return match a.cmp(b) {
             Less => helper(self, a, b),
@@ -824,7 +824,8 @@ fn helper(this: &RegionVarBindings,
     fn glb_concrete_regions(&self,
                             a: Region,
                             b: Region)
-                         -> cres<'tcx, Region> {
+                            -> RelateResult<'tcx, Region>
+    {
         debug!("glb_concrete_regions({:?}, {:?})", a, b);
         match (a, b) {
             (ReLateBound(..), _) |
@@ -866,9 +867,10 @@ fn glb_concrete_regions(&self,
                 // is the scope `s_id`.  Otherwise, as we do not know
                 // big the free region is precisely, the GLB is undefined.
                 let fr_scope = fr.scope.to_code_extent();
-                match self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) {
-                    Some(r_id) if r_id == fr_scope => Ok(s),
-                    _ => Err(ty::terr_regions_no_overlap(b, a))
+                if self.tcx.region_maps.nearest_common_ancestor(fr_scope, s_id) == fr_scope {
+                    Ok(s)
+                } else {
+                    Err(ty::terr_regions_no_overlap(b, a))
                 }
             }
 
@@ -898,7 +900,8 @@ fn glb_concrete_regions(&self,
     /// returned.
     fn glb_free_regions(&self,
                         a: &FreeRegion,
-                        b: &FreeRegion) -> cres<'tcx, ty::Region>
+                        b: &FreeRegion)
+                        -> RelateResult<'tcx, ty::Region>
     {
         return match a.cmp(b) {
             Less => helper(self, a, b),
@@ -908,7 +911,7 @@ fn glb_free_regions(&self,
 
         fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
                             a: &FreeRegion,
-                            b: &FreeRegion) -> cres<'tcx, ty::Region>
+                            b: &FreeRegion) -> RelateResult<'tcx, ty::Region>
         {
             if this.tcx.region_maps.sub_free_region(*a, *b) {
                 Ok(ty::ReFree(*a))
@@ -926,7 +929,8 @@ fn intersect_scopes(&self,
                         region_a: ty::Region,
                         region_b: ty::Region,
                         scope_a: region::CodeExtent,
-                        scope_b: region::CodeExtent) -> cres<'tcx, Region>
+                        scope_b: region::CodeExtent)
+                        -> RelateResult<'tcx, Region>
     {
         // We want to generate the intersection of two
         // scopes or two free regions.  So, if one of
@@ -934,10 +938,13 @@ fn intersect_scopes(&self,
         // it. Otherwise fail.
         debug!("intersect_scopes(scope_a={:?}, scope_b={:?}, region_a={:?}, region_b={:?})",
                scope_a, scope_b, region_a, region_b);
-        match self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b) {
-            Some(r_id) if scope_a == r_id => Ok(ReScope(scope_b)),
-            Some(r_id) if scope_b == r_id => Ok(ReScope(scope_a)),
-            _ => Err(ty::terr_regions_no_overlap(region_a, region_b))
+        let r_id = self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b);
+        if r_id == scope_a {
+            Ok(ReScope(scope_b))
+        } else if r_id == scope_b {
+            Ok(ReScope(scope_a))
+        } else {
+            Err(ty::terr_regions_no_overlap(region_a, region_b))
         }
     }
 }
index 5d23fe3f1348dc0657adf9a41dc8e3a4e94ff2d0..31b654a5b3fd3b5fcfba885019ade59349aa69a6 100644 (file)
@@ -8,64 +8,49 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::*;
-use super::cres;
+use super::combine::{self, CombineFields};
 use super::higher_ranked::HigherRankedRelations;
 use super::Subtype;
 use super::type_variable::{SubtypeOf, SupertypeOf};
 
 use middle::ty::{self, Ty};
 use middle::ty::TyVar;
-use util::ppaux::Repr;
+use middle::ty_relate::{Relate, RelateResult, TypeRelation};
+use util::ppaux::{Repr};
 
 /// "Greatest lower bound" (common subtype)
-pub struct Sub<'f, 'tcx: 'f> {
-    fields: CombineFields<'f, 'tcx>
+pub struct Sub<'a, 'tcx: 'a> {
+    fields: CombineFields<'a, 'tcx>
 }
 
-#[allow(non_snake_case)]
-pub fn Sub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Sub<'f, 'tcx> {
-    Sub { fields: cf }
+impl<'a, 'tcx> Sub<'a, 'tcx> {
+    pub fn new(f: CombineFields<'a, 'tcx>) -> Sub<'a, 'tcx> {
+        Sub { fields: f }
+    }
 }
 
-impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
-    fn tag(&self) -> String { "Sub".to_string() }
-    fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
-
-    fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-                         -> cres<'tcx, Ty<'tcx>>
-    {
-        match v {
-            ty::Invariant => self.equate().tys(a, b),
-            ty::Covariant => self.tys(a, b),
-            ty::Bivariant => self.bivariate().tys(a, b),
-            ty::Contravariant => Sub(self.fields.switch_expected()).tys(b, a),
-        }
-    }
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
+    fn tag(&self) -> &'static str { "Sub" }
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.infcx.tcx }
+    fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
-    fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-                             -> cres<'tcx, ty::Region>
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               variance: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>
     {
-        match v {
-            ty::Invariant => self.equate().regions(a, b),
-            ty::Covariant => self.regions(a, b),
-            ty::Bivariant => self.bivariate().regions(a, b),
-            ty::Contravariant => Sub(self.fields.switch_expected()).regions(b, a),
+        match variance {
+            ty::Invariant => self.fields.equate().relate(a, b),
+            ty::Covariant => self.relate(a, b),
+            ty::Bivariant => self.fields.bivariate().relate(a, b),
+            ty::Contravariant => self.fields.switch_expected().sub().relate(b, a),
         }
     }
 
-    fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
-        debug!("{}.regions({}, {})",
-               self.tag(),
-               a.repr(self.tcx()),
-               b.repr(self.tcx()));
-        self.infcx().region_vars.make_subregion(Subtype(self.trace()), a, b);
-        Ok(a)
-    }
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        debug!("{}.tys({}, {})", self.tag(), a.repr(self.tcx()), b.repr(self.tcx()));
 
-    fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
-        debug!("{}.tys({}, {})", self.tag(),
-               a.repr(self.tcx()), b.repr(self.tcx()));
         if a == b { return Ok(a); }
 
         let infcx = self.fields.infcx;
@@ -80,8 +65,8 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
             }
             (&ty::ty_infer(TyVar(a_id)), _) => {
                 try!(self.fields
-                       .switch_expected()
-                       .instantiate(b, SupertypeOf, a_id));
+                         .switch_expected()
+                         .instantiate(b, SupertypeOf, a_id));
                 Ok(a)
             }
             (_, &ty::ty_infer(TyVar(b_id))) => {
@@ -94,14 +79,25 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
             }
 
             _ => {
-                super_tys(self, a, b)
+                combine::super_combine_tys(self.fields.infcx, self, a, b)
             }
         }
     }
 
-    fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
-        where T : Combineable<'tcx>
+    fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
+        debug!("{}.regions({}, {})",
+               self.tag(),
+               a.repr(self.tcx()),
+               b.repr(self.tcx()));
+        let origin = Subtype(self.fields.trace.clone());
+        self.fields.infcx.region_vars.make_subregion(origin, a, b);
+        Ok(a)
+    }
+
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a,'tcx>
     {
-        self.higher_ranked_sub(a, b)
+        self.fields.higher_ranked_sub(a, b)
     }
 }
index 8a736d47b5d8944a338c1ad9a9dcdc3ee2bea29f..39271d4cdc597cb8f448c5dc8205f568b92164ee 100644 (file)
 
 use std::marker;
 
-use middle::ty::{expected_found, IntVarValue};
+use middle::ty::{IntVarValue};
 use middle::ty::{self, Ty};
-use middle::infer::{uok, ures};
-use middle::infer::InferCtxt;
-use std::cell::RefCell;
 use std::fmt::Debug;
 use std::marker::PhantomData;
 use syntax::ast;
 pub trait UnifyKey : Clone + Debug + PartialEq {
     type Value : UnifyValue;
 
-    fn index(&self) -> usize;
+    fn index(&self) -> u32;
 
-    fn from_index(u: usize) -> Self;
-
-    // Given an inference context, returns the unification table
-    // appropriate to this key type.
-    fn unification_table<'v>(infcx: &'v InferCtxt)
-                             -> &'v RefCell<UnificationTable<Self>>;
+    fn from_index(u: u32) -> Self;
 
     fn tag(k: Option<Self>) -> &'static str;
 }
@@ -130,21 +122,25 @@ pub fn commit(&mut self, snapshot: Snapshot<K>) {
 
     pub fn new_key(&mut self, value: K::Value) -> K {
         let index = self.values.push(Root(value, 0));
-        let k = UnifyKey::from_index(index);
+        let k = UnifyKey::from_index(index as u32);
         debug!("{}: created new key: {:?}",
                UnifyKey::tag(None::<K>),
                k);
         k
     }
 
-    /// Find the root node for `vid`. This uses the standard union-find algorithm with path
-    /// compression: http://en.wikipedia.org/wiki/Disjoint-set_data_structure
-    pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node<K> {
-        let index = vid.index();
+    /// Find the root node for `vid`. This uses the standard
+    /// union-find algorithm with path compression:
+    /// <http://en.wikipedia.org/wiki/Disjoint-set_data_structure>.
+    ///
+    /// NB. This is a building-block operation and you would probably
+    /// prefer to call `probe` below.
+    fn get(&mut self, vid: K) -> Node<K> {
+        let index = vid.index() as usize;
         let value = (*self.values.get(index)).clone();
         match value {
             Redirect(redirect) => {
-                let node: Node<K> = self.get(tcx, redirect.clone());
+                let node: Node<K> = self.get(redirect.clone());
                 if node.key != redirect {
                     // Path compression
                     self.values.set(index, Redirect(node.key.clone()));
@@ -158,58 +154,58 @@ pub fn get(&mut self, tcx: &ty::ctxt, vid: K) -> Node<K> {
     }
 
     fn is_root(&self, key: &K) -> bool {
-        match *self.values.get(key.index()) {
+        let index = key.index() as usize;
+        match *self.values.get(index) {
             Redirect(..) => false,
             Root(..) => true,
         }
     }
 
-    /// Sets the value for `vid` to `new_value`. `vid` MUST be a root node! Also, we must be in the
-    /// middle of a snapshot.
-    pub fn set<'tcx>(&mut self,
-                     _tcx: &ty::ctxt<'tcx>,
-                     key: K,
-                     new_value: VarValue<K>)
-    {
+    /// Sets the value for `vid` to `new_value`. `vid` MUST be a root
+    /// node! This is an internal operation used to impl other things.
+    fn set(&mut self, key: K, new_value: VarValue<K>) {
         assert!(self.is_root(&key));
 
         debug!("Updating variable {:?} to {:?}",
                key, new_value);
 
-        self.values.set(key.index(), new_value);
+        let index = key.index() as usize;
+        self.values.set(index, new_value);
     }
 
-    /// Either redirects node_a to node_b or vice versa, depending on the relative rank. Returns
-    /// the new root and rank. You should then update the value of the new root to something
-    /// suitable.
-    pub fn unify<'tcx>(&mut self,
-                       tcx: &ty::ctxt<'tcx>,
-                       node_a: &Node<K>,
-                       node_b: &Node<K>)
-                       -> (K, usize)
-    {
+    /// Either redirects `node_a` to `node_b` or vice versa, depending
+    /// on the relative rank. The value associated with the new root
+    /// will be `new_value`.
+    ///
+    /// NB: This is the "union" operation of "union-find". It is
+    /// really more of a building block. If the values associated with
+    /// your key are non-trivial, you would probably prefer to call
+    /// `unify_var_var` below.
+    fn unify(&mut self, node_a: &Node<K>, node_b: &Node<K>, new_value: K::Value) {
         debug!("unify(node_a(id={:?}, rank={:?}), node_b(id={:?}, rank={:?}))",
                node_a.key,
                node_a.rank,
                node_b.key,
                node_b.rank);
 
-        if node_a.rank > node_b.rank {
+        let (new_root, new_rank) = if node_a.rank > node_b.rank {
             // a has greater rank, so a should become b's parent,
             // i.e., b should redirect to a.
-            self.set(tcx, node_b.key.clone(), Redirect(node_a.key.clone()));
+            self.set(node_b.key.clone(), Redirect(node_a.key.clone()));
             (node_a.key.clone(), node_a.rank)
         } else if node_a.rank < node_b.rank {
             // b has greater rank, so a should redirect to b.
-            self.set(tcx, node_a.key.clone(), Redirect(node_b.key.clone()));
+            self.set(node_a.key.clone(), Redirect(node_b.key.clone()));
             (node_b.key.clone(), node_b.rank)
         } else {
             // If equal, redirect one to the other and increment the
             // other's rank.
             assert_eq!(node_a.rank, node_b.rank);
-            self.set(tcx, node_b.key.clone(), Redirect(node_a.key.clone()));
+            self.set(node_b.key.clone(), Redirect(node_a.key.clone()));
             (node_a.key.clone(), node_a.rank + 1)
-        }
+        };
+
+        self.set(new_root, Root(new_value, new_rank));
     }
 }
 
@@ -223,69 +219,26 @@ fn reverse(&mut self, _: &mut Vec<VarValue<K>>, _: ()) {
 }
 
 ///////////////////////////////////////////////////////////////////////////
-// Code to handle simple keys like ints, floats---anything that
-// doesn't have a subtyping relationship we need to worry about.
-
-/// Indicates a type that does not have any kind of subtyping
-/// relationship.
-pub trait SimplyUnifiable<'tcx> : Clone + PartialEq + Debug {
-    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
-    fn to_type_err(expected_found<Self>) -> ty::type_err<'tcx>;
-}
-
-pub fn err<'tcx, V:SimplyUnifiable<'tcx>>(a_is_expected: bool,
-                                          a_t: V,
-                                          b_t: V)
-                                          -> ures<'tcx> {
-    if a_is_expected {
-        Err(SimplyUnifiable::to_type_err(
-            ty::expected_found {expected: a_t, found: b_t}))
-    } else {
-        Err(SimplyUnifiable::to_type_err(
-            ty::expected_found {expected: b_t, found: a_t}))
-    }
-}
-
-pub trait InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V>
-    where K : UnifyKey<Value=Option<V>>,
-          V : SimplyUnifiable<'tcx>,
-          Option<V> : UnifyValue,
-{
-    fn simple_vars(&self,
-                   a_is_expected: bool,
-                   a_id: K,
-                   b_id: K)
-                   -> ures<'tcx>;
-    fn simple_var_t(&self,
-                    a_is_expected: bool,
-                    a_id: K,
-                    b: V)
-                    -> ures<'tcx>;
-    fn probe_var(&self, a_id: K) -> Option<Ty<'tcx>>;
-}
-
-impl<'a,'tcx,V,K> InferCtxtMethodsForSimplyUnifiableTypes<'tcx,K,V> for InferCtxt<'a,'tcx>
-    where K : UnifyKey<Value=Option<V>>,
-          V : SimplyUnifiable<'tcx>,
-          Option<V> : UnifyValue,
+// Code to handle keys which carry a value, like ints,
+// floats---anything that doesn't have a subtyping relationship we
+// need to worry about.
+
+impl<'tcx,K,V> UnificationTable<K>
+    where K: UnifyKey<Value=Option<V>>,
+          V: Clone+PartialEq,
+          Option<V>: UnifyValue,
 {
-    /// Unifies two simple keys. Because simple keys do not have any subtyping relationships, if
-    /// both keys have already been associated with a value, then those two values must be the
-    /// same.
-    fn simple_vars(&self,
-                   a_is_expected: bool,
-                   a_id: K,
-                   b_id: K)
-                   -> ures<'tcx>
+    pub fn unify_var_var(&mut self,
+                         a_id: K,
+                         b_id: K)
+                         -> Result<(),(V,V)>
     {
-        let tcx = self.tcx;
-        let table = UnifyKey::unification_table(self);
-        let node_a: Node<K> = table.borrow_mut().get(tcx, a_id);
-        let node_b: Node<K> = table.borrow_mut().get(tcx, b_id);
+        let node_a = self.get(a_id);
+        let node_b = self.get(b_id);
         let a_id = node_a.key.clone();
         let b_id = node_b.key.clone();
 
-        if a_id == b_id { return uok(); }
+        if a_id == b_id { return Ok(()); }
 
         let combined = {
             match (&node_a.value, &node_b.value) {
@@ -293,61 +246,52 @@ fn simple_vars(&self,
                     None
                 }
                 (&Some(ref v), &None) | (&None, &Some(ref v)) => {
-                    Some((*v).clone())
+                    Some(v.clone())
                 }
                 (&Some(ref v1), &Some(ref v2)) => {
                     if *v1 != *v2 {
-                        return err(a_is_expected, (*v1).clone(), (*v2).clone())
+                        return Err((v1.clone(), v2.clone()));
                     }
-                    Some((*v1).clone())
+                    Some(v1.clone())
                 }
             }
         };
 
-        let (new_root, new_rank) = table.borrow_mut().unify(tcx,
-                                                            &node_a,
-                                                            &node_b);
-        table.borrow_mut().set(tcx, new_root, Root(combined, new_rank));
-        return Ok(())
+        Ok(self.unify(&node_a, &node_b, combined))
     }
 
     /// Sets the value of the key `a_id` to `b`. Because simple keys do not have any subtyping
     /// relationships, if `a_id` already has a value, it must be the same as `b`.
-    fn simple_var_t(&self,
-                    a_is_expected: bool,
-                    a_id: K,
-                    b: V)
-                    -> ures<'tcx>
+    pub fn unify_var_value(&mut self,
+                           a_id: K,
+                           b: V)
+                           -> Result<(),(V,V)>
     {
-        let tcx = self.tcx;
-        let table = UnifyKey::unification_table(self);
-        let node_a = table.borrow_mut().get(tcx, a_id);
+        let node_a = self.get(a_id);
         let a_id = node_a.key.clone();
 
         match node_a.value {
             None => {
-                table.borrow_mut().set(tcx, a_id, Root(Some(b), node_a.rank));
-                return Ok(());
+                self.set(a_id, Root(Some(b), node_a.rank));
+                Ok(())
             }
 
             Some(ref a_t) => {
                 if *a_t == b {
-                    return Ok(());
+                    Ok(())
                 } else {
-                    return err(a_is_expected, (*a_t).clone(), b);
+                    Err((a_t.clone(), b))
                 }
             }
         }
     }
 
-    fn probe_var(&self, a_id: K) -> Option<Ty<'tcx>> {
-        let tcx = self.tcx;
-        let table = UnifyKey::unification_table(self);
-        let node_a = table.borrow_mut().get(tcx, a_id);
-        match node_a.value {
-            None => None,
-            Some(ref a_t) => Some(a_t.to_type(tcx))
-        }
+    pub fn has_value(&mut self, id: K) -> bool {
+        self.get(id).value.is_some()
+    }
+
+    pub fn probe(&mut self, a_id: K) -> Option<V> {
+        self.get(a_id).value.clone()
     }
 }
 
@@ -355,33 +299,24 @@ fn probe_var(&self, a_id: K) -> Option<Ty<'tcx>> {
 
 // Integral type keys
 
+pub trait ToType<'tcx> {
+    fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx>;
+}
+
 impl UnifyKey for ty::IntVid {
     type Value = Option<IntVarValue>;
-
-    fn index(&self) -> usize { self.index as usize }
-
-    fn from_index(i: usize) -> ty::IntVid { ty::IntVid { index: i as u32 } }
-
-    fn unification_table<'v>(infcx: &'v InferCtxt) -> &'v RefCell<UnificationTable<ty::IntVid>> {
-        return &infcx.int_unification_table;
-    }
-
-    fn tag(_: Option<ty::IntVid>) -> &'static str {
-        "IntVid"
-    }
+    fn index(&self) -> u32 { self.index }
+    fn from_index(i: u32) -> ty::IntVid { ty::IntVid { index: i } }
+    fn tag(_: Option<ty::IntVid>) -> &'static str { "IntVid" }
 }
 
-impl<'tcx> SimplyUnifiable<'tcx> for IntVarValue {
+impl<'tcx> ToType<'tcx> for IntVarValue {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
             ty::IntType(i) => ty::mk_mach_int(tcx, i),
             ty::UintType(i) => ty::mk_mach_uint(tcx, i),
         }
     }
-
-    fn to_type_err(err: expected_found<IntVarValue>) -> ty::type_err<'tcx> {
-        return ty::terr_int_mismatch(err);
-    }
 }
 
 impl UnifyValue for Option<IntVarValue> { }
@@ -390,29 +325,16 @@ impl UnifyValue for Option<IntVarValue> { }
 
 impl UnifyKey for ty::FloatVid {
     type Value = Option<ast::FloatTy>;
-
-    fn index(&self) -> usize { self.index as usize }
-
-    fn from_index(i: usize) -> ty::FloatVid { ty::FloatVid { index: i as u32 } }
-
-    fn unification_table<'v>(infcx: &'v InferCtxt) -> &'v RefCell<UnificationTable<ty::FloatVid>> {
-        return &infcx.float_unification_table;
-    }
-
-    fn tag(_: Option<ty::FloatVid>) -> &'static str {
-        "FloatVid"
-    }
+    fn index(&self) -> u32 { self.index }
+    fn from_index(i: u32) -> ty::FloatVid { ty::FloatVid { index: i } }
+    fn tag(_: Option<ty::FloatVid>) -> &'static str { "FloatVid" }
 }
 
 impl UnifyValue for Option<ast::FloatTy> {
 }
 
-impl<'tcx> SimplyUnifiable<'tcx> for ast::FloatTy {
+impl<'tcx> ToType<'tcx> for ast::FloatTy {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         ty::mk_mach_float(tcx, *self)
     }
-
-    fn to_type_err(err: expected_found<ast::FloatTy>) -> ty::type_err<'tcx> {
-        ty::terr_float_mismatch(err)
-    }
 }
index 3a253735f925b032e93390ce3618f6c4aa4aec87..d8efb5655aaabc2c62ade363978214b7183ecc9a 100644 (file)
@@ -32,7 +32,7 @@
 /// reexporting a public struct doesn't inline the doc).
 pub type PublicItems = NodeSet;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum LastPrivate {
     LastMod(PrivateDep),
     // `use` directives (imports) can refer to two separate definitions in the
@@ -46,14 +46,14 @@ pub enum LastPrivate {
                type_used: ImportUse},
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum PrivateDep {
     AllPublic,
     DependsOn(ast::DefId),
 }
 
 // How an import is used.
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum ImportUse {
     Unused,       // The import is not used.
     Used,         // The import is used.
index d8c5f89325b34f101dc3c70086c7b2f0e692cf9b..b68f8fa9b988d1663b381b34d09c45b641f8fde4 100644 (file)
@@ -206,50 +206,66 @@ pub fn span(&self, ast_map: &ast_map::Map) -> Option<Span> {
 }
 
 /// The region maps encode information about region relationships.
-///
-/// - `scope_map` maps from a scope id to the enclosing scope id; this is
-///   usually corresponding to the lexical nesting, though in the case of
-///   closures the parent scope is the innermost conditional expression or repeating
-///   block. (Note that the enclosing scope id for the block
-///   associated with a closure is the closure itself.)
-///
-/// - `var_map` maps from a variable or binding id to the block in which
-///   that variable is declared.
-///
-/// - `free_region_map` maps from a free region `a` to a list of free
-///   regions `bs` such that `a <= b for all b in bs`
-///   - the free region map is populated during type check as we check
-///     each function. See the function `relate_free_regions` for
-///     more information.
-///
-/// - `rvalue_scopes` includes entries for those expressions whose cleanup
-///   scope is larger than the default. The map goes from the expression
-///   id to the cleanup scope id. For rvalues not present in this table,
-///   the appropriate cleanup scope is the innermost enclosing statement,
-///   conditional expression, or repeating block (see `terminating_scopes`).
-///
-/// - `terminating_scopes` is a set containing the ids of each statement,
-///   or conditional/repeating expression. These scopes are calling "terminating
-///   scopes" because, when attempting to find the scope of a temporary, by
-///   default we search up the enclosing scopes until we encounter the
-///   terminating scope. A conditional/repeating
-///   expression is one which is not guaranteed to execute exactly once
-///   upon entering the parent scope. This could be because the expression
-///   only executes conditionally, such as the expression `b` in `a && b`,
-///   or because the expression may execute many times, such as a loop
-///   body. The reason that we distinguish such expressions is that, upon
-///   exiting the parent scope, we cannot statically know how many times
-///   the expression executed, and thus if the expression creates
-///   temporaries we cannot know statically how many such temporaries we
-///   would have to cleanup. Therefore we ensure that the temporaries never
-///   outlast the conditional/repeating expression, preventing the need
-///   for dynamic checks and/or arbitrary amounts of stack space.
 pub struct RegionMaps {
+    /// `scope_map` maps from a scope id to the enclosing scope id;
+    /// this is usually corresponding to the lexical nesting, though
+    /// in the case of closures the parent scope is the innermost
+    /// conditional expression or repeating block. (Note that the
+    /// enclosing scope id for the block associated with a closure is
+    /// the closure itself.)
     scope_map: RefCell<FnvHashMap<CodeExtent, CodeExtent>>,
+
+    /// `var_map` maps from a variable or binding id to the block in
+    /// which that variable is declared.
     var_map: RefCell<NodeMap<CodeExtent>>,
+
+    /// `free_region_map` maps from a free region `a` to a list of
+    /// free regions `bs` such that `a <= b for all b in bs`
+    ///
+    /// NB. the free region map is populated during type check as we
+    /// check each function. See the function `relate_free_regions`
+    /// for more information.
     free_region_map: RefCell<FnvHashMap<FreeRegion, Vec<FreeRegion>>>,
+
+    /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is
+    /// larger than the default. The map goes from the expression id
+    /// to the cleanup scope id. For rvalues not present in this
+    /// table, the appropriate cleanup scope is the innermost
+    /// enclosing statement, conditional expression, or repeating
+    /// block (see `terminating_scopes`).
     rvalue_scopes: RefCell<NodeMap<CodeExtent>>,
+
+    /// `terminating_scopes` is a set containing the ids of each
+    /// statement, or conditional/repeating expression. These scopes
+    /// are calling "terminating scopes" because, when attempting to
+    /// find the scope of a temporary, by default we search up the
+    /// enclosing scopes until we encounter the terminating scope. A
+    /// conditional/repeating expression is one which is not
+    /// guaranteed to execute exactly once upon entering the parent
+    /// scope. This could be because the expression only executes
+    /// conditionally, such as the expression `b` in `a && b`, or
+    /// because the expression may execute many times, such as a loop
+    /// body. The reason that we distinguish such expressions is that,
+    /// upon exiting the parent scope, we cannot statically know how
+    /// many times the expression executed, and thus if the expression
+    /// creates temporaries we cannot know statically how many such
+    /// temporaries we would have to cleanup. Therefore we ensure that
+    /// the temporaries never outlast the conditional/repeating
+    /// expression, preventing the need for dynamic checks and/or
+    /// arbitrary amounts of stack space.
     terminating_scopes: RefCell<FnvHashSet<CodeExtent>>,
+
+    /// Encodes the hierarchy of fn bodies. Every fn body (including
+    /// closures) forms its own distinct region hierarchy, rooted in
+    /// the block that is the fn body. This map points from the id of
+    /// that root block to the id of the root block for the enclosing
+    /// fn, if any. Thus the map structures the fn bodies into a
+    /// hierarchy based on their lexical mapping. This is used to
+    /// handle the relationships between regions in a fn and in a
+    /// closure defined by that fn. See the "Modeling closures"
+    /// section of the README in middle::infer::region_inference for
+    /// more details.
+    fn_tree: RefCell<NodeMap<ast::NodeId>>,
 }
 
 /// Carries the node id for the innermost block or match expression,
@@ -320,6 +336,14 @@ fn to_code_extent(&self) -> Option<CodeExtent> {
 
 #[derive(Debug, Copy)]
 pub struct Context {
+    /// the root of the current region tree. This is typically the id
+    /// of the innermost fn body. Each fn forms its own disjoint tree
+    /// in the region hierarchy. These fn bodies are themselves
+    /// arranged into a tree. See the "Modeling closures" section of
+    /// the README in middle::infer::region_inference for more
+    /// details.
+    root_id: Option<ast::NodeId>,
+
     /// the scope that contains any new variables declared
     var_parent: InnermostDeclaringBlock,
 
@@ -381,19 +405,40 @@ pub fn relate_free_regions(&self, sub: FreeRegion, sup: FreeRegion) {
         self.free_region_map.borrow_mut().insert(sub, vec!(sup));
     }
 
+    /// Records that `sub_fn` is defined within `sup_fn`. These ids
+    /// should be the id of the block that is the fn body, which is
+    /// also the root of the region hierarchy for that fn.
+    fn record_fn_parent(&self, sub_fn: ast::NodeId, sup_fn: ast::NodeId) {
+        debug!("record_fn_parent(sub_fn={:?}, sup_fn={:?})", sub_fn, sup_fn);
+        assert!(sub_fn != sup_fn);
+        let previous = self.fn_tree.borrow_mut().insert(sub_fn, sup_fn);
+        assert!(previous.is_none());
+    }
+
+    fn fn_is_enclosed_by(&self, mut sub_fn: ast::NodeId, sup_fn: ast::NodeId) -> bool {
+        let fn_tree = self.fn_tree.borrow();
+        loop {
+            if sub_fn == sup_fn { return true; }
+            match fn_tree.get(&sub_fn) {
+                Some(&s) => { sub_fn = s; }
+                None => { return false; }
+            }
+        }
+    }
+
     pub fn record_encl_scope(&self, sub: CodeExtent, sup: CodeExtent) {
         debug!("record_encl_scope(sub={:?}, sup={:?})", sub, sup);
         assert!(sub != sup);
         self.scope_map.borrow_mut().insert(sub, sup);
     }
 
-    pub fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
+    fn record_var_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime);
         assert!(var != lifetime.node_id());
         self.var_map.borrow_mut().insert(var, lifetime);
     }
 
-    pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
+    fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
         debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime);
         assert!(var != lifetime.node_id());
         self.rvalue_scopes.borrow_mut().insert(var, lifetime);
@@ -402,7 +447,7 @@ pub fn record_rvalue_scope(&self, var: ast::NodeId, lifetime: CodeExtent) {
     /// Records that a scope is a TERMINATING SCOPE. Whenever we create automatic temporaries --
     /// e.g. by an expression like `a().f` -- they will be freed within the innermost terminating
     /// scope.
-    pub fn mark_as_terminating_scope(&self, scope_id: CodeExtent) {
+    fn mark_as_terminating_scope(&self, scope_id: CodeExtent) {
         debug!("record_terminating_scope(scope_id={:?})", scope_id);
         self.terminating_scopes.borrow_mut().insert(scope_id);
     }
@@ -562,15 +607,15 @@ pub fn is_subregion_of(&self,
     pub fn nearest_common_ancestor(&self,
                                    scope_a: CodeExtent,
                                    scope_b: CodeExtent)
-                                   -> Option<CodeExtent> {
-        if scope_a == scope_b { return Some(scope_a); }
+                                   -> CodeExtent {
+        if scope_a == scope_b { return scope_a; }
 
         let a_ancestors = ancestors_of(self, scope_a);
         let b_ancestors = ancestors_of(self, scope_b);
         let mut a_index = a_ancestors.len() - 1;
         let mut b_index = b_ancestors.len() - 1;
 
-        // Here, ~[ab]_ancestors is a vector going from narrow to broad.
+        // Here, [ab]_ancestors is a vector going from narrow to broad.
         // The end of each vector will be the item where the scope is
         // defined; if there are any common ancestors, then the tails of
         // the vector will be the same.  So basically we want to walk
@@ -579,23 +624,47 @@ pub fn nearest_common_ancestor(&self,
         // then the corresponding scope is a superscope of the other.
 
         if a_ancestors[a_index] != b_ancestors[b_index] {
-            return None;
+            // In this case, the two regions belong to completely
+            // different functions.  Compare those fn for lexical
+            // nesting. The reasoning behind this is subtle.  See the
+            // "Modeling closures" section of the README in
+            // middle::infer::region_inference for more details.
+            let a_root_scope = a_ancestors[a_index];
+            let b_root_scope = a_ancestors[a_index];
+            return match (a_root_scope, b_root_scope) {
+                (CodeExtent::DestructionScope(a_root_id),
+                 CodeExtent::DestructionScope(b_root_id)) => {
+                    if self.fn_is_enclosed_by(a_root_id, b_root_id) {
+                        // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a`
+                        scope_b
+                    } else if self.fn_is_enclosed_by(b_root_id, a_root_id) {
+                        // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b`
+                        scope_a
+                    } else {
+                        // neither fn encloses the other
+                        unreachable!()
+                    }
+                }
+                _ => {
+                    // root ids are always Misc right now
+                    unreachable!()
+                }
+            };
         }
 
         loop {
             // Loop invariant: a_ancestors[a_index] == b_ancestors[b_index]
             // for all indices between a_index and the end of the array
-            if a_index == 0 { return Some(scope_a); }
-            if b_index == 0 { return Some(scope_b); }
+            if a_index == 0 { return scope_a; }
+            if b_index == 0 { return scope_b; }
             a_index -= 1;
             b_index -= 1;
             if a_ancestors[a_index] != b_ancestors[b_index] {
-                return Some(a_ancestors[a_index + 1]);
+                return a_ancestors[a_index + 1];
             }
         }
 
-        fn ancestors_of(this: &RegionMaps, scope: CodeExtent)
-            -> Vec<CodeExtent> {
+        fn ancestors_of(this: &RegionMaps, scope: CodeExtent) -> Vec<CodeExtent> {
             // debug!("ancestors_of(scope={:?})", scope);
             let mut result = vec!(scope);
             let mut scope = scope;
@@ -645,6 +714,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
     let prev_cx = visitor.cx;
 
     let blk_scope = CodeExtent::Misc(blk.id);
+
     // If block was previously marked as a terminating scope during
     // the recursive visit of its parent node in the AST, then we need
     // to account for the destruction scope representing the extent of
@@ -684,6 +754,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
     // itself has returned.
 
     visitor.cx = Context {
+        root_id: prev_cx.root_id,
         var_parent: InnermostDeclaringBlock::Block(blk.id),
         parent: InnermostEnclosingExpr::Some(blk.id),
     };
@@ -710,6 +781,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &ast::Block) {
                 record_superlifetime(
                     visitor, declaring.to_code_extent(), statement.span);
                 visitor.cx = Context {
+                    root_id: prev_cx.root_id,
                     var_parent: InnermostDeclaringBlock::Statement(declaring),
                     parent: InnermostEnclosingExpr::Statement(declaring),
                 };
@@ -1103,6 +1175,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) {
     // Items create a new outer block scope as far as we're concerned.
     let prev_cx = visitor.cx;
     visitor.cx = Context {
+        root_id: None,
         var_parent: InnermostDeclaringBlock::None,
         parent: InnermostEnclosingExpr::None
     };
@@ -1111,7 +1184,7 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &ast::Item) {
 }
 
 fn resolve_fn(visitor: &mut RegionResolutionVisitor,
-              fk: FnKind,
+              _: FnKind,
               decl: &ast::FnDecl,
               body: &ast::Block,
               sp: Span,
@@ -1127,42 +1200,36 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
 
     let body_scope = CodeExtent::from_node_id(body.id);
     visitor.region_maps.mark_as_terminating_scope(body_scope);
+
     let dtor_scope = CodeExtent::DestructionScope(body.id);
     visitor.region_maps.record_encl_scope(body_scope, dtor_scope);
+
     record_superlifetime(visitor, dtor_scope, body.span);
 
+    if let Some(root_id) = visitor.cx.root_id {
+        visitor.region_maps.record_fn_parent(body.id, root_id);
+    }
+
     let outer_cx = visitor.cx;
 
     // The arguments and `self` are parented to the body of the fn.
     visitor.cx = Context {
+        root_id: Some(body.id),
         parent: InnermostEnclosingExpr::Some(body.id),
         var_parent: InnermostDeclaringBlock::Block(body.id)
     };
     visit::walk_fn_decl(visitor, decl);
 
-    // The body of the fn itself is either a root scope (top-level fn)
-    // or it continues with the inherited scope (closures).
-    match fk {
-        visit::FkItemFn(..) | visit::FkMethod(..) => {
-            visitor.cx = Context {
-                parent: InnermostEnclosingExpr::None,
-                var_parent: InnermostDeclaringBlock::None
-            };
-            visitor.visit_block(body);
-            visitor.cx = outer_cx;
-        }
-        visit::FkFnBlock(..) => {
-            // FIXME(#3696) -- at present we are place the closure body
-            // within the region hierarchy exactly where it appears lexically.
-            // This is wrong because the closure may live longer
-            // than the enclosing expression. We should probably fix this,
-            // but the correct fix is a bit subtle, and I am also not sure
-            // that the present approach is unsound -- it may not permit
-            // any illegal programs. See issue for more details.
-            visitor.cx = outer_cx;
-            visitor.visit_block(body);
-        }
-    }
+    // The body of the every fn is a root scope.
+    visitor.cx = Context {
+        root_id: Some(body.id),
+        parent: InnermostEnclosingExpr::None,
+        var_parent: InnermostDeclaringBlock::None
+    };
+    visitor.visit_block(body);
+
+    // Restore context we had at the start.
+    visitor.cx = outer_cx;
 }
 
 impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> {
@@ -1203,12 +1270,14 @@ pub fn resolve_crate(sess: &Session, krate: &ast::Crate) -> RegionMaps {
         free_region_map: RefCell::new(FnvHashMap()),
         rvalue_scopes: RefCell::new(NodeMap()),
         terminating_scopes: RefCell::new(FnvHashSet()),
+        fn_tree: RefCell::new(NodeMap()),
     };
     {
         let mut visitor = RegionResolutionVisitor {
             sess: sess,
             region_maps: &maps,
             cx: Context {
+                root_id: None,
                 parent: InnermostEnclosingExpr::None,
                 var_parent: InnermostDeclaringBlock::None,
             }
@@ -1225,6 +1294,7 @@ pub fn resolve_inlined_item(sess: &Session,
         sess: sess,
         region_maps: region_maps,
         cx: Context {
+            root_id: None,
             parent: InnermostEnclosingExpr::None,
             var_parent: InnermostDeclaringBlock::None
         }
index 11d073ce72e735990c61f70ab273b6c21ea8783d..411be28b89695162d75d435751b793d64ec6788b 100644 (file)
 use super::project;
 use super::util;
 
-use middle::subst::{Subst, TypeSpace};
+use middle::subst::{Subst, Substs, TypeSpace};
 use middle::ty::{self, ToPolyTraitRef, Ty};
 use middle::infer::{self, InferCtxt};
-use std::collections::HashSet;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::codemap::DUMMY_SP;
+use syntax::codemap::{DUMMY_SP, Span};
 use util::ppaux::Repr;
 
+#[derive(Copy)]
+struct ParamIsLocal(bool);
+
 /// True if there exist types that satisfy both of the two given impls.
 pub fn overlapping_impls(infcx: &InferCtxt,
                          impl1_def_id: ast::DefId,
@@ -56,10 +58,16 @@ fn overlap(selcx: &mut SelectionContext,
            a_def_id.repr(selcx.tcx()),
            b_def_id.repr(selcx.tcx()));
 
-    let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, a_def_id);
-    let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, b_def_id);
+    let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx,
+                                                                a_def_id,
+                                                                util::free_substs_for_impl);
+
+    let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx,
+                                                                b_def_id,
+                                                                util::fresh_type_vars_for_impl);
 
     debug!("overlap: a_trait_ref={}", a_trait_ref.repr(selcx.tcx()));
+
     debug!("overlap: b_trait_ref={}", b_trait_ref.repr(selcx.tcx()));
 
     // Does `a <: b` hold? If not, no overlap.
@@ -74,28 +82,68 @@ fn overlap(selcx: &mut SelectionContext,
     debug!("overlap: subtraitref check succeeded");
 
     // Are any of the obligations unsatisfiable? If so, no overlap.
+    let tcx = selcx.tcx();
+    let infcx = selcx.infcx();
     let opt_failing_obligation =
         a_obligations.iter()
                      .chain(b_obligations.iter())
+                     .map(|o| infcx.resolve_type_vars_if_possible(o))
                      .find(|o| !selcx.evaluate_obligation(o));
 
     if let Some(failing_obligation) = opt_failing_obligation {
-        debug!("overlap: obligation unsatisfiable {}", failing_obligation.repr(selcx.tcx()));
-        return false;
+        debug!("overlap: obligation unsatisfiable {}", failing_obligation.repr(tcx));
+        return false
     }
 
     true
 }
 
+pub fn trait_ref_is_knowable<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> bool
+{
+    debug!("trait_ref_is_knowable(trait_ref={})", trait_ref.repr(tcx));
+
+    // if the orphan rules pass, that means that no ancestor crate can
+    // impl this, so it's up to us.
+    if orphan_check_trait_ref(tcx, trait_ref, ParamIsLocal(false)).is_ok() {
+        debug!("trait_ref_is_knowable: orphan check passed");
+        return true;
+    }
+
+    // if the trait is not marked fundamental, then it's always possible that
+    // an ancestor crate will impl this in the future, if they haven't
+    // already
+    if
+        trait_ref.def_id.krate != ast::LOCAL_CRATE &&
+        !ty::has_attr(tcx, trait_ref.def_id, "fundamental")
+    {
+        debug!("trait_ref_is_knowable: trait is neither local nor fundamental");
+        return false;
+    }
+
+    // find out when some downstream (or cousin) crate could impl this
+    // trait-ref, presuming that all the parameters were instantiated
+    // with downstream types. If not, then it could only be
+    // implemented by an upstream crate, which means that the impl
+    // must be visible to us, and -- since the trait is fundamental
+    // -- we can test.
+    orphan_check_trait_ref(tcx, trait_ref, ParamIsLocal(true)).is_err()
+}
+
+type SubstsFn = for<'a,'tcx> fn(infcx: &InferCtxt<'a, 'tcx>,
+                                span: Span,
+                                impl_def_id: ast::DefId)
+                                -> Substs<'tcx>;
+
 /// Instantiate fresh variables for all bound parameters of the impl
 /// and return the impl trait ref with those variables substituted.
 fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
-                                     impl_def_id: ast::DefId)
+                                     impl_def_id: ast::DefId,
+                                     substs_fn: SubstsFn)
                                      -> (Rc<ty::TraitRef<'tcx>>,
                                          Vec<PredicateObligation<'tcx>>)
 {
     let impl_substs =
-        &util::fresh_substs_for_impl(selcx.infcx(), DUMMY_SP, impl_def_id);
+        &substs_fn(selcx.infcx(), DUMMY_SP, impl_def_id);
     let impl_trait_ref =
         ty::impl_trait_ref(selcx.tcx(), impl_def_id).unwrap();
     let impl_trait_ref =
@@ -134,12 +182,12 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
                           impl_def_id: ast::DefId)
                           -> Result<(), OrphanCheckErr<'tcx>>
 {
-    debug!("impl_is_local({})", impl_def_id.repr(tcx));
+    debug!("orphan_check({})", impl_def_id.repr(tcx));
 
     // We only except this routine to be invoked on implementations
     // of a trait, not inherent implementations.
     let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
-    debug!("trait_ref={}", trait_ref.repr(tcx));
+    debug!("orphan_check: trait_ref={}", trait_ref.repr(tcx));
 
     // If the *trait* is local to the crate, ok.
     if trait_ref.def_id.krate == ast::LOCAL_CRATE {
@@ -148,34 +196,106 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
         return Ok(());
     }
 
+    orphan_check_trait_ref(tcx, &trait_ref, ParamIsLocal(false))
+}
+
+fn orphan_check_trait_ref<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                trait_ref: &ty::TraitRef<'tcx>,
+                                param_is_local: ParamIsLocal)
+                                -> Result<(), OrphanCheckErr<'tcx>>
+{
+    debug!("orphan_check_trait_ref(trait_ref={}, param_is_local={})",
+           trait_ref.repr(tcx), param_is_local.0);
+
     // First, create an ordered iterator over all the type parameters to the trait, with the self
     // type appearing first.
     let input_tys = Some(trait_ref.self_ty());
     let input_tys = input_tys.iter().chain(trait_ref.substs.types.get_slice(TypeSpace).iter());
-    let mut input_tys = input_tys;
 
     // Find the first input type that either references a type parameter OR
     // some local type.
-    match input_tys.find(|&&input_ty| references_local_or_type_parameter(tcx, input_ty)) {
-        Some(&input_ty) => {
-            // Within this first type, check that all type parameters are covered by a local
-            // type constructor. Note that if there is no local type constructor, then any
-            // type parameter at all will be an error.
-            let covered_params = type_parameters_covered_by_ty(tcx, input_ty);
-            let all_params = type_parameters_reachable_from_ty(input_ty);
-            for &param in all_params.difference(&covered_params) {
-                return Err(OrphanCheckErr::UncoveredTy(param));
+    for input_ty in input_tys {
+        if ty_is_local(tcx, input_ty, param_is_local) {
+            debug!("orphan_check_trait_ref: ty_is_local `{}`", input_ty.repr(tcx));
+
+            // First local input type. Check that there are no
+            // uncovered type parameters.
+            let uncovered_tys = uncovered_tys(tcx, input_ty, param_is_local);
+            for uncovered_ty in uncovered_tys {
+                if let Some(param) = uncovered_ty.walk().find(|t| is_type_parameter(t)) {
+                    debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx));
+                    return Err(OrphanCheckErr::UncoveredTy(param));
+                }
             }
+
+            // OK, found local type, all prior types upheld invariant.
+            return Ok(());
         }
-        None => {
-            return Err(OrphanCheckErr::NoLocalInputType);
+
+        // Otherwise, enforce invariant that there are no type
+        // parameters reachable.
+        if !param_is_local.0 {
+            if let Some(param) = input_ty.walk().find(|t| is_type_parameter(t)) {
+                debug!("orphan_check_trait_ref: uncovered type `{}`", param.repr(tcx));
+                return Err(OrphanCheckErr::UncoveredTy(param));
+            }
         }
     }
 
-    return Ok(());
+    // If we exit above loop, never found a local type.
+    debug!("orphan_check_trait_ref: no local type");
+    return Err(OrphanCheckErr::NoLocalInputType);
+}
+
+fn uncovered_tys<'tcx>(tcx: &ty::ctxt<'tcx>,
+                       ty: Ty<'tcx>,
+                       param_is_local: ParamIsLocal)
+                       -> Vec<Ty<'tcx>>
+{
+    if ty_is_local_constructor(tcx, ty, param_is_local) {
+        vec![]
+    } else if fundamental_ty(tcx, ty) {
+        ty.walk_shallow()
+          .flat_map(|t| uncovered_tys(tcx, t, param_is_local).into_iter())
+          .collect()
+    } else {
+        vec![ty]
+    }
 }
 
-fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
+fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool {
+    match ty.sty {
+        // FIXME(#20590) straighten story about projection types
+        ty::ty_projection(..) | ty::ty_param(..) => true,
+        _ => false,
+    }
+}
+
+fn ty_is_local<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>, param_is_local: ParamIsLocal) -> bool
+{
+    ty_is_local_constructor(tcx, ty, param_is_local) ||
+        fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, param_is_local))
+}
+
+fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool
+{
+    match ty.sty {
+        ty::ty_uniq(..) | ty::ty_rptr(..) =>
+            true,
+        ty::ty_enum(def_id, _) | ty::ty_struct(def_id, _) =>
+            ty::has_attr(tcx, def_id, "fundamental"),
+        ty::ty_trait(ref data) =>
+            ty::has_attr(tcx, data.principal_def_id(), "fundamental"),
+        _ =>
+            false
+    }
+}
+
+fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                 ty: Ty<'tcx>,
+                                 param_is_local: ParamIsLocal)
+                                 -> bool
+{
     debug!("ty_is_local_constructor({})", ty.repr(tcx));
 
     match ty.sty {
@@ -190,11 +310,15 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
         ty::ty_ptr(..) |
         ty::ty_rptr(..) |
         ty::ty_tup(..) |
-        ty::ty_param(..) |
+        ty::ty_infer(..) |
         ty::ty_projection(..) => {
             false
         }
 
+        ty::ty_param(..) => {
+            param_is_local.0
+        }
+
         ty::ty_enum(def_id, _) |
         ty::ty_struct(def_id, _) => {
             def_id.krate == ast::LOCAL_CRATE
@@ -210,7 +334,6 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
         }
 
         ty::ty_closure(..) |
-        ty::ty_infer(..) |
         ty::ty_err => {
             tcx.sess.bug(
                 &format!("ty_is_local invoked on unexpected type: {}",
@@ -219,30 +342,4 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     }
 }
 
-fn type_parameters_covered_by_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                       ty: Ty<'tcx>)
-                                       -> HashSet<Ty<'tcx>>
-{
-    if ty_is_local_constructor(tcx, ty) {
-        type_parameters_reachable_from_ty(ty)
-    } else {
-        ty.walk_children().flat_map(|t| type_parameters_covered_by_ty(tcx, t).into_iter()).collect()
-    }
-}
-
-/// All type parameters reachable from `ty`
-fn type_parameters_reachable_from_ty<'tcx>(ty: Ty<'tcx>) -> HashSet<Ty<'tcx>> {
-    ty.walk().filter(|&t| is_type_parameter(t)).collect()
-}
-
-fn references_local_or_type_parameter<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.walk().any(|ty| is_type_parameter(ty) || ty_is_local_constructor(tcx, ty))
-}
 
-fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        // FIXME(#20590) straighten story about projection types
-        ty::ty_projection(..) | ty::ty_param(..) => true,
-        _ => false,
-    }
-}
index 1594d8b2e0d047b06a836e72ea02afe7a307416d..7488b8f046e74eff8215258fe5127b4c99895384 100644 (file)
@@ -81,7 +81,7 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
            obligation.repr(selcx.tcx()));
 
     let infcx = selcx.infcx();
-    infcx.try(|snapshot| {
+    infcx.commit_if_ok(|snapshot| {
         let (skol_predicate, skol_map) =
             infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot);
 
@@ -291,6 +291,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 }
 
+#[derive(Clone)]
 pub struct Normalized<'tcx,T> {
     pub value: T,
     pub obligations: Vec<PredicateObligation<'tcx>>,
index 9e4f63dca45659fc5acdf7894e24f7bd979c65e5..bb2d37c944c86d3833f61e6943cd5e2e748f9dec 100644 (file)
@@ -17,6 +17,7 @@
 use self::BuiltinBoundConditions::*;
 use self::EvaluationResult::*;
 
+use super::coherence;
 use super::DerivedObligationCause;
 use super::project;
 use super::project::{normalize_with_depth, Normalized};
 use middle::infer;
 use middle::infer::{InferCtxt, TypeFreshener};
 use middle::ty_fold::TypeFoldable;
+use middle::ty_match;
+use middle::ty_relate::TypeRelation;
 use std::cell::RefCell;
-use std::collections::hash_map::HashMap;
 use std::rc::Rc;
 use syntax::{abi, ast};
 use util::common::ErrorReported;
+use util::nodemap::FnvHashMap;
 use util::ppaux::Repr;
 
 pub struct SelectionContext<'cx, 'tcx:'cx> {
@@ -81,13 +84,13 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
     /// selection-context's freshener. Used to check for recursion.
     fresh_trait_ref: ty::PolyTraitRef<'tcx>,
 
-    previous: Option<&'prev TraitObligationStack<'prev, 'tcx>>
+    previous: TraitObligationStackList<'prev, 'tcx>,
 }
 
 #[derive(Clone)]
 pub struct SelectionCache<'tcx> {
-    hashmap: RefCell<HashMap<Rc<ty::TraitRef<'tcx>>,
-                             SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
+    hashmap: RefCell<FnvHashMap<Rc<ty::TraitRef<'tcx>>,
+                                SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
 }
 
 pub enum MethodMatchResult {
@@ -245,7 +248,7 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
         debug!("select({})", obligation.repr(self.tcx()));
         assert!(!obligation.predicate.has_escaping_regions());
 
-        let stack = self.push_stack(None, obligation);
+        let stack = self.push_stack(TraitObligationStackList::empty(), obligation);
         match try!(self.candidate_from_obligation(&stack)) {
             None => {
                 self.consider_unification_despite_ambiguity(obligation);
@@ -327,7 +330,8 @@ pub fn evaluate_obligation(&mut self,
         debug!("evaluate_obligation({})",
                obligation.repr(self.tcx()));
 
-        self.evaluate_predicate_recursively(None, obligation).may_apply()
+        self.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
+            .may_apply()
     }
 
     fn evaluate_builtin_bound_recursively<'o>(&mut self,
@@ -346,7 +350,7 @@ fn evaluate_builtin_bound_recursively<'o>(&mut self,
 
         match obligation {
             Ok(obligation) => {
-                self.evaluate_predicate_recursively(Some(previous_stack), &obligation)
+                self.evaluate_predicate_recursively(previous_stack.list(), &obligation)
             }
             Err(ErrorReported) => {
                 EvaluatedToOk
@@ -355,7 +359,7 @@ fn evaluate_builtin_bound_recursively<'o>(&mut self,
     }
 
     fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
-                                                stack: Option<&TraitObligationStack<'o, 'tcx>>,
+                                                stack: TraitObligationStackList<'o, 'tcx>,
                                                 predicates: I)
                                                 -> EvaluationResult<'tcx>
         where I : Iterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
@@ -372,7 +376,7 @@ fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
     }
 
     fn evaluate_predicate_recursively<'o>(&mut self,
-                                          previous_stack: Option<&TraitObligationStack<'o, 'tcx>>,
+                                          previous_stack: TraitObligationStackList<'o, 'tcx>,
                                           obligation: &PredicateObligation<'tcx>)
                                            -> EvaluationResult<'tcx>
     {
@@ -423,14 +427,14 @@ fn evaluate_predicate_recursively<'o>(&mut self,
     }
 
     fn evaluate_obligation_recursively<'o>(&mut self,
-                                           previous_stack: Option<&TraitObligationStack<'o, 'tcx>>,
+                                           previous_stack: TraitObligationStackList<'o, 'tcx>,
                                            obligation: &TraitObligation<'tcx>)
                                            -> EvaluationResult<'tcx>
     {
         debug!("evaluate_obligation_recursively({})",
                obligation.repr(self.tcx()));
 
-        let stack = self.push_stack(previous_stack.map(|x| x), obligation);
+        let stack = self.push_stack(previous_stack, obligation);
 
         let result = self.evaluate_stack(&stack);
 
@@ -472,7 +476,8 @@ fn evaluate_stack<'o>(&mut self,
             unbound_input_types &&
              (self.intercrate ||
               stack.iter().skip(1).any(
-                  |prev| stack.fresh_trait_ref.def_id() == prev.fresh_trait_ref.def_id()))
+                  |prev| self.match_fresh_trait_refs(&stack.fresh_trait_ref,
+                                                     &prev.fresh_trait_ref)))
         {
             debug!("evaluate_stack({}) --> unbound argument, recursion -->  ambiguous",
                    stack.fresh_trait_ref.repr(self.tcx()));
@@ -538,7 +543,8 @@ pub fn evaluate_impl(&mut self,
                                                        obligation.recursion_depth + 1,
                                                        skol_map,
                                                        snapshot);
-                    self.winnow_selection(None, VtableImpl(vtable_impl)).may_apply()
+                    self.winnow_selection(TraitObligationStackList::empty(),
+                                          VtableImpl(vtable_impl)).may_apply()
                 }
                 Err(()) => {
                     false
@@ -607,6 +613,11 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
             return Ok(Some(ErrorCandidate));
         }
 
+        if !self.is_knowable(stack) {
+            debug!("intercrate not knowable");
+            return Ok(None);
+        }
+
         let candidate_set = try!(self.assemble_candidates(stack));
 
         if candidate_set.ambiguous {
@@ -707,6 +718,27 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
         Ok(Some(candidate))
     }
 
+    fn is_knowable<'o>(&mut self,
+                       stack: &TraitObligationStack<'o, 'tcx>)
+                       -> bool
+    {
+        debug!("is_knowable(intercrate={})", self.intercrate);
+
+        if !self.intercrate {
+            return true;
+        }
+
+        let obligation = &stack.obligation;
+        let predicate = self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
+
+        // ok to skip binder because of the nature of the
+        // trait-ref-is-knowable check, which does not care about
+        // bound regions
+        let trait_ref = &predicate.skip_binder().trait_ref;
+
+        coherence::trait_ref_is_knowable(self.tcx(), trait_ref)
+    }
+
     fn pick_candidate_cache(&self) -> &SelectionCache<'tcx> {
         // If there are any where-clauses in scope, then we always use
         // a cache local to this particular scope. Otherwise, we
@@ -1026,7 +1058,7 @@ fn evaluate_where_clause<'o>(&mut self,
         self.infcx().probe(move |_| {
             match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
                 Ok(obligations) => {
-                    self.evaluate_predicates_recursively(Some(stack), obligations.iter())
+                    self.evaluate_predicates_recursively(stack.list(), obligations.iter())
                 }
                 Err(()) => {
                     EvaluatedToErr(Unimplemented)
@@ -1242,7 +1274,7 @@ fn assemble_candidates_from_object_ty(&mut self,
             return;
         }
 
-        self.infcx.try(|snapshot| {
+        self.infcx.commit_if_ok(|snapshot| {
             let bound_self_ty =
                 self.infcx.resolve_type_vars_if_possible(&obligation.self_ty());
             let (self_ty, _) =
@@ -1310,7 +1342,8 @@ fn winnow_candidate<'o>(&mut self,
         let result = self.infcx.probe(|_| {
             let candidate = (*candidate).clone();
             match self.confirm_candidate(stack.obligation, candidate) {
-                Ok(selection) => self.winnow_selection(Some(stack), selection),
+                Ok(selection) => self.winnow_selection(stack.list(),
+                                                       selection),
                 Err(error) => EvaluatedToErr(error),
             }
         });
@@ -1320,7 +1353,7 @@ fn winnow_candidate<'o>(&mut self,
     }
 
     fn winnow_selection<'o>(&mut self,
-                            stack: Option<&TraitObligationStack<'o, 'tcx>>,
+                            stack: TraitObligationStackList<'o,'tcx>,
                             selection: Selection<'tcx>)
                             -> EvaluationResult<'tcx>
     {
@@ -1778,7 +1811,7 @@ fn collect_predicates_for_types(&mut self,
 
         // For each type, produce a vector of resulting obligations
         let obligations: Result<Vec<Vec<_>>, _> = bound_types.iter().map(|nested_ty| {
-            self.infcx.try(|snapshot| {
+            self.infcx.commit_if_ok(|snapshot| {
                 let (skol_ty, skol_map) =
                     self.infcx().skolemize_late_bound_regions(nested_ty, snapshot);
                 let Normalized { value: normalized_ty, mut obligations } =
@@ -1888,7 +1921,7 @@ fn confirm_projection_candidate(&mut self,
                                     obligation: &TraitObligation<'tcx>)
     {
         let _: Result<(),()> =
-            self.infcx.try(|snapshot| {
+            self.infcx.commit_if_ok(|snapshot| {
                 let result =
                     self.match_projection_obligation_against_bounds_from_trait(obligation,
                                                                                snapshot);
@@ -2043,7 +2076,7 @@ fn vtable_default_impl(&mut self,
                                                                 trait_def_id,
                                                                 nested);
 
-        let trait_obligations: Result<VecPerParamSpace<_>,()> = self.infcx.try(|snapshot| {
+        let trait_obligations: Result<VecPerParamSpace<_>,()> = self.infcx.commit_if_ok(|snapshot| {
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
             let (trait_ref, skol_map) =
                 self.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot);
@@ -2077,7 +2110,7 @@ fn confirm_impl_candidate(&mut self,
 
         // First, create the substitutions by matching the impl again,
         // this time not in a probe.
-        self.infcx.try(|snapshot| {
+        self.infcx.commit_if_ok(|snapshot| {
             let (skol_obligation_trait_ref, skol_map) =
                 self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
             let substs =
@@ -2303,9 +2336,9 @@ fn match_impl(&mut self,
             return Err(());
         }
 
-        let impl_substs = util::fresh_substs_for_impl(self.infcx,
-                                                      obligation.cause.span,
-                                                      impl_def_id);
+        let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
+                                                         obligation.cause.span,
+                                                         impl_def_id);
 
         let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
                                                   &impl_substs);
@@ -2423,9 +2456,9 @@ fn match_inherent_impl(&mut self,
     {
         // Create fresh type variables for each type parameter declared
         // on the impl etc.
-        let impl_substs = util::fresh_substs_for_impl(self.infcx,
-                                                      obligation_cause.span,
-                                                      impl_def_id);
+        let impl_substs = util::fresh_type_vars_for_impl(self.infcx,
+                                                         obligation_cause.span,
+                                                         impl_def_id);
 
         // Find the self type for the impl.
         let impl_self_ty = ty::lookup_item_type(self.tcx(), impl_def_id).ty;
@@ -2475,8 +2508,17 @@ fn match_self_types(&mut self,
     ///////////////////////////////////////////////////////////////////////////
     // Miscellany
 
+    fn match_fresh_trait_refs(&self,
+                              previous: &ty::PolyTraitRef<'tcx>,
+                              current: &ty::PolyTraitRef<'tcx>)
+                              -> bool
+    {
+        let mut matcher = ty_match::Match::new(self.tcx());
+        matcher.relate(previous, current).is_ok()
+    }
+
     fn push_stack<'o,'s:'o>(&mut self,
-                            previous_stack: Option<&'s TraitObligationStack<'s, 'tcx>>,
+                            previous_stack: TraitObligationStackList<'s, 'tcx>,
                             obligation: &'o TraitObligation<'tcx>)
                             -> TraitObligationStack<'o, 'tcx>
     {
@@ -2486,7 +2528,7 @@ fn push_stack<'o,'s:'o>(&mut self,
         TraitObligationStack {
             obligation: obligation,
             fresh_trait_ref: fresh_trait_ref,
-            previous: previous_stack.map(|p| p), // FIXME variance
+            previous: previous_stack,
         }
     }
 
@@ -2634,22 +2676,41 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 impl<'tcx> SelectionCache<'tcx> {
     pub fn new() -> SelectionCache<'tcx> {
         SelectionCache {
-            hashmap: RefCell::new(HashMap::new())
+            hashmap: RefCell::new(FnvHashMap())
         }
     }
 }
 
-impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
-    fn iter(&self) -> Option<&TraitObligationStack<'o, 'tcx>> {
-        Some(self)
+impl<'o,'tcx> TraitObligationStack<'o,'tcx> {
+    fn list(&'o self) -> TraitObligationStackList<'o,'tcx> {
+        TraitObligationStackList::with(self)
     }
+
+    fn iter(&'o self) -> TraitObligationStackList<'o,'tcx> {
+        self.list()
+    }
+}
+
+#[derive(Copy, Clone)]
+struct TraitObligationStackList<'o,'tcx:'o> {
+    head: Option<&'o TraitObligationStack<'o,'tcx>>
 }
 
-impl<'o, 'tcx> Iterator for Option<&'o TraitObligationStack<'o, 'tcx>> {
+impl<'o,'tcx> TraitObligationStackList<'o,'tcx> {
+    fn empty() -> TraitObligationStackList<'o,'tcx> {
+        TraitObligationStackList { head: None }
+    }
+
+    fn with(r: &'o TraitObligationStack<'o,'tcx>) -> TraitObligationStackList<'o,'tcx> {
+        TraitObligationStackList { head: Some(r) }
+    }
+}
+
+impl<'o,'tcx> Iterator for TraitObligationStackList<'o,'tcx>{
     type Item = &'o TraitObligationStack<'o,'tcx>;
 
-    fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
-        match *self {
+    fn next(&mut self) -> Option<&'o TraitObligationStack<'o,'tcx>> {
+        match self.head {
             Some(o) => {
                 *self = o.previous;
                 Some(o)
@@ -2659,7 +2720,7 @@ fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
     }
 }
 
-impl<'o, 'tcx> Repr<'tcx> for TraitObligationStack<'o, 'tcx> {
+impl<'o,'tcx> Repr<'tcx> for TraitObligationStack<'o,'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         format!("TraitObligationStack({})",
                 self.obligation.repr(tcx))
index 7c7db4a64c02eec186a47ad066fbe5100361d566..297cea13207e57a99a5f9871db3e36b9e8a752dd 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use middle::region;
 use middle::subst::{Substs, VecPerParamSpace};
 use middle::infer::InferCtxt;
 use middle::ty::{self, Ty, AsPredicate, ToPolyTraitRef};
@@ -285,7 +286,6 @@ fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
     }
 }
 
-
 ///////////////////////////////////////////////////////////////////////////
 // Other
 ///////////////////////////////////////////////////////////////////////////
@@ -294,16 +294,44 @@ fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
 // declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
 // would return ($0, $1) where $0 and $1 are freshly instantiated type
 // variables.
-pub fn fresh_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                       span: Span,
-                                       impl_def_id: ast::DefId)
-                                       -> Substs<'tcx>
+pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                                          span: Span,
+                                          impl_def_id: ast::DefId)
+                                          -> Substs<'tcx>
 {
     let tcx = infcx.tcx;
     let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
     infcx.fresh_substs_for_generics(span, &impl_generics)
 }
 
+// determine the `self` type, using fresh variables for all variables
+// declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
+// would return ($0, $1) where $0 and $1 are freshly instantiated type
+// variables.
+pub fn free_substs_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                                      _span: Span,
+                                      impl_def_id: ast::DefId)
+                                      -> Substs<'tcx>
+{
+    let tcx = infcx.tcx;
+    let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
+
+    let some_types = impl_generics.types.map(|def| {
+        ty::mk_param_from_def(tcx, def)
+    });
+
+    let some_regions = impl_generics.regions.map(|def| {
+        // FIXME. This destruction scope information is pretty darn
+        // bogus; after all, the impl might not even be in this crate!
+        // But given what we do in coherence, it is harmless enough
+        // for now I think. -nmatsakis
+        let extent = region::DestructionScopeData::new(ast::DUMMY_NODE_ID);
+        ty::free_region_from_def(extent, def)
+    });
+
+    Substs::new(some_types, some_regions)
+}
+
 impl<'tcx, N> fmt::Debug for VtableImplData<'tcx, N> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "VtableImpl({:?})", self.impl_def_id)
index 161fae11ea6d42c1f254f80f5db9e700c447e72e..0814ec2c84e7085f62573c1d6b9235ed6a9f9867 100644 (file)
@@ -58,7 +58,7 @@
 use middle::traits;
 use middle::ty;
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
-use middle::ty_walk::TypeWalker;
+use middle::ty_walk::{self, TypeWalker};
 use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
 use util::ppaux::ty_to_string;
 use util::ppaux::{Repr, UserString};
 
 use arena::TypedArena;
 use std::borrow::{Borrow, Cow};
-use std::cell::{Cell, RefCell};
+use std::cell::{Cell, RefCell, Ref};
 use std::cmp;
 use std::fmt;
 use std::hash::{Hash, SipHasher, Hasher};
 use std::mem;
+use std::num::ToPrimitive;
 use std::ops;
 use std::rc::Rc;
 use std::vec::IntoIter;
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
 use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
 use syntax::ast_util::{self, is_local, lit_is_str, local_def};
-use syntax::attr::{self, AttrMetaMethods};
+use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 use syntax::codemap::Span;
 use syntax::parse::token::{self, InternedString, special_idents};
-use syntax::{ast, ast_map};
+use syntax::print::pprust;
+use syntax::ptr::P;
+use syntax::ast;
+use syntax::ast_map::{self, LinkedPath};
 
 pub type Disr = u64;
 
@@ -685,7 +689,7 @@ pub struct ctxt<'tcx> {
     /// Stores the types for various nodes in the AST.  Note that this table
     /// is not guaranteed to be populated until after typeck.  See
     /// typeck::check::fn_ctxt for details.
-    pub node_types: RefCell<NodeMap<Ty<'tcx>>>,
+    node_types: RefCell<NodeMap<Ty<'tcx>>>,
 
     /// Stores the type parameters which were substituted to obtain the type
     /// of this node.  This only applies to nodes that refer to entities
@@ -850,6 +854,13 @@ pub struct ctxt<'tcx> {
     pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
 }
 
+impl<'tcx> ctxt<'tcx> {
+    pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> { self.node_types.borrow() }
+    pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) {
+        self.node_types.borrow_mut().insert(id, ty);
+    }
+}
+
 // Flags that we track on types. These flags are propagated upwards
 // through the type during type construction, so that we can quickly
 // check whether the type has various kinds of types in it without
@@ -3157,21 +3168,11 @@ pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
         TypeWalker::new(self)
     }
 
-    /// Iterator that walks types reachable from `self`, in
-    /// depth-first order. Note that this is a shallow walk. For
-    /// example:
-    ///
-    /// ```notrust
-    /// isize => { }
-    /// Foo<Bar<isize>> => { Bar<isize>, isize }
-    /// [isize] => { isize }
-    /// ```
-    pub fn walk_children(&'tcx self) -> TypeWalker<'tcx> {
-        // Walks type reachable from `self` but not `self
-        let mut walker = self.walk();
-        let r = walker.next();
-        assert_eq!(r, Some(self));
-        walker
+    /// Iterator that walks the immediate children of `self`.  Hence
+    /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]`
+    /// (but not `i32`, like `walk`).
+    pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> {
+        ty_walk::walk_shallow(self)
     }
 
     pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
@@ -5474,7 +5475,7 @@ pub fn with_path<T, F>(cx: &ctxt, id: ast::DefId, f: F) -> T where
     if id.krate == ast::LOCAL_CRATE {
         cx.map.with_path(id.node, f)
     } else {
-        f(csearch::get_item_path(cx, id).iter().cloned().chain(None))
+        f(csearch::get_item_path(cx, id).iter().cloned().chain(LinkedPath::empty()))
     }
 }
 
@@ -5489,63 +5490,268 @@ pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
      }
 }
 
+trait IntTypeExt {
+    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>;
+    fn i64_to_disr(&self, val: i64) -> Option<Disr>;
+    fn u64_to_disr(&self, val: u64) -> Option<Disr>;
+    fn disr_incr(&self, val: Disr) -> Option<Disr>;
+    fn disr_string(&self, val: Disr) -> String;
+    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr;
+}
+
+impl IntTypeExt for attr::IntType {
+    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
+        match *self {
+            SignedInt(ast::TyI8)      => cx.types.i8,
+            SignedInt(ast::TyI16)     => cx.types.i16,
+            SignedInt(ast::TyI32)     => cx.types.i32,
+            SignedInt(ast::TyI64)     => cx.types.i64,
+            SignedInt(ast::TyIs)   => cx.types.isize,
+            UnsignedInt(ast::TyU8)    => cx.types.u8,
+            UnsignedInt(ast::TyU16)   => cx.types.u16,
+            UnsignedInt(ast::TyU32)   => cx.types.u32,
+            UnsignedInt(ast::TyU64)   => cx.types.u64,
+            UnsignedInt(ast::TyUs) => cx.types.usize,
+        }
+    }
+
+    fn i64_to_disr(&self, val: i64) -> Option<Disr> {
+        match *self {
+            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    fn u64_to_disr(&self, val: u64) -> Option<Disr> {
+        match *self {
+            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    fn disr_incr(&self, val: Disr) -> Option<Disr> {
+        macro_rules! add1 {
+            ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) }
+        }
+        match *self {
+            // SignedInt repr means we *want* to reinterpret the bits
+            // treating the highest bit of Disr as a sign-bit, so
+            // cast to i64 before range-checking.
+            SignedInt(ast::TyI8)    => add1!((val as i64).to_i8()),
+            SignedInt(ast::TyI16)   => add1!((val as i64).to_i16()),
+            SignedInt(ast::TyI32)   => add1!((val as i64).to_i32()),
+            SignedInt(ast::TyI64)   => add1!(Some(val as i64)),
+
+            UnsignedInt(ast::TyU8)  => add1!(val.to_u8()),
+            UnsignedInt(ast::TyU16) => add1!(val.to_u16()),
+            UnsignedInt(ast::TyU32) => add1!(val.to_u32()),
+            UnsignedInt(ast::TyU64) => add1!(Some(val)),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    // This returns a String because (1.) it is only used for
+    // rendering an error message and (2.) a string can represent the
+    // full range from `i64::MIN` through `u64::MAX`.
+    fn disr_string(&self, val: Disr) -> String {
+        match *self {
+            SignedInt(ast::TyI8)    => format!("{}", val as i8 ),
+            SignedInt(ast::TyI16)   => format!("{}", val as i16),
+            SignedInt(ast::TyI32)   => format!("{}", val as i32),
+            SignedInt(ast::TyI64)   => format!("{}", val as i64),
+            UnsignedInt(ast::TyU8)  => format!("{}", val as u8 ),
+            UnsignedInt(ast::TyU16) => format!("{}", val as u16),
+            UnsignedInt(ast::TyU32) => format!("{}", val as u32),
+            UnsignedInt(ast::TyU64) => format!("{}", val as u64),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr {
+        macro_rules! add1 {
+            ($e:expr) => { ($e).wrapping_add(1) as Disr }
+        }
+        let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
+        match *self {
+            SignedInt(ast::TyI8)    => add1!(val as i8 ),
+            SignedInt(ast::TyI16)   => add1!(val as i16),
+            SignedInt(ast::TyI32)   => add1!(val as i32),
+            SignedInt(ast::TyI64)   => add1!(val as i64),
+            UnsignedInt(ast::TyU8)  => add1!(val as u8 ),
+            UnsignedInt(ast::TyU16) => add1!(val as u16),
+            UnsignedInt(ast::TyU32) => add1!(val as u32),
+            UnsignedInt(ast::TyU64) => add1!(val as u64),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+}
+
+/// Returns `(normalized_type, ty)`, where `normalized_type` is the
+/// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8},
+/// and `ty` is the original type (i.e. may include `isize` or
+/// `usize`).
+pub fn enum_repr_type<'tcx>(cx: &ctxt<'tcx>,
+                            opt_hint: Option<&attr::ReprAttr>)
+                            -> (attr::IntType, Ty<'tcx>)
+{
+    let repr_type = match opt_hint {
+        // Feed in the given type
+        Some(&attr::ReprInt(_, int_t)) => int_t,
+        // ... but provide sensible default if none provided
+        //
+        // NB. Historically `fn enum_variants` generate i64 here, while
+        // rustc_typeck::check would generate isize.
+        _ => SignedInt(ast::TyIs),
+    };
+
+    let repr_type_ty = repr_type.to_ty(cx);
+    let repr_type = match repr_type {
+        SignedInt(ast::TyIs) =>
+            SignedInt(cx.sess.target.int_type),
+        UnsignedInt(ast::TyUs) =>
+            UnsignedInt(cx.sess.target.uint_type),
+        other => other
+    };
+
+    (repr_type, repr_type_ty)
+}
+
+fn report_discrim_overflow(cx: &ctxt,
+                           variant_span: Span,
+                           variant_name: &str,
+                           repr_type: attr::IntType,
+                           prev_val: Disr) {
+    let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
+    let computed_value = repr_type.disr_string(computed_value);
+    let prev_val = repr_type.disr_string(prev_val);
+    let repr_type = repr_type.to_ty(cx).user_string(cx);
+    span_err!(cx.sess, variant_span, E0370,
+              "enum discriminant overflowed on value after {}: {}; \
+               set explicitly via {} = {} if that is desired outcome",
+              prev_val, repr_type, variant_name, computed_value);
+}
+
+// This computes the discriminant values for the sequence of Variants
+// attached to a particular enum, taking into account the #[repr] (if
+// any) provided via the `opt_hint`.
+fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>,
+                               vs: &'tcx [P<ast::Variant>],
+                               opt_hint: Option<&attr::ReprAttr>)
+                               -> Vec<Rc<ty::VariantInfo<'tcx>>> {
+    let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
+    let mut prev_disr_val: Option<ty::Disr> = None;
+
+    let (repr_type, repr_type_ty) = ty::enum_repr_type(cx, opt_hint);
+
+    for v in vs {
+        // If the discriminant value is specified explicitly in the
+        // enum, check whether the initialization expression is valid,
+        // otherwise use the last value plus one.
+        let current_disr_val;
+
+        // This closure marks cases where, when an error occurs during
+        // the computation, attempt to assign a (hopefully) fresh
+        // value to avoid spurious error reports downstream.
+        let attempt_fresh_value = move || -> Disr {
+            repr_type.disr_wrap_incr(prev_disr_val)
+        };
+
+        match v.node.disr_expr {
+            Some(ref e) => {
+                debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
+
+                // check_expr (from check_const pass) doesn't guarantee
+                // that the expression is in a form that eval_const_expr can
+                // handle, so we may still get an internal compiler error
+                //
+                // pnkfelix: The above comment was transcribed from
+                // the version of this code taken from rustc_typeck.
+                // Presumably the implication is that we need to deal
+                // with such ICE's as they arise.
+                //
+                // Since this can be called from `ty::enum_variants`
+                // anyway, best thing is to make `eval_const_expr`
+                // more robust (on case-by-case basis).
+
+                match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) {
+                    Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
+                    Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
+                    Ok(_) => {
+                        span_err!(cx.sess, e.span, E0079,
+                                  "expected signed integer constant");
+                        current_disr_val = attempt_fresh_value();
+                    }
+                    Err(ref err) => {
+                        span_err!(cx.sess, err.span, E0080,
+                                  "constant evaluation error: {}",
+                                  err.description());
+                        current_disr_val = attempt_fresh_value();
+                    }
+                }
+            },
+            None => {
+                current_disr_val = match prev_disr_val {
+                    Some(prev_disr_val) => {
+                        if let Some(v) = repr_type.disr_incr(prev_disr_val) {
+                            v
+                        } else {
+                            report_discrim_overflow(cx, v.span, v.node.name.as_str(),
+                                                    repr_type, prev_disr_val);
+                            attempt_fresh_value()
+                        }
+                    }
+                    None => ty::INITIAL_DISCRIMINANT_VALUE
+                }
+            }
+        }
+
+        let variant_info = Rc::new(VariantInfo::from_ast_variant(cx, &**v, current_disr_val));
+        prev_disr_val = Some(current_disr_val);
+
+        variants.push(variant_info);
+    }
+
+    return variants;
+}
+
 pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                            -> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
     memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
         if ast::LOCAL_CRATE != id.krate {
             Rc::new(csearch::get_enum_variants(cx, id))
         } else {
-            /*
-              Although both this code and check_enum_variants in typeck/check
-              call eval_const_expr, it should never get called twice for the same
-              expr, since check_enum_variants also updates the enum_var_cache
-             */
             match cx.map.get(id.node) {
                 ast_map::NodeItem(ref item) => {
                     match item.node {
                         ast::ItemEnum(ref enum_definition, _) => {
-                            let mut last_discriminant: Option<Disr> = None;
-                            Rc::new(enum_definition.variants.iter().map(|variant| {
-
-                                let mut discriminant = INITIAL_DISCRIMINANT_VALUE;
-                                if let Some(ref e) = variant.node.disr_expr {
-                                    // Preserve all values, and prefer signed.
-                                    let ty = Some(cx.types.i64);
-                                    match const_eval::eval_const_expr_partial(cx, &**e, ty) {
-                                        Ok(const_eval::const_int(val)) => {
-                                            discriminant = val as Disr;
-                                        }
-                                        Ok(const_eval::const_uint(val)) => {
-                                            discriminant = val as Disr;
-                                        }
-                                        Ok(_) => {
-                                            span_err!(cx.sess, e.span, E0304,
-                                                      "expected signed integer constant");
-                                        }
-                                        Err(err) => {
-                                            span_err!(cx.sess, err.span, E0305,
-                                                      "constant evaluation error: {}",
-                                                      err.description());
-                                        }
-                                    }
-                                } else {
-                                    if let Some(val) = last_discriminant {
-                                        if let Some(v) = val.checked_add(1) {
-                                            discriminant = v
-                                        } else {
-                                            cx.sess.span_err(
-                                                variant.span,
-                                                &format!("Discriminant overflowed!"));
-                                        }
-                                    } else {
-                                        discriminant = INITIAL_DISCRIMINANT_VALUE;
-                                    }
-                                }
-
-                                last_discriminant = Some(discriminant);
-                                Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
-                                                                      discriminant))
-                            }).collect())
+                            Rc::new(compute_enum_variants(
+                                cx,
+                                &enum_definition.variants,
+                                lookup_repr_hints(cx, id).get(0)))
                         }
                         _ => {
                             cx.sess.bug("enum_variants: id not bound to an enum")
@@ -5831,19 +6037,20 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize {
                 "expected positive integer for repeat count, found {}",
                 found);
         }
-        Err(_) => {
+        Err(err) => {
+            let err_description = err.description();
             let found = match count_expr.node {
                 ast::ExprPath(None, ast::Path {
                     global: false,
                     ref segments,
                     ..
                 }) if segments.len() == 1 =>
-                    "variable",
+                    format!("{}", "found variable"),
                 _ =>
-                    "non-constant expression"
+                    format!("but {}", err_description),
             };
             span_err!(tcx.sess, count_expr.span, E0307,
-                "expected constant integer for repeat count, found {}",
+                "expected constant integer for repeat count, {}",
                 found);
         }
     }
index f17ba78007bb2270eacd8b47a26ac605068b7a3c..5f77574f65ed4351692f8cc5868678bd73117b25 100644 (file)
@@ -39,6 +39,8 @@
 use middle::ty::{self, Ty};
 use middle::traits;
 use std::rc::Rc;
+use syntax::abi;
+use syntax::ast;
 use syntax::owned_slice::OwnedSlice;
 use util::ppaux::Repr;
 
@@ -47,7 +49,7 @@
 
 /// The TypeFoldable trait is implemented for every type that can be folded.
 /// Basically, every type that has a corresponding method in TypeFolder.
-pub trait TypeFoldable<'tcx> {
+pub trait TypeFoldable<'tcx>: Repr<'tcx> + Clone {
     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
 }
 
@@ -149,12 +151,20 @@ fn fold_item_substs(&mut self, i: ty::ItemSubsts<'tcx>) -> ty::ItemSubsts<'tcx>
 // can easily refactor the folding into the TypeFolder trait as
 // needed.
 
-impl<'tcx> TypeFoldable<'tcx> for () {
-    fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> () {
-        ()
+macro_rules! CopyImpls {
+    ($($ty:ty),+) => {
+        $(
+            impl<'tcx> TypeFoldable<'tcx> for $ty {
+                fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> $ty {
+                    *self
+                }
+            }
+        )+
     }
 }
 
+CopyImpls! { (), ast::Unsafety, abi::Abi }
+
 impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
         (self.0.fold_with(folder), self.1.fold_with(folder))
diff --git a/src/librustc/middle/ty_match.rs b/src/librustc/middle/ty_match.rs
new file mode 100644 (file)
index 0000000..bb00fad
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::ty::{self, Ty};
+use middle::ty_relate::{self, Relate, TypeRelation, RelateResult};
+use util::ppaux::Repr;
+
+/// A type "A" *matches* "B" if the fresh types in B could be
+/// substituted with values so as to make it equal to A. Matching is
+/// intended to be used only on freshened types, and it basically
+/// indicates if the non-freshened versions of A and B could have been
+/// unified.
+///
+/// It is only an approximation. If it yields false, unification would
+/// definitely fail, but a true result doesn't mean unification would
+/// succeed. This is because we don't track the "side-constraints" on
+/// type variables, nor do we track if the same freshened type appears
+/// more than once. To some extent these approximations could be
+/// fixed, given effort.
+///
+/// Like subtyping, matching is really a binary relation, so the only
+/// important thing about the result is Ok/Err. Also, matching never
+/// affects any type variables or unification state.
+pub struct Match<'a, 'tcx: 'a> {
+    tcx: &'a ty::ctxt<'tcx>
+}
+
+impl<'a, 'tcx> Match<'a, 'tcx> {
+    pub fn new(tcx: &'a ty::ctxt<'tcx>) -> Match<'a, 'tcx> {
+        Match { tcx: tcx }
+    }
+}
+
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> {
+    fn tag(&self) -> &'static str { "Match" }
+    fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.tcx }
+    fn a_is_expected(&self) -> bool { true } // irrelevant
+
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               _: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>
+    {
+        self.relate(a, b)
+    }
+
+    fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
+        debug!("{}.regions({}, {})",
+               self.tag(),
+               a.repr(self.tcx()),
+               b.repr(self.tcx()));
+        Ok(a)
+    }
+
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        debug!("{}.tys({}, {})", self.tag(),
+               a.repr(self.tcx()), b.repr(self.tcx()));
+        if a == b { return Ok(a); }
+
+        match (&a.sty, &b.sty) {
+            (_, &ty::ty_infer(ty::FreshTy(_))) |
+            (_, &ty::ty_infer(ty::FreshIntTy(_))) => {
+                Ok(a)
+            }
+
+            (&ty::ty_infer(_), _) |
+            (_, &ty::ty_infer(_)) => {
+                Err(ty::terr_sorts(ty_relate::expected_found(self, &a, &b)))
+            }
+
+            (&ty::ty_err, _) | (_, &ty::ty_err) => {
+                Ok(self.tcx().types.err)
+            }
+
+            _ => {
+                ty_relate::super_relate_tys(self, a, b)
+            }
+        }
+    }
+
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a,'tcx>
+    {
+        Ok(ty::Binder(try!(self.relate(a.skip_binder(), b.skip_binder()))))
+    }
+}
diff --git a/src/librustc/middle/ty_relate/mod.rs b/src/librustc/middle/ty_relate/mod.rs
new file mode 100644 (file)
index 0000000..1205b7d
--- /dev/null
@@ -0,0 +1,655 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Generalized type relating mechanism. A type relation R relates a
+//! pair of values (A, B). A and B are usually types or regions but
+//! can be other things. Examples of type relations are subtyping,
+//! type equality, etc.
+
+use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs};
+use middle::ty::{self, Ty};
+use middle::ty_fold::TypeFoldable;
+use std::rc::Rc;
+use syntax::abi;
+use syntax::ast;
+use util::ppaux::Repr;
+
+pub type RelateResult<'tcx, T> = Result<T, ty::type_err<'tcx>>;
+
+pub trait TypeRelation<'a,'tcx> : Sized {
+    fn tcx(&self) -> &'a ty::ctxt<'tcx>;
+
+    /// Returns a static string we can use for printouts.
+    fn tag(&self) -> &'static str;
+
+    /// Returns true if the value `a` is the "expected" type in the
+    /// relation. Just affects error messages.
+    fn a_is_expected(&self) -> bool;
+
+    /// Generic relation routine suitable for most anything.
+    fn relate<T:Relate<'a,'tcx>>(&mut self, a: &T, b: &T) -> RelateResult<'tcx, T> {
+        Relate::relate(self, a, b)
+    }
+
+    /// Switch variance for the purpose of relating `a` and `b`.
+    fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
+                                               variance: ty::Variance,
+                                               a: &T,
+                                               b: &T)
+                                               -> RelateResult<'tcx, T>;
+
+    // Overrideable relations. You shouldn't typically call these
+    // directly, instead call `relate()`, which in turn calls
+    // these. This is both more uniform but also allows us to add
+    // additional hooks for other types in the future if needed
+    // without making older code, which called `relate`, obsolete.
+
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>)
+           -> RelateResult<'tcx, Ty<'tcx>>;
+
+    fn regions(&mut self, a: ty::Region, b: ty::Region)
+               -> RelateResult<'tcx, ty::Region>;
+
+    fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
+                  -> RelateResult<'tcx, ty::Binder<T>>
+        where T: Relate<'a,'tcx>;
+}
+
+pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> {
+    fn relate<R:TypeRelation<'a,'tcx>>(relation: &mut R,
+                                       a: &Self,
+                                       b: &Self)
+                                       -> RelateResult<'tcx, Self>;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Relate impls
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::mt<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::mt<'tcx>,
+                 b: &ty::mt<'tcx>)
+                 -> RelateResult<'tcx, ty::mt<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        debug!("{}.mts({}, {})",
+               relation.tag(),
+               a.repr(relation.tcx()),
+               b.repr(relation.tcx()));
+        if a.mutbl != b.mutbl {
+            Err(ty::terr_mutability)
+        } else {
+            let mutbl = a.mutbl;
+            let variance = match mutbl {
+                ast::MutImmutable => ty::Covariant,
+                ast::MutMutable => ty::Invariant,
+            };
+            let ty = try!(relation.relate_with_variance(variance, &a.ty, &b.ty));
+            Ok(ty::mt {ty: ty, mutbl: mutbl})
+        }
+    }
+}
+
+// substitutions are not themselves relatable without more context,
+// but they is an important subroutine for things that ARE relatable,
+// like traits etc.
+fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R,
+                                    item_def_id: ast::DefId,
+                                    a_subst: &Substs<'tcx>,
+                                    b_subst: &Substs<'tcx>)
+                                    -> RelateResult<'tcx, Substs<'tcx>>
+    where R: TypeRelation<'a,'tcx>
+{
+    debug!("substs: item_def_id={} a_subst={} b_subst={}",
+           item_def_id.repr(relation.tcx()),
+           a_subst.repr(relation.tcx()),
+           b_subst.repr(relation.tcx()));
+
+    let variances;
+    let opt_variances = if relation.tcx().variance_computed.get() {
+        variances = ty::item_variances(relation.tcx(), item_def_id);
+        Some(&*variances)
+    } else {
+        None
+    };
+    relate_substs(relation, opt_variances, a_subst, b_subst)
+}
+
+fn relate_substs<'a,'tcx,R>(relation: &mut R,
+                            variances: Option<&ty::ItemVariances>,
+                            a_subst: &Substs<'tcx>,
+                            b_subst: &Substs<'tcx>)
+                            -> RelateResult<'tcx, Substs<'tcx>>
+    where R: TypeRelation<'a,'tcx>
+{
+    let mut substs = Substs::empty();
+
+    for &space in &ParamSpace::all() {
+        let a_tps = a_subst.types.get_slice(space);
+        let b_tps = b_subst.types.get_slice(space);
+        let t_variances = variances.map(|v| v.types.get_slice(space));
+        let tps = try!(relate_type_params(relation, t_variances, a_tps, b_tps));
+        substs.types.replace(space, tps);
+    }
+
+    match (&a_subst.regions, &b_subst.regions) {
+        (&ErasedRegions, _) | (_, &ErasedRegions) => {
+            substs.regions = ErasedRegions;
+        }
+
+        (&NonerasedRegions(ref a), &NonerasedRegions(ref b)) => {
+            for &space in &ParamSpace::all() {
+                let a_regions = a.get_slice(space);
+                let b_regions = b.get_slice(space);
+                let r_variances = variances.map(|v| v.regions.get_slice(space));
+                let regions = try!(relate_region_params(relation,
+                                                        r_variances,
+                                                        a_regions,
+                                                        b_regions));
+                substs.mut_regions().replace(space, regions);
+            }
+        }
+    }
+
+    Ok(substs)
+}
+
+fn relate_type_params<'a,'tcx,R>(relation: &mut R,
+                                 variances: Option<&[ty::Variance]>,
+                                 a_tys: &[Ty<'tcx>],
+                                 b_tys: &[Ty<'tcx>])
+                                 -> RelateResult<'tcx, Vec<Ty<'tcx>>>
+    where R: TypeRelation<'a,'tcx>
+{
+    if a_tys.len() != b_tys.len() {
+        return Err(ty::terr_ty_param_size(expected_found(relation,
+                                                         &a_tys.len(),
+                                                         &b_tys.len())));
+    }
+
+    (0 .. a_tys.len())
+        .map(|i| {
+            let a_ty = a_tys[i];
+            let b_ty = b_tys[i];
+            let v = variances.map_or(ty::Invariant, |v| v[i]);
+            relation.relate_with_variance(v, &a_ty, &b_ty)
+        })
+        .collect()
+}
+
+fn relate_region_params<'a,'tcx:'a,R>(relation: &mut R,
+                                      variances: Option<&[ty::Variance]>,
+                                      a_rs: &[ty::Region],
+                                      b_rs: &[ty::Region])
+                                      -> RelateResult<'tcx, Vec<ty::Region>>
+    where R: TypeRelation<'a,'tcx>
+{
+    let tcx = relation.tcx();
+    let num_region_params = a_rs.len();
+
+    debug!("relate_region_params(a_rs={}, \
+            b_rs={}, variances={})",
+           a_rs.repr(tcx),
+           b_rs.repr(tcx),
+           variances.repr(tcx));
+
+    assert_eq!(num_region_params,
+               variances.map_or(num_region_params,
+                                |v| v.len()));
+
+    assert_eq!(num_region_params, b_rs.len());
+
+    (0..a_rs.len())
+        .map(|i| {
+            let a_r = a_rs[i];
+            let b_r = b_rs[i];
+            let variance = variances.map_or(ty::Invariant, |v| v[i]);
+            relation.relate_with_variance(variance, &a_r, &b_r)
+        })
+        .collect()
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BareFnTy<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::BareFnTy<'tcx>,
+                 b: &ty::BareFnTy<'tcx>)
+                 -> RelateResult<'tcx, ty::BareFnTy<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        let unsafety = try!(relation.relate(&a.unsafety, &b.unsafety));
+        let abi = try!(relation.relate(&a.abi, &b.abi));
+        let sig = try!(relation.relate(&a.sig, &b.sig));
+        Ok(ty::BareFnTy {unsafety: unsafety,
+                         abi: abi,
+                         sig: sig})
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::FnSig<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::FnSig<'tcx>,
+                 b: &ty::FnSig<'tcx>)
+                 -> RelateResult<'tcx, ty::FnSig<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        if a.variadic != b.variadic {
+            return Err(ty::terr_variadic_mismatch(
+                expected_found(relation, &a.variadic, &b.variadic)));
+        }
+
+        let inputs = try!(relate_arg_vecs(relation,
+                                          &a.inputs,
+                                          &b.inputs));
+
+        let output = try!(match (a.output, b.output) {
+            (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) =>
+                Ok(ty::FnConverging(try!(relation.relate(&a_ty, &b_ty)))),
+            (ty::FnDiverging, ty::FnDiverging) =>
+                Ok(ty::FnDiverging),
+            (a, b) =>
+                Err(ty::terr_convergence_mismatch(
+                    expected_found(relation, &(a != ty::FnDiverging), &(b != ty::FnDiverging)))),
+        });
+
+        return Ok(ty::FnSig {inputs: inputs,
+                             output: output,
+                             variadic: a.variadic});
+    }
+}
+
+fn relate_arg_vecs<'a,'tcx,R>(relation: &mut R,
+                              a_args: &[Ty<'tcx>],
+                              b_args: &[Ty<'tcx>])
+                              -> RelateResult<'tcx, Vec<Ty<'tcx>>>
+    where R: TypeRelation<'a,'tcx>
+{
+    if a_args.len() != b_args.len() {
+        return Err(ty::terr_arg_count);
+    }
+
+    a_args.iter()
+          .zip(b_args.iter())
+          .map(|(a, b)| relation.relate_with_variance(ty::Contravariant, a, b))
+          .collect()
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ast::Unsafety {
+    fn relate<R>(relation: &mut R,
+                 a: &ast::Unsafety,
+                 b: &ast::Unsafety)
+                 -> RelateResult<'tcx, ast::Unsafety>
+        where R: TypeRelation<'a,'tcx>
+    {
+        if a != b {
+            Err(ty::terr_unsafety_mismatch(expected_found(relation, a, b)))
+        } else {
+            Ok(*a)
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for abi::Abi {
+    fn relate<R>(relation: &mut R,
+                 a: &abi::Abi,
+                 b: &abi::Abi)
+                 -> RelateResult<'tcx, abi::Abi>
+        where R: TypeRelation<'a,'tcx>
+    {
+        if a == b {
+            Ok(*a)
+        } else {
+            Err(ty::terr_abi_mismatch(expected_found(relation, a, b)))
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionTy<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::ProjectionTy<'tcx>,
+                 b: &ty::ProjectionTy<'tcx>)
+                 -> RelateResult<'tcx, ty::ProjectionTy<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        if a.item_name != b.item_name {
+            Err(ty::terr_projection_name_mismatched(
+                expected_found(relation, &a.item_name, &b.item_name)))
+        } else {
+            let trait_ref = try!(relation.relate(&*a.trait_ref, &*b.trait_ref));
+            Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ProjectionPredicate<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::ProjectionPredicate<'tcx>,
+                 b: &ty::ProjectionPredicate<'tcx>)
+                 -> RelateResult<'tcx, ty::ProjectionPredicate<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        let projection_ty = try!(relation.relate(&a.projection_ty, &b.projection_ty));
+        let ty = try!(relation.relate(&a.ty, &b.ty));
+        Ok(ty::ProjectionPredicate { projection_ty: projection_ty, ty: ty })
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for Vec<ty::PolyProjectionPredicate<'tcx>> {
+    fn relate<R>(relation: &mut R,
+                 a: &Vec<ty::PolyProjectionPredicate<'tcx>>,
+                 b: &Vec<ty::PolyProjectionPredicate<'tcx>>)
+                 -> RelateResult<'tcx, Vec<ty::PolyProjectionPredicate<'tcx>>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        // To be compatible, `a` and `b` must be for precisely the
+        // same set of traits and item names. We always require that
+        // projection bounds lists are sorted by trait-def-id and item-name,
+        // so we can just iterate through the lists pairwise, so long as they are the
+        // same length.
+        if a.len() != b.len() {
+            Err(ty::terr_projection_bounds_length(expected_found(relation, &a.len(), &b.len())))
+        } else {
+            a.iter()
+                .zip(b.iter())
+                .map(|(a, b)| relation.relate(a, b))
+                .collect()
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::ExistentialBounds<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::ExistentialBounds<'tcx>,
+                 b: &ty::ExistentialBounds<'tcx>)
+                 -> RelateResult<'tcx, ty::ExistentialBounds<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        let r = try!(relation.relate_with_variance(ty::Contravariant,
+                                                   &a.region_bound,
+                                                   &b.region_bound));
+        let nb = try!(relation.relate(&a.builtin_bounds, &b.builtin_bounds));
+        let pb = try!(relation.relate(&a.projection_bounds, &b.projection_bounds));
+        Ok(ty::ExistentialBounds { region_bound: r,
+                                   builtin_bounds: nb,
+                                   projection_bounds: pb })
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::BuiltinBounds {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::BuiltinBounds,
+                 b: &ty::BuiltinBounds)
+                 -> RelateResult<'tcx, ty::BuiltinBounds>
+        where R: TypeRelation<'a,'tcx>
+    {
+        // Two sets of builtin bounds are only relatable if they are
+        // precisely the same (but see the coercion code).
+        if a != b {
+            Err(ty::terr_builtin_bounds(expected_found(relation, a, b)))
+        } else {
+            Ok(*a)
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::TraitRef<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::TraitRef<'tcx>,
+                 b: &ty::TraitRef<'tcx>)
+                 -> RelateResult<'tcx, ty::TraitRef<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        // Different traits cannot be related
+        if a.def_id != b.def_id {
+            Err(ty::terr_traits(expected_found(relation, &a.def_id, &b.def_id)))
+        } else {
+            let substs = try!(relate_item_substs(relation, a.def_id, a.substs, b.substs));
+            Ok(ty::TraitRef { def_id: a.def_id, substs: relation.tcx().mk_substs(substs) })
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for Ty<'tcx> {
+    fn relate<R>(relation: &mut R,
+                 a: &Ty<'tcx>,
+                 b: &Ty<'tcx>)
+                 -> RelateResult<'tcx, Ty<'tcx>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        relation.tys(a, b)
+    }
+}
+
+/// The main "type relation" routine. Note that this does not handle
+/// inference artifacts, so you should filter those out before calling
+/// it.
+pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
+                                      a: Ty<'tcx>,
+                                      b: Ty<'tcx>)
+                                      -> RelateResult<'tcx, Ty<'tcx>>
+    where R: TypeRelation<'a,'tcx>
+{
+    let tcx = relation.tcx();
+    let a_sty = &a.sty;
+    let b_sty = &b.sty;
+    debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
+    match (a_sty, b_sty) {
+        (&ty::ty_infer(_), _) |
+        (_, &ty::ty_infer(_)) =>
+        {
+            // The caller should handle these cases!
+            tcx.sess.bug("var types encountered in super_relate_tys")
+        }
+
+        (&ty::ty_err, _) | (_, &ty::ty_err) =>
+        {
+            Ok(tcx.types.err)
+        }
+
+        (&ty::ty_char, _) |
+        (&ty::ty_bool, _) |
+        (&ty::ty_int(_), _) |
+        (&ty::ty_uint(_), _) |
+        (&ty::ty_float(_), _) |
+        (&ty::ty_str, _)
+            if a == b =>
+        {
+            Ok(a)
+        }
+
+        (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p))
+            if a_p.idx == b_p.idx && a_p.space == b_p.space =>
+        {
+            Ok(a)
+        }
+
+        (&ty::ty_enum(a_id, a_substs), &ty::ty_enum(b_id, b_substs))
+            if a_id == b_id =>
+        {
+            let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
+            Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
+        }
+
+        (&ty::ty_trait(ref a_), &ty::ty_trait(ref b_)) =>
+        {
+            let principal = try!(relation.relate(&a_.principal, &b_.principal));
+            let bounds = try!(relation.relate(&a_.bounds, &b_.bounds));
+            Ok(ty::mk_trait(tcx, principal, bounds))
+        }
+
+        (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
+            if a_id == b_id =>
+        {
+            let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
+            Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs)))
+        }
+
+        (&ty::ty_closure(a_id, a_substs),
+         &ty::ty_closure(b_id, b_substs))
+            if a_id == b_id =>
+        {
+            // All ty_closure types with the same id represent
+            // the (anonymous) type of the same closure expression. So
+            // all of their regions should be equated.
+            let substs = try!(relate_substs(relation, None, a_substs, b_substs));
+            Ok(ty::mk_closure(tcx, a_id, tcx.mk_substs(substs)))
+        }
+
+        (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) =>
+        {
+            let typ = try!(relation.relate(&a_inner, &b_inner));
+            Ok(ty::mk_uniq(tcx, typ))
+        }
+
+        (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) =>
+        {
+            let mt = try!(relation.relate(a_mt, b_mt));
+            Ok(ty::mk_ptr(tcx, mt))
+        }
+
+        (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) =>
+        {
+            let r = try!(relation.relate_with_variance(ty::Contravariant, a_r, b_r));
+            let mt = try!(relation.relate(a_mt, b_mt));
+            Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
+        }
+
+        (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) =>
+        {
+            let t = try!(relation.relate(&a_t, &b_t));
+            if sz_a == sz_b {
+                Ok(ty::mk_vec(tcx, t, Some(sz_a)))
+            } else {
+                Err(ty::terr_fixed_array_size(expected_found(relation, &sz_a, &sz_b)))
+            }
+        }
+
+        (&ty::ty_vec(a_t, None), &ty::ty_vec(b_t, None)) =>
+        {
+            let t = try!(relation.relate(&a_t, &b_t));
+            Ok(ty::mk_vec(tcx, t, None))
+        }
+
+        (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) =>
+        {
+            if as_.len() == bs.len() {
+                let ts = try!(as_.iter()
+                                 .zip(bs.iter())
+                                 .map(|(a, b)| relation.relate(a, b))
+                                 .collect::<Result<_, _>>());
+                Ok(ty::mk_tup(tcx, ts))
+            } else if as_.len() != 0 && bs.len() != 0 {
+                Err(ty::terr_tuple_size(
+                    expected_found(relation, &as_.len(), &bs.len())))
+            } else {
+                Err(ty::terr_sorts(expected_found(relation, &a, &b)))
+            }
+        }
+
+        (&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty))
+            if a_opt_def_id == b_opt_def_id =>
+        {
+            let fty = try!(relation.relate(a_fty, b_fty));
+            Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
+        }
+
+        (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) =>
+        {
+            let projection_ty = try!(relation.relate(a_data, b_data));
+            Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
+        }
+
+        _ =>
+        {
+            Err(ty::terr_sorts(expected_found(relation, &a, &b)))
+        }
+    }
+}
+
+impl<'a,'tcx:'a> Relate<'a,'tcx> for ty::Region {
+    fn relate<R>(relation: &mut R,
+                 a: &ty::Region,
+                 b: &ty::Region)
+                 -> RelateResult<'tcx, ty::Region>
+        where R: TypeRelation<'a,'tcx>
+    {
+        relation.regions(*a, *b)
+    }
+}
+
+impl<'a,'tcx:'a,T> Relate<'a,'tcx> for ty::Binder<T>
+    where T: Relate<'a,'tcx>
+{
+    fn relate<R>(relation: &mut R,
+                 a: &ty::Binder<T>,
+                 b: &ty::Binder<T>)
+                 -> RelateResult<'tcx, ty::Binder<T>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        relation.binders(a, b)
+    }
+}
+
+impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Rc<T>
+    where T: Relate<'a,'tcx>
+{
+    fn relate<R>(relation: &mut R,
+                 a: &Rc<T>,
+                 b: &Rc<T>)
+                 -> RelateResult<'tcx, Rc<T>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        let a: &T = a;
+        let b: &T = b;
+        Ok(Rc::new(try!(relation.relate(a, b))))
+    }
+}
+
+impl<'a,'tcx:'a,T> Relate<'a,'tcx> for Box<T>
+    where T: Relate<'a,'tcx>
+{
+    fn relate<R>(relation: &mut R,
+                 a: &Box<T>,
+                 b: &Box<T>)
+                 -> RelateResult<'tcx, Box<T>>
+        where R: TypeRelation<'a,'tcx>
+    {
+        let a: &T = a;
+        let b: &T = b;
+        Ok(Box::new(try!(relation.relate(a, b))))
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Error handling
+
+pub fn expected_found<'a,'tcx,R,T>(relation: &mut R,
+                                   a: &T,
+                                   b: &T)
+                                   -> ty::expected_found<T>
+    where R: TypeRelation<'a,'tcx>, T: Clone
+{
+    expected_found_bool(relation.a_is_expected(), a, b)
+}
+
+pub fn expected_found_bool<T>(a_is_expected: bool,
+                              a: &T,
+                              b: &T)
+                              -> ty::expected_found<T>
+    where T: Clone
+{
+    let a = a.clone();
+    let b = b.clone();
+    if a_is_expected {
+        ty::expected_found {expected: a, found: b}
+    } else {
+        ty::expected_found {expected: b, found: a}
+    }
+}
+
index 5d492f1c95e11c81ccb8b4a528e2484a4a3712af..ec09d6dcc1ee2c05e35f121c7b4d1e5e7af6f942 100644 (file)
@@ -12,6 +12,7 @@
 
 use middle::ty::{self, Ty};
 use std::iter::Iterator;
+use std::vec::IntoIter;
 
 pub struct TypeWalker<'tcx> {
     stack: Vec<Ty<'tcx>>,
@@ -23,60 +24,6 @@ pub fn new(ty: Ty<'tcx>) -> TypeWalker<'tcx> {
         TypeWalker { stack: vec!(ty), last_subtree: 1, }
     }
 
-    fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) {
-        match parent_ty.sty {
-            ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
-            ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
-            }
-            ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
-                self.stack.push(ty);
-            }
-            ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
-                self.stack.push(mt.ty);
-            }
-            ty::ty_projection(ref data) => {
-                self.push_reversed(data.trait_ref.substs.types.as_slice());
-            }
-            ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
-                self.push_reversed(principal.substs().types.as_slice());
-                self.push_reversed(&bounds.projection_bounds.iter().map(|pred| {
-                    pred.0.ty
-                }).collect::<Vec<_>>());
-            }
-            ty::ty_enum(_, ref substs) |
-            ty::ty_struct(_, ref substs) |
-            ty::ty_closure(_, ref substs) => {
-                self.push_reversed(substs.types.as_slice());
-            }
-            ty::ty_tup(ref ts) => {
-                self.push_reversed(ts);
-            }
-            ty::ty_bare_fn(_, ref ft) => {
-                self.push_sig_subtypes(&ft.sig);
-            }
-        }
-    }
-
-    fn push_sig_subtypes(&mut self, sig: &ty::PolyFnSig<'tcx>) {
-        match sig.0.output {
-            ty::FnConverging(output) => { self.stack.push(output); }
-            ty::FnDiverging => { }
-        }
-        self.push_reversed(&sig.0.inputs);
-    }
-
-    fn push_reversed(&mut self, tys: &[Ty<'tcx>]) {
-        // We push slices on the stack in reverse order so as to
-        // maintain a pre-order traversal. As of the time of this
-        // writing, the fact that the traversal is pre-order is not
-        // known to be significant to any code, but it seems like the
-        // natural order one would expect (basically, the order of the
-        // types as they are written).
-        for &ty in tys.iter().rev() {
-            self.stack.push(ty);
-        }
-    }
-
     /// Skips the subtree of types corresponding to the last type
     /// returned by `next()`.
     ///
@@ -105,10 +52,70 @@ fn next(&mut self) -> Option<Ty<'tcx>> {
             }
             Some(ty) => {
                 self.last_subtree = self.stack.len();
-                self.push_subtypes(ty);
+                push_subtypes(&mut self.stack, ty);
                 debug!("next: stack={:?}", self.stack);
                 Some(ty)
             }
         }
     }
 }
+
+pub fn walk_shallow<'tcx>(ty: Ty<'tcx>) -> IntoIter<Ty<'tcx>> {
+    let mut stack = vec![];
+    push_subtypes(&mut stack, ty);
+    stack.into_iter()
+}
+
+fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) {
+    match parent_ty.sty {
+        ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
+        ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
+        }
+        ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
+            stack.push(ty);
+        }
+        ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
+            stack.push(mt.ty);
+        }
+        ty::ty_projection(ref data) => {
+            push_reversed(stack, data.trait_ref.substs.types.as_slice());
+        }
+        ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
+            push_reversed(stack, principal.substs().types.as_slice());
+            push_reversed(stack, &bounds.projection_bounds.iter().map(|pred| {
+                pred.0.ty
+            }).collect::<Vec<_>>());
+        }
+        ty::ty_enum(_, ref substs) |
+        ty::ty_struct(_, ref substs) |
+        ty::ty_closure(_, ref substs) => {
+            push_reversed(stack, substs.types.as_slice());
+        }
+        ty::ty_tup(ref ts) => {
+            push_reversed(stack, ts);
+        }
+        ty::ty_bare_fn(_, ref ft) => {
+            push_sig_subtypes(stack, &ft.sig);
+        }
+    }
+}
+
+fn push_sig_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, sig: &ty::PolyFnSig<'tcx>) {
+    match sig.0.output {
+        ty::FnConverging(output) => { stack.push(output); }
+        ty::FnDiverging => { }
+    }
+    push_reversed(stack, &sig.0.inputs);
+}
+
+fn push_reversed<'tcx>(stack: &mut Vec<Ty<'tcx>>, tys: &[Ty<'tcx>]) {
+    // We push slices on the stack in reverse order so as to
+    // maintain a pre-order traversal. As of the time of this
+    // writing, the fact that the traversal is pre-order is not
+    // known to be significant to any code, but it seems like the
+    // natural order one would expect (basically, the order of the
+    // types as they are written).
+    for &ty in tys.iter().rev() {
+        stack.push(ty);
+    }
+}
index 60ae053dbaf04eeabc5f1b6684bf6347a8768e6c..d71a68e2050524970304e1147c739ce190e88558 100644 (file)
@@ -228,8 +228,9 @@ pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) ->
 #[cfg(unix)]
 pub fn path2cstr(p: &Path) -> CString {
     use std::os::unix::prelude::*;
-    use std::ffi::AsOsStr;
-    CString::new(p.as_os_str().as_bytes()).unwrap()
+    use std::ffi::OsStr;
+    let p: &OsStr = p.as_ref();
+    CString::new(p.as_bytes()).unwrap()
 }
 #[cfg(windows)]
 pub fn path2cstr(p: &Path) -> CString {
index 452589a2407545100b3da60857c9901629e4b8b2..60b422b3769d5bc0a2c322a590d89b776a691493 100644 (file)
@@ -384,13 +384,7 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
         }
         ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty),
         ty_err => "[type error]".to_string(),
-        ty_param(ref param_ty) => {
-            if cx.sess.verbose() {
-                param_ty.repr(cx)
-            } else {
-                param_ty.user_string(cx)
-            }
-        }
+        ty_param(ref param_ty) => param_ty.user_string(cx),
         ty_enum(did, substs) | ty_struct(did, substs) => {
             let base = ty::item_path_str(cx, did);
             parameterized(cx, &base, substs, did, &[],
@@ -1532,3 +1526,9 @@ fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
         }
     }
 }
+
+impl<'tcx> Repr<'tcx> for ast::Unsafety {
+    fn repr(&self, _: &ctxt<'tcx>) -> String {
+        format!("{:?}", *self)
+    }
+}
index 6d8891dd4fe078f058ed3ed958ede8b891013147..231f6ee3be6adb317f0c5ac4bd6551919047d87d 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::io;
+use std::env;
 #[allow(deprecated)] use std::old_path::{self, GenericPath};
 #[allow(deprecated)] use std::old_io;
 use std::path::{Path, PathBuf};
@@ -20,18 +21,16 @@ 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::from(p.as_str().unwrap())),
-        Err(e) => Err(io::Error::new(io::ErrorKind::Other,
-                                     "realpath error",
-                                     Some(e.to_string())))
+        Err(e) => Err(io::Error::new(io::ErrorKind::Other, e))
     }
 }
 
 #[allow(deprecated)]
 fn old_realpath(original: &old_path::Path) -> old_io::IoResult<old_path::Path> {
     use std::old_io::fs;
-    use std::os;
     const MAX_LINKS_FOLLOWED: usize = 256;
-    let original = try!(os::getcwd()).join(original);
+    let original = old_path::Path::new(env::current_dir().unwrap()
+                                           .to_str().unwrap()).join(original);
 
     // Right now lstat on windows doesn't work quite well
     if cfg!(windows) {
index fe457841e9116c81c5ea88b21240f13b9f3a6c45..7591ebf67f868e8ee43c71568f8aadc2845fd804 100644 (file)
 #![feature(collections)]
 #![feature(core)]
 #![feature(old_fs)]
-#![feature(io)]
 #![feature(old_io)]
 #![feature(old_path)]
-#![feature(os)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(rand)]
 #![feature(path_ext)]
-#![feature(std_misc)]
 #![feature(step_by)]
-#![feature(convert)]
 #![cfg_attr(test, feature(test, rand))]
 
 extern crate syntax;
index 8f0387059e4a9d2418026461782f3d9c585f4008..898f20e74518fca23d44b4912ea5da69d2d7eb47 100644 (file)
@@ -14,7 +14,7 @@
 
 #![allow(deprecated)] // to_be32
 
-use std::iter::{range_step, repeat};
+use std::iter::repeat;
 use std::num::Int;
 use std::slice::bytes::{MutableByteVector, copy_memory};
 use serialize::hex::ToHex;
@@ -368,7 +368,7 @@ macro_rules! sha2_round {
 
         // Putting the message schedule inside the same loop as the round calculations allows for
         // the compiler to generate better code.
-        for t in range_step(0, 48, 8) {
+        for t in (0..48).step_by(8) {
             schedule_round!(t + 16);
             schedule_round!(t + 17);
             schedule_round!(t + 18);
@@ -388,7 +388,7 @@ macro_rules! sha2_round {
             sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
         }
 
-        for t in range_step(48, 64, 8) {
+        for t in (48..64).step_by(8) {
             sha2_round!(a, b, c, d, e, f, g, h, K32, t);
             sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
             sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
index 2fbbe7d1f7c5ea60e7865617f78a5ecc8898e4da..42cbdd7577d8e3b5d27d3b8d9d7d17b6a5dbe90d 100644 (file)
@@ -47,9 +47,10 @@ pub fn get_sdk_root(sdk_name: &str) -> String {
                               Ok(String::from_utf8(output.stdout).unwrap())
                           } else {
                               let error = String::from_utf8(output.stderr);
+                              let error = format!("process exit with error: {}",
+                                                  error.unwrap());
                               Err(io::Error::new(io::ErrorKind::Other,
-                                                 "process exit with error",
-                                                 error.ok()))
+                                                 &error[..]))
                           }
                       });
 
index d4503ae7fc9872e3309111bb953f80a9324e9ca2..b12732f8794564ded4b09bcb5323db2c895e0d27 100644 (file)
@@ -11,7 +11,7 @@
 use std::env;
 use std::io::{self, Error, ErrorKind};
 use std::fs;
-use std::path::{self, PathBuf, AsPath};
+use std::path::{self, PathBuf, Path};
 use std::rand::{thread_rng, Rng};
 
 /// A wrapper for a path to temporary directory implementing automatic
@@ -36,10 +36,10 @@ 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>>(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);
@@ -67,8 +67,7 @@ pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
         }
 
         Err(Error::new(ErrorKind::AlreadyExists,
-                       "too many temporary directories already exist",
-                       None))
+                       "too many temporary directories already exist"))
     }
 
     /// Attempts to make a temporary directory inside of `env::temp_dir()` whose
index 456d5f7a60ab7bec88aa167507125b6da085e801..be416327dad3b192f521255d2007790372478f7a 100644 (file)
@@ -27,7 +27,6 @@
 
 #![feature(box_syntax)]
 #![feature(collections)]
-#![feature(core)]
 #![feature(libc)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(exit_status)]
-#![feature(io)]
 #![feature(set_stdio)]
 #![feature(unicode)]
-#![feature(convert)]
 
 extern crate arena;
 extern crate flate;
index 9e693a64ef0a2bf5710e77d22c5b513da98a806d..37c9647c92b77df43fcdb94aaab1d5d5d270028b 100644 (file)
@@ -226,6 +226,10 @@ fn post(&self,
                 try!(pp::space(&mut s.s));
                 s.synth_comment(item.id.to_string())
             }
+            pprust::NodeSubItem(id) => {
+                try!(pp::space(&mut s.s));
+                s.synth_comment(id.to_string())
+            }
             pprust::NodeBlock(blk) => {
                 try!(pp::space(&mut s.s));
                 s.synth_comment(format!("block {}", blk.id))
@@ -699,8 +703,8 @@ fn print_flowgraph<W: Write>(variants: Vec<borrowck_dot::Variant>,
 
     fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
         r.map_err(|ioerr| {
-            io::Error::new(io::ErrorKind::Other, "graphviz::render failed",
-                           Some(ioerr.to_string()))
+            io::Error::new(io::ErrorKind::Other,
+                           &format!("graphviz::render failed: {}", ioerr)[..])
         })
     }
 }
index fcb0b9bdd3cfb05db2e0d6fefd0e54ae999227e3..f9be71561e384b5b2a85800eeca108ef90fef1c7 100644 (file)
@@ -22,7 +22,7 @@
 use rustc_typeck::middle::subst;
 use rustc_typeck::middle::subst::Subst;
 use rustc_typeck::middle::ty::{self, Ty};
-use rustc_typeck::middle::infer::combine::Combine;
+use rustc_typeck::middle::ty_relate::TypeRelation;
 use rustc_typeck::middle::infer;
 use rustc_typeck::middle::infer::lub::Lub;
 use rustc_typeck::middle::infer::glb::Glb;
@@ -350,21 +350,21 @@ pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> {
 
     pub fn sub(&self) -> Sub<'a, 'tcx> {
         let trace = self.dummy_type_trace();
-        Sub(self.infcx.combine_fields(true, trace))
+        self.infcx.sub(true, trace)
     }
 
     pub fn lub(&self) -> Lub<'a, 'tcx> {
         let trace = self.dummy_type_trace();
-        Lub(self.infcx.combine_fields(true, trace))
+        self.infcx.lub(true, trace)
     }
 
     pub fn glb(&self) -> Glb<'a, 'tcx> {
         let trace = self.dummy_type_trace();
-        Glb(self.infcx.combine_fields(true, trace))
+        self.infcx.glb(true, trace)
     }
 
     pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> {
-        match self.lub().tys(t1, t2) {
+        match self.lub().relate(&t1, &t2) {
             Ok(t) => t,
             Err(ref e) => panic!("unexpected error computing LUB: {}",
                                 ty::type_err_to_str(self.infcx.tcx, e))
@@ -374,7 +374,7 @@ pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> {
     /// Checks that `t1 <: t2` is true (this may register additional
     /// region checks).
     pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
-        match self.sub().tys(t1, t2) {
+        match self.sub().relate(&t1, &t2) {
             Ok(_) => { }
             Err(ref e) => {
                 panic!("unexpected error computing sub({},{}): {}",
@@ -388,7 +388,7 @@ pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
     /// Checks that `t1 <: t2` is false (this may register additional
     /// region checks).
     pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
-        match self.sub().tys(t1, t2) {
+        match self.sub().relate(&t1, &t2) {
             Err(_) => { }
             Ok(_) => {
                 panic!("unexpected success computing sub({},{})",
@@ -400,7 +400,7 @@ pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
 
     /// Checks that `LUB(t1,t2) == t_lub`
     pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) {
-        match self.lub().tys(t1, t2) {
+        match self.lub().relate(&t1, &t2) {
             Ok(t) => {
                 self.assert_eq(t, t_lub);
             }
@@ -417,7 +417,7 @@ pub fn check_glb(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_glb: Ty<'tcx>) {
                self.ty_to_string(t1),
                self.ty_to_string(t2),
                self.ty_to_string(t_glb));
-        match self.glb().tys(t1, t2) {
+        match self.glb().relate(&t1, &t2) {
             Err(e) => {
                 panic!("unexpected error computing LUB: {:?}", e)
             }
@@ -588,6 +588,7 @@ fn lub_free_free() {
 fn lub_returning_scope() {
     test_env(EMPTY_SOURCE_STR,
              errors(&["cannot infer an appropriate lifetime"]), |env| {
+                 env.create_simple_region_hierarchy();
                  let t_rptr_scope10 = env.t_rptr_scope(10);
                  let t_rptr_scope11 = env.t_rptr_scope(11);
 
@@ -808,12 +809,11 @@ fn walk_ty() {
         let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
         let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
         let walked: Vec<_> = uniq_ty.walk().collect();
-        assert_eq!([uniq_ty,
-                    tup2_ty,
-                    tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
-                    tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
-                    uint_ty],
-                   walked);
+        assert_eq!(walked, [uniq_ty,
+                            tup2_ty,
+                            tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
+                            tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
+                            uint_ty]);
     })
 }
 
index cc6a85e86ce077646aa5ee75b4c0c0cb0899cd94..647f4bc6a40fdbe7118dd31349b6de4657af6bae 100644 (file)
@@ -42,8 +42,9 @@ pub fn open(dst: &Path) -> Option<ArchiveRO> {
         #[cfg(unix)]
         fn path2cstr(p: &Path) -> CString {
             use std::os::unix::prelude::*;
-            use std::ffi::AsOsStr;
-            CString::new(p.as_os_str().as_bytes()).unwrap()
+            use std::ffi::OsStr;
+            let p: &OsStr = p.as_ref();
+            CString::new(p.as_bytes()).unwrap()
         }
         #[cfg(windows)]
         fn path2cstr(p: &Path) -> CString {
index c7b5b2e75346f9d2f77b31d24fe276eae5332e4c..cdafa4a16d07dbd88a46007f5e5bd81ad653f959 100644 (file)
@@ -30,7 +30,6 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(staged_api)]
-#![cfg_attr(unix, feature(std_misc))]
 
 extern crate libc;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
@@ -1976,6 +1975,7 @@ pub fn LLVMDICompositeTypeSetTypeArray(Builder: DIBuilderRef,
     pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
 
     pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
+    pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
 
     pub fn LLVMInitializeX86TargetInfo();
     pub fn LLVMInitializeX86Target();
index ff635a6c46b22a34c6d4e2f913bad68e46f7d793..ece83b578d25774a9653d13fe6a0b61274f05028 100644 (file)
@@ -162,9 +162,12 @@ fn is_unbound(&self) -> bool {
 }
 
 enum NameDefinition {
-    NoNameDefinition,           //< The name was unbound.
-    ChildNameDefinition(Def, LastPrivate), //< The name identifies an immediate child.
-    ImportNameDefinition(Def, LastPrivate) //< The name identifies an import.
+    // The name was unbound.
+    NoNameDefinition,
+    // The name identifies an immediate child.
+    ChildNameDefinition(Def, LastPrivate),
+    // The name identifies an import.
+    ImportNameDefinition(Def, LastPrivate),
 }
 
 impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> {
@@ -795,11 +798,6 @@ pub struct Resolver<'a, 'tcx:'a> {
     // The current self type if inside an impl (used for better errors).
     current_self_type: Option<Ty>,
 
-    // The ident for the keyword "self".
-    self_name: Name,
-    // The ident for the non-keyword "Self".
-    type_self_name: Name,
-
     // The idents for the primitive types.
     primitive_type_table: PrimitiveTypeTable,
 
@@ -869,9 +867,6 @@ fn new(session: &'a Session,
             current_trait_ref: None,
             current_self_type: None,
 
-            self_name: special_names::self_,
-            type_self_name: special_names::type_self,
-
             primitive_type_table: PrimitiveTypeTable::new(),
 
             def_map: RefCell::new(NodeMap()),
@@ -1822,7 +1817,7 @@ fn resolve_item(&mut self, item: &Item) {
                 let mut self_type_rib = Rib::new(ItemRibKind);
 
                 // plain insert (no renaming, types are not currently hygienic....)
-                let name = self.type_self_name;
+                let name = special_names::type_self;
                 self_type_rib.bindings.insert(name, DlDef(DefSelfTy(item.id)));
                 self.type_ribs.push(self_type_rib);
 
@@ -2047,8 +2042,9 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
 
     fn with_optional_trait_ref<T, F>(&mut self,
                                      opt_trait_ref: Option<&TraitRef>,
-                                     f: F) -> T where
-        F: FnOnce(&mut Resolver) -> T,
+                                     f: F)
+                                     -> T
+        where F: FnOnce(&mut Resolver) -> T,
     {
         let mut new_val = None;
         if let Some(trait_ref) = opt_trait_ref {
@@ -2585,11 +2581,7 @@ fn resolve_path(&mut self,
         let span = path.span;
         let segments = &path.segments[..path.segments.len()-path_depth];
 
-        let mk_res = |(def, lp)| PathResolution {
-            base_def: def,
-            last_private: lp,
-            depth: path_depth
-        };
+        let mk_res = |(def, lp)| PathResolution::new(def, lp, path_depth);
 
         if path.global {
             let def = self.resolve_crate_relative_path(span, segments, namespace);
@@ -2603,25 +2595,25 @@ fn resolve_path(&mut self,
                                         check_ribs,
                                         span);
 
-        if segments.len() > 1 {
-            let def = self.resolve_module_relative_path(span, segments, namespace);
-            match (def, unqualified_def) {
-                (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
-                    self.session
-                        .add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
-                                  id, span,
-                                  "unnecessary qualification".to_string());
-                }
-                _ => ()
-            }
+        if segments.len() <= 1 {
+            return unqualified_def.map(mk_res);
+        }
 
-            def.map(mk_res)
-        } else {
-            unqualified_def.map(mk_res)
+        let def = self.resolve_module_relative_path(span, segments, namespace);
+        match (def, unqualified_def) {
+            (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
+                self.session
+                    .add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
+                              id, span,
+                              "unnecessary qualification".to_string());
+            }
+            _ => {}
         }
+
+        def.map(mk_res)
     }
 
-    // resolve a single identifier (used as a varref)
+    // Resolve a single identifier.
     fn resolve_identifier(&mut self,
                           identifier: Ident,
                           namespace: Namespace,
@@ -2662,8 +2654,7 @@ fn resolve_definition_of_name_in_module(&mut self,
                 match child_name_bindings.def_for_namespace(namespace) {
                     Some(def) => {
                         // Found it. Stop the search here.
-                        let p = child_name_bindings.defined_in_public_namespace(
-                                        namespace);
+                        let p = child_name_bindings.defined_in_public_namespace(namespace);
                         let lp = if p {LastMod(AllPublic)} else {
                             LastMod(DependsOn(def.def_id()))
                         };
@@ -2734,8 +2725,8 @@ fn resolve_module_relative_path(&mut self,
 
         let containing_module;
         let last_private;
-        let module = self.current_module.clone();
-        match self.resolve_module_path(module,
+        let current_module = self.current_module.clone();
+        match self.resolve_module_path(current_module,
                                        &module_path[..],
                                        UseLexicalScope,
                                        span,
@@ -2858,8 +2849,7 @@ fn resolve_identifier_in_local_ribs(&mut self,
 
         match search_result {
             Some(DlDef(def)) => {
-                debug!("(resolving path in local ribs) resolved `{}` to \
-                        local: {:?}",
+                debug!("(resolving path in local ribs) resolved `{}` to local: {:?}",
                        token::get_ident(ident),
                        def);
                 Some(def)
@@ -2904,15 +2894,13 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
                 panic!("unexpected indeterminate result");
             }
             Failed(err) => {
-                match err {
-                    Some((span, msg)) =>
-                        self.resolve_error(span, &format!("failed to resolve. {}",
-                                                         msg)),
-                    None => ()
-                }
-
                 debug!("(resolving item path by identifier in lexical scope) \
                          failed to resolve {}", token::get_name(name));
+
+                if let Some((span, msg)) = err {
+                    self.resolve_error(span, &format!("failed to resolve. {}", msg))
+                }
+
                 return None;
             }
         }
@@ -2964,10 +2952,10 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
                 }
             } else {
                 match this.resolve_module_path(root,
-                                                &name_path[..],
-                                                UseLexicalScope,
-                                                span,
-                                                PathSearch) {
+                                               &name_path[..],
+                                               UseLexicalScope,
+                                               span,
+                                               PathSearch) {
                     Success((module, _)) => Some(module),
                     _ => None
                 }
@@ -3203,8 +3191,8 @@ fn resolve_expr(&mut self, expr: &Expr) {
                                 false // Stop advancing
                             });
 
-                            if method_scope && &token::get_name(self.self_name)[..]
-                                                                == path_name {
+                            if method_scope &&
+                               &token::get_name(special_names::self_)[..] == path_name {
                                     self.resolve_error(
                                         expr.span,
                                         "`self` is not available \
index a3ac0473bfa26c3b31b0fb751b48a4af5207a048..b0eacd1a55d4150221e924c8b3bf390f8d81d9ca 100644 (file)
@@ -39,7 +39,6 @@
 #![feature(unicode)]
 #![feature(path_ext)]
 #![feature(fs)]
-#![feature(convert)]
 #![feature(path_relative_from)]
 
 #![allow(trivial_casts)]
index a415875d852cc8bb8a94ae4d0fba41156c674f75..26fcf947e4f900e179c6365bbc0fb5ddaad20674 100644 (file)
@@ -272,7 +272,7 @@ fn process_formals(&mut self, formals: &Vec<ast::Arg>, qualname: &str) {
                 let typ =
                     ppaux::ty_to_string(
                         &self.analysis.ty_cx,
-                        *self.analysis.ty_cx.node_types.borrow().get(&id).unwrap());
+                        *self.analysis.ty_cx.node_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?)
                 self.fmt.formal_str(p.span,
@@ -436,7 +436,7 @@ fn process_struct_field_def(&mut self,
                 let typ =
                     ppaux::ty_to_string(
                         &self.analysis.ty_cx,
-                        *self.analysis.ty_cx.node_types.borrow().get(&field.node.id).unwrap());
+                        *self.analysis.ty_cx.node_types().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),
@@ -1471,7 +1471,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 types = self.analysis.ty_cx.node_types();
             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?).
index 61e332f87ad1a2683aeb65b8676b7e4cfc570509..20677ab93fc57ecfca93af7b6cc8efe0e1cbf4a2 100644 (file)
@@ -41,7 +41,7 @@
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::weak_lang_items;
 use middle::subst::{Subst, Substs};
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size};
 use session::config::{self, NoDebugInfo};
 use session::Session;
 use trans::_match;
@@ -52,7 +52,7 @@
 use trans::cleanup::CleanupMethods;
 use trans::cleanup;
 use trans::closure;
-use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_integral};
+use trans::common::{Block, C_bool, C_bytes_in_context, C_i32, C_int, C_integral};
 use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
 use trans::common::{CrateContext, ExternMap, FunctionContext};
 use trans::common::{Result, NodeIdAndSpan};
@@ -824,6 +824,15 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
             let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
         }
+        ty::ty_struct(_, _) if type_is_simd(cx.tcx(), rhs_t) => {
+            let mut res = C_bool(cx.ccx(), false);
+            for i in 0 .. simd_size(cx.tcx(), rhs_t) {
+                res = Or(cx, res,
+                         IsNull(cx,
+                                ExtractElement(cx, rhs, C_int(cx.ccx(), i as i64))), debug_loc);
+            }
+            (res, false)
+        }
         _ => {
             cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
                                   ty_to_string(cx.tcx(), rhs_t)));
index 745098d6e87d11f9b1b8cac372e313dadbb91e40..995f3caf588701907a11b4d158284fd475861071 100644 (file)
@@ -963,6 +963,32 @@ pub fn const_to_uint(v: ValueRef) -> u64 {
     }
 }
 
+fn is_const_integral(v: ValueRef) -> bool {
+    unsafe {
+        !llvm::LLVMIsAConstantInt(v).is_null()
+    }
+}
+
+pub fn const_to_opt_int(v: ValueRef) -> Option<i64> {
+    unsafe {
+        if is_const_integral(v) {
+            Some(llvm::LLVMConstIntGetSExtValue(v))
+        } else {
+            None
+        }
+    }
+}
+
+pub fn const_to_opt_uint(v: ValueRef) -> Option<u64> {
+    unsafe {
+        if is_const_integral(v) {
+            Some(llvm::LLVMConstIntGetZExtValue(v))
+        } else {
+            None
+        }
+    }
+}
+
 pub fn is_undef(val: ValueRef) -> bool {
     unsafe {
         llvm::LLVMIsUndef(val) != False
index 0a9df2b5dc180dba91802d120abf6ea96d901e8c..c32cb28ec78dbb9bbdbf83fced5510b615f2780e 100644 (file)
 use llvm::{ConstFCmp, ConstICmp, SetLinkage, SetUnnamedAddr};
 use llvm::{InternalLinkage, ValueRef, Bool, True};
 use middle::{check_const, const_eval, def};
+use middle::const_eval::{const_int_checked_neg, const_uint_checked_neg};
+use middle::const_eval::{const_int_checked_add, const_uint_checked_add};
+use middle::const_eval::{const_int_checked_sub, const_uint_checked_sub};
+use middle::const_eval::{const_int_checked_mul, const_uint_checked_mul};
+use middle::const_eval::{const_int_checked_div, const_uint_checked_div};
+use middle::const_eval::{const_int_checked_rem, const_uint_checked_rem};
+use middle::const_eval::{const_int_checked_shl, const_uint_checked_shl};
+use middle::const_eval::{const_int_checked_shr, const_uint_checked_shr};
 use trans::{adt, closure, debuginfo, expr, inline, machine};
 use trans::base::{self, push_ctxt};
 use trans::common::*;
@@ -336,6 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
     let tsize = machine::llsize_of_alloc(cx, llty);
     if csize != tsize {
+        cx.sess().abort_if_errors();
         unsafe {
             // FIXME these values could use some context
             llvm::LLVMDumpValue(llconst);
@@ -348,6 +357,100 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     (llconst, ety_adjusted)
 }
 
+fn check_unary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
+                             te: ValueRef) {
+    // The only kind of unary expression that we check for validity
+    // here is `-expr`, to check if it "overflows" (e.g. `-i32::MIN`).
+    if let ast::ExprUnary(ast::UnNeg, ref inner_e) = e.node {
+
+        // An unfortunate special case: we parse e.g. -128 as a
+        // negation of the literal 128, which means if we're expecting
+        // a i8 (or if it was already suffixed, e.g. `-128_i8`), then
+        // 128 will have already overflowed to -128, and so then the
+        // constant evaluator thinks we're trying to negate -128.
+        //
+        // Catch this up front by looking for ExprLit directly,
+        // and just accepting it.
+        if let ast::ExprLit(_) = inner_e.node { return; }
+
+        let result = match t.sty {
+            ty::ty_int(int_type) => {
+                let input = match const_to_opt_int(te) {
+                    Some(v) => v,
+                    None => return,
+                };
+                const_int_checked_neg(
+                    input, e, Some(const_eval::IntTy::from(cx.tcx(), int_type)))
+            }
+            ty::ty_uint(uint_type) => {
+                let input = match const_to_opt_uint(te) {
+                    Some(v) => v,
+                    None => return,
+                };
+                const_uint_checked_neg(
+                    input, e, Some(const_eval::UintTy::from(cx.tcx(), uint_type)))
+            }
+            _ => return,
+        };
+
+        // We do not actually care about a successful result.
+        if let Err(err) = result {
+            cx.tcx().sess.span_err(e.span, &err.description());
+        }
+    }
+}
+
+fn check_binary_expr_validity(cx: &CrateContext, e: &ast::Expr, t: Ty,
+                              te1: ValueRef, te2: ValueRef) {
+    let b = if let ast::ExprBinary(b, _, _) = e.node { b } else { return };
+
+    let result = match t.sty {
+        ty::ty_int(int_type) => {
+            let (lhs, rhs) = match (const_to_opt_int(te1),
+                                    const_to_opt_int(te2)) {
+                (Some(v1), Some(v2)) => (v1, v2),
+                _ => return,
+            };
+
+            let opt_ety = Some(const_eval::IntTy::from(cx.tcx(), int_type));
+            match b.node {
+                ast::BiAdd => const_int_checked_add(lhs, rhs, e, opt_ety),
+                ast::BiSub => const_int_checked_sub(lhs, rhs, e, opt_ety),
+                ast::BiMul => const_int_checked_mul(lhs, rhs, e, opt_ety),
+                ast::BiDiv => const_int_checked_div(lhs, rhs, e, opt_ety),
+                ast::BiRem => const_int_checked_rem(lhs, rhs, e, opt_ety),
+                ast::BiShl => const_int_checked_shl(lhs, rhs, e, opt_ety),
+                ast::BiShr => const_int_checked_shr(lhs, rhs, e, opt_ety),
+                _ => return,
+            }
+        }
+        ty::ty_uint(uint_type) => {
+            let (lhs, rhs) = match (const_to_opt_uint(te1),
+                                    const_to_opt_uint(te2)) {
+                (Some(v1), Some(v2)) => (v1, v2),
+                _ => return,
+            };
+
+            let opt_ety = Some(const_eval::UintTy::from(cx.tcx(), uint_type));
+            match b.node {
+                ast::BiAdd => const_uint_checked_add(lhs, rhs, e, opt_ety),
+                ast::BiSub => const_uint_checked_sub(lhs, rhs, e, opt_ety),
+                ast::BiMul => const_uint_checked_mul(lhs, rhs, e, opt_ety),
+                ast::BiDiv => const_uint_checked_div(lhs, rhs, e, opt_ety),
+                ast::BiRem => const_uint_checked_rem(lhs, rhs, e, opt_ety),
+                ast::BiShl => const_uint_checked_shl(lhs, rhs, e, opt_ety),
+                ast::BiShr => const_uint_checked_shr(lhs, rhs, e, opt_ety),
+                _ => return,
+            }
+        }
+        _ => return,
+    };
+    // We do not actually care about a successful result.
+    if let Err(err) = result {
+        cx.tcx().sess.span_err(e.span, &err.description());
+    }
+}
+
 fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    e: &ast::Expr,
                                    ety: Ty<'tcx>,
@@ -386,7 +489,8 @@ 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.node, te1, te2);
+
+            check_binary_expr_validity(cx, e, ty, te1, te2);
 
             match b.node {
               ast::BiAdd   => {
@@ -416,8 +520,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               ast::BiBitXor => llvm::LLVMConstXor(te1, te2),
               ast::BiBitAnd => llvm::LLVMConstAnd(te1, te2),
               ast::BiBitOr  => llvm::LLVMConstOr(te1, te2),
-              ast::BiShl    => llvm::LLVMConstShl(te1, te2),
+              ast::BiShl    => {
+                let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
+                llvm::LLVMConstShl(te1, te2)
+              }
               ast::BiShr    => {
+                let te2 = base::cast_shift_const_rhs(b.node, te1, te2);
                 if signed { llvm::LLVMConstAShr(te1, te2) }
                 else      { llvm::LLVMConstLShr(te1, te2) }
               }
@@ -439,8 +547,11 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               }
             }
           },
-          ast::ExprUnary(u, ref e) => {
-            let (te, ty) = const_expr(cx, &**e, param_substs);
+          ast::ExprUnary(u, ref inner_e) => {
+            let (te, ty) = const_expr(cx, &**inner_e, param_substs);
+
+            check_unary_expr_validity(cx, e, ty, te);
+
             let is_float = ty::type_is_fp(ty);
             match u {
               ast::UnUniq | ast::UnDeref => {
@@ -661,11 +772,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::ExprRepeat(ref elem, ref count) => {
             let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
             let llunitty = type_of::type_of(cx, unit_ty);
-            let n = match const_eval::eval_const_expr_partial(cx.tcx(), &**count, None) {
-                Ok(const_eval::const_int(i))  => i as usize,
-                Ok(const_eval::const_uint(i)) => i as usize,
-                _ => cx.sess().span_bug(count.span, "count must be integral const expression.")
-            };
+            let n = ty::eval_repeat_count(cx.tcx(), count);
             let unit_val = const_expr(cx, &**elem, param_substs).0;
             let vs: Vec<_> = repeat(unit_val).take(n).collect();
             if val_ty(unit_val) != llunitty {
index bd31580333fab25f5cfba61820afbdfcea84dfb0..5b1ac88c2089b951113911b16527cba09b547af8 100644 (file)
@@ -40,6 +40,10 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     let fcx = cx.fcx;
     debug!("trans_stmt({})", s.repr(cx.tcx()));
 
+    if cx.unreachable.get() {
+        return cx;
+    }
+
     if cx.sess().asm_comments() {
         add_span_comment(cx, s.span, &s.repr(cx.tcx()));
     }
@@ -76,6 +80,11 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
                                    -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_stmt_semi");
+
+    if cx.unreachable.get() {
+        return cx;
+    }
+
     let ty = expr_ty(cx, e);
     if cx.fcx.type_needs_drop(ty) {
         expr::trans_to_lvalue(cx, e, "stmt").bcx
@@ -89,6 +98,11 @@ pub fn trans_block<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                mut dest: expr::Dest)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_block");
+
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     let fcx = bcx.fcx;
     let mut bcx = bcx;
 
@@ -141,6 +155,11 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
            bcx.to_str(), if_id, bcx.expr_to_string(cond), thn.id,
            dest.to_string(bcx.ccx()));
     let _icx = push_ctxt("trans_if");
+
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     let mut bcx = bcx;
 
     let cond_val = unpack_result!(bcx, expr::trans(bcx, cond).to_llbool());
@@ -214,6 +233,11 @@ pub fn trans_while<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                body: &ast::Block)
                                -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_while");
+
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     let fcx = bcx.fcx;
 
     //            bcx
@@ -257,6 +281,11 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                               body: &ast::Block)
                               -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_loop");
+
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     let fcx = bcx.fcx;
 
     //            bcx
@@ -296,12 +325,13 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     exit: usize)
                                     -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_break_cont");
-    let fcx = bcx.fcx;
 
     if bcx.unreachable.get() {
         return bcx;
     }
 
+    let fcx = bcx.fcx;
+
     // Locate loop that we will break to
     let loop_id = match opt_label {
         None => fcx.top_loop_scope(),
@@ -341,6 +371,11 @@ pub fn trans_ret<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              retval_expr: Option<&ast::Expr>)
                              -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_ret");
+
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     let fcx = bcx.fcx;
     let mut bcx = bcx;
     let dest = match (fcx.llretslotptr.get(), retval_expr) {
@@ -372,6 +407,10 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let ccx = bcx.ccx();
     let _icx = push_ctxt("trans_fail_value");
 
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     let v_str = C_str_slice(ccx, fail_str);
     let loc = bcx.sess().codemap().lookup_char_pos(call_info.span.lo);
     let filename = token::intern_and_get_ident(&loc.file.name);
@@ -399,6 +438,10 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let ccx = bcx.ccx();
     let _icx = push_ctxt("trans_fail_bounds_check");
 
+    if bcx.unreachable.get() {
+        return bcx;
+    }
+
     // Extract the file/line from the span
     let loc = bcx.sess().codemap().lookup_char_pos(call_info.span.lo);
     let filename = token::intern_and_get_ident(&loc.file.name);
index f2c24501c66c8e6c97856919fa471b01f01b0fcb..8e9ae2eba0bcd688201775bdd050285ab1d7db22 100644 (file)
@@ -3207,7 +3207,7 @@ fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
 fn assert_type_for_node_id(cx: &CrateContext,
                            node_id: ast::NodeId,
                            error_reporting_span: Span) {
-    if !cx.tcx().node_types.borrow().contains_key(&node_id) {
+    if !cx.tcx().node_types().contains_key(&node_id) {
         cx.sess().span_bug(error_reporting_span,
                            "debuginfo: Could not find type for node id!");
     }
index 0d6ca7430d38ed0792bba57990444c3697090ea4..939142cff1c32b6d7aba9d61bf675e7fc75c0cdd 100644 (file)
@@ -140,13 +140,7 @@ fn projected_ty(&self,
                     span: Span,
                     _trait_ref: Rc<ty::TraitRef<'tcx>>,
                     _item_name: ast::Name)
-                    -> Ty<'tcx>
-    {
-        span_err!(self.tcx().sess, span, E0213,
-            "associated types are not accepted in this context");
-
-        self.tcx().types.err
-    }
+                    -> Ty<'tcx>;
 }
 
 pub fn ast_region_to_region(tcx: &ty::ctxt, lifetime: &ast::Lifetime)
@@ -924,9 +918,12 @@ fn ast_path_to_ty<'tcx>(
         }
     };
 
-    let substs = ast_path_substs_for_ty(this, rscope,
-                                        span, param_mode,
-                                        &generics, item_segment);
+    let substs = ast_path_substs_for_ty(this,
+                                        rscope,
+                                        span,
+                                        param_mode,
+                                        &generics,
+                                        item_segment);
 
     // FIXME(#12938): This is a hack until we have full support for DST.
     if Some(did) == this.tcx().lang_items.owned_box() {
@@ -1044,6 +1041,12 @@ fn report_ambiguous_associated_type(tcx: &ty::ctxt,
               type_str, trait_str, name);
 }
 
+// Create a type from a a path to an associated type.
+// For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
+// and item_segment is the path segment for D. We return a type and a def for
+// the whole path.
+// Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
+// parameter or Self.
 fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                    span: Span,
                                    ty: Ty<'tcx>,
@@ -1052,35 +1055,43 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                    -> (Ty<'tcx>, def::Def)
 {
     let tcx = this.tcx();
-    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
     let assoc_name = item_segment.identifier.name;
 
-    let is_param = match (&ty.sty, ty_path_def) {
-        (&ty::ty_param(_), def::DefTyParam(..)) |
-        (&ty::ty_param(_), def::DefSelfTy(_)) => true,
-        _ => false
-    };
+    debug!("associated_path_def_to_ty: {}::{}", ty.repr(tcx), token::get_name(assoc_name));
 
-    let ty_param_node_id = if is_param {
-        ty_path_def.local_node_id()
-    } else {
-        report_ambiguous_associated_type(
-            tcx, span, &ty.user_string(tcx), "Trait", &token::get_name(assoc_name));
-        return (tcx.types.err, ty_path_def);
-    };
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
+
+    // Check that the path prefix given by ty/ty_path_def is a type parameter/Self.
+    match (&ty.sty, ty_path_def) {
+        (&ty::ty_param(_), def::DefTyParam(..)) |
+        (&ty::ty_param(_), def::DefSelfTy(_)) => {}
+        _ => {
+            report_ambiguous_associated_type(tcx,
+                                             span,
+                                             &ty.user_string(tcx),
+                                             "Trait",
+                                             &token::get_name(assoc_name));
+            return (tcx.types.err, ty_path_def);
+        }
+    }
 
+    let ty_param_node_id = ty_path_def.local_node_id();
     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,
-        Err(ErrorReported) => { return (tcx.types.err, ty_path_def); }
+        Err(ErrorReported) => {
+            return (tcx.types.err, ty_path_def);
+        }
     };
 
-    // ensure the super predicates and stop if we encountered an error
+    // Ensure the super predicates and stop if we encountered an error.
     if bounds.iter().any(|b| this.ensure_super_predicates(span, b.def_id()).is_err()) {
         return (this.tcx().types.err, ty_path_def);
     }
 
+    // Check that there is exactly one way to find an associated type with the
+    // correct name.
     let mut suitable_bounds: Vec<_> =
         traits::transitive_bounds(tcx, &bounds)
         .filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
@@ -1118,7 +1129,8 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         // by type collection, which may be in progress at this point.
         match this.tcx().map.expect_item(trait_did.node).node {
             ast::ItemTrait(_, _, _, ref trait_items) => {
-                let item = trait_items.iter().find(|i| i.ident.name == assoc_name)
+                let item = trait_items.iter()
+                                      .find(|i| i.ident.name == assoc_name)
                                       .expect("missing associated type");
                 ast_util::local_def(item.id)
             }
@@ -1129,6 +1141,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         let item = trait_items.iter().find(|i| i.name() == assoc_name);
         item.expect("missing associated type").def_id()
     };
+
     (ty, def::DefAssociatedTy(trait_did, item_did))
 }
 
@@ -1150,8 +1163,11 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
         ty
     } else {
         let path_str = ty::item_path_str(tcx, trait_def_id);
-        report_ambiguous_associated_type(
-            tcx, span, "Type", &path_str, &token::get_ident(item_segment.identifier));
+        report_ambiguous_associated_type(tcx,
+                                         span,
+                                         "Type",
+                                         &path_str,
+                                         &token::get_ident(item_segment.identifier));
         return tcx.types.err;
     };
 
@@ -1204,13 +1220,15 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
+// Note that both base_segments and assoc_segments may be empty, although not at
+// the same time.
 pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                         rscope: &RegionScope,
                                         span: Span,
                                         param_mode: PathParamMode,
-                                        def: &mut def::Def,
+                                        def: &def::Def,
                                         opt_self_ty: Option<Ty<'tcx>>,
-                                        segments: &[ast::PathSegment],
+                                        base_segments: &[ast::PathSegment],
                                         assoc_segments: &[ast::PathSegment])
                                         -> Ty<'tcx> {
     let tcx = this.tcx();
@@ -1226,52 +1244,64 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                                           span,
                                                           param_mode,
                                                           trait_def_id,
-                                                          segments.last().unwrap(),
+                                                          base_segments.last().unwrap(),
                                                           &mut projection_bounds);
 
-            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
-            trait_ref_to_object_type(this, rscope, span, trait_ref,
-                                     projection_bounds, &[])
+            check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
+            trait_ref_to_object_type(this,
+                                     rscope,
+                                     span,
+                                     trait_ref,
+                                     projection_bounds,
+                                     &[])
         }
         def::DefTy(did, _) | def::DefStruct(did) => {
-            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
+            check_path_args(tcx, base_segments.init(), NO_TPS | NO_REGIONS);
             ast_path_to_ty(this, rscope, span,
                            param_mode, did,
-                           segments.last().unwrap())
+                           base_segments.last().unwrap())
         }
         def::DefTyParam(space, index, _, name) => {
-            check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
+            check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
             ty::mk_param(tcx, space, index, name)
         }
         def::DefSelfTy(_) => {
-            // n.b.: resolve guarantees that the this type only appears in a
+            // N.b.: resolve guarantees that the this type only appears in a
             // trait, which we rely upon in various places when creating
-            // substs
-            check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
+            // substs.
+            check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
             ty::mk_self_type(tcx)
         }
         def::DefAssociatedTy(trait_did, _) => {
-            check_path_args(tcx, &segments[..segments.len()-2], NO_TPS | NO_REGIONS);
-            qpath_to_ty(this, rscope, span, param_mode,
-                        opt_self_ty, trait_did,
-                        &segments[segments.len()-2],
-                        segments.last().unwrap())
+            check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS);
+            qpath_to_ty(this,
+                        rscope,
+                        span,
+                        param_mode,
+                        opt_self_ty,
+                        trait_did,
+                        &base_segments[base_segments.len()-2],
+                        base_segments.last().unwrap())
         }
         def::DefMod(id) => {
             // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
             // FIXME(#22519) This part of the resolution logic should be
             // avoided entirely for that form, once we stop needed a Def
             // for `associated_path_def_to_ty`.
-            if segments.is_empty() {
-                opt_self_ty.expect("missing T in <T>::a::b::c")
-            } else {
-                span_err!(tcx.sess, span, E0247, "found module name used as a type: {}",
+
+            if !base_segments.is_empty() {
+                span_err!(tcx.sess,
+                          span,
+                          E0247,
+                          "found module name used as a type: {}",
                           tcx.map.node_to_string(id.node));
                 return this.tcx().types.err;
             }
+
+            opt_self_ty.expect("missing T in <T>::a::b::c")
         }
         def::DefPrimTy(prim_ty) => {
-            prim_ty_to_ty(tcx, segments, prim_ty)
+            prim_ty_to_ty(tcx, base_segments, prim_ty)
         }
         _ => {
             span_err!(tcx.sess, span, E0248,
@@ -1282,15 +1312,19 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
 
     // If any associated type segments remain, attempt to resolve them.
     let mut ty = base_ty;
+    let mut def = *def;
     for segment in assoc_segments {
         if ty.sty == ty::ty_err {
             break;
         }
         // This is pretty bad (it will fail except for T::A and Self::A).
-        let (a_ty, a_def) = associated_path_def_to_ty(this, span,
-                                                      ty, *def, segment);
+        let (a_ty, a_def) = associated_path_def_to_ty(this,
+                                                      span,
+                                                      ty,
+                                                      def,
+                                                      segment);
         ty = a_ty;
-        *def = a_def;
+        def = a_def;
     }
     ty
 }
@@ -1378,13 +1412,16 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                 tcx.sess.span_bug(ast_ty.span,
                                   &format!("unbound path {}", ast_ty.repr(tcx)))
             };
-            let mut def = path_res.base_def;
+            let def = path_res.base_def;
             let base_ty_end = path.segments.len() - path_res.depth;
             let opt_self_ty = maybe_qself.as_ref().map(|qself| {
                 ast_ty_to_ty(this, rscope, &qself.ty)
             });
-            let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span,
-                                                PathParamMode::Explicit, &mut def,
+            let ty = finish_resolving_def_to_ty(this,
+                                                rscope,
+                                                ast_ty.span,
+                                                PathParamMode::Explicit,
+                                                &def,
                                                 opt_self_ty,
                                                 &path.segments[..base_ty_end],
                                                 &path.segments[base_ty_end..]);
index 31ac0a57ba0e14361d7c990855a02f01c1048e42..3f9c14e0afe398ab8d3b905cf60e3ef082dfb029 100644 (file)
@@ -83,9 +83,7 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                   UnresolvedTypeAction::Error,
                   LvaluePreference::NoPreference,
                   |adj_ty, idx| {
-                      let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
-                      try_overloaded_call_step(fcx, call_expr, callee_expr,
-                                               adj_ty, autoderefref)
+                      try_overloaded_call_step(fcx, call_expr, callee_expr, adj_ty, idx)
                   });
 
     match result {
@@ -119,13 +117,15 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       call_expr: &'tcx ast::Expr,
                                       callee_expr: &'tcx ast::Expr,
                                       adjusted_ty: Ty<'tcx>,
-                                      autoderefref: ty::AutoDerefRef<'tcx>)
+                                      autoderefs: usize)
                                       -> Option<CallStep<'tcx>>
 {
-    debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefref={})",
+    debug!("try_overloaded_call_step(call_expr={}, adjusted_ty={}, autoderefs={})",
            call_expr.repr(fcx.tcx()),
            adjusted_ty.repr(fcx.tcx()),
-           autoderefref.repr(fcx.tcx()));
+           autoderefs);
+
+    let autoderefref = ty::AutoDerefRef { autoderefs: autoderefs, autoref: None };
 
     // If the callee is a bare function or a closure, then we're all set.
     match structurally_resolved_type(fcx, callee_expr.span, adjusted_ty).sty {
@@ -161,6 +161,18 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
 
+        // Hack: we know that there are traits implementing Fn for &F
+        // where F:Fn and so forth. In the particular case of types
+        // like `x: &mut FnMut()`, if there is a call `x()`, we would
+        // normally translate to `FnMut::call_mut(&mut x, ())`, but
+        // that winds up requiring `mut x: &mut FnMut()`. A little
+        // over the top. The simplest fix by far is to just ignore
+        // this case and deref again, so we wind up with
+        // `FnMut::call_mut(&mut *x, ())`.
+        ty::ty_rptr(..) if autoderefs == 0 => {
+            return None;
+        }
+
         _ => {}
     }
 
index ae1dbbb1b00ad2ca0dc0d619344fc5aaea99e8e5..ced6cec3ef0dc3daef00349ce18f90f9e057a242 100644 (file)
 
 use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction};
 
-use middle::infer::{self, cres, Coercion, TypeTrace};
-use middle::infer::combine::Combine;
-use middle::infer::sub::Sub;
+use middle::infer::{self, Coercion};
 use middle::subst;
 use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
 use middle::ty::{self, mt, Ty};
+use middle::ty_relate::RelateResult;
 use util::common::indent;
 use util::ppaux;
 use util::ppaux::Repr;
 
 struct Coerce<'a, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
-    trace: TypeTrace<'tcx>
+    origin: infer::TypeOrigin,
 }
 
-type CoerceResult<'tcx> = cres<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
+type CoerceResult<'tcx> = RelateResult<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
 
 impl<'f, 'tcx> Coerce<'f, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> {
@@ -87,14 +86,16 @@ fn tcx(&self) -> &ty::ctxt<'tcx> {
     }
 
     fn subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
-        let sub = Sub(self.fcx.infcx().combine_fields(false, self.trace.clone()));
-        try!(sub.tys(a, b));
+        try!(self.fcx.infcx().sub_types(false, self.origin.clone(), a, b));
         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));
+    fn outlives(&self,
+                origin: infer::SubregionOrigin<'tcx>,
+                a: ty::Region,
+                b: ty::Region)
+                -> RelateResult<'tcx, ()> {
+        infer::mk_subr(self.fcx.infcx(), origin, b, a);
         Ok(())
     }
 
@@ -190,7 +191,7 @@ fn coerce_borrowed_pointer(&self,
             _ => return self.subtype(a, b)
         }
 
-        let coercion = Coercion(self.trace.clone());
+        let coercion = Coercion(self.origin.span());
         let r_borrow = self.fcx.infcx().next_region_var(coercion);
         let autoref = Some(AutoPtr(r_borrow, mutbl_b, None));
 
@@ -214,7 +215,7 @@ fn coerce_borrowed_pointer(&self,
             }
             let ty = ty::mk_rptr(self.tcx(), r_borrow,
                                  mt {ty: inner_ty, mutbl: mutbl_b});
-            if let Err(err) = self.fcx.infcx().try(|_| self.subtype(ty, b)) {
+            if let Err(err) = self.subtype(ty, b) {
                 if first_error.is_none() {
                     first_error = Some(err);
                 }
@@ -264,12 +265,12 @@ fn coerce_unsized(&self,
                             return Err(ty::terr_mutability);
                         }
 
-                        let coercion = Coercion(self.trace.clone());
+                        let coercion = Coercion(self.origin.span());
                         let r_borrow = self.fcx.infcx().next_region_var(coercion);
                         let ty = ty::mk_rptr(self.tcx(),
                                              self.tcx().mk_region(r_borrow),
                                              ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                        try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+                        try!(self.subtype(ty, b));
                         debug!("Success, coerced with AutoDerefRef(1, \
                                 AutoPtr(AutoUnsize({:?})))", kind);
                         Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -290,7 +291,7 @@ fn coerce_unsized(&self,
 
                         let ty = ty::mk_ptr(self.tcx(),
                                              ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                        try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+                        try!(self.subtype(ty, b));
                         debug!("Success, coerced with AutoDerefRef(1, \
                                 AutoPtr(AutoUnsize({:?})))", kind);
                         Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -306,7 +307,7 @@ fn coerce_unsized(&self,
                 match self.unsize_ty(t_a, t_b) {
                     Some((ty, kind)) => {
                         let ty = ty::mk_uniq(self.tcx(), ty);
-                        try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+                        try!(self.subtype(ty, b));
                         debug!("Success, coerced with AutoDerefRef(1, \
                                 AutoUnsizeUniq({:?}))", kind);
                         Ok(Some(AdjustDerefRef(AutoDerefRef {
@@ -365,9 +366,10 @@ fn unsize_ty(&self,
                             let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
 
                             // relate `a1` to `b`
-                            let result = self.fcx.infcx().try(|_| {
+                            let result = self.fcx.infcx().commit_if_ok(|_| {
                                 // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
-                                try!(self.outlives(data_a.bounds.region_bound,
+                                try!(self.outlives(infer::RelateObjectBound(self.origin.span()),
+                                                   data_a.bounds.region_bound,
                                                    data_b.bounds.region_bound));
                                 self.subtype(ty_a1, ty_b)
                             });
@@ -399,7 +401,7 @@ fn unsize_ty(&self,
                         let mut result = None;
                         let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
                         for (i, (tp_a, tp_b)) in tps {
-                            if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
+                            if self.subtype(*tp_a, *tp_b).is_ok() {
                                 continue;
                             }
                             match self.unsize_ty(*tp_a, *tp_b) {
@@ -408,7 +410,7 @@ fn unsize_ty(&self,
                                     let mut new_substs = substs_a.clone();
                                     new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
                                     let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
-                                    if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
+                                    if self.subtype(ty, ty_b).is_err() {
                                         debug!("Unsized type parameter '{}', but still \
                                                 could not match types {} and {}",
                                                ppaux::ty_to_string(tcx, *tp_a),
@@ -534,14 +536,13 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                              expr: &ast::Expr,
                              a: Ty<'tcx>,
                              b: Ty<'tcx>)
-                             -> cres<'tcx, ()> {
+                             -> RelateResult<'tcx, ()> {
     debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx()));
     let adjustment = try!(indent(|| {
-        fcx.infcx().commit_if_ok(|| {
-            let origin = infer::ExprAssignable(expr.span);
+        fcx.infcx().commit_if_ok(|_| {
             Coerce {
                 fcx: fcx,
-                trace: infer::TypeTrace::types(origin, false, a, b)
+                origin: infer::ExprAssignable(expr.span),
             }.coerce(expr, a, b)
         })
     }));
index 1c5f2c5607857bfb2ccb923238500431054e1b3a..532277d75b2e06af52afc2002fffe37f62957b58 100644 (file)
@@ -282,7 +282,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
-    let err = infcx.try(|snapshot| {
+    let err = infcx.commit_if_ok(|snapshot| {
         let origin = infer::MethodCompatCheck(impl_m_span);
 
         let (impl_sig, _) =
index 49f4399b2c7b43b32638072928b096ef9be7a3b4..2f7e0073e1751ad0f99ee08fc7714ee5269749ff 100644 (file)
@@ -95,7 +95,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
         ty::lookup_item_type(tcx, self_type_did);
 
     let infcx = infer::new_infer_ctxt(tcx);
-    infcx.try(|snapshot| {
+    infcx.commit_if_ok(|snapshot| {
         let (named_type_to_skolem, skol_map) =
             infcx.construct_skolemized_subst(named_type_generics, snapshot);
         let named_type_skolem = named_type.subst(tcx, &named_type_to_skolem);
index 6349ea57f2ff15d96801592117cc9fc0ace1d2a5..e203019bd0638fe43d2fe0ea2d8d307c35db27b5 100644 (file)
@@ -1130,7 +1130,7 @@ fn collapse_candidates_to_trait_pick(&self,
     ///////////////////////////////////////////////////////////////////////////
     // MISCELLANY
 
-    fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::ures<'tcx> {
+    fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::UnitResult<'tcx> {
         self.infcx().sub_types(false, infer::Misc(DUMMY_SP), sub, sup)
     }
 
index 16501ec280791d2886daffee7a0d39d9e71d4645..b9a0070f205be88a8c13ee04790774564fed509c 100644 (file)
@@ -85,7 +85,7 @@
 use check::_match::pat_ctxt;
 use fmt_macros::{Parser, Piece, Position};
 use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
-use middle::{const_eval, def};
+use middle::def;
 use middle::infer;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::McResult;
@@ -94,7 +94,7 @@
 use middle::region::{self, CodeExtent};
 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
 use middle::traits;
-use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
+use middle::ty::{FnSig, GenericPredicates, TypeScheme};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
 use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::liberate_late_bound_regions;
@@ -3329,7 +3329,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                 &format!("unbound path {}", expr.repr(tcx)))
           };
 
-          let mut def = path_res.base_def;
+          let def = path_res.base_def;
           if path_res.depth == 0 {
               let (scheme, predicates) =
                   type_scheme_and_predicates_for_def(fcx, expr.span, def);
@@ -3339,9 +3339,11 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
           } else {
               let ty_segments = path.segments.init();
               let base_ty_end = path.segments.len() - path_res.depth;
-              let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, expr.span,
+              let ty = astconv::finish_resolving_def_to_ty(fcx,
+                                                           fcx,
+                                                           expr.span,
                                                            PathParamMode::Optional,
-                                                           &mut def,
+                                                           &def,
                                                            opt_self_ty,
                                                            &ty_segments[..base_ty_end],
                                                            &ty_segments[base_ty_end..]);
@@ -4283,68 +4285,30 @@ fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
     fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                           vs: &'tcx [P<ast::Variant>],
                           id: ast::NodeId,
-                          hint: attr::ReprAttr)
-                          -> Vec<Rc<ty::VariantInfo<'tcx>>> {
+                          hint: attr::ReprAttr) {
         #![allow(trivial_numeric_casts)]
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
-        let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
         let mut disr_vals: Vec<ty::Disr> = Vec::new();
-        let mut prev_disr_val: Option<ty::Disr> = None;
 
-        for v in vs {
+        let inh = static_inherited_fields(ccx);
+        let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
 
-            // If the discriminant value is specified explicitly in the enum check whether the
-            // initialization expression is valid, otherwise use the last value plus one.
-            let mut current_disr_val = match prev_disr_val {
-                Some(prev_disr_val) => {
-                    if let Some(v) = prev_disr_val.checked_add(1) {
-                        v
-                    } else {
-                        ty::INITIAL_DISCRIMINANT_VALUE
-                    }
-                }
-                None => ty::INITIAL_DISCRIMINANT_VALUE
-            };
+        let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint));
+        for v in vs {
+            if let Some(ref e) = v.node.disr_expr {
+                check_const_with_ty(&fcx, e.span, e, repr_type_ty);
+            }
+        }
 
-            match v.node.disr_expr {
-                Some(ref e) => {
-                    debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
+        let def_id = local_def(id);
 
-                    let inh = static_inherited_fields(ccx);
-                    let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
-                    let declty = match hint {
-                        attr::ReprAny | attr::ReprPacked |
-                        attr::ReprExtern => fcx.tcx().types.isize,
+        // ty::enum_variants guards against discriminant overflows, so
+        // we need not check for that.
+        let variants = ty::enum_variants(ccx.tcx, def_id);
 
-                        attr::ReprInt(_, attr::SignedInt(ity)) => {
-                            ty::mk_mach_int(fcx.tcx(), ity)
-                        }
-                        attr::ReprInt(_, attr::UnsignedInt(ity)) => {
-                            ty::mk_mach_uint(fcx.tcx(), ity)
-                        },
-                    };
-                    check_const_with_ty(&fcx, e.span, &**e, declty);
-                    // check_expr (from check_const pass) doesn't guarantee
-                    // that the expression is in a form that eval_const_expr can
-                    // handle, so we may still get an internal compiler error
-
-                    match const_eval::eval_const_expr_partial(ccx.tcx, &**e, Some(declty)) {
-                        Ok(const_eval::const_int(val)) => current_disr_val = val as Disr,
-                        Ok(const_eval::const_uint(val)) => current_disr_val = val as Disr,
-                        Ok(_) => {
-                            span_err!(ccx.tcx.sess, e.span, E0079,
-                                "expected signed integer constant");
-                        }
-                        Err(ref err) => {
-                            span_err!(ccx.tcx.sess, err.span, E0080,
-                                      "constant evaluation error: {}",
-                                      err.description());
-                        }
-                    }
-                },
-                None => ()
-            };
+        for (v, variant) in vs.iter().zip(variants.iter()) {
+            let current_disr_val = variant.disr_val;
 
             // Check for duplicate discriminant values
             match disr_vals.iter().position(|&x| x == current_disr_val) {
@@ -4372,15 +4336,7 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 }
             }
             disr_vals.push(current_disr_val);
-
-            let variant_info = Rc::new(VariantInfo::from_ast_variant(ccx.tcx, &**v,
-                                                                     current_disr_val));
-            prev_disr_val = Some(current_disr_val);
-
-            variants.push(variant_info);
         }
-
-        return variants;
     }
 
     let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
@@ -4396,10 +4352,7 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         };
     }
 
-    let variants = do_check(ccx, vs, id, hint);
-
-    // cache so that ty::enum_variants won't repeat this work
-    ccx.tcx.enum_var_cache.borrow_mut().insert(local_def(id), Rc::new(variants));
+    do_check(ccx, vs, id, hint);
 
     check_representable(ccx.tcx, sp, id, "enum");
 
index 3edea6d3004449b3e8d586902180feb24886e07c..9171367468026a8f9226b4537b22500f4ff51394 100644 (file)
@@ -1542,7 +1542,7 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
             debug!("projection_bounds: outlives={} (2)",
                    outlives.repr(tcx));
 
-            let region_result = infcx.try(|_| {
+            let region_result = infcx.commit_if_ok(|_| {
                 let (outlives, _) =
                     infcx.replace_late_bound_regions_with_fresh_var(
                         span,
index eaf07a3ef13a7d6326711ddeadfe5b6ca00c6f95..51d0c18872dc4213b9756cb3585bb5d7a8bc34cd 100644 (file)
@@ -30,7 +30,6 @@
 use middle::ty::ty_projection;
 use middle::ty;
 use CrateCtxt;
-use middle::infer::combine::Combine;
 use middle::infer::InferCtxt;
 use middle::infer::new_infer_ctxt;
 use std::collections::HashSet;
index 7b76f3681c16330bcef1e1bae46ab7679427cb6c..b450e6b398a6a00d8ef1dd716c198559f829f8a2 100644 (file)
@@ -215,25 +215,21 @@ fn check_item(&self, item: &ast::Item) {
                 match traits::orphan_check(self.tcx, def_id) {
                     Ok(()) => { }
                     Err(traits::OrphanCheckErr::NoLocalInputType) => {
-                        if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
-                            span_err!(
-                                self.tcx.sess, item.span, E0117,
-                                "the impl does not reference any \
-                                 types defined in this crate; \
-                                 only traits defined in the current crate can be \
-                                 implemented for arbitrary types");
-                            return;
-                        }
+                        span_err!(
+                            self.tcx.sess, item.span, E0117,
+                            "the impl does not reference any \
+                             types defined in this crate; \
+                             only traits defined in the current crate can be \
+                             implemented for arbitrary types");
+                        return;
                     }
                     Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
-                        if !ty::has_attr(self.tcx, trait_def_id, "old_orphan_check") {
-                            span_err!(self.tcx.sess, item.span, E0210,
-                                    "type parameter `{}` must be used as the type parameter for \
-                                     some local type (e.g. `MyStruct<T>`); only traits defined in \
-                                     the current crate can be implemented for a type parameter",
-                                    param_ty.user_string(self.tcx));
-                            return;
-                        }
+                        span_err!(self.tcx.sess, item.span, E0210,
+                                "type parameter `{}` must be used as the type parameter for \
+                                 some local type (e.g. `MyStruct<T>`); only traits defined in \
+                                 the current crate can be implemented for a type parameter",
+                                param_ty.user_string(self.tcx));
+                        return;
                     }
                 }
 
index 7d01bece01cb808188d027b30b37b22736fbbb49..a8d93c8bd111a054b8a49bfc9f97c3de14913fd8 100644 (file)
@@ -51,8 +51,6 @@
     E0075,
     E0076,
     E0077,
-    E0079,
-    E0080,
     E0081,
     E0082,
     E0083,
index 91410fa808c78a8436c7d639ba2a78a1eabac0fb..9d6c04b1ad49d90957a2f373b6685f4a4ae15693 100644 (file)
@@ -146,7 +146,7 @@ pub struct CrateCtxt<'a, 'tcx: 'a> {
 fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
     debug!("write_ty_to_tcx({}, {})", node_id, ppaux::ty_to_string(tcx, ty));
     assert!(!ty::type_needs_infer(ty));
-    tcx.node_types.borrow_mut().insert(node_id, ty);
+    tcx.node_type_insert(node_id, ty);
 }
 
 fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
index 8c85eaff23ce5610646d337a94d837d878859b1c..760fa329fd9866808f68a7570a4bd2ba48b19c99 100644 (file)
@@ -20,7 +20,7 @@
 
 #[cfg(unix)]
 mod imp {
-    use std::ffi::{AsOsStr, CString};
+    use std::ffi::{CString, OsStr};
     use std::os::unix::prelude::*;
     use std::path::Path;
     use std::io;
@@ -116,7 +116,8 @@ pub struct Lock {
 
     impl Lock {
         pub fn new(p: &Path) -> Lock {
-            let buf = CString::new(p.as_os_str().as_bytes()).unwrap();
+            let os: &OsStr = p.as_ref();
+            let buf = CString::new(os.as_bytes()).unwrap();
             let fd = unsafe {
                 libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
                            libc::S_IRWXU)
@@ -164,9 +165,9 @@ fn drop(&mut self) {
 #[cfg(windows)]
 mod imp {
     use libc;
-    use std::ffi::AsOsStr;
     use std::io;
     use std::mem;
+    use std::ffi::OsStr;
     use std::os::windows::prelude::*;
     use std::path::Path;
     use std::ptr;
@@ -194,7 +195,8 @@ pub struct Lock {
 
     impl Lock {
         pub fn new(p: &Path) -> Lock {
-            let mut p_16: Vec<_> = p.as_os_str().encode_wide().collect();
+            let os: &OsStr = p.as_ref();
+            let mut p_16: Vec<_> = os.encode_wide().collect();
             p_16.push(0);
             let handle = unsafe {
                 libc::CreateFileW(p_16.as_ptr(),
index 431cb4a28989e1902866b7d5674b38c3dd17839b..1ff3411f8fc14368809ab1f5339c68dbc4421b5e 100644 (file)
@@ -23,7 +23,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(collections)]
-#![feature(core)]
 #![feature(exit_status)]
 #![feature(set_stdio)]
 #![feature(libc)]
@@ -36,7 +35,6 @@
 #![feature(file_path)]
 #![feature(path_ext)]
 #![feature(path_relative_from)]
-#![feature(convert)]
 #![feature(slice_patterns)]
 
 extern crate arena;
index 2d5d8cd501a46100e1fc493b03d382b6139ca784..cdfe212bf23ddccd9c0b97cce4e73c0c97b545e2 100644 (file)
 //!     let encoded = json::encode(&object).unwrap();
 //!
 //!     // Deserialize using `json::decode`
-//!     let decoded: TestStruct = json::decode(encoded.as_slice()).unwrap();
+//!     let decoded: TestStruct = json::decode(&encoded[..]).unwrap();
 //! }
 //! ```
 //!
@@ -367,8 +367,8 @@ impl std::error::Error for EncoderError {
     fn description(&self) -> &str { "encoder error" }
 }
 
-impl std::error::FromError<fmt::Error> for EncoderError {
-    fn from_error(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
+impl From<fmt::Error> for EncoderError {
+    fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
 }
 
 pub type EncodeResult = Result<(), EncoderError>;
index b79323b3f962de18e5241780813d3fba3c188831..2e86712c9bccf66cb24f1d45c0ff3884d5e2526b 100644 (file)
@@ -36,7 +36,6 @@
 #![feature(std_misc)]
 #![feature(unicode)]
 #![feature(str_char)]
-#![feature(convert)]
 #![cfg_attr(test, feature(test, old_io))]
 
 // test harness access
index bc0f109de15b649ee94a34bd3989d7931c5f4ef2..a636c1a812ddcbf2df4c3b5b009b36be5a072955 100644 (file)
@@ -1482,8 +1482,7 @@ pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
         }
     }
 
-    #[unstable(feature = "collections",
-               reason = "matches entry v3 specification, waiting for dust to settle")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
     pub fn or_insert(self, default: V) -> &'a mut V {
@@ -1493,8 +1492,7 @@ pub fn or_insert(self, default: V) -> &'a mut V {
         }
     }
 
-    #[unstable(feature = "collections",
-               reason = "matches entry v3 specification, waiting for dust to settle")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the result of the default function if empty,
     /// and returns a mutable reference to the value in the entry.
     pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
index 87380471c8001e88e5fa65e2fe1fe746dc82cf8f..5fbc21797ab5a0442d82ebd5fc2254f54219b9fb 100644 (file)
@@ -1192,7 +1192,7 @@ fn test_move_iter() {
         };
 
         let v = hs.into_iter().collect::<Vec<char>>();
-        assert!(['a', 'b'] == v || ['b', 'a'] == v);
+        assert!(v == ['a', 'b'] || v == ['b', 'a']);
     }
 
     #[test]
index aa3195cbf018b2e43178fc19968d4da6db1641c1..053ceceb49621f1525c9eb54ea11ca9382d90bbd 100644 (file)
@@ -15,7 +15,7 @@
 use clone::Clone;
 use cmp;
 use hash::{Hash, Hasher};
-use iter::{Iterator, ExactSizeIterator, count};
+use iter::{Iterator, ExactSizeIterator};
 use marker::{Copy, Send, Sync, Sized, self};
 use mem::{min_align_of, size_of};
 use mem;
index d8a95133d94144dc6d062ca552a9c08314177dfa..e76d5460eb0c4218317461061e587fca3de7ddf5 100644 (file)
@@ -18,7 +18,7 @@
 use prelude::v1::*;
 
 use env;
-use ffi::{AsOsStr, CString, OsString};
+use ffi::{CString, OsString};
 use mem;
 use path::{Path, PathBuf};
 
@@ -190,7 +190,6 @@ mod dl {
     use ffi::{CStr, OsStr};
     use str;
     use libc;
-    use os::unix::prelude::*;
     use ptr;
 
     pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> {
index 71f072302fb21c8fef6cf1b7a6e55075e0fc8e96..931cf46a58f2266ee822e6b6eb60a656e460f6ca 100644 (file)
@@ -20,7 +20,7 @@
 
 use iter::IntoIterator;
 use error::Error;
-use ffi::{OsString, AsOsStr};
+use ffi::{OsStr, OsString};
 use fmt;
 use io;
 use path::{Path, PathBuf};
@@ -176,7 +176,7 @@ fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 /// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
-pub fn var<K: ?Sized>(key: &K) -> Result<String, VarError> where K: AsOsStr {
+pub fn var<K: ?Sized>(key: &K) -> Result<String, VarError> where K: AsRef<OsStr> {
     match var_os(key) {
         Some(s) => s.into_string().map_err(VarError::NotUnicode),
         None => Err(VarError::NotPresent)
@@ -198,9 +198,9 @@ pub fn var<K: ?Sized>(key: &K) -> Result<String, VarError> where K: AsOsStr {
 /// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
-pub fn var_os<K: ?Sized>(key: &K) -> Option<OsString> where K: AsOsStr {
+pub fn var_os<K: ?Sized>(key: &K) -> Option<OsString> where K: AsRef<OsStr> {
     let _g = ENV_LOCK.lock();
-    os_imp::getenv(key.as_os_str())
+    os_imp::getenv(key.as_ref())
 }
 
 /// Possible errors from the `env::var` method.
@@ -255,17 +255,30 @@ fn description(&self) -> &str {
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn set_var<K: ?Sized, V: ?Sized>(k: &K, v: &V)
-    where K: AsOsStr, V: AsOsStr
+    where K: AsRef<OsStr>, V: AsRef<OsStr>
 {
     let _g = ENV_LOCK.lock();
-    os_imp::setenv(k.as_os_str(), v.as_os_str())
+    os_imp::setenv(k.as_ref(), v.as_ref())
 }
 
-/// Remove a variable from the environment entirely.
+/// Remove an environment variable from the environment of the currently running process.
+///
+/// # Examples
+///
+/// ```
+/// use std::env;
+///
+/// let key = "KEY";
+/// env::set_var(key, "VALUE");
+/// assert_eq!(env::var(key), Ok("VALUE".to_string()));
+///
+/// env::remove_var(key);
+/// assert!(env::var(key).is_err());
+/// ```
 #[stable(feature = "env", since = "1.0.0")]
-pub fn remove_var<K: ?Sized>(k: &K) where K: AsOsStr {
+pub fn remove_var<K: ?Sized>(k: &K) where K: AsRef<OsStr> {
     let _g = ENV_LOCK.lock();
-    os_imp::unsetenv(k.as_os_str())
+    os_imp::unsetenv(k.as_ref())
 }
 
 /// An iterator over `Path` instances for parsing an environment variable
@@ -296,8 +309,8 @@ pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a> }
 /// }
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
-pub fn split_paths<T: AsOsStr + ?Sized>(unparsed: &T) -> SplitPaths {
-    SplitPaths { inner: os_imp::split_paths(unparsed.as_os_str()) }
+pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths {
+    SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
 }
 
 #[stable(feature = "env", since = "1.0.0")]
@@ -327,7 +340,6 @@ pub struct JoinPathsError {
 /// # Examples
 ///
 /// ```
-/// # #![feature(convert)]
 /// use std::env;
 /// use std::path::PathBuf;
 ///
@@ -340,7 +352,7 @@ pub struct JoinPathsError {
 /// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
-    where I: IntoIterator<Item=T>, T: AsOsStr
+    where I: IntoIterator<Item=T>, T: AsRef<OsStr>
 {
     os_imp::join_paths(paths.into_iter()).map_err(|e| {
         JoinPathsError { inner: e }
@@ -398,6 +410,19 @@ pub fn home_dir() -> Option<PathBuf> {
 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
 /// 'USERPROFILE' environment variable  if any are set and not the empty
 /// string. Otherwise, tmpdir returns the path to the Windows directory.
+///
+/// ```
+/// use std::env;
+/// use std::fs::File;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let mut dir = env::temp_dir();
+/// dir.push("foo.txt");
+///
+/// let f = try!(File::create(dir));
+/// # Ok(())
+/// # }
+/// ```
 #[stable(feature = "env", since = "1.0.0")]
 pub fn temp_dir() -> PathBuf {
     os_imp::temp_dir()
@@ -557,6 +582,7 @@ pub mod consts {
     #[stable(feature = "env", since = "1.0.0")]
     pub const ARCH: &'static str = super::arch::ARCH;
 
+    /// The family of the operating system. In this case, `unix`.
     #[stable(feature = "env", since = "1.0.0")]
     pub const FAMILY: &'static str = super::os::FAMILY;
 
@@ -740,7 +766,7 @@ fn make_rand_name() -> OsString {
         let mut rng = rand::thread_rng();
         let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
                                      .collect::<String>());
-        let n = OsString::from_string(n);
+        let n = OsString::from(n);
         assert!(var_os(&n).is_none());
         n
     }
index a00f77080252c70292950b2ac17202478674be99..de91e5f32683939d5bee102c8739c14a0d6b5e25 100644 (file)
@@ -10,9 +10,9 @@
 
 #![unstable(feature = "std_misc")]
 
-use convert::Into;
+use convert::{Into, From};
 use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
-use error::{Error, FromError};
+use error::Error;
 use fmt;
 use io;
 use iter::Iterator;
@@ -132,15 +132,6 @@ pub struct CStr {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct NulError(usize, Vec<u8>);
 
-/// 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>;
-}
-
 impl CString {
     /// Create a new C-compatible string from a container of bytes.
     ///
@@ -178,57 +169,6 @@ pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
         }
     }
 
-    /// Create a new C-compatible string from a byte slice.
-    ///
-    /// This method will copy the data of the slice provided into a new
-    /// allocation, ensuring that there is a trailing 0 byte.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// # #![feature(libc)]
-    /// extern crate libc;
-    /// use std::ffi::CString;
-    ///
-    /// extern { fn puts(s: *const libc::c_char); }
-    ///
-    /// fn main() {
-    ///     let to_print = CString::new("Hello!").unwrap();
-    ///     unsafe {
-    ///         puts(to_print.as_ptr());
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the provided slice contains any
-    /// interior nul bytes.
-    #[unstable(feature = "std_misc")]
-    #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
-    #[allow(deprecated)]
-    pub fn from_slice(v: &[u8]) -> CString {
-        CString::from_vec(v.to_vec())
-    }
-
-    /// Create a C-compatible string from a byte vector.
-    ///
-    /// This method will consume ownership of the provided vector, appending a 0
-    /// byte to the end after verifying that there are no interior 0 bytes.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the provided slice contains any
-    /// interior nul bytes.
-    #[unstable(feature = "std_misc")]
-    #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
-    pub fn from_vec(v: Vec<u8>) -> CString {
-        match v.iter().position(|x| *x == 0) {
-            Some(i) => panic!("null byte found in slice at: {}", i),
-            None => unsafe { CString::from_vec_unchecked(v) },
-        }
-    }
-
     /// Create a C-compatible string from a byte vector without checking for
     /// interior 0 bytes.
     ///
@@ -298,17 +238,17 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl FromError<NulError> for io::Error {
-    fn from_error(_: NulError) -> io::Error {
+impl From<NulError> for io::Error {
+    fn from(_: NulError) -> io::Error {
         io::Error::new(io::ErrorKind::InvalidInput,
-                       "data provided contains a nul byte", None)
+                       "data provided contains a nul byte")
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
-impl FromError<NulError> for old_io::IoError {
-    fn from_error(_: NulError) -> old_io::IoError {
+impl From<NulError> for old_io::IoError {
+    fn from(_: NulError) -> old_io::IoError {
         old_io::IoError {
             kind: old_io::IoErrorKind::InvalidInput,
             desc: "data provided contains a nul byte",
@@ -424,41 +364,6 @@ fn cmp(&self, other: &CStr) -> Ordering {
     }
 }
 
-/// Deprecated in favor of `CStr`
-#[unstable(feature = "std_misc")]
-#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")]
-pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
-    let len = libc::strlen(*raw);
-    slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
-}
-
-/// Deprecated in favor of `CStr`
-#[unstable(feature = "std_misc")]
-#[deprecated(since = "1.0.0",
-             reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")]
-pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
-                                          -> &'a [u8] {
-    let len = libc::strlen(*raw) + 1;
-    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 }
-}
-
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
index f17dc6542491bad149819704d118debd755ac9a7..1b7e913d46cbf49120c0f2798a5135477dec53ff 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::c_str::{CString, CStr};
-pub use self::c_str::{NulError, IntoBytes};
-#[allow(deprecated)]
-pub use self::c_str::c_str_to_bytes;
-#[allow(deprecated)]
-pub use self::c_str::c_str_to_bytes_with_nul;
+pub use self::c_str::{CString, CStr, NulError};
 
 #[stable(feature = "rust1", since = "1.0.0")]
-pub use self::os_str::OsString;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use self::os_str::OsStr;
+pub use self::os_str::{OsString, OsStr};
 
 mod c_str;
 mod os_str;
index 49dbac4585bc31edb20ec5ae49e0ab59eed42013..ab20efe25eb19da63db8ffd9e5f2020c41d674ce 100644 (file)
 //! for conversion to/from various other string types. Eventually these types
 //! will offer a full-fledged string API.
 
-#![unstable(feature = "os",
+#![unstable(feature = "os_str",
             reason = "recently added as part of path/io reform")]
 
 use core::prelude::*;
 
 use borrow::{Borrow, Cow, ToOwned};
+use ffi::CString;
 use fmt::{self, Debug};
 use mem;
 use string::String;
@@ -42,6 +43,7 @@
 use cmp;
 use hash::{Hash, Hasher};
 use old_path::{Path, GenericPath};
+use vec::Vec;
 
 use sys::os_str::{Buf, Slice};
 use sys_common::{AsInner, IntoInner, FromInner};
@@ -61,26 +63,41 @@ pub struct OsStr {
 }
 
 impl OsString {
-    /// Constructs an `OsString` at no cost by consuming a `String`.
+    /// Constructs a new empty `OsString`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[deprecated(since = "1.0.0", reason = "use `from` instead")]
-    pub fn from_string(s: String) -> OsString {
-        OsString::from(s)
+    pub fn new() -> OsString {
+        OsString { inner: Buf::from_string(String::new()) }
     }
 
-    /// Constructs an `OsString` by copying from a `&str` slice.
+    /// Construct an `OsString` from a byte sequence.
     ///
-    /// 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::from(s)
+    /// # Platform behavior
+    ///
+    /// On Unix systems, any byte sequence can be successfully
+    /// converted into an `OsString`.
+    ///
+    /// On Windows system, only UTF-8 byte sequences will successfully
+    /// convert; non UTF-8 data will produce `None`.
+    #[unstable(feature = "convert", reason = "recently added")]
+    pub fn from_bytes<B>(bytes: B) -> Option<OsString> where B: Into<Vec<u8>> {
+        #[cfg(unix)]
+        fn from_bytes_inner(vec: Vec<u8>) -> Option<OsString> {
+            use os::unix::ffi::OsStringExt;
+            Some(OsString::from_vec(vec))
+        }
+
+        #[cfg(windows)]
+        fn from_bytes_inner(vec: Vec<u8>) -> Option<OsString> {
+            String::from_utf8(vec).ok().map(OsString::from)
+        }
+
+        from_bytes_inner(bytes.into())
     }
 
-    /// Constructs a new empty `OsString`.
+    /// Convert to an `OsStr` slice.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> OsString {
-        OsString { inner: Buf::from_string(String::new()) }
+    pub fn as_os_str(&self) -> &OsStr {
+        self
     }
 
     /// Convert the `OsString` into a `String` if it contains valid Unicode data.
@@ -91,13 +108,6 @@ pub fn into_string(self) -> Result<String, OsString> {
         self.inner.into_string().map_err(|buf| OsString { inner: buf} )
     }
 
-    /// Extend the string with the given `&OsStr` slice.
-    #[deprecated(since = "1.0.0", reason = "renamed to `push`")]
-    #[unstable(feature = "os")]
-    pub fn push_os_str(&mut self, s: &OsStr) {
-        self.inner.push_slice(&s.inner)
-    }
-
     /// Extend the string with the given `&OsStr` slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
@@ -211,8 +221,16 @@ fn hash<H: Hasher>(&self, state: &mut H) {
 }
 
 impl OsStr {
+    /// Coerce into an `OsStr` slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &OsStr {
+        s.as_ref()
+    }
+
     /// Coerce directly from a `&str` slice to a `&OsStr` slice.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[deprecated(since = "1.0.0",
+                 reason = "use `OsStr::new` instead")]
     pub fn from_str(s: &str) -> &OsStr {
         unsafe { mem::transmute(Slice::from_str(s)) }
     }
@@ -239,6 +257,36 @@ pub fn to_os_string(&self) -> OsString {
         OsString { inner: self.inner.to_owned() }
     }
 
+    /// Yield this `OsStr` as a byte slice.
+    ///
+    /// # Platform behavior
+    ///
+    /// On Unix systems, this is a no-op.
+    ///
+    /// On Windows systems, this returns `None` unless the `OsStr` is
+    /// valid unicode, in which case it produces UTF-8-encoded
+    /// data. This may entail checking validity.
+    #[unstable(feature = "convert", reason = "recently added")]
+    pub fn to_bytes(&self) -> Option<&[u8]> {
+        if cfg!(windows) {
+            self.to_str().map(|s| s.as_bytes())
+        } else {
+            Some(self.bytes())
+        }
+    }
+
+    /// Create a `CString` containing this `OsStr` data.
+    ///
+    /// Fails if the `OsStr` contains interior nulls.
+    ///
+    /// This is a convenience for creating a `CString` from
+    /// `self.to_bytes()`, and inherits the platform behavior of the
+    /// `to_bytes` method.
+    #[unstable(feature = "convert", reason = "recently added")]
+    pub fn to_cstring(&self) -> Option<CString> {
+        self.to_bytes().and_then(|b| CString::new(b).ok())
+    }
+
     /// Get the underlying byte representation.
     ///
     /// Note: it is *crucial* that this API is private, to avoid
@@ -258,14 +306,14 @@ fn eq(&self, other: &OsStr) -> bool {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq<str> for OsStr {
     fn eq(&self, other: &str) -> bool {
-        *self == *OsStr::from_str(other)
+        *self == *OsStr::new(other)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl PartialEq<OsStr> for str {
     fn eq(&self, other: &OsStr) -> bool {
-        *other == *OsStr::from_str(self)
+        *other == *OsStr::new(self)
     }
 }
 
@@ -292,7 +340,7 @@ fn ge(&self, other: &OsStr) -> bool { self.bytes().ge(other.bytes()) }
 impl PartialOrd<str> for OsStr {
     #[inline]
     fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
-        self.partial_cmp(OsStr::from_str(other))
+        self.partial_cmp(OsStr::new(other))
     }
 }
 
@@ -359,7 +407,7 @@ fn as_os_str(&self) -> &OsStr {
 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for str {
     fn as_os_str(&self) -> &OsStr {
-        OsStr::from_str(self)
+        unsafe { mem::transmute(Slice::from_str(self)) }
     }
 }
 
@@ -367,7 +415,7 @@ fn as_os_str(&self) -> &OsStr {
 #[deprecated(since = "1.0.0", reason = "trait is deprecated")]
 impl AsOsStr for String {
     fn as_os_str(&self) -> &OsStr {
-        OsStr::from_str(&self[..])
+        unsafe { mem::transmute(Slice::from_str(self)) }
     }
 }
 
@@ -388,14 +436,14 @@ fn as_ref(&self) -> &OsStr {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for str {
     fn as_ref(&self) -> &OsStr {
-        OsStr::from_str(self)
+        unsafe { mem::transmute(Slice::from_str(self)) }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<OsStr> for String {
     fn as_ref(&self) -> &OsStr {
-        OsStr::from_str(&self[..])
+        unsafe { mem::transmute(Slice::from_str(self)) }
     }
 }
 
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
new file mode 100644 (file)
index 0000000..4f97ae8
--- /dev/null
@@ -0,0 +1,1646 @@
+// 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.
+
+//! Filesystem manipulation operations
+//!
+//! This module contains basic methods to manipulate the contents of the local
+//! filesystem. All methods in this module represent cross-platform filesystem
+//! operations. Extra platform-specific functionality can be found in the
+//! extension traits of `std::os::$platform`.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use core::prelude::*;
+
+use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
+use path::{Path, PathBuf};
+use sys::fs2 as fs_imp;
+use sys_common::{AsInnerMut, FromInner, AsInner};
+use vec::Vec;
+
+/// A reference to an open file on the filesystem.
+///
+/// An instance of a `File` can be read and/or written depending on what options
+/// it was opened with. Files also implement `Seek` to alter the logical cursor
+/// that the file contains internally.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::io::prelude::*;
+/// use std::fs::File;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let mut f = try!(File::create("foo.txt"));
+/// try!(f.write_all(b"Hello, world!"));
+///
+/// let mut f = try!(File::open("foo.txt"));
+/// let mut s = String::new();
+/// try!(f.read_to_string(&mut s));
+/// assert_eq!(s, "Hello, world!");
+/// # Ok(())
+/// # }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct File {
+    inner: fs_imp::File,
+    path: Option<PathBuf>,
+}
+
+/// Metadata information about a file.
+///
+/// This structure is returned from the `metadata` function or method and
+/// represents known metadata about a file such as its permissions, size,
+/// modification times, etc.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Metadata(fs_imp::FileAttr);
+
+/// Iterator over the entries in a directory.
+///
+/// This iterator is returned from the `read_dir` function of this module and
+/// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
+/// information like the entry's path and possibly other metadata can be
+/// learned.
+///
+/// # Failure
+///
+/// This `io::Result` will be an `Err` if there's some sort of intermittent
+/// IO error during iteration.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct ReadDir(fs_imp::ReadDir);
+
+/// Entries returned by the `ReadDir` iterator.
+///
+/// An instance of `DirEntry` represents an entry inside of a directory on the
+/// filesystem. Each entry can be inspected via methods to learn about the full
+/// path or possibly other metadata through per-platform extension traits.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct DirEntry(fs_imp::DirEntry);
+
+/// An iterator that recursively walks over the contents of a directory.
+#[unstable(feature = "fs_walk",
+           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 struct WalkDir {
+    cur: Option<ReadDir>,
+    stack: Vec<io::Result<ReadDir>>,
+}
+
+/// Options and flags which can be used to configure how a file is opened.
+///
+/// This builder exposes the ability to configure how a `File` is opened and
+/// what operations are permitted on the open file. The `File::open` and
+/// `File::create` methods are aliases for commonly used options using this
+/// builder.
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct OpenOptions(fs_imp::OpenOptions);
+
+/// Representation of the various permissions on a file.
+///
+/// This module only currently provides one bit of information, `readonly`,
+/// which is exposed on all currently supported platforms. Unix-specific
+/// functionality, such as mode bits, is available through the
+/// `os::unix::PermissionsExt` trait.
+#[derive(Clone, PartialEq, Eq, Debug)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Permissions(fs_imp::FilePermissions);
+
+impl File {
+    /// Attempts to open a file in read-only mode.
+    ///
+    /// See the `OpenOptions::open` method for more details.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if `path` does not already exist.
+    /// Other errors may also be returned according to `OpenOptions::open`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
+        OpenOptions::new().read(true).open(path)
+    }
+
+    /// Open a file in write-only mode.
+    ///
+    /// This function will create a file if it does not exist,
+    /// and will truncate it if it does.
+    ///
+    /// See the `OpenOptions::open` function for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
+        OpenOptions::new().write(true).create(true).truncate(true).open(path)
+    }
+
+    /// Returns the original path that was used to open this file.
+    #[unstable(feature = "file_path",
+               reason = "this abstraction is imposed by this library instead \
+                         of the underlying OS and may be removed")]
+    pub fn path(&self) -> Option<&Path> {
+        self.path.as_ref().map(|p| &**p)
+    }
+
+    /// Attempt to sync all OS-internal metadata to disk.
+    ///
+    /// This function will attempt to ensure that all in-core data reaches the
+    /// filesystem before returning.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::prelude::*;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// try!(f.write_all(b"Hello, world!"));
+    ///
+    /// try!(f.sync_all());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn sync_all(&self) -> io::Result<()> {
+        self.inner.fsync()
+    }
+
+    /// This function is similar to `sync_all`, except that it may not
+    /// synchronize file metadata to the filesystem.
+    ///
+    /// This is intended for use cases that must synchronize content, but don't
+    /// need the metadata on disk. The goal of this method is to reduce disk
+    /// operations.
+    ///
+    /// Note that some platforms may simply implement this in terms of
+    /// `sync_all`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::prelude::*;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// try!(f.write_all(b"Hello, world!"));
+    ///
+    /// try!(f.sync_data());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn sync_data(&self) -> io::Result<()> {
+        self.inner.datasync()
+    }
+
+    /// Truncates or extends the underlying file, updating the size of
+    /// this file to become `size`.
+    ///
+    /// If the `size` is less than the current file's size, then the file will
+    /// be shrunk. If it is greater than the current file's size, then the file
+    /// will be extended to `size` and have all of the intermediate data filled
+    /// in with 0s.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// try!(f.set_len(0));
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn set_len(&self, size: u64) -> io::Result<()> {
+        self.inner.truncate(size)
+    }
+
+    /// Queries metadata about the underlying file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn metadata(&self) -> io::Result<Metadata> {
+        self.inner.file_attr().map(Metadata)
+    }
+}
+
+impl AsInner<fs_imp::File> for File {
+    fn as_inner(&self) -> &fs_imp::File { &self.inner }
+}
+impl FromInner<fs_imp::File> for File {
+    fn from_inner(f: fs_imp::File) -> File {
+        File { inner: f, path: None }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Read for File {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.read(buf)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Write for File {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.inner.write(buf)
+    }
+    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Seek for File {
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        self.inner.seek(pos)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> Read for &'a File {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.read(buf)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> Write for &'a File {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.inner.write(buf)
+    }
+    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> Seek for &'a File {
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        self.inner.seek(pos)
+    }
+}
+
+impl OpenOptions {
+    /// Creates a blank net set of options ready for configuration.
+    ///
+    /// All options are initially set to `false`.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new() -> OpenOptions {
+        OpenOptions(fs_imp::OpenOptions::new())
+    }
+
+    /// Set the option for read access.
+    ///
+    /// This option, when true, will indicate that the file should be
+    /// `read`-able if opened.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn read(&mut self, read: bool) -> &mut OpenOptions {
+        self.0.read(read); self
+    }
+
+    /// Set the option for write access.
+    ///
+    /// This option, when true, will indicate that the file should be
+    /// `write`-able if opened.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn write(&mut self, write: bool) -> &mut OpenOptions {
+        self.0.write(write); self
+    }
+
+    /// Set the option for the append mode.
+    ///
+    /// This option, when true, means that writes will append to a file instead
+    /// of overwriting previous contents.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn append(&mut self, append: bool) -> &mut OpenOptions {
+        self.0.append(append); self
+    }
+
+    /// Set the option for truncating a previous file.
+    ///
+    /// If a file is successfully opened with this option set it will truncate
+    /// the file to 0 length if it already exists.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
+        self.0.truncate(truncate); self
+    }
+
+    /// Set the option for creating a new file.
+    ///
+    /// This option indicates whether a new file will be created if the file
+    /// does not yet already exist.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn create(&mut self, create: bool) -> &mut OpenOptions {
+        self.0.create(create); self
+    }
+
+    /// Open a file at `path` with the options specified by `self`.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error under a number of different
+    /// circumstances, to include but not limited to:
+    ///
+    /// * Opening a file that does not exist with read access.
+    /// * Attempting to open a file with access that the user lacks
+    ///   permissions for
+    /// * Filesystem-level errors (full disk, etc)
+    #[stable(feature = "rust1", since = "1.0.0")]
+    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: Some(path.to_path_buf()), inner: inner })
+    }
+}
+
+impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
+    fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
+}
+
+impl Metadata {
+    /// Returns whether this metadata is for a directory.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn is_dir(&self) -> bool { self.0.is_dir() }
+
+    /// Returns whether this metadata is for a regular file.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn is_file(&self) -> bool { self.0.is_file() }
+
+    /// Returns the size of the file, in bytes, this metadata is for.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn len(&self) -> u64 { self.0.size() }
+
+    /// Returns the permissions of the file this metadata is for.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn permissions(&self) -> Permissions {
+        Permissions(self.0.perm())
+    }
+
+    /// Returns the most recent access time for a file.
+    ///
+    /// The return value is in milliseconds since the epoch.
+    #[unstable(feature = "fs_time",
+               reason = "the return type of u64 is not quite appropriate for \
+                         this method and may change if the standard library \
+                         gains a type to represent a moment in time")]
+    pub fn accessed(&self) -> u64 { self.0.accessed() }
+
+    /// Returns the most recent modification time for a file.
+    ///
+    /// The return value is in milliseconds since the epoch.
+    #[unstable(feature = "fs_time",
+               reason = "the return type of u64 is not quite appropriate for \
+                         this method and may change if the standard library \
+                         gains a type to represent a moment in time")]
+    pub fn modified(&self) -> u64 { self.0.modified() }
+}
+
+impl Permissions {
+    /// Returns whether these permissions describe a readonly file.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn readonly(&self) -> bool { self.0.readonly() }
+
+    /// Modify the readonly flag for this set of permissions.
+    ///
+    /// This operation does **not** modify the filesystem. To modify the
+    /// filesystem use the `fs::set_permissions` function.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn set_readonly(&mut self, readonly: bool) {
+        self.0.set_readonly(readonly)
+    }
+}
+
+impl FromInner<fs_imp::FilePermissions> for Permissions {
+    fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
+        Permissions(f)
+    }
+}
+
+impl AsInner<fs_imp::FilePermissions> for Permissions {
+    fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        self.0.next().map(|entry| entry.map(DirEntry))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl DirEntry {
+    /// Returns the full path to the file that this entry represents.
+    ///
+    /// The full path is created by joining the original path to `read_dir` or
+    /// `walk_dir` with the filename of this entry.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn path(&self) -> PathBuf { self.0.path() }
+}
+
+/// Remove a file from the underlying filesystem.
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// use std::fs;
+///
+/// fs::remove_file("/some/file/path.txt");
+/// ```
+///
+/// Note that, just because an unlink call was successful, it is not
+/// guaranteed that a file is immediately deleted (e.g. depending on
+/// platform, other open file descriptors may prevent immediate removal).
+///
+/// # Errors
+///
+/// This function will return an error if `path` points to a directory, if the
+/// 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: 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,
+/// directory, etc.
+///
+/// This function will traverse soft links to query information about the
+/// destination file.
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// # fn foo() -> std::io::Result<()> {
+/// use std::fs;
+///
+/// let attr = try!(fs::metadata("/some/file/path.txt"));
+/// // inspect attr ...
+/// # Ok(())
+/// # }
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the user lacks the requisite
+/// 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: AsRef<Path>>(path: P) -> io::Result<Metadata> {
+    fs_imp::stat(path.as_ref()).map(Metadata)
+}
+
+/// Rename a file or directory to a new name.
+///
+/// # Examples
+///
+/// ```rust,no_run
+/// use std::fs;
+///
+/// fs::rename("foo", "bar");
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the provided `from` doesn't exist, if
+/// the process lacks permissions to view the contents, if `from` and `to`
+/// reside on separate filesystems, or if some other intermittent I/O error
+/// occurs.
+#[stable(feature = "rust1", since = "1.0.0")]
+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
+/// copy the permission bits of the original file to the destination file.
+///
+/// This function will **overwrite** the contents of `to`.
+///
+/// Note that if `from` and `to` both point to the same file, then the file
+/// will likely get truncated by this operation.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// fs::copy("foo.txt", "bar.txt");
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not
+/// limited to just these cases:
+///
+/// * The `from` path is not a file
+/// * The `from` file does not exist
+/// * 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: 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"))
+    }
+
+    let mut reader = try!(File::open(from));
+    let mut writer = try!(File::create(to));
+    let perm = try!(reader.metadata()).permissions();
+
+    let ret = try!(io::copy(&mut reader, &mut writer));
+    try!(set_permissions(to, perm));
+    Ok(ret)
+}
+
+/// Creates a new hard link on the filesystem.
+///
+/// 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: 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: 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.
+///
+/// # Errors
+///
+/// This function will return an error on failure. Failure conditions include
+/// 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: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
+    fs_imp::readlink(path.as_ref())
+}
+
+/// Create a new, empty directory at the provided path
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// fs::create_dir("/some/dir");
+/// ```
+///
+/// # Errors
+///
+/// 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: AsRef<Path>>(path: P) -> io::Result<()> {
+    fs_imp::mkdir(path.as_ref())
+}
+
+/// Recursively create a directory and all of its parent components if they
+/// are missing.
+///
+/// # Errors
+///
+/// This function will fail if any directory in the path specified by `path`
+/// does not already exist and it could not be created otherwise. The specific
+/// 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: AsRef<Path>>(path: P) -> io::Result<()> {
+    let path = path.as_ref();
+    if path == Path::new("") || path.is_dir() { return Ok(()) }
+    if let Some(p) = path.parent() { try!(create_dir_all(p)) }
+    create_dir(path)
+}
+
+/// Remove an existing, empty directory
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// fs::remove_dir("/some/dir");
+/// ```
+///
+/// # Errors
+///
+/// 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: AsRef<Path>>(path: P) -> io::Result<()> {
+    fs_imp::rmdir(path.as_ref())
+}
+
+/// Removes a directory at this path, after removing all its contents. Use
+/// carefully!
+///
+/// This function does **not** follow soft links and it will simply remove the
+/// soft link itself.
+///
+/// # Errors
+///
+/// See `file::remove_file` and `fs::remove_dir`
+#[stable(feature = "rust1", since = "1.0.0")]
+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));
+        if stat.is_dir() {
+            try!(remove_dir_all(&*child));
+        } else {
+            try!(remove_file(&*child));
+        }
+    }
+    return remove_dir(path);
+
+    #[cfg(unix)]
+    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::lstat(path) }
+    #[cfg(windows)]
+    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
+}
+
+/// Returns an iterator over the entries within a directory.
+///
+/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
+/// be encountered after an iterator is initially constructed.
+///
+/// # Examples
+///
+/// ```
+/// # #![feature(path_ext)]
+/// use std::io;
+/// use std::fs::{self, PathExt, DirEntry};
+/// use std::path::Path;
+///
+/// // one possible implementation of fs::walk_dir only visiting files
+/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> {
+///     if dir.is_dir() {
+///         for entry in try!(fs::read_dir(dir)) {
+///             let entry = try!(entry);
+///             if entry.path().is_dir() {
+///                 try!(visit_dirs(&entry.path(), cb));
+///             } else {
+///                 cb(entry);
+///             }
+///         }
+///     }
+///     Ok(())
+/// }
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the provided `path` doesn't exist, if
+/// 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: 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
+/// rooted at `path`.
+///
+/// The path given will not be iterated over, and this will perform iteration in
+/// some top-down order.  The contents of unreadable subdirectories are ignored.
+///
+/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
+/// be encountered after an iterator is initially constructed.
+#[unstable(feature = "fs_walk",
+           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: AsRef<Path>>(path: P) -> io::Result<WalkDir> {
+    let start = try!(read_dir(path));
+    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
+}
+
+#[unstable(feature = "fs_walk")]
+impl Iterator for WalkDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        loop {
+            if let Some(ref mut cur) = self.cur {
+                match cur.next() {
+                    Some(Err(e)) => return Some(Err(e)),
+                    Some(Ok(next)) => {
+                        let path = next.path();
+                        if path.is_dir() {
+                            self.stack.push(read_dir(&*path));
+                        }
+                        return Some(Ok(next))
+                    }
+                    None => {}
+                }
+            }
+            self.cur = None;
+            match self.stack.pop() {
+                Some(Err(e)) => return Some(Err(e)),
+                Some(Ok(next)) => self.cur = Some(next),
+                None => return None,
+            }
+        }
+    }
+}
+
+/// Utility methods for paths.
+#[unstable(feature = "path_ext",
+           reason = "the precise set of methods exposed on this trait may \
+                     change and some methods may be removed")]
+pub trait PathExt {
+    /// Get information on the file, directory, etc at this path.
+    ///
+    /// Consult the `fs::stat` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with `file::stat`.
+    fn metadata(&self) -> io::Result<Metadata>;
+
+    /// Boolean value indicator whether the underlying file exists on the local
+    /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
+    fn exists(&self) -> bool;
+
+    /// Whether the underlying implementation (be it a file path, or something
+    /// else) points at a "regular file" on the FS. Will return false for paths
+    /// to non-existent locations or directories or other non-regular files
+    /// (named pipes, etc). Follows links when making this determination.
+    fn is_file(&self) -> bool;
+
+    /// Whether the underlying implementation (be it a file path, or something
+    /// else) is pointing at a directory in the underlying FS. Will return
+    /// false for paths to non-existent locations or if the item is not a
+    /// directory (eg files, named pipes, etc). Follows links when making this
+    /// determination.
+    fn is_dir(&self) -> bool;
+}
+
+impl PathExt for Path {
+    fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
+
+    fn exists(&self) -> bool { metadata(self).is_ok() }
+
+    fn is_file(&self) -> bool {
+        metadata(self).map(|s| s.is_file()).unwrap_or(false)
+    }
+    fn is_dir(&self) -> bool {
+        metadata(self).map(|s| s.is_dir()).unwrap_or(false)
+    }
+}
+
+/// Changes the timestamps for a file's last modification and access time.
+///
+/// The file at the path specified will have its last access time set to
+/// `atime` and its modification time set to `mtime`. The times specified should
+/// be in milliseconds.
+#[unstable(feature = "fs_time",
+           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: AsRef<Path>>(path: P, accessed: u64,
+                                 modified: u64) -> io::Result<()> {
+    fs_imp::utimes(path.as_ref(), accessed, modified)
+}
+
+/// Changes the permissions found on a file or a directory.
+///
+/// # Examples
+///
+/// ```
+/// # #![feature(fs)]
+/// # fn foo() -> std::io::Result<()> {
+/// use std::fs;
+///
+/// let mut perms = try!(fs::metadata("foo.txt")).permissions();
+/// perms.set_readonly(true);
+/// try!(fs::set_permissions("foo.txt", perms));
+/// # Ok(())
+/// # }
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the provided `path` doesn't exist, if
+/// the process lacks permissions to change the attributes of the file, or if
+/// some other I/O error is encountered.
+#[unstable(feature = "fs",
+           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: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
+    fs_imp::set_perm(path.as_ref(), perm.0)
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(deprecated)] //rand
+
+    use prelude::v1::*;
+    use io::prelude::*;
+
+    use env;
+    use fs::{self, File, OpenOptions};
+    use io::{ErrorKind, SeekFrom};
+    use path::PathBuf;
+    use path::Path as Path2;
+    use os;
+    use rand::{self, StdRng, Rng};
+    use str;
+
+    macro_rules! check { ($e:expr) => (
+        match $e {
+            Ok(t) => t,
+            Err(e) => panic!("{} failed with: {}", stringify!($e), e),
+        }
+    ) }
+
+    macro_rules! error { ($e:expr, $s:expr) => (
+        match $e {
+            Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
+            Err(ref err) => assert!(err.to_string().contains($s),
+                                    format!("`{}` did not contain `{}`", err, $s))
+        }
+    ) }
+
+    pub struct TempDir(PathBuf);
+
+    impl TempDir {
+        fn join(&self, path: &str) -> PathBuf {
+            let TempDir(ref p) = *self;
+            p.join(path)
+        }
+
+        fn path<'a>(&'a self) -> &'a Path2 {
+            let TempDir(ref p) = *self;
+            p
+        }
+    }
+
+    impl Drop for TempDir {
+        fn drop(&mut self) {
+            // Gee, seeing how we're testing the fs module I sure hope that we
+            // at least implement this correctly!
+            let TempDir(ref p) = *self;
+            check!(fs::remove_dir_all(p));
+        }
+    }
+
+    pub fn tmpdir() -> TempDir {
+        let p = env::temp_dir();
+        let ret = p.join(&format!("rust-{}", rand::random::<u32>()));
+        check!(fs::create_dir(&ret));
+        TempDir(ret)
+    }
+
+    #[test]
+    fn file_test_io_smoke_test() {
+        let message = "it's alright. have a good time";
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test.txt");
+        {
+            let mut write_stream = check!(File::create(filename));
+            check!(write_stream.write(message.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            let mut read_buf = [0; 1028];
+            let read_str = match check!(read_stream.read(&mut read_buf)) {
+                -1|0 => panic!("shouldn't happen"),
+                n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
+            };
+            assert_eq!(read_str, message);
+        }
+        check!(fs::remove_file(filename));
+    }
+
+    #[test]
+    fn invalid_path_raises() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_that_does_not_exist.txt");
+        let result = File::open(filename);
+
+        if cfg!(unix) {
+            error!(result, "o such file or directory");
+        }
+        // error!(result, "couldn't open path as file");
+        // error!(result, format!("path={}; mode=open; access=read", filename.display()));
+    }
+
+    #[test]
+    fn file_test_iounlinking_invalid_path_should_raise_condition() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt");
+
+        let result = fs::remove_file(filename);
+
+        if cfg!(unix) {
+            error!(result, "o such file or directory");
+        }
+        // error!(result, "couldn't unlink path");
+        // error!(result, format!("path={}", filename.display()));
+    }
+
+    #[test]
+    fn file_test_io_non_positional_read() {
+        let message: &str = "ten-four";
+        let mut read_mem = [0; 8];
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_positional.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(message.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            {
+                let read_buf = &mut read_mem[0..4];
+                check!(read_stream.read(read_buf));
+            }
+            {
+                let read_buf = &mut read_mem[4..8];
+                check!(read_stream.read(read_buf));
+            }
+        }
+        check!(fs::remove_file(filename));
+        let read_str = str::from_utf8(&read_mem).unwrap();
+        assert_eq!(read_str, message);
+    }
+
+    #[test]
+    fn file_test_io_seek_and_tell_smoke_test() {
+        let message = "ten-four";
+        let mut read_mem = [0; 4];
+        let set_cursor = 4 as u64;
+        let mut tell_pos_pre_read;
+        let mut tell_pos_post_read;
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(message.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            check!(read_stream.seek(SeekFrom::Start(set_cursor)));
+            tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0)));
+            check!(read_stream.read(&mut read_mem));
+            tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0)));
+        }
+        check!(fs::remove_file(filename));
+        let read_str = str::from_utf8(&read_mem).unwrap();
+        assert_eq!(read_str, &message[4..8]);
+        assert_eq!(tell_pos_pre_read, set_cursor);
+        assert_eq!(tell_pos_post_read, message.len() as u64);
+    }
+
+    #[test]
+    fn file_test_io_seek_and_write() {
+        let initial_msg =   "food-is-yummy";
+        let overwrite_msg =    "-the-bar!!";
+        let final_msg =     "foo-the-bar!!";
+        let seek_idx = 3;
+        let mut read_mem = [0; 13];
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(initial_msg.as_bytes()));
+            check!(rw_stream.seek(SeekFrom::Start(seek_idx)));
+            check!(rw_stream.write(overwrite_msg.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            check!(read_stream.read(&mut read_mem));
+        }
+        check!(fs::remove_file(filename));
+        let read_str = str::from_utf8(&read_mem).unwrap();
+        assert!(read_str == final_msg);
+    }
+
+    #[test]
+    fn file_test_io_seek_shakedown() {
+        //                   01234567890123
+        let initial_msg =   "qwer-asdf-zxcv";
+        let chunk_one: &str = "qwer";
+        let chunk_two: &str = "asdf";
+        let chunk_three: &str = "zxcv";
+        let mut read_mem = [0; 4];
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(initial_msg.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+
+            check!(read_stream.seek(SeekFrom::End(-4)));
+            check!(read_stream.read(&mut read_mem));
+            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three);
+
+            check!(read_stream.seek(SeekFrom::Current(-9)));
+            check!(read_stream.read(&mut read_mem));
+            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two);
+
+            check!(read_stream.seek(SeekFrom::Start(0)));
+            check!(read_stream.read(&mut read_mem));
+            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one);
+        }
+        check!(fs::remove_file(filename));
+    }
+
+    #[test]
+    fn file_test_stat_is_correct_on_is_file() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
+        {
+            let mut opts = OpenOptions::new();
+            let mut fs = check!(opts.read(true).write(true)
+                                    .create(true).open(filename));
+            let msg = "hw";
+            fs.write(msg.as_bytes()).unwrap();
+
+            let fstat_res = check!(fs.metadata());
+            assert!(fstat_res.is_file());
+        }
+        let stat_res_fn = check!(fs::metadata(filename));
+        assert!(stat_res_fn.is_file());
+        let stat_res_meth = check!(filename.metadata());
+        assert!(stat_res_meth.is_file());
+        check!(fs::remove_file(filename));
+    }
+
+    #[test]
+    fn file_test_stat_is_correct_on_is_dir() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_stat_correct_on_is_dir");
+        check!(fs::create_dir(filename));
+        let stat_res_fn = check!(fs::metadata(filename));
+        assert!(stat_res_fn.is_dir());
+        let stat_res_meth = check!(filename.metadata());
+        assert!(stat_res_meth.is_dir());
+        check!(fs::remove_dir(filename));
+    }
+
+    #[test]
+    fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("fileinfo_false_on_dir");
+        check!(fs::create_dir(dir));
+        assert!(dir.is_file() == false);
+        check!(fs::remove_dir(dir));
+    }
+
+    #[test]
+    fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
+        let tmpdir = tmpdir();
+        let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt");
+        check!(check!(File::create(file)).write(b"foo"));
+        assert!(file.exists());
+        check!(fs::remove_file(file));
+        assert!(!file.exists());
+    }
+
+    #[test]
+    fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("before_and_after_dir");
+        assert!(!dir.exists());
+        check!(fs::create_dir(dir));
+        assert!(dir.exists());
+        assert!(dir.is_dir());
+        check!(fs::remove_dir(dir));
+        assert!(!dir.exists());
+    }
+
+    #[test]
+    fn file_test_directoryinfo_readdir() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("di_readdir");
+        check!(fs::create_dir(dir));
+        let prefix = "foo";
+        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());
+            let msg = msg_str.as_bytes();
+            check!(w.write(msg));
+        }
+        let files = check!(fs::read_dir(dir));
+        let mut mem = [0; 4];
+        for f in files {
+            let f = f.unwrap().path();
+            {
+                let n = f.file_stem().unwrap();
+                check!(check!(File::open(&f)).read(&mut mem));
+                let read_str = str::from_utf8(&mem).unwrap();
+                let expected = format!("{}{}", prefix, n.to_str().unwrap());
+                assert_eq!(expected, read_str);
+            }
+            check!(fs::remove_file(&f));
+        }
+        check!(fs::remove_dir(dir));
+    }
+
+    #[test]
+    fn file_test_walk_dir() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("walk_dir");
+        check!(fs::create_dir(dir));
+
+        let dir1 = &dir.join("01/02/03");
+        check!(fs::create_dir_all(dir1));
+        check!(File::create(&dir1.join("04")));
+
+        let dir2 = &dir.join("11/12/13");
+        check!(fs::create_dir_all(dir2));
+        check!(File::create(&dir2.join("14")));
+
+        let files = check!(fs::walk_dir(dir));
+        let mut cur = [0; 2];
+        for f in files {
+            let f = f.unwrap().path();
+            let stem = f.file_stem().unwrap().to_str().unwrap();
+            let root = stem.as_bytes()[0] - b'0';
+            let name = stem.as_bytes()[1] - b'0';
+            assert!(cur[root as usize] < name);
+            cur[root as usize] = name;
+        }
+
+        check!(fs::remove_dir_all(dir));
+    }
+
+    #[test]
+    fn mkdir_path_already_exists_error() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("mkdir_error_twice");
+        check!(fs::create_dir(dir));
+        let e = fs::create_dir(dir).err().unwrap();
+        assert_eq!(e.kind(), ErrorKind::AlreadyExists);
+    }
+
+    #[test]
+    fn recursive_mkdir() {
+        let tmpdir = tmpdir();
+        let dir = tmpdir.join("d1/d2");
+        check!(fs::create_dir_all(&dir));
+        assert!(dir.is_dir())
+    }
+
+    #[test]
+    fn recursive_mkdir_failure() {
+        let tmpdir = tmpdir();
+        let dir = tmpdir.join("d1");
+        let file = dir.join("f1");
+
+        check!(fs::create_dir_all(&dir));
+        check!(File::create(&file));
+
+        let result = fs::create_dir_all(&file);
+
+        assert!(result.is_err());
+        // error!(result, "couldn't recursively mkdir");
+        // error!(result, "couldn't create directory");
+        // error!(result, "mode=0700");
+        // error!(result, format!("path={}", file.display()));
+    }
+
+    #[test]
+    fn recursive_mkdir_slash() {
+        check!(fs::create_dir_all(&Path2::new("/")));
+    }
+
+    // FIXME(#12795) depends on lstat to work on windows
+    #[cfg(not(windows))]
+    #[test]
+    fn recursive_rmdir() {
+        let tmpdir = tmpdir();
+        let d1 = tmpdir.join("d1");
+        let dt = d1.join("t");
+        let dtt = dt.join("t");
+        let d2 = tmpdir.join("d2");
+        let canary = d2.join("do_not_delete");
+        check!(fs::create_dir_all(&dtt));
+        check!(fs::create_dir_all(&d2));
+        check!(check!(File::create(&canary)).write(b"foo"));
+        check!(fs::soft_link(&d2, &dt.join("d2")));
+        check!(fs::remove_dir_all(&d1));
+
+        assert!(!d1.is_dir());
+        assert!(canary.exists());
+    }
+
+    #[test]
+    fn unicode_path_is_dir() {
+        assert!(Path2::new(".").is_dir());
+        assert!(!Path2::new("test/stdtest/fs.rs").is_dir());
+
+        let tmpdir = tmpdir();
+
+        let mut dirpath = tmpdir.path().to_path_buf();
+        dirpath.push(&format!("test-가一ー你好"));
+        check!(fs::create_dir(&dirpath));
+        assert!(dirpath.is_dir());
+
+        let mut filepath = dirpath;
+        filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs");
+        check!(File::create(&filepath)); // ignore return; touch only
+        assert!(!filepath.is_dir());
+        assert!(filepath.exists());
+    }
+
+    #[test]
+    fn unicode_path_exists() {
+        assert!(Path2::new(".").exists());
+        assert!(!Path2::new("test/nonexistent-bogus-path").exists());
+
+        let tmpdir = tmpdir();
+        let unicode = tmpdir.path();
+        let unicode = unicode.join(&format!("test-각丁ー再见"));
+        check!(fs::create_dir(&unicode));
+        assert!(unicode.exists());
+        assert!(!Path2::new("test/unicode-bogus-path-각丁ー再见").exists());
+    }
+
+    #[test]
+    fn copy_file_does_not_exist() {
+        let from = Path2::new("test/nonexistent-bogus-path");
+        let to = Path2::new("test/other-bogus-path");
+
+        match fs::copy(&from, &to) {
+            Ok(..) => panic!(),
+            Err(..) => {
+                assert!(!from.exists());
+                assert!(!to.exists());
+            }
+        }
+    }
+
+    #[test]
+    fn copy_file_ok() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        check!(check!(File::create(&input)).write(b"hello"));
+        check!(fs::copy(&input, &out));
+        let mut v = Vec::new();
+        check!(check!(File::open(&out)).read_to_end(&mut v));
+        assert_eq!(v, b"hello");
+
+        assert_eq!(check!(input.metadata()).permissions(),
+                   check!(out.metadata()).permissions());
+    }
+
+    #[test]
+    fn copy_file_dst_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        check!(File::create(&out));
+        match fs::copy(&*out, tmpdir.path()) {
+            Ok(..) => panic!(), Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn copy_file_dst_exists() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in");
+        let output = tmpdir.join("out");
+
+        check!(check!(File::create(&input)).write("foo".as_bytes()));
+        check!(check!(File::create(&output)).write("bar".as_bytes()));
+        check!(fs::copy(&input, &output));
+
+        let mut v = Vec::new();
+        check!(check!(File::open(&output)).read_to_end(&mut v));
+        assert_eq!(v, b"foo".to_vec());
+    }
+
+    #[test]
+    fn copy_file_src_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        match fs::copy(tmpdir.path(), &out) {
+            Ok(..) => panic!(), Err(..) => {}
+        }
+        assert!(!out.exists());
+    }
+
+    #[test]
+    fn copy_file_preserves_perm_bits() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        let attr = check!(check!(File::create(&input)).metadata());
+        let mut p = attr.permissions();
+        p.set_readonly(true);
+        check!(fs::set_permissions(&input, p));
+        check!(fs::copy(&input, &out));
+        assert!(check!(out.metadata()).permissions().readonly());
+        check!(fs::set_permissions(&input, attr.permissions()));
+        check!(fs::set_permissions(&out, attr.permissions()));
+    }
+
+    #[cfg(not(windows))] // FIXME(#10264) operation not permitted?
+    #[test]
+    fn symlinks_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        check!(check!(File::create(&input)).write("foobar".as_bytes()));
+        check!(fs::soft_link(&input, &out));
+        // if cfg!(not(windows)) {
+        //     assert_eq!(check!(lstat(&out)).kind, FileType::Symlink);
+        //     assert_eq!(check!(out.lstat()).kind, FileType::Symlink);
+        // }
+        assert_eq!(check!(fs::metadata(&out)).len(),
+                   check!(fs::metadata(&input)).len());
+        let mut v = Vec::new();
+        check!(check!(File::open(&out)).read_to_end(&mut v));
+        assert_eq!(v, b"foobar".to_vec());
+    }
+
+    #[cfg(not(windows))] // apparently windows doesn't like symlinks
+    #[test]
+    fn symlink_noexist() {
+        let tmpdir = tmpdir();
+        // symlinks can point to things that don't exist
+        check!(fs::soft_link(&tmpdir.join("foo"), &tmpdir.join("bar")));
+        assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))),
+                   tmpdir.join("foo"));
+    }
+
+    #[test]
+    fn readlink_not_symlink() {
+        let tmpdir = tmpdir();
+        match fs::read_link(tmpdir.path()) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn links_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        check!(check!(File::create(&input)).write("foobar".as_bytes()));
+        check!(fs::hard_link(&input, &out));
+        assert_eq!(check!(fs::metadata(&out)).len(),
+                   check!(fs::metadata(&input)).len());
+        assert_eq!(check!(fs::metadata(&out)).len(),
+                   check!(input.metadata()).len());
+        let mut v = Vec::new();
+        check!(check!(File::open(&out)).read_to_end(&mut v));
+        assert_eq!(v, b"foobar".to_vec());
+
+        // can't link to yourself
+        match fs::hard_link(&input, &input) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+        // can't link to something that doesn't exist
+        match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn chmod_works() {
+        let tmpdir = tmpdir();
+        let file = tmpdir.join("in.txt");
+
+        check!(File::create(&file));
+        let attr = check!(fs::metadata(&file));
+        assert!(!attr.permissions().readonly());
+        let mut p = attr.permissions();
+        p.set_readonly(true);
+        check!(fs::set_permissions(&file, p.clone()));
+        let attr = check!(fs::metadata(&file));
+        assert!(attr.permissions().readonly());
+
+        match fs::set_permissions(&tmpdir.join("foo"), p.clone()) {
+            Ok(..) => panic!("wanted an error"),
+            Err(..) => {}
+        }
+
+        p.set_readonly(false);
+        check!(fs::set_permissions(&file, p));
+    }
+
+    #[test]
+    fn sync_doesnt_kill_anything() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = check!(File::create(&path));
+        check!(file.sync_all());
+        check!(file.sync_data());
+        check!(file.write(b"foo"));
+        check!(file.sync_all());
+        check!(file.sync_data());
+    }
+
+    #[test]
+    fn truncate_works() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = check!(File::create(&path));
+        check!(file.write(b"foo"));
+        check!(file.sync_all());
+
+        // Do some simple things with truncation
+        assert_eq!(check!(file.metadata()).len(), 3);
+        check!(file.set_len(10));
+        assert_eq!(check!(file.metadata()).len(), 10);
+        check!(file.write(b"bar"));
+        check!(file.sync_all());
+        assert_eq!(check!(file.metadata()).len(), 10);
+
+        let mut v = Vec::new();
+        check!(check!(File::open(&path)).read_to_end(&mut v));
+        assert_eq!(v, b"foobar\0\0\0\0".to_vec());
+
+        // Truncate to a smaller length, don't seek, and then write something.
+        // Ensure that the intermediate zeroes are all filled in (we have `seek`ed
+        // past the end of the file).
+        check!(file.set_len(2));
+        assert_eq!(check!(file.metadata()).len(), 2);
+        check!(file.write(b"wut"));
+        check!(file.sync_all());
+        assert_eq!(check!(file.metadata()).len(), 9);
+        let mut v = Vec::new();
+        check!(check!(File::open(&path)).read_to_end(&mut v));
+        assert_eq!(v, b"fo\0\0\0\0wut".to_vec());
+    }
+
+    #[test]
+    fn open_flavors() {
+        use fs::OpenOptions as OO;
+        fn c<T: Clone>(t: &T) -> T { t.clone() }
+
+        let tmpdir = tmpdir();
+
+        let mut r = OO::new(); r.read(true);
+        let mut w = OO::new(); w.write(true);
+        let mut rw = OO::new(); rw.write(true).read(true);
+
+        match r.open(&tmpdir.join("a")) {
+            Ok(..) => panic!(), Err(..) => {}
+        }
+
+        // Perform each one twice to make sure that it succeeds the second time
+        // (where the file exists)
+        check!(c(&w).create(true).open(&tmpdir.join("b")));
+        assert!(tmpdir.join("b").exists());
+        check!(c(&w).create(true).open(&tmpdir.join("b")));
+        check!(w.open(&tmpdir.join("b")));
+
+        check!(c(&rw).create(true).open(&tmpdir.join("c")));
+        assert!(tmpdir.join("c").exists());
+        check!(c(&rw).create(true).open(&tmpdir.join("c")));
+        check!(rw.open(&tmpdir.join("c")));
+
+        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
+        assert!(tmpdir.join("d").exists());
+        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
+        check!(c(&w).append(true).open(&tmpdir.join("d")));
+
+        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
+        assert!(tmpdir.join("e").exists());
+        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
+        check!(c(&rw).append(true).open(&tmpdir.join("e")));
+
+        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
+        assert!(tmpdir.join("f").exists());
+        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
+        check!(c(&w).truncate(true).open(&tmpdir.join("f")));
+
+        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
+        assert!(tmpdir.join("g").exists());
+        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
+        check!(c(&rw).truncate(true).open(&tmpdir.join("g")));
+
+        check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes()));
+        check!(r.open(&tmpdir.join("h")));
+        {
+            let mut f = check!(r.open(&tmpdir.join("h")));
+            assert!(f.write("wut".as_bytes()).is_err());
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+        {
+            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
+            check!(f.write("bar".as_bytes()));
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
+        {
+            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
+            check!(f.write("bar".as_bytes()));
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+    }
+
+    #[test]
+    fn utime() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("a");
+        check!(File::create(&path));
+        // These numbers have to be bigger than the time in the day to account
+        // for timezones Windows in particular will fail in certain timezones
+        // with small enough values
+        check!(fs::set_file_times(&path, 100000, 200000));
+        assert_eq!(check!(path.metadata()).accessed(), 100000);
+        assert_eq!(check!(path.metadata()).modified(), 200000);
+    }
+
+    #[test]
+    fn utime_noexist() {
+        let tmpdir = tmpdir();
+
+        match fs::set_file_times(&tmpdir.join("a"), 100, 200) {
+            Ok(..) => panic!(),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn binary_file() {
+        let mut bytes = [0; 1024];
+        StdRng::new().unwrap().fill_bytes(&mut bytes);
+
+        let tmpdir = tmpdir();
+
+        check!(check!(File::create(&tmpdir.join("test"))).write(&bytes));
+        let mut v = Vec::new();
+        check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v));
+        assert!(v == &bytes[..]);
+    }
+
+    #[test]
+    #[cfg(not(windows))]
+    fn unlink_readonly() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("file");
+        check!(File::create(&path));
+        let mut perm = check!(fs::metadata(&path)).permissions();
+        perm.set_readonly(true);
+        check!(fs::set_permissions(&path, perm));
+        check!(fs::remove_file(&path));
+    }
+
+    #[test]
+    fn mkdir_trailing_slash() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("file");
+        check!(fs::create_dir_all(&path.join("a/")));
+    }
+}
diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs
deleted file mode 100644 (file)
index a3128ef..0000000
+++ /dev/null
@@ -1,1646 +0,0 @@
-// 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.
-
-//! Filesystem manipulation operations
-//!
-//! This module contains basic methods to manipulate the contents of the local
-//! filesystem. All methods in this module represent cross-platform filesystem
-//! operations. Extra platform-specific functionality can be found in the
-//! extension traits of `std::os::$platform`.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use core::prelude::*;
-
-use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
-use path::{Path, PathBuf};
-use sys::fs2 as fs_imp;
-use sys_common::{AsInnerMut, FromInner, AsInner};
-use vec::Vec;
-
-#[allow(deprecated)]
-pub use self::tempdir::TempDir;
-
-mod tempdir;
-
-/// A reference to an open file on the filesystem.
-///
-/// An instance of a `File` can be read and/or written depending on what options
-/// it was opened with. Files also implement `Seek` to alter the logical cursor
-/// that the file contains internally.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::io::prelude::*;
-/// use std::fs::File;
-///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut f = try!(File::create("foo.txt"));
-/// try!(f.write_all(b"Hello, world!"));
-///
-/// let mut f = try!(File::open("foo.txt"));
-/// let mut s = String::new();
-/// try!(f.read_to_string(&mut s));
-/// assert_eq!(s, "Hello, world!");
-/// # Ok(())
-/// # }
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct File {
-    inner: fs_imp::File,
-    path: PathBuf,
-}
-
-/// Metadata information about a file.
-///
-/// This structure is returned from the `metadata` function or method and
-/// represents known metadata about a file such as its permissions, size,
-/// modification times, etc.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Metadata(fs_imp::FileAttr);
-
-/// Iterator over the entries in a directory.
-///
-/// This iterator is returned from the `read_dir` function of this module and
-/// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
-/// information like the entry's path and possibly other metadata can be
-/// learned.
-///
-/// # Failure
-///
-/// This `io::Result` will be an `Err` if there's some sort of intermittent
-/// IO error during iteration.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct ReadDir(fs_imp::ReadDir);
-
-/// Entries returned by the `ReadDir` iterator.
-///
-/// An instance of `DirEntry` represents an entry inside of a directory on the
-/// filesystem. Each entry can be inspected via methods to learn about the full
-/// path or possibly other metadata through per-platform extension traits.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct DirEntry(fs_imp::DirEntry);
-
-/// An iterator that recursively walks over the contents of a directory.
-#[unstable(feature = "fs_walk",
-           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 struct WalkDir {
-    cur: Option<ReadDir>,
-    stack: Vec<io::Result<ReadDir>>,
-}
-
-/// Options and flags which can be used to configure how a file is opened.
-///
-/// This builder exposes the ability to configure how a `File` is opened and
-/// what operations are permitted on the open file. The `File::open` and
-/// `File::create` methods are aliases for commonly used options using this
-/// builder.
-#[derive(Clone)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct OpenOptions(fs_imp::OpenOptions);
-
-/// Representation of the various permissions on a file.
-///
-/// This module only currently provides one bit of information, `readonly`,
-/// which is exposed on all currently supported platforms. Unix-specific
-/// functionality, such as mode bits, is available through the
-/// `os::unix::PermissionsExt` trait.
-#[derive(Clone, PartialEq, Eq, Debug)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Permissions(fs_imp::FilePermissions);
-
-impl File {
-    /// Attempts to open a file in read-only mode.
-    ///
-    /// See the `OpenOptions::open` method for more details.
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if `path` does not already exist.
-    /// Other errors may also be returned according to `OpenOptions::open`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = try!(File::open("foo.txt"));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
-        OpenOptions::new().read(true).open(path)
-    }
-
-    /// Open a file in write-only mode.
-    ///
-    /// This function will create a file if it does not exist,
-    /// and will truncate it if it does.
-    ///
-    /// See the `OpenOptions::open` function for more details.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = try!(File::create("foo.txt"));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
-        OpenOptions::new().write(true).create(true).truncate(true).open(path)
-    }
-
-    /// Returns the original path that was used to open this file.
-    #[unstable(feature = "file_path",
-               reason = "this abstraction is imposed by this library instead \
-                         of the underlying OS and may be removed")]
-    pub fn path(&self) -> Option<&Path> {
-        Some(&self.path)
-    }
-
-    /// Attempt to sync all OS-internal metadata to disk.
-    ///
-    /// This function will attempt to ensure that all in-core data reaches the
-    /// filesystem before returning.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::prelude::*;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = try!(File::create("foo.txt"));
-    /// try!(f.write_all(b"Hello, world!"));
-    ///
-    /// try!(f.sync_all());
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn sync_all(&self) -> io::Result<()> {
-        self.inner.fsync()
-    }
-
-    /// This function is similar to `sync_all`, except that it may not
-    /// synchronize file metadata to the filesystem.
-    ///
-    /// This is intended for use cases that must synchronize content, but don't
-    /// need the metadata on disk. The goal of this method is to reduce disk
-    /// operations.
-    ///
-    /// Note that some platforms may simply implement this in terms of
-    /// `sync_all`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    /// use std::io::prelude::*;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = try!(File::create("foo.txt"));
-    /// try!(f.write_all(b"Hello, world!"));
-    ///
-    /// try!(f.sync_data());
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn sync_data(&self) -> io::Result<()> {
-        self.inner.datasync()
-    }
-
-    /// Truncates or extends the underlying file, updating the size of
-    /// this file to become `size`.
-    ///
-    /// If the `size` is less than the current file's size, then the file will
-    /// be shrunk. If it is greater than the current file's size, then the file
-    /// will be extended to `size` and have all of the intermediate data filled
-    /// in with 0s.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = try!(File::open("foo.txt"));
-    /// try!(f.set_len(0));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn set_len(&self, size: u64) -> io::Result<()> {
-        self.inner.truncate(size)
-    }
-
-    /// Queries metadata about the underlying file.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::fs::File;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// let mut f = try!(File::open("foo.txt"));
-    /// let metadata = try!(f.metadata());
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn metadata(&self) -> io::Result<Metadata> {
-        self.inner.file_attr().map(Metadata)
-    }
-}
-
-impl AsInner<fs_imp::File> for File {
-    fn as_inner(&self) -> &fs_imp::File { &self.inner }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Read for File {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Write for File {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.inner.write(buf)
-    }
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Seek for File {
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.inner.seek(pos)
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Read for &'a File {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Write for &'a File {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.inner.write(buf)
-    }
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Seek for &'a File {
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.inner.seek(pos)
-    }
-}
-
-impl OpenOptions {
-    /// Creates a blank net set of options ready for configuration.
-    ///
-    /// All options are initially set to `false`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> OpenOptions {
-        OpenOptions(fs_imp::OpenOptions::new())
-    }
-
-    /// Set the option for read access.
-    ///
-    /// This option, when true, will indicate that the file should be
-    /// `read`-able if opened.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn read(&mut self, read: bool) -> &mut OpenOptions {
-        self.0.read(read); self
-    }
-
-    /// Set the option for write access.
-    ///
-    /// This option, when true, will indicate that the file should be
-    /// `write`-able if opened.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn write(&mut self, write: bool) -> &mut OpenOptions {
-        self.0.write(write); self
-    }
-
-    /// Set the option for the append mode.
-    ///
-    /// This option, when true, means that writes will append to a file instead
-    /// of overwriting previous contents.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn append(&mut self, append: bool) -> &mut OpenOptions {
-        self.0.append(append); self
-    }
-
-    /// Set the option for truncating a previous file.
-    ///
-    /// If a file is successfully opened with this option set it will truncate
-    /// the file to 0 length if it already exists.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
-        self.0.truncate(truncate); self
-    }
-
-    /// Set the option for creating a new file.
-    ///
-    /// This option indicates whether a new file will be created if the file
-    /// does not yet already exist.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn create(&mut self, create: bool) -> &mut OpenOptions {
-        self.0.create(create); self
-    }
-
-    /// Open a file at `path` with the options specified by `self`.
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error under a number of different
-    /// circumstances, to include but not limited to:
-    ///
-    /// * Opening a file that does not exist with read access.
-    /// * Attempting to open a file with access that the user lacks
-    ///   permissions for
-    /// * Filesystem-level errors (full disk, etc)
-    #[stable(feature = "rust1", since = "1.0.0")]
-    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 })
-    }
-}
-
-impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
-    fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
-}
-
-impl Metadata {
-    /// Returns whether this metadata is for a directory.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_dir(&self) -> bool { self.0.is_dir() }
-
-    /// Returns whether this metadata is for a regular file.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_file(&self) -> bool { self.0.is_file() }
-
-    /// Returns the size of the file, in bytes, this metadata is for.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn len(&self) -> u64 { self.0.size() }
-
-    /// Returns the permissions of the file this metadata is for.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn permissions(&self) -> Permissions {
-        Permissions(self.0.perm())
-    }
-
-    /// Returns the most recent access time for a file.
-    ///
-    /// The return value is in milliseconds since the epoch.
-    #[unstable(feature = "fs_time",
-               reason = "the return type of u64 is not quite appropriate for \
-                         this method and may change if the standard library \
-                         gains a type to represent a moment in time")]
-    pub fn accessed(&self) -> u64 { self.0.accessed() }
-
-    /// Returns the most recent modification time for a file.
-    ///
-    /// The return value is in milliseconds since the epoch.
-    #[unstable(feature = "fs_time",
-               reason = "the return type of u64 is not quite appropriate for \
-                         this method and may change if the standard library \
-                         gains a type to represent a moment in time")]
-    pub fn modified(&self) -> u64 { self.0.modified() }
-}
-
-impl Permissions {
-    /// Returns whether these permissions describe a readonly file.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn readonly(&self) -> bool { self.0.readonly() }
-
-    /// Modify the readonly flag for this set of permissions.
-    ///
-    /// This operation does **not** modify the filesystem. To modify the
-    /// filesystem use the `fs::set_permissions` function.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn set_readonly(&mut self, readonly: bool) {
-        self.0.set_readonly(readonly)
-    }
-}
-
-impl FromInner<fs_imp::FilePermissions> for Permissions {
-    fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
-        Permissions(f)
-    }
-}
-
-impl AsInner<fs_imp::FilePermissions> for Permissions {
-    fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        self.0.next().map(|entry| entry.map(DirEntry))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl DirEntry {
-    /// Returns the full path to the file that this entry represents.
-    ///
-    /// The full path is created by joining the original path to `read_dir` or
-    /// `walk_dir` with the filename of this entry.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn path(&self) -> PathBuf { self.0.path() }
-}
-
-/// Remove a file from the underlying filesystem.
-///
-/// # Examples
-///
-/// ```rust,no_run
-/// use std::fs;
-///
-/// fs::remove_file("/some/file/path.txt");
-/// ```
-///
-/// Note that, just because an unlink call was successful, it is not
-/// guaranteed that a file is immediately deleted (e.g. depending on
-/// platform, other open file descriptors may prevent immediate removal).
-///
-/// # Errors
-///
-/// This function will return an error if `path` points to a directory, if the
-/// 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: 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,
-/// directory, etc.
-///
-/// This function will traverse soft links to query information about the
-/// destination file.
-///
-/// # Examples
-///
-/// ```rust,no_run
-/// # fn foo() -> std::io::Result<()> {
-/// use std::fs;
-///
-/// let attr = try!(fs::metadata("/some/file/path.txt"));
-/// // inspect attr ...
-/// # Ok(())
-/// # }
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the user lacks the requisite
-/// 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: AsRef<Path>>(path: P) -> io::Result<Metadata> {
-    fs_imp::stat(path.as_ref()).map(Metadata)
-}
-
-/// Rename a file or directory to a new name.
-///
-/// # Examples
-///
-/// ```rust,no_run
-/// use std::fs;
-///
-/// fs::rename("foo", "bar");
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the provided `from` doesn't exist, if
-/// the process lacks permissions to view the contents, if `from` and `to`
-/// reside on separate filesystems, or if some other intermittent I/O error
-/// occurs.
-#[stable(feature = "rust1", since = "1.0.0")]
-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
-/// copy the permission bits of the original file to the destination file.
-///
-/// This function will **overwrite** the contents of `to`.
-///
-/// Note that if `from` and `to` both point to the same file, then the file
-/// will likely get truncated by this operation.
-///
-/// # Examples
-///
-/// ```
-/// use std::fs;
-///
-/// fs::copy("foo.txt", "bar.txt");
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error in the following situations, but is not
-/// limited to just these cases:
-///
-/// * The `from` path is not a file
-/// * The `from` file does not exist
-/// * 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: 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",
-                              None))
-    }
-
-    let mut reader = try!(File::open(from));
-    let mut writer = try!(File::create(to));
-    let perm = try!(reader.metadata()).permissions();
-
-    let ret = try!(io::copy(&mut reader, &mut writer));
-    try!(set_permissions(to, perm));
-    Ok(ret)
-}
-
-/// Creates a new hard link on the filesystem.
-///
-/// 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: 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: 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.
-///
-/// # Errors
-///
-/// This function will return an error on failure. Failure conditions include
-/// 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: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
-    fs_imp::readlink(path.as_ref())
-}
-
-/// Create a new, empty directory at the provided path
-///
-/// # Examples
-///
-/// ```
-/// use std::fs;
-///
-/// fs::create_dir("/some/dir");
-/// ```
-///
-/// # Errors
-///
-/// 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: AsRef<Path>>(path: P) -> io::Result<()> {
-    fs_imp::mkdir(path.as_ref())
-}
-
-/// Recursively create a directory and all of its parent components if they
-/// are missing.
-///
-/// # Errors
-///
-/// This function will fail if any directory in the path specified by `path`
-/// does not already exist and it could not be created otherwise. The specific
-/// 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: AsRef<Path>>(path: P) -> io::Result<()> {
-    let path = path.as_ref();
-    if path == Path::new("") || path.is_dir() { return Ok(()) }
-    if let Some(p) = path.parent() { try!(create_dir_all(p)) }
-    create_dir(path)
-}
-
-/// Remove an existing, empty directory
-///
-/// # Examples
-///
-/// ```
-/// use std::fs;
-///
-/// fs::remove_dir("/some/dir");
-/// ```
-///
-/// # Errors
-///
-/// 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: AsRef<Path>>(path: P) -> io::Result<()> {
-    fs_imp::rmdir(path.as_ref())
-}
-
-/// Removes a directory at this path, after removing all its contents. Use
-/// carefully!
-///
-/// This function does **not** follow soft links and it will simply remove the
-/// soft link itself.
-///
-/// # Errors
-///
-/// See `file::remove_file` and `fs::remove_dir`
-#[stable(feature = "rust1", since = "1.0.0")]
-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));
-        if stat.is_dir() {
-            try!(remove_dir_all(&*child));
-        } else {
-            try!(remove_file(&*child));
-        }
-    }
-    return remove_dir(path);
-
-    #[cfg(unix)]
-    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::lstat(path) }
-    #[cfg(windows)]
-    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
-}
-
-/// Returns an iterator over the entries within a directory.
-///
-/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
-/// be encountered after an iterator is initially constructed.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(path_ext)]
-/// use std::io;
-/// use std::fs::{self, PathExt, DirEntry};
-/// use std::path::Path;
-///
-/// // one possible implementation of fs::walk_dir only visiting files
-/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> {
-///     if dir.is_dir() {
-///         for entry in try!(fs::read_dir(dir)) {
-///             let entry = try!(entry);
-///             if entry.path().is_dir() {
-///                 try!(visit_dirs(&entry.path(), cb));
-///             } else {
-///                 cb(entry);
-///             }
-///         }
-///     }
-///     Ok(())
-/// }
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the provided `path` doesn't exist, if
-/// 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: 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
-/// rooted at `path`.
-///
-/// The path given will not be iterated over, and this will perform iteration in
-/// some top-down order.  The contents of unreadable subdirectories are ignored.
-///
-/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
-/// be encountered after an iterator is initially constructed.
-#[unstable(feature = "fs_walk",
-           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: AsRef<Path>>(path: P) -> io::Result<WalkDir> {
-    let start = try!(read_dir(path));
-    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
-}
-
-#[unstable(feature = "fs_walk")]
-impl Iterator for WalkDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        loop {
-            if let Some(ref mut cur) = self.cur {
-                match cur.next() {
-                    Some(Err(e)) => return Some(Err(e)),
-                    Some(Ok(next)) => {
-                        let path = next.path();
-                        if path.is_dir() {
-                            self.stack.push(read_dir(&*path));
-                        }
-                        return Some(Ok(next))
-                    }
-                    None => {}
-                }
-            }
-            self.cur = None;
-            match self.stack.pop() {
-                Some(Err(e)) => return Some(Err(e)),
-                Some(Ok(next)) => self.cur = Some(next),
-                None => return None,
-            }
-        }
-    }
-}
-
-/// Utility methods for paths.
-#[unstable(feature = "path_ext",
-           reason = "the precise set of methods exposed on this trait may \
-                     change and some methods may be removed")]
-pub trait PathExt {
-    /// Get information on the file, directory, etc at this path.
-    ///
-    /// Consult the `fs::stat` documentation for more info.
-    ///
-    /// This call preserves identical runtime/error semantics with `file::stat`.
-    fn metadata(&self) -> io::Result<Metadata>;
-
-    /// Boolean value indicator whether the underlying file exists on the local
-    /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
-    fn exists(&self) -> bool;
-
-    /// Whether the underlying implementation (be it a file path, or something
-    /// else) points at a "regular file" on the FS. Will return false for paths
-    /// to non-existent locations or directories or other non-regular files
-    /// (named pipes, etc). Follows links when making this determination.
-    fn is_file(&self) -> bool;
-
-    /// Whether the underlying implementation (be it a file path, or something
-    /// else) is pointing at a directory in the underlying FS. Will return
-    /// false for paths to non-existent locations or if the item is not a
-    /// directory (eg files, named pipes, etc). Follows links when making this
-    /// determination.
-    fn is_dir(&self) -> bool;
-}
-
-impl PathExt for Path {
-    fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
-
-    fn exists(&self) -> bool { metadata(self).is_ok() }
-
-    fn is_file(&self) -> bool {
-        metadata(self).map(|s| s.is_file()).unwrap_or(false)
-    }
-    fn is_dir(&self) -> bool {
-        metadata(self).map(|s| s.is_dir()).unwrap_or(false)
-    }
-}
-
-/// Changes the timestamps for a file's last modification and access time.
-///
-/// The file at the path specified will have its last access time set to
-/// `atime` and its modification time set to `mtime`. The times specified should
-/// be in milliseconds.
-#[unstable(feature = "fs_time",
-           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: AsRef<Path>>(path: P, accessed: u64,
-                                 modified: u64) -> io::Result<()> {
-    fs_imp::utimes(path.as_ref(), accessed, modified)
-}
-
-/// Changes the permissions found on a file or a directory.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(fs)]
-/// # fn foo() -> std::io::Result<()> {
-/// use std::fs;
-///
-/// let mut perms = try!(fs::metadata("foo.txt")).permissions();
-/// perms.set_readonly(true);
-/// try!(fs::set_permissions("foo.txt", perms));
-/// # Ok(())
-/// # }
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the provided `path` doesn't exist, if
-/// the process lacks permissions to change the attributes of the file, or if
-/// some other I/O error is encountered.
-#[unstable(feature = "fs",
-           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: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
-    fs_imp::set_perm(path.as_ref(), perm.0)
-}
-
-#[cfg(test)]
-mod tests {
-    #![allow(deprecated)] //rand
-
-    use prelude::v1::*;
-    use io::prelude::*;
-
-    use env;
-    use fs::{self, File, OpenOptions};
-    use io::{ErrorKind, SeekFrom};
-    use path::PathBuf;
-    use path::Path as Path2;
-    use os;
-    use rand::{self, StdRng, Rng};
-    use str;
-
-    macro_rules! check { ($e:expr) => (
-        match $e {
-            Ok(t) => t,
-            Err(e) => panic!("{} failed with: {}", stringify!($e), e),
-        }
-    ) }
-
-    macro_rules! error { ($e:expr, $s:expr) => (
-        match $e {
-            Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
-            Err(ref err) => assert!(err.to_string().contains($s),
-                                    format!("`{}` did not contain `{}`", err, $s))
-        }
-    ) }
-
-    pub struct TempDir(PathBuf);
-
-    impl TempDir {
-        fn join(&self, path: &str) -> PathBuf {
-            let TempDir(ref p) = *self;
-            p.join(path)
-        }
-
-        fn path<'a>(&'a self) -> &'a Path2 {
-            let TempDir(ref p) = *self;
-            p
-        }
-    }
-
-    impl Drop for TempDir {
-        fn drop(&mut self) {
-            // Gee, seeing how we're testing the fs module I sure hope that we
-            // at least implement this correctly!
-            let TempDir(ref p) = *self;
-            check!(fs::remove_dir_all(p));
-        }
-    }
-
-    pub fn tmpdir() -> TempDir {
-        let p = env::temp_dir();
-        let ret = p.join(&format!("rust-{}", rand::random::<u32>()));
-        check!(fs::create_dir(&ret));
-        TempDir(ret)
-    }
-
-    #[test]
-    fn file_test_io_smoke_test() {
-        let message = "it's alright. have a good time";
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test.txt");
-        {
-            let mut write_stream = check!(File::create(filename));
-            check!(write_stream.write(message.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            let mut read_buf = [0; 1028];
-            let read_str = match check!(read_stream.read(&mut read_buf)) {
-                -1|0 => panic!("shouldn't happen"),
-                n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
-            };
-            assert_eq!(read_str, message);
-        }
-        check!(fs::remove_file(filename));
-    }
-
-    #[test]
-    fn invalid_path_raises() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_that_does_not_exist.txt");
-        let result = File::open(filename);
-
-        if cfg!(unix) {
-            error!(result, "o such file or directory");
-        }
-        // error!(result, "couldn't open path as file");
-        // error!(result, format!("path={}; mode=open; access=read", filename.display()));
-    }
-
-    #[test]
-    fn file_test_iounlinking_invalid_path_should_raise_condition() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt");
-
-        let result = fs::remove_file(filename);
-
-        if cfg!(unix) {
-            error!(result, "o such file or directory");
-        }
-        // error!(result, "couldn't unlink path");
-        // error!(result, format!("path={}", filename.display()));
-    }
-
-    #[test]
-    fn file_test_io_non_positional_read() {
-        let message: &str = "ten-four";
-        let mut read_mem = [0; 8];
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_positional.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(message.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            {
-                let read_buf = &mut read_mem[0..4];
-                check!(read_stream.read(read_buf));
-            }
-            {
-                let read_buf = &mut read_mem[4..8];
-                check!(read_stream.read(read_buf));
-            }
-        }
-        check!(fs::remove_file(filename));
-        let read_str = str::from_utf8(&read_mem).unwrap();
-        assert_eq!(read_str, message);
-    }
-
-    #[test]
-    fn file_test_io_seek_and_tell_smoke_test() {
-        let message = "ten-four";
-        let mut read_mem = [0; 4];
-        let set_cursor = 4 as u64;
-        let mut tell_pos_pre_read;
-        let mut tell_pos_post_read;
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(message.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            check!(read_stream.seek(SeekFrom::Start(set_cursor)));
-            tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0)));
-            check!(read_stream.read(&mut read_mem));
-            tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0)));
-        }
-        check!(fs::remove_file(filename));
-        let read_str = str::from_utf8(&read_mem).unwrap();
-        assert_eq!(read_str, &message[4..8]);
-        assert_eq!(tell_pos_pre_read, set_cursor);
-        assert_eq!(tell_pos_post_read, message.len() as u64);
-    }
-
-    #[test]
-    fn file_test_io_seek_and_write() {
-        let initial_msg =   "food-is-yummy";
-        let overwrite_msg =    "-the-bar!!";
-        let final_msg =     "foo-the-bar!!";
-        let seek_idx = 3;
-        let mut read_mem = [0; 13];
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(initial_msg.as_bytes()));
-            check!(rw_stream.seek(SeekFrom::Start(seek_idx)));
-            check!(rw_stream.write(overwrite_msg.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            check!(read_stream.read(&mut read_mem));
-        }
-        check!(fs::remove_file(filename));
-        let read_str = str::from_utf8(&read_mem).unwrap();
-        assert!(read_str == final_msg);
-    }
-
-    #[test]
-    fn file_test_io_seek_shakedown() {
-        //                   01234567890123
-        let initial_msg =   "qwer-asdf-zxcv";
-        let chunk_one: &str = "qwer";
-        let chunk_two: &str = "asdf";
-        let chunk_three: &str = "zxcv";
-        let mut read_mem = [0; 4];
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(initial_msg.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-
-            check!(read_stream.seek(SeekFrom::End(-4)));
-            check!(read_stream.read(&mut read_mem));
-            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three);
-
-            check!(read_stream.seek(SeekFrom::Current(-9)));
-            check!(read_stream.read(&mut read_mem));
-            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two);
-
-            check!(read_stream.seek(SeekFrom::Start(0)));
-            check!(read_stream.read(&mut read_mem));
-            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one);
-        }
-        check!(fs::remove_file(filename));
-    }
-
-    #[test]
-    fn file_test_stat_is_correct_on_is_file() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
-        {
-            let mut opts = OpenOptions::new();
-            let mut fs = check!(opts.read(true).write(true)
-                                    .create(true).open(filename));
-            let msg = "hw";
-            fs.write(msg.as_bytes()).unwrap();
-
-            let fstat_res = check!(fs.metadata());
-            assert!(fstat_res.is_file());
-        }
-        let stat_res_fn = check!(fs::metadata(filename));
-        assert!(stat_res_fn.is_file());
-        let stat_res_meth = check!(filename.metadata());
-        assert!(stat_res_meth.is_file());
-        check!(fs::remove_file(filename));
-    }
-
-    #[test]
-    fn file_test_stat_is_correct_on_is_dir() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_stat_correct_on_is_dir");
-        check!(fs::create_dir(filename));
-        let stat_res_fn = check!(fs::metadata(filename));
-        assert!(stat_res_fn.is_dir());
-        let stat_res_meth = check!(filename.metadata());
-        assert!(stat_res_meth.is_dir());
-        check!(fs::remove_dir(filename));
-    }
-
-    #[test]
-    fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("fileinfo_false_on_dir");
-        check!(fs::create_dir(dir));
-        assert!(dir.is_file() == false);
-        check!(fs::remove_dir(dir));
-    }
-
-    #[test]
-    fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
-        let tmpdir = tmpdir();
-        let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt");
-        check!(check!(File::create(file)).write(b"foo"));
-        assert!(file.exists());
-        check!(fs::remove_file(file));
-        assert!(!file.exists());
-    }
-
-    #[test]
-    fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("before_and_after_dir");
-        assert!(!dir.exists());
-        check!(fs::create_dir(dir));
-        assert!(dir.exists());
-        assert!(dir.is_dir());
-        check!(fs::remove_dir(dir));
-        assert!(!dir.exists());
-    }
-
-    #[test]
-    fn file_test_directoryinfo_readdir() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("di_readdir");
-        check!(fs::create_dir(dir));
-        let prefix = "foo";
-        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());
-            let msg = msg_str.as_bytes();
-            check!(w.write(msg));
-        }
-        let files = check!(fs::read_dir(dir));
-        let mut mem = [0; 4];
-        for f in files {
-            let f = f.unwrap().path();
-            {
-                let n = f.file_stem().unwrap();
-                check!(check!(File::open(&f)).read(&mut mem));
-                let read_str = str::from_utf8(&mem).unwrap();
-                let expected = format!("{}{}", prefix, n.to_str().unwrap());
-                assert_eq!(expected, read_str);
-            }
-            check!(fs::remove_file(&f));
-        }
-        check!(fs::remove_dir(dir));
-    }
-
-    #[test]
-    fn file_test_walk_dir() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("walk_dir");
-        check!(fs::create_dir(dir));
-
-        let dir1 = &dir.join("01/02/03");
-        check!(fs::create_dir_all(dir1));
-        check!(File::create(&dir1.join("04")));
-
-        let dir2 = &dir.join("11/12/13");
-        check!(fs::create_dir_all(dir2));
-        check!(File::create(&dir2.join("14")));
-
-        let files = check!(fs::walk_dir(dir));
-        let mut cur = [0; 2];
-        for f in files {
-            let f = f.unwrap().path();
-            let stem = f.file_stem().unwrap().to_str().unwrap();
-            let root = stem.as_bytes()[0] - b'0';
-            let name = stem.as_bytes()[1] - b'0';
-            assert!(cur[root as usize] < name);
-            cur[root as usize] = name;
-        }
-
-        check!(fs::remove_dir_all(dir));
-    }
-
-    #[test]
-    fn mkdir_path_already_exists_error() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("mkdir_error_twice");
-        check!(fs::create_dir(dir));
-        let e = fs::create_dir(dir).err().unwrap();
-        assert_eq!(e.kind(), ErrorKind::AlreadyExists);
-    }
-
-    #[test]
-    fn recursive_mkdir() {
-        let tmpdir = tmpdir();
-        let dir = tmpdir.join("d1/d2");
-        check!(fs::create_dir_all(&dir));
-        assert!(dir.is_dir())
-    }
-
-    #[test]
-    fn recursive_mkdir_failure() {
-        let tmpdir = tmpdir();
-        let dir = tmpdir.join("d1");
-        let file = dir.join("f1");
-
-        check!(fs::create_dir_all(&dir));
-        check!(File::create(&file));
-
-        let result = fs::create_dir_all(&file);
-
-        assert!(result.is_err());
-        // error!(result, "couldn't recursively mkdir");
-        // error!(result, "couldn't create directory");
-        // error!(result, "mode=0700");
-        // error!(result, format!("path={}", file.display()));
-    }
-
-    #[test]
-    fn recursive_mkdir_slash() {
-        check!(fs::create_dir_all(&Path2::new("/")));
-    }
-
-    // FIXME(#12795) depends on lstat to work on windows
-    #[cfg(not(windows))]
-    #[test]
-    fn recursive_rmdir() {
-        let tmpdir = tmpdir();
-        let d1 = tmpdir.join("d1");
-        let dt = d1.join("t");
-        let dtt = dt.join("t");
-        let d2 = tmpdir.join("d2");
-        let canary = d2.join("do_not_delete");
-        check!(fs::create_dir_all(&dtt));
-        check!(fs::create_dir_all(&d2));
-        check!(check!(File::create(&canary)).write(b"foo"));
-        check!(fs::soft_link(&d2, &dt.join("d2")));
-        check!(fs::remove_dir_all(&d1));
-
-        assert!(!d1.is_dir());
-        assert!(canary.exists());
-    }
-
-    #[test]
-    fn unicode_path_is_dir() {
-        assert!(Path2::new(".").is_dir());
-        assert!(!Path2::new("test/stdtest/fs.rs").is_dir());
-
-        let tmpdir = tmpdir();
-
-        let mut dirpath = tmpdir.path().to_path_buf();
-        dirpath.push(&format!("test-가一ー你好"));
-        check!(fs::create_dir(&dirpath));
-        assert!(dirpath.is_dir());
-
-        let mut filepath = dirpath;
-        filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs");
-        check!(File::create(&filepath)); // ignore return; touch only
-        assert!(!filepath.is_dir());
-        assert!(filepath.exists());
-    }
-
-    #[test]
-    fn unicode_path_exists() {
-        assert!(Path2::new(".").exists());
-        assert!(!Path2::new("test/nonexistent-bogus-path").exists());
-
-        let tmpdir = tmpdir();
-        let unicode = tmpdir.path();
-        let unicode = unicode.join(&format!("test-각丁ー再见"));
-        check!(fs::create_dir(&unicode));
-        assert!(unicode.exists());
-        assert!(!Path2::new("test/unicode-bogus-path-각丁ー再见").exists());
-    }
-
-    #[test]
-    fn copy_file_does_not_exist() {
-        let from = Path2::new("test/nonexistent-bogus-path");
-        let to = Path2::new("test/other-bogus-path");
-
-        match fs::copy(&from, &to) {
-            Ok(..) => panic!(),
-            Err(..) => {
-                assert!(!from.exists());
-                assert!(!to.exists());
-            }
-        }
-    }
-
-    #[test]
-    fn copy_file_ok() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        check!(check!(File::create(&input)).write(b"hello"));
-        check!(fs::copy(&input, &out));
-        let mut v = Vec::new();
-        check!(check!(File::open(&out)).read_to_end(&mut v));
-        assert_eq!(v.as_slice(), b"hello");
-
-        assert_eq!(check!(input.metadata()).permissions(),
-                   check!(out.metadata()).permissions());
-    }
-
-    #[test]
-    fn copy_file_dst_dir() {
-        let tmpdir = tmpdir();
-        let out = tmpdir.join("out");
-
-        check!(File::create(&out));
-        match fs::copy(&*out, tmpdir.path()) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn copy_file_dst_exists() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in");
-        let output = tmpdir.join("out");
-
-        check!(check!(File::create(&input)).write("foo".as_bytes()));
-        check!(check!(File::create(&output)).write("bar".as_bytes()));
-        check!(fs::copy(&input, &output));
-
-        let mut v = Vec::new();
-        check!(check!(File::open(&output)).read_to_end(&mut v));
-        assert_eq!(v, b"foo".to_vec());
-    }
-
-    #[test]
-    fn copy_file_src_dir() {
-        let tmpdir = tmpdir();
-        let out = tmpdir.join("out");
-
-        match fs::copy(tmpdir.path(), &out) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-        assert!(!out.exists());
-    }
-
-    #[test]
-    fn copy_file_preserves_perm_bits() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        let attr = check!(check!(File::create(&input)).metadata());
-        let mut p = attr.permissions();
-        p.set_readonly(true);
-        check!(fs::set_permissions(&input, p));
-        check!(fs::copy(&input, &out));
-        assert!(check!(out.metadata()).permissions().readonly());
-        check!(fs::set_permissions(&input, attr.permissions()));
-        check!(fs::set_permissions(&out, attr.permissions()));
-    }
-
-    #[cfg(not(windows))] // FIXME(#10264) operation not permitted?
-    #[test]
-    fn symlinks_work() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        check!(check!(File::create(&input)).write("foobar".as_bytes()));
-        check!(fs::soft_link(&input, &out));
-        // if cfg!(not(windows)) {
-        //     assert_eq!(check!(lstat(&out)).kind, FileType::Symlink);
-        //     assert_eq!(check!(out.lstat()).kind, FileType::Symlink);
-        // }
-        assert_eq!(check!(fs::metadata(&out)).len(),
-                   check!(fs::metadata(&input)).len());
-        let mut v = Vec::new();
-        check!(check!(File::open(&out)).read_to_end(&mut v));
-        assert_eq!(v, b"foobar".to_vec());
-    }
-
-    #[cfg(not(windows))] // apparently windows doesn't like symlinks
-    #[test]
-    fn symlink_noexist() {
-        let tmpdir = tmpdir();
-        // symlinks can point to things that don't exist
-        check!(fs::soft_link(&tmpdir.join("foo"), &tmpdir.join("bar")));
-        assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))),
-                   tmpdir.join("foo"));
-    }
-
-    #[test]
-    fn readlink_not_symlink() {
-        let tmpdir = tmpdir();
-        match fs::read_link(tmpdir.path()) {
-            Ok(..) => panic!("wanted a failure"),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn links_work() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        check!(check!(File::create(&input)).write("foobar".as_bytes()));
-        check!(fs::hard_link(&input, &out));
-        assert_eq!(check!(fs::metadata(&out)).len(),
-                   check!(fs::metadata(&input)).len());
-        assert_eq!(check!(fs::metadata(&out)).len(),
-                   check!(input.metadata()).len());
-        let mut v = Vec::new();
-        check!(check!(File::open(&out)).read_to_end(&mut v));
-        assert_eq!(v, b"foobar".to_vec());
-
-        // can't link to yourself
-        match fs::hard_link(&input, &input) {
-            Ok(..) => panic!("wanted a failure"),
-            Err(..) => {}
-        }
-        // can't link to something that doesn't exist
-        match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) {
-            Ok(..) => panic!("wanted a failure"),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn chmod_works() {
-        let tmpdir = tmpdir();
-        let file = tmpdir.join("in.txt");
-
-        check!(File::create(&file));
-        let attr = check!(fs::metadata(&file));
-        assert!(!attr.permissions().readonly());
-        let mut p = attr.permissions();
-        p.set_readonly(true);
-        check!(fs::set_permissions(&file, p.clone()));
-        let attr = check!(fs::metadata(&file));
-        assert!(attr.permissions().readonly());
-
-        match fs::set_permissions(&tmpdir.join("foo"), p.clone()) {
-            Ok(..) => panic!("wanted an error"),
-            Err(..) => {}
-        }
-
-        p.set_readonly(false);
-        check!(fs::set_permissions(&file, p));
-    }
-
-    #[test]
-    fn sync_doesnt_kill_anything() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("in.txt");
-
-        let mut file = check!(File::create(&path));
-        check!(file.sync_all());
-        check!(file.sync_data());
-        check!(file.write(b"foo"));
-        check!(file.sync_all());
-        check!(file.sync_data());
-    }
-
-    #[test]
-    fn truncate_works() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("in.txt");
-
-        let mut file = check!(File::create(&path));
-        check!(file.write(b"foo"));
-        check!(file.sync_all());
-
-        // Do some simple things with truncation
-        assert_eq!(check!(file.metadata()).len(), 3);
-        check!(file.set_len(10));
-        assert_eq!(check!(file.metadata()).len(), 10);
-        check!(file.write(b"bar"));
-        check!(file.sync_all());
-        assert_eq!(check!(file.metadata()).len(), 10);
-
-        let mut v = Vec::new();
-        check!(check!(File::open(&path)).read_to_end(&mut v));
-        assert_eq!(v, b"foobar\0\0\0\0".to_vec());
-
-        // Truncate to a smaller length, don't seek, and then write something.
-        // Ensure that the intermediate zeroes are all filled in (we have `seek`ed
-        // past the end of the file).
-        check!(file.set_len(2));
-        assert_eq!(check!(file.metadata()).len(), 2);
-        check!(file.write(b"wut"));
-        check!(file.sync_all());
-        assert_eq!(check!(file.metadata()).len(), 9);
-        let mut v = Vec::new();
-        check!(check!(File::open(&path)).read_to_end(&mut v));
-        assert_eq!(v, b"fo\0\0\0\0wut".to_vec());
-    }
-
-    #[test]
-    fn open_flavors() {
-        use fs::OpenOptions as OO;
-        fn c<T: Clone>(t: &T) -> T { t.clone() }
-
-        let tmpdir = tmpdir();
-
-        let mut r = OO::new(); r.read(true);
-        let mut w = OO::new(); w.write(true);
-        let mut rw = OO::new(); rw.write(true).read(true);
-
-        match r.open(&tmpdir.join("a")) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-
-        // Perform each one twice to make sure that it succeeds the second time
-        // (where the file exists)
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        assert!(tmpdir.join("b").exists());
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        check!(w.open(&tmpdir.join("b")));
-
-        check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        assert!(tmpdir.join("c").exists());
-        check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        check!(rw.open(&tmpdir.join("c")));
-
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        assert!(tmpdir.join("d").exists());
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        check!(c(&w).append(true).open(&tmpdir.join("d")));
-
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        assert!(tmpdir.join("e").exists());
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        check!(c(&rw).append(true).open(&tmpdir.join("e")));
-
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        assert!(tmpdir.join("f").exists());
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        check!(c(&w).truncate(true).open(&tmpdir.join("f")));
-
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        assert!(tmpdir.join("g").exists());
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        check!(c(&rw).truncate(true).open(&tmpdir.join("g")));
-
-        check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes()));
-        check!(r.open(&tmpdir.join("h")));
-        {
-            let mut f = check!(r.open(&tmpdir.join("h")));
-            assert!(f.write("wut".as_bytes()).is_err());
-        }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
-        {
-            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
-            check!(f.write("bar".as_bytes()));
-        }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
-        {
-            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
-            check!(f.write("bar".as_bytes()));
-        }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
-    }
-
-    #[test]
-    fn utime() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("a");
-        check!(File::create(&path));
-        // These numbers have to be bigger than the time in the day to account
-        // for timezones Windows in particular will fail in certain timezones
-        // with small enough values
-        check!(fs::set_file_times(&path, 100000, 200000));
-        assert_eq!(check!(path.metadata()).accessed(), 100000);
-        assert_eq!(check!(path.metadata()).modified(), 200000);
-    }
-
-    #[test]
-    fn utime_noexist() {
-        let tmpdir = tmpdir();
-
-        match fs::set_file_times(&tmpdir.join("a"), 100, 200) {
-            Ok(..) => panic!(),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn binary_file() {
-        let mut bytes = [0; 1024];
-        StdRng::new().unwrap().fill_bytes(&mut bytes);
-
-        let tmpdir = tmpdir();
-
-        check!(check!(File::create(&tmpdir.join("test"))).write(&bytes));
-        let mut v = Vec::new();
-        check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v));
-        assert!(v == bytes.as_slice());
-    }
-
-    #[test]
-    #[cfg(not(windows))]
-    fn unlink_readonly() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("file");
-        check!(File::create(&path));
-        let mut perm = check!(fs::metadata(&path)).permissions();
-        perm.set_readonly(true);
-        check!(fs::set_permissions(&path, perm));
-        check!(fs::remove_file(&path));
-    }
-
-    #[test]
-    fn mkdir_trailing_slash() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("file");
-        check!(fs::create_dir_all(&path.join("a/")));
-    }
-}
diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs
deleted file mode 100644 (file)
index 8cc1dde..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-// 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.
-
-#![unstable(feature = "tempdir", reason = "needs an RFC before stabilization")]
-#![deprecated(since = "1.0.0",
-              reason = "use the `tempdir` crate from crates.io instead")]
-#![allow(deprecated)]
-
-use prelude::v1::*;
-
-use env;
-use io::{self, Error, ErrorKind};
-use fs;
-use path::{self, PathBuf};
-use rand::{thread_rng, Rng};
-
-/// A wrapper for a path to temporary directory implementing automatic
-/// scope-based deletion.
-pub struct TempDir {
-    path: Option<PathBuf>,
-}
-
-// How many times should we (re)try finding an unused random name? It should be
-// enough that an attacker will run out of luck before we run out of patience.
-const NUM_RETRIES: u32 = 1 << 31;
-// How many characters should we include in a random file name? It needs to
-// be enough to dissuade an attacker from trying to preemptively create names
-// of that length, but not so huge that we unnecessarily drain the random number
-// generator of entropy.
-const NUM_RAND_CHARS: usize = 12;
-
-impl TempDir {
-    /// Attempts to make a temporary directory inside of `tmpdir` whose name
-    /// will have the prefix `prefix`. The directory will be automatically
-    /// deleted once the returned wrapper is destroyed.
-    ///
-    /// If no directory can be created, `Err` is returned.
-    #[allow(deprecated)] // rand usage
-    pub fn new_in<P: AsRef<path::Path>>(tmpdir: P, prefix: &str) -> io::Result<TempDir> {
-        let storage;
-        let mut tmpdir = tmpdir.as_ref();
-        if !tmpdir.is_absolute() {
-            let cur_dir = try!(env::current_dir());
-            storage = cur_dir.join(tmpdir);
-            tmpdir = &storage;
-            // return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
-        }
-
-        let mut rng = thread_rng();
-        for _ in 0..NUM_RETRIES {
-            let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
-            let leaf = if prefix.len() > 0 {
-                format!("{}.{}", prefix, suffix)
-            } else {
-                // If we're given an empty string for a prefix, then creating a
-                // directory starting with "." would lead to it being
-                // semi-invisible on some systems.
-                suffix
-            };
-            let path = tmpdir.join(&leaf);
-            match fs::create_dir(&path) {
-                Ok(_) => return Ok(TempDir { path: Some(path) }),
-                Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
-                Err(e) => return Err(e)
-            }
-        }
-
-        Err(Error::new(ErrorKind::AlreadyExists,
-                       "too many temporary directories already exist",
-                       None))
-    }
-
-    /// Attempts to make a temporary directory inside of `env::temp_dir()` whose
-    /// name will have the prefix `prefix`. The directory will be automatically
-    /// deleted once the returned wrapper is destroyed.
-    ///
-    /// If no directory can be created, `Err` is returned.
-    #[allow(deprecated)]
-    pub fn new(prefix: &str) -> io::Result<TempDir> {
-        TempDir::new_in(&env::temp_dir(), prefix)
-    }
-
-    /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
-    /// This discards the wrapper so that the automatic deletion of the
-    /// temporary directory is prevented.
-    pub fn into_path(mut self) -> PathBuf {
-        self.path.take().unwrap()
-    }
-
-    /// Access the wrapped `std::path::Path` to the temporary directory.
-    pub fn path(&self) -> &path::Path {
-        self.path.as_ref().unwrap()
-    }
-
-    /// Close and remove the temporary directory
-    ///
-    /// Although `TempDir` removes the directory on drop, in the destructor
-    /// any errors are ignored. To detect errors cleaning up the temporary
-    /// directory, call `close` instead.
-    pub fn close(mut self) -> io::Result<()> {
-        self.cleanup_dir()
-    }
-
-    fn cleanup_dir(&mut self) -> io::Result<()> {
-        match self.path {
-            Some(ref p) => fs::remove_dir_all(p),
-            None => Ok(())
-        }
-    }
-}
-
-impl Drop for TempDir {
-    fn drop(&mut self) {
-        let _ = self.cleanup_dir();
-    }
-}
-
-// the tests for this module need to change the path using change_dir,
-// and this doesn't play nicely with other tests so these unit tests are located
-// in src/test/run-pass/tempfile.rs
index 8eea06bf6b0c729f672d0bff9ebbc4843bf277b4..6fe35614a85b6da4e61be246ba0ab116cae70854 100644 (file)
@@ -16,7 +16,7 @@
 use io::prelude::*;
 
 use cmp;
-use error::{self, FromError};
+use error;
 use fmt;
 use io::{self, DEFAULT_BUF_SIZE, Error, ErrorKind};
 use ptr;
@@ -165,7 +165,7 @@ fn flush_buf(&mut self) -> io::Result<()> {
             match self.inner.as_mut().unwrap().write(&self.buf[written..]) {
                 Ok(0) => {
                     ret = Err(Error::new(ErrorKind::WriteZero,
-                                         "failed to write the buffered data", None));
+                                         "failed to write the buffered data"));
                     break;
                 }
                 Ok(n) => written += n,
@@ -264,8 +264,8 @@ pub fn into_inner(self) -> W { self.0 }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> FromError<IntoInnerError<W>> for Error {
-    fn from_error(iie: IntoInnerError<W>) -> Error { iie.1 }
+impl<W> From<IntoInnerError<W>> for Error {
+    fn from(iie: IntoInnerError<W>) -> Error { iie.1 }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -503,34 +503,34 @@ fn test_buffered_reader() {
 
         let mut buf = [0, 0, 0];
         let nread = reader.read(&mut buf);
-        assert_eq!(Ok(3), nread);
+        assert_eq!(nread.unwrap(), 3);
         let b: &[_] = &[5, 6, 7];
         assert_eq!(buf, b);
 
         let mut buf = [0, 0];
         let nread = reader.read(&mut buf);
-        assert_eq!(Ok(2), nread);
+        assert_eq!(nread.unwrap(), 2);
         let b: &[_] = &[0, 1];
         assert_eq!(buf, b);
 
         let mut buf = [0];
         let nread = reader.read(&mut buf);
-        assert_eq!(Ok(1), nread);
+        assert_eq!(nread.unwrap(), 1);
         let b: &[_] = &[2];
         assert_eq!(buf, b);
 
         let mut buf = [0, 0, 0];
         let nread = reader.read(&mut buf);
-        assert_eq!(Ok(1), nread);
+        assert_eq!(nread.unwrap(), 1);
         let b: &[_] = &[3, 0, 0];
         assert_eq!(buf, b);
 
         let nread = reader.read(&mut buf);
-        assert_eq!(Ok(1), nread);
+        assert_eq!(nread.unwrap(), 1);
         let b: &[_] = &[4, 0, 0];
         assert_eq!(buf, b);
 
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
     #[test]
@@ -592,7 +592,7 @@ fn read(&mut self, _: &mut [u8]) -> io::Result<usize> { Ok(0) }
         }
 
         let mut stream = BufStream::new(S);
-        assert_eq!(stream.read(&mut [0; 10]), Ok(0));
+        assert_eq!(stream.read(&mut [0; 10]).unwrap(), 0);
         stream.write(&[0; 10]).unwrap();
         stream.flush().unwrap();
     }
@@ -658,10 +658,10 @@ fn test_lines() {
         let in_buf: &[u8] = b"a\nb\nc";
         let reader = BufReader::with_capacity(2, in_buf);
         let mut it = reader.lines();
-        assert_eq!(it.next(), Some(Ok("a".to_string())));
-        assert_eq!(it.next(), Some(Ok("b".to_string())));
-        assert_eq!(it.next(), Some(Ok("c".to_string())));
-        assert_eq!(it.next(), None);
+        assert_eq!(it.next().unwrap().unwrap(), "a".to_string());
+        assert_eq!(it.next().unwrap().unwrap(), "b".to_string());
+        assert_eq!(it.next().unwrap().unwrap(), "c".to_string());
+        assert!(it.next().is_none());
     }
 
     #[test]
@@ -669,20 +669,20 @@ fn test_short_reads() {
         let inner = ShortReader{lengths: vec![0, 1, 2, 0, 1, 0]};
         let mut reader = BufReader::new(inner);
         let mut buf = [0, 0];
-        assert_eq!(reader.read(&mut buf), Ok(0));
-        assert_eq!(reader.read(&mut buf), Ok(1));
-        assert_eq!(reader.read(&mut buf), Ok(2));
-        assert_eq!(reader.read(&mut buf), Ok(0));
-        assert_eq!(reader.read(&mut buf), Ok(1));
-        assert_eq!(reader.read(&mut buf), Ok(0));
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
+        assert_eq!(reader.read(&mut buf).unwrap(), 1);
+        assert_eq!(reader.read(&mut buf).unwrap(), 2);
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
+        assert_eq!(reader.read(&mut buf).unwrap(), 1);
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
     #[test]
     fn read_char_buffered() {
         let buf = [195, 159];
         let reader = BufReader::with_capacity(1, &buf[..]);
-        assert_eq!(reader.chars().next(), Some(Ok('ß')));
+        assert_eq!(reader.chars().next().unwrap().unwrap(), 'ß');
     }
 
     #[test]
@@ -690,9 +690,9 @@ fn test_chars() {
         let buf = [195, 159, b'a'];
         let reader = BufReader::with_capacity(1, &buf[..]);
         let mut it = reader.chars();
-        assert_eq!(it.next(), Some(Ok('ß')));
-        assert_eq!(it.next(), Some(Ok('a')));
-        assert_eq!(it.next(), None);
+        assert_eq!(it.next().unwrap().unwrap(), 'ß');
+        assert_eq!(it.next().unwrap().unwrap(), 'a');
+        assert!(it.next().is_none());
     }
 
     #[test]
index d8e403376bdc734a6d7a4db7988cf785c675d6ea..6433c29bb9d6e456d0701828cd576c58d2afe591 100644 (file)
@@ -75,8 +75,7 @@ fn seek(&mut self, style: SeekFrom) -> io::Result<u64> {
 
             if pos < 0 {
                 Err(Error::new(ErrorKind::InvalidInput,
-                               "invalid seek to a negative position",
-                               None))
+                               "invalid seek to a negative position"))
             } else {
                 self.pos = pos as u64;
                 Ok(self.pos)
@@ -172,9 +171,9 @@ mod tests {
     #[test]
     fn test_vec_writer() {
         let mut writer = Vec::new();
-        assert_eq!(writer.write(&[0]), Ok(1));
-        assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
-        assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
+        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
         assert_eq!(writer, b);
     }
@@ -182,9 +181,9 @@ fn test_vec_writer() {
     #[test]
     fn test_mem_writer() {
         let mut writer = Cursor::new(Vec::new());
-        assert_eq!(writer.write(&[0]), Ok(1));
-        assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
-        assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
+        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
         assert_eq!(&writer.get_ref()[..], b);
     }
@@ -195,16 +194,16 @@ fn test_buf_writer() {
         {
             let mut writer = Cursor::new(&mut buf[..]);
             assert_eq!(writer.position(), 0);
-            assert_eq!(writer.write(&[0]), Ok(1));
+            assert_eq!(writer.write(&[0]).unwrap(), 1);
             assert_eq!(writer.position(), 1);
-            assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
-            assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
+            assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+            assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
             assert_eq!(writer.position(), 8);
-            assert_eq!(writer.write(&[]), Ok(0));
+            assert_eq!(writer.write(&[]).unwrap(), 0);
             assert_eq!(writer.position(), 8);
 
-            assert_eq!(writer.write(&[8, 9]), Ok(1));
-            assert_eq!(writer.write(&[10]), Ok(0));
+            assert_eq!(writer.write(&[8, 9]).unwrap(), 1);
+            assert_eq!(writer.write(&[10]).unwrap(), 0);
         }
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8];
         assert_eq!(buf, b);
@@ -216,22 +215,22 @@ fn test_buf_writer_seek() {
         {
             let mut writer = Cursor::new(&mut buf[..]);
             assert_eq!(writer.position(), 0);
-            assert_eq!(writer.write(&[1]), Ok(1));
+            assert_eq!(writer.write(&[1]).unwrap(), 1);
             assert_eq!(writer.position(), 1);
 
-            assert_eq!(writer.seek(SeekFrom::Start(2)), Ok(2));
+            assert_eq!(writer.seek(SeekFrom::Start(2)).unwrap(), 2);
             assert_eq!(writer.position(), 2);
-            assert_eq!(writer.write(&[2]), Ok(1));
+            assert_eq!(writer.write(&[2]).unwrap(), 1);
             assert_eq!(writer.position(), 3);
 
-            assert_eq!(writer.seek(SeekFrom::Current(-2)), Ok(1));
+            assert_eq!(writer.seek(SeekFrom::Current(-2)).unwrap(), 1);
             assert_eq!(writer.position(), 1);
-            assert_eq!(writer.write(&[3]), Ok(1));
+            assert_eq!(writer.write(&[3]).unwrap(), 1);
             assert_eq!(writer.position(), 2);
 
-            assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7));
+            assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
             assert_eq!(writer.position(), 7);
-            assert_eq!(writer.write(&[4]), Ok(1));
+            assert_eq!(writer.write(&[4]).unwrap(), 1);
             assert_eq!(writer.position(), 8);
 
         }
@@ -243,31 +242,31 @@ fn test_buf_writer_seek() {
     fn test_buf_writer_error() {
         let mut buf = [0 as u8; 2];
         let mut writer = Cursor::new(&mut buf[..]);
-        assert_eq!(writer.write(&[0]), Ok(1));
-        assert_eq!(writer.write(&[0, 0]), Ok(1));
-        assert_eq!(writer.write(&[0, 0]), Ok(0));
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
+        assert_eq!(writer.write(&[0, 0]).unwrap(), 1);
+        assert_eq!(writer.write(&[0, 0]).unwrap(), 0);
     }
 
     #[test]
     fn test_mem_reader() {
         let mut reader = Cursor::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
         let mut buf = [];
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
         assert_eq!(reader.position(), 0);
         let mut buf = [0];
-        assert_eq!(reader.read(&mut buf), Ok(1));
+        assert_eq!(reader.read(&mut buf).unwrap(), 1);
         assert_eq!(reader.position(), 1);
         let b: &[_] = &[0];
         assert_eq!(buf, b);
         let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf), Ok(4));
+        assert_eq!(reader.read(&mut buf).unwrap(), 4);
         assert_eq!(reader.position(), 5);
         let b: &[_] = &[1, 2, 3, 4];
         assert_eq!(buf, b);
-        assert_eq!(reader.read(&mut buf), Ok(3));
+        assert_eq!(reader.read(&mut buf).unwrap(), 3);
         let b: &[_] = &[5, 6, 7];
         assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
     #[test]
@@ -281,57 +280,57 @@ fn read_to_end() {
     #[test]
     fn test_slice_reader() {
         let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let mut reader = &mut in_buf.as_slice();
+        let mut reader = &mut &in_buf[..];
         let mut buf = [];
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
         let mut buf = [0];
-        assert_eq!(reader.read(&mut buf), Ok(1));
+        assert_eq!(reader.read(&mut buf).unwrap(), 1);
         assert_eq!(reader.len(), 7);
         let b: &[_] = &[0];
-        assert_eq!(buf.as_slice(), b);
+        assert_eq!(&buf[..], b);
         let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf), Ok(4));
+        assert_eq!(reader.read(&mut buf).unwrap(), 4);
         assert_eq!(reader.len(), 3);
         let b: &[_] = &[1, 2, 3, 4];
-        assert_eq!(buf.as_slice(), b);
-        assert_eq!(reader.read(&mut buf), Ok(3));
+        assert_eq!(&buf[..], b);
+        assert_eq!(reader.read(&mut buf).unwrap(), 3);
         let b: &[_] = &[5, 6, 7];
         assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
     #[test]
     fn test_buf_reader() {
         let in_buf = vec![0, 1, 2, 3, 4, 5, 6, 7];
-        let mut reader = Cursor::new(in_buf.as_slice());
+        let mut reader = Cursor::new(&in_buf[..]);
         let mut buf = [];
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
         assert_eq!(reader.position(), 0);
         let mut buf = [0];
-        assert_eq!(reader.read(&mut buf), Ok(1));
+        assert_eq!(reader.read(&mut buf).unwrap(), 1);
         assert_eq!(reader.position(), 1);
         let b: &[_] = &[0];
         assert_eq!(buf, b);
         let mut buf = [0; 4];
-        assert_eq!(reader.read(&mut buf), Ok(4));
+        assert_eq!(reader.read(&mut buf).unwrap(), 4);
         assert_eq!(reader.position(), 5);
         let b: &[_] = &[1, 2, 3, 4];
         assert_eq!(buf, b);
-        assert_eq!(reader.read(&mut buf), Ok(3));
+        assert_eq!(reader.read(&mut buf).unwrap(), 3);
         let b: &[_] = &[5, 6, 7];
         assert_eq!(&buf[..3], b);
-        assert_eq!(reader.read(&mut buf), Ok(0));
+        assert_eq!(reader.read(&mut buf).unwrap(), 0);
     }
 
     #[test]
     fn test_read_char() {
         let b = &b"Vi\xE1\xBB\x87t"[..];
         let mut c = Cursor::new(b).chars();
-        assert_eq!(c.next(), Some(Ok('V')));
-        assert_eq!(c.next(), Some(Ok('i')));
-        assert_eq!(c.next(), Some(Ok('ệ')));
-        assert_eq!(c.next(), Some(Ok('t')));
-        assert_eq!(c.next(), None);
+        assert_eq!(c.next().unwrap().unwrap(), 'V');
+        assert_eq!(c.next().unwrap().unwrap(), 'i');
+        assert_eq!(c.next().unwrap().unwrap(), 'ệ');
+        assert_eq!(c.next().unwrap().unwrap(), 't');
+        assert!(c.next().is_none());
     }
 
     #[test]
@@ -345,17 +344,17 @@ fn test_read_bad_char() {
     fn seek_past_end() {
         let buf = [0xff];
         let mut r = Cursor::new(&buf[..]);
-        assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10));
-        assert_eq!(r.read(&mut [0]), Ok(0));
+        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+        assert_eq!(r.read(&mut [0]).unwrap(), 0);
 
         let mut r = Cursor::new(vec!(10));
-        assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10));
-        assert_eq!(r.read(&mut [0]), Ok(0));
+        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+        assert_eq!(r.read(&mut [0]).unwrap(), 0);
 
         let mut buf = [0];
         let mut r = Cursor::new(&mut buf[..]);
-        assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10));
-        assert_eq!(r.write(&[3]), Ok(0));
+        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+        assert_eq!(r.write(&[3]).unwrap(), 0);
     }
 
     #[test]
@@ -376,32 +375,32 @@ fn seek_before_0() {
     fn test_seekable_mem_writer() {
         let mut writer = Cursor::new(Vec::<u8>::new());
         assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write(&[0]), Ok(1));
+        assert_eq!(writer.write(&[0]).unwrap(), 1);
         assert_eq!(writer.position(), 1);
-        assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
-        assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
+        assert_eq!(writer.write(&[1, 2, 3]).unwrap(), 3);
+        assert_eq!(writer.write(&[4, 5, 6, 7]).unwrap(), 4);
         assert_eq!(writer.position(), 8);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
         assert_eq!(&writer.get_ref()[..], b);
 
-        assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0));
+        assert_eq!(writer.seek(SeekFrom::Start(0)).unwrap(), 0);
         assert_eq!(writer.position(), 0);
-        assert_eq!(writer.write(&[3, 4]), Ok(2));
+        assert_eq!(writer.write(&[3, 4]).unwrap(), 2);
         let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
         assert_eq!(&writer.get_ref()[..], b);
 
-        assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3));
-        assert_eq!(writer.write(&[0, 1]), Ok(2));
+        assert_eq!(writer.seek(SeekFrom::Current(1)).unwrap(), 3);
+        assert_eq!(writer.write(&[0, 1]).unwrap(), 2);
         let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
         assert_eq!(&writer.get_ref()[..], b);
 
-        assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7));
-        assert_eq!(writer.write(&[1, 2]), Ok(2));
+        assert_eq!(writer.seek(SeekFrom::End(-1)).unwrap(), 7);
+        assert_eq!(writer.write(&[1, 2]).unwrap(), 2);
         let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
         assert_eq!(&writer.get_ref()[..], b);
 
-        assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10));
-        assert_eq!(writer.write(&[1]), Ok(1));
+        assert_eq!(writer.seek(SeekFrom::End(1)).unwrap(), 10);
+        assert_eq!(writer.write(&[1]).unwrap(), 1);
         let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
         assert_eq!(&writer.get_ref()[..], b);
     }
@@ -409,8 +408,8 @@ fn test_seekable_mem_writer() {
     #[test]
     fn vec_seek_past_end() {
         let mut r = Cursor::new(Vec::new());
-        assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10));
-        assert_eq!(r.write(&[3]), Ok(1));
+        assert_eq!(r.seek(SeekFrom::Start(10)).unwrap(), 10);
+        assert_eq!(r.write(&[3]).unwrap(), 1);
     }
 
     #[test]
index f445ace081e4ffc9f2b66b4e2317d07f76076bdb..b84dcb8fb620616f256927c8d68e69b8567ba0e9 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 use boxed::Box;
-use clone::Clone;
+use convert::Into;
 use error;
 use fmt;
+use marker::Send;
 use option::Option::{self, Some, None};
 use result;
-use string::String;
 use sys;
 
 /// A type for results generated by I/O related functions where the `Err` type
 /// Errors mostly originate from the underlying OS, but custom instances of
 /// `Error` can be created with crafted error messages and a particular value of
 /// `ErrorKind`.
-#[derive(PartialEq, Eq, Clone, Debug)]
+#[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Error {
     repr: Repr,
 }
 
-#[derive(PartialEq, Eq, Clone, Debug)]
+#[derive(Debug)]
 enum Repr {
     Os(i32),
     Custom(Box<Custom>),
 }
 
-#[derive(PartialEq, Eq, Clone, Debug)]
+#[derive(Debug)]
 struct Custom {
     kind: ErrorKind,
-    desc: &'static str,
-    detail: Option<String>
+    error: Box<error::Error+Send>,
 }
 
 /// A list specifying general categories of I/O error.
@@ -125,18 +124,34 @@ enum cannot be exhaustively matched against")]
 }
 
 impl Error {
-    /// Creates a new custom error from a specified kind/description/detail.
-    #[unstable(feature = "io", reason = "the exact makeup of an Error may
-                                         change to include `Box<Error>` for \
-                                         example")]
-    pub fn new(kind: ErrorKind,
-               description: &'static str,
-               detail: Option<String>) -> Error {
+    /// Creates a new I/O error from a known kind of error as well as an
+    /// arbitrary error payload.
+    ///
+    /// This function is used to generically create I/O errors which do not
+    /// originate from the OS itself. The `error` argument is an arbitrary
+    /// payload which will be contained in this `Error`. Accessors as well as
+    /// downcasting will soon be added to this type as well to access the custom
+    /// information.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{Error, ErrorKind};
+    ///
+    /// // errors can be created from strings
+    /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
+    ///
+    /// // errors can also be created from other errors
+    /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn new<E>(kind: ErrorKind, error: E) -> Error
+        where E: Into<Box<error::Error+Send>>
+    {
         Error {
             repr: Repr::Custom(Box::new(Custom {
                 kind: kind,
-                desc: description,
-                detail: detail,
+                error: error.into(),
             }))
         }
     }
@@ -162,8 +177,7 @@ pub fn from_os_error(code: i32) -> Error {
     ///
     /// If this `Error` was constructed via `last_os_error` then this function
     /// will return `Some`, otherwise it will return `None`.
-    #[unstable(feature = "io", reason = "function was just added and the return \
-                                         type may become an abstract OS error")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn raw_os_error(&self) -> Option<i32> {
         match self.repr {
             Repr::Os(i) => Some(i),
@@ -179,27 +193,6 @@ pub fn kind(&self) -> ErrorKind {
             Repr::Custom(ref c) => c.kind,
         }
     }
-
-    /// Returns a short description for this error message
-    #[unstable(feature = "io")]
-    #[deprecated(since = "1.0.0", reason = "use the Error trait's description \
-                                            method instead")]
-    pub fn description(&self) -> &str {
-        match self.repr {
-            Repr::Os(..) => "os error",
-            Repr::Custom(ref c) => c.desc,
-        }
-    }
-
-    /// Returns a detailed error message for this error (if one is available)
-    #[unstable(feature = "io")]
-    #[deprecated(since = "1.0.0", reason = "use the to_string() method instead")]
-    pub fn detail(&self) -> Option<String> {
-        match self.repr {
-            Repr::Os(code) => Some(sys::os::error_string(code)),
-            Repr::Custom(ref s) => s.detail.clone(),
-        }
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -210,21 +203,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                 let detail = sys::os::error_string(code);
                 write!(fmt, "{} (os error {})", detail, code)
             }
-            Repr::Custom(ref c) => {
-                match **c {
-                    Custom {
-                        kind: ErrorKind::Other,
-                        desc: "unknown error",
-                        detail: Some(ref detail)
-                    } => {
-                        write!(fmt, "{}", detail)
-                    }
-                    Custom { detail: None, desc, .. } =>
-                        write!(fmt, "{}", desc),
-                    Custom { detail: Some(ref detail), desc, .. } =>
-                        write!(fmt, "{} ({})", desc, detail)
-                }
-            }
+            Repr::Custom(ref c) => c.error.fmt(fmt),
         }
     }
 }
@@ -234,7 +213,7 @@ impl error::Error for Error {
     fn description(&self) -> &str {
         match self.repr {
             Repr::Os(..) => "os error",
-            Repr::Custom(ref c) => c.desc,
+            Repr::Custom(ref c) => c.error.description(),
         }
     }
 }
index 52daba362131eda7392c0d0c71e49faa5350ff49..67bc45d3b62a1fd4d514b238786ccab5be086af8 100644 (file)
@@ -180,7 +180,7 @@ fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
         if try!(self.write(data)) == data.len() {
             Ok(())
         } else {
-            Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None))
+            Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"))
         }
     }
 
index 830a88bb6c95b1fe75d54d797233cbc1a3f6fd5d..c6335015d7251d67d73bd1cf5dc90ac03a57e31a 100644 (file)
@@ -83,7 +83,7 @@ fn drop(&mut self) {
         if str::from_utf8(&g.s[g.len..]).is_err() {
             ret.and_then(|_| {
                 Err(Error::new(ErrorKind::InvalidInput,
-                               "stream did not contain valid UTF-8", None))
+                               "stream did not contain valid UTF-8"))
             })
         } else {
             g.len = g.s.len();
@@ -101,18 +101,14 @@ fn drop(&mut self) {
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
     let start_len = buf.len();
     let mut len = start_len;
-    let mut cap_bump = 16;
+    let mut new_write_size = 16;
     let ret;
     loop {
         if len == buf.len() {
-            if buf.capacity() == buf.len() {
-                if cap_bump < DEFAULT_BUF_SIZE {
-                    cap_bump *= 2;
-                }
-                buf.reserve(cap_bump);
+            if new_write_size < DEFAULT_BUF_SIZE {
+                new_write_size *= 2;
             }
-            let new_area = buf.capacity() - buf.len();
-            buf.extend(iter::repeat(0).take(new_area));
+            buf.extend(iter::repeat(0).take(new_write_size));
         }
 
         match r.read(&mut buf[len..]) {
@@ -359,8 +355,7 @@ fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
         while buf.len() > 0 {
             match self.write(buf) {
                 Ok(0) => return Err(Error::new(ErrorKind::WriteZero,
-                                               "failed to write whole buffer",
-                                               None)),
+                                               "failed to write whole buffer")),
                 Ok(n) => buf = &buf[n..],
                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
                 Err(e) => return Err(e),
@@ -441,9 +436,7 @@ fn broadcast<W: Write>(self, other: W) -> Broadcast<Self, W>
 ///
 /// The stream typically has a fixed size, allowing seeking relative to either
 /// end or the current offset.
-#[unstable(feature = "io", reason = "the central `seek` method may be split \
-                                     into multiple methods instead of taking \
-                                     an enum as an argument")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub trait Seek {
     /// Seek to an offset, in bytes, in a stream
     ///
@@ -459,14 +452,16 @@ pub trait Seek {
     /// # Errors
     ///
     /// Seeking to a negative offset is considered an error
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
 }
 
 /// Enumeration of possible methods to seek within an I/O object.
 #[derive(Copy, PartialEq, Eq, Clone, Debug)]
-#[unstable(feature = "io", reason = "awaiting the stability of Seek")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum SeekFrom {
     /// Set the offset to the provided number of bytes.
+    #[stable(feature = "rust1", since = "1.0.0")]
     Start(u64),
 
     /// Set the offset to the size of this object plus the specified number of
@@ -474,6 +469,7 @@ pub enum SeekFrom {
     ///
     /// It is possible to seek beyond the end of an object, but is an error to
     /// seek before byte 0.
+    #[stable(feature = "rust1", since = "1.0.0")]
     End(i64),
 
     /// Set the offset to the current position plus the specified number of
@@ -481,6 +477,7 @@ pub enum SeekFrom {
     ///
     /// It is possible to seek beyond the end of an object, but is an error to
     /// seek before byte 0.
+    #[stable(feature = "rust1", since = "1.0.0")]
     Current(i64),
 }
 
@@ -780,7 +777,7 @@ pub struct Chars<R> {
 
 /// An enumeration of possible errors that can be generated from the `Chars`
 /// adapter.
-#[derive(PartialEq, Clone, Debug)]
+#[derive(Debug)]
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
 pub enum CharsError {
     /// Variant representing that the underlying stream was read successfully
@@ -919,18 +916,18 @@ mod tests {
     fn read_until() {
         let mut buf = Cursor::new(&b"12"[..]);
         let mut v = Vec::new();
-        assert_eq!(buf.read_until(b'3', &mut v), Ok(2));
+        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 2);
         assert_eq!(v, b"12");
 
         let mut buf = Cursor::new(&b"1233"[..]);
         let mut v = Vec::new();
-        assert_eq!(buf.read_until(b'3', &mut v), Ok(3));
+        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 3);
         assert_eq!(v, b"123");
         v.truncate(0);
-        assert_eq!(buf.read_until(b'3', &mut v), Ok(1));
+        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 1);
         assert_eq!(v, b"3");
         v.truncate(0);
-        assert_eq!(buf.read_until(b'3', &mut v), Ok(0));
+        assert_eq!(buf.read_until(b'3', &mut v).unwrap(), 0);
         assert_eq!(v, []);
     }
 
@@ -938,32 +935,32 @@ fn read_until() {
     fn split() {
         let buf = Cursor::new(&b"12"[..]);
         let mut s = buf.split(b'3');
-        assert_eq!(s.next(), Some(Ok(vec![b'1', b'2'])));
-        assert_eq!(s.next(), None);
+        assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']);
+        assert!(s.next().is_none());
 
         let buf = Cursor::new(&b"1233"[..]);
         let mut s = buf.split(b'3');
-        assert_eq!(s.next(), Some(Ok(vec![b'1', b'2'])));
-        assert_eq!(s.next(), Some(Ok(vec![])));
-        assert_eq!(s.next(), None);
+        assert_eq!(s.next().unwrap().unwrap(), vec![b'1', b'2']);
+        assert_eq!(s.next().unwrap().unwrap(), vec![]);
+        assert!(s.next().is_none());
     }
 
     #[test]
     fn read_line() {
         let mut buf = Cursor::new(&b"12"[..]);
         let mut v = String::new();
-        assert_eq!(buf.read_line(&mut v), Ok(2));
+        assert_eq!(buf.read_line(&mut v).unwrap(), 2);
         assert_eq!(v, "12");
 
         let mut buf = Cursor::new(&b"12\n\n"[..]);
         let mut v = String::new();
-        assert_eq!(buf.read_line(&mut v), Ok(3));
+        assert_eq!(buf.read_line(&mut v).unwrap(), 3);
         assert_eq!(v, "12\n");
         v.truncate(0);
-        assert_eq!(buf.read_line(&mut v), Ok(1));
+        assert_eq!(buf.read_line(&mut v).unwrap(), 1);
         assert_eq!(v, "\n");
         v.truncate(0);
-        assert_eq!(buf.read_line(&mut v), Ok(0));
+        assert_eq!(buf.read_line(&mut v).unwrap(), 0);
         assert_eq!(v, "");
     }
 
@@ -971,26 +968,26 @@ fn read_line() {
     fn lines() {
         let buf = Cursor::new(&b"12"[..]);
         let mut s = buf.lines();
-        assert_eq!(s.next(), Some(Ok("12".to_string())));
-        assert_eq!(s.next(), None);
+        assert_eq!(s.next().unwrap().unwrap(), "12".to_string());
+        assert!(s.next().is_none());
 
         let buf = Cursor::new(&b"12\n\n"[..]);
         let mut s = buf.lines();
-        assert_eq!(s.next(), Some(Ok("12".to_string())));
-        assert_eq!(s.next(), Some(Ok(String::new())));
-        assert_eq!(s.next(), None);
+        assert_eq!(s.next().unwrap().unwrap(), "12".to_string());
+        assert_eq!(s.next().unwrap().unwrap(), "".to_string());
+        assert!(s.next().is_none());
     }
 
     #[test]
     fn read_to_end() {
         let mut c = Cursor::new(&b""[..]);
         let mut v = Vec::new();
-        assert_eq!(c.read_to_end(&mut v), Ok(0));
+        assert_eq!(c.read_to_end(&mut v).unwrap(), 0);
         assert_eq!(v, []);
 
         let mut c = Cursor::new(&b"1"[..]);
         let mut v = Vec::new();
-        assert_eq!(c.read_to_end(&mut v), Ok(1));
+        assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
         assert_eq!(v, b"1");
     }
 
@@ -998,12 +995,12 @@ fn read_to_end() {
     fn read_to_string() {
         let mut c = Cursor::new(&b""[..]);
         let mut v = String::new();
-        assert_eq!(c.read_to_string(&mut v), Ok(0));
+        assert_eq!(c.read_to_string(&mut v).unwrap(), 0);
         assert_eq!(v, "");
 
         let mut c = Cursor::new(&b"1"[..]);
         let mut v = String::new();
-        assert_eq!(c.read_to_string(&mut v), Ok(1));
+        assert_eq!(c.read_to_string(&mut v).unwrap(), 1);
         assert_eq!(v, "1");
 
         let mut c = Cursor::new(&b"\xff"[..]);
@@ -1017,11 +1014,11 @@ fn take_eof() {
 
         impl Read for R {
             fn read(&mut self, _: &mut [u8]) -> io::Result<usize> {
-                Err(io::Error::new(io::ErrorKind::Other, "", None))
+                Err(io::Error::new(io::ErrorKind::Other, ""))
             }
         }
 
         let mut buf = [0; 1];
-        assert_eq!(Ok(0), R.take(0).read(&mut buf));
+        assert_eq!(0, R.take(0).read(&mut buf).unwrap());
     }
 }
index 20426025257c3761a8bba56c4281f5093ac49ccb..c82f9515e8d52813ba494a6b0a48b0b71bc27a65 100644 (file)
@@ -111,33 +111,33 @@ mod test {
     #[test]
     fn sink_sinks() {
         let mut s = sink();
-        assert_eq!(s.write(&[]), Ok(0));
-        assert_eq!(s.write(&[0]), Ok(1));
-        assert_eq!(s.write(&[0; 1024]), Ok(1024));
-        assert_eq!(s.by_ref().write(&[0; 1024]), Ok(1024));
+        assert_eq!(s.write(&[]).unwrap(), 0);
+        assert_eq!(s.write(&[0]).unwrap(), 1);
+        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
+        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
     }
 
     #[test]
     fn empty_reads() {
         let mut e = empty();
-        assert_eq!(e.read(&mut []), Ok(0));
-        assert_eq!(e.read(&mut [0]), Ok(0));
-        assert_eq!(e.read(&mut [0; 1024]), Ok(0));
-        assert_eq!(e.by_ref().read(&mut [0; 1024]), Ok(0));
+        assert_eq!(e.read(&mut []).unwrap(), 0);
+        assert_eq!(e.read(&mut [0]).unwrap(), 0);
+        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
+        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
     }
 
     #[test]
     fn repeat_repeats() {
         let mut r = repeat(4);
         let mut b = [0; 1024];
-        assert_eq!(r.read(&mut b), Ok(1024));
+        assert_eq!(r.read(&mut b).unwrap(), 1024);
         assert!(b.iter().all(|b| *b == 4));
     }
 
     #[test]
     fn take_some_bytes() {
         assert_eq!(repeat(4).take(100).bytes().count(), 100);
-        assert_eq!(repeat(4).take(100).bytes().next(), Some(Ok(4)));
+        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
         assert_eq!(repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(), 20);
     }
 
@@ -146,7 +146,7 @@ fn tee() {
         let mut buf = [0; 10];
         {
             let mut ptr: &mut [u8] = &mut buf;
-            assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]), Ok(5));
+            assert_eq!(repeat(4).tee(&mut ptr).take(5).read(&mut [0; 10]).unwrap(), 5);
         }
         assert_eq!(buf, [4, 4, 4, 4, 4, 0, 0, 0, 0, 0]);
     }
@@ -160,7 +160,7 @@ fn broadcast() {
             let mut ptr2: &mut [u8] = &mut buf2;
 
             assert_eq!((&mut ptr1).broadcast(&mut ptr2)
-                                  .write(&[1, 2, 3]), Ok(3));
+                                  .write(&[1, 2, 3]).unwrap(), 3);
         }
         assert_eq!(buf1, buf2);
         assert_eq!(buf1, [1, 2, 3, 0, 0, 0, 0, 0, 0, 0]);
index b7cb8f9ed50fdcbec680f17db933b23fca299ae4..41ac3d60df5581db331d3cc4bdd6a4ac99586622 100644 (file)
@@ -44,7 +44,7 @@
 //! lives in the [`vec`](vec/index.html) module. Contiguous, unsized regions
 //! of memory, `[T]`, commonly called "slices", and their borrowed versions,
 //! `&[T]`, commonly called "borrowed slices", are built-in types for which the
-//! for which the [`slice`](slice/index.html) module defines many methods.
+//! [`slice`](slice/index.html) module defines many methods.
 //!
 //! `&str`, a UTF-8 string, is a built-in type, and the standard library
 //! defines methods for it on a variety of traits in the
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(macro_reexport)]
 #![feature(unique)]
-#![feature(convert)]
 #![feature(allow_internal_unstable)]
 #![feature(str_char)]
 #![feature(into_cow)]
-#![feature(slice_patterns)]
 #![feature(std_misc)]
+#![feature(slice_patterns)]
 #![feature(debug_builders)]
 #![cfg_attr(test, feature(test, rustc_private, std_misc))]
 
 #[cfg(not(test))] pub use core::cmp;
 pub use core::convert;
 pub use core::default;
-#[allow(deprecated)]
-pub use core::finally;
 pub use core::hash;
 pub use core::intrinsics;
 pub use core::iter;
index 645bc5db753d0a1067c5d3beb2c15301a0c3242d..b3d1adb44218a7e302037dd466640ece8a2039e0 100644 (file)
@@ -101,7 +101,7 @@ macro_rules! try {
     ($expr:expr) => (match $expr {
         $crate::result::Result::Ok(val) => val,
         $crate::result::Result::Err(err) => {
-            return $crate::result::Result::Err($crate::error::FromError::from_error(err))
+            return $crate::result::Result::Err($crate::convert::From::from(err))
         }
     })
 }
index a08b33b342bece06aebe3183e2646b9301a2d70b..c45230e91ba9ea9b8e17b23657836934dd210cbf 100644 (file)
@@ -435,7 +435,7 @@ macro_rules! try_opt {
                 match $e {
                     Some(r) => r,
                     None => return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                                      $msg, None)),
+                                                      $msg)),
                 }
             )
         }
@@ -697,8 +697,11 @@ fn check(str_addr: &str, unspec: bool, loopback: bool,
               false, false, false, true,  false, false, false, Some(Global));
     }
 
-    fn tsa<A: ToSocketAddrs>(a: A) -> io::Result<Vec<SocketAddr>> {
-        Ok(try!(a.to_socket_addrs()).collect())
+    fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
+        match a.to_socket_addrs() {
+            Ok(a) => Ok(a.collect()),
+            Err(e) => Err(e.to_string()),
+        }
     }
 
     #[test]
index ee57300765e8ef3fb19a8ceeef83642cd5743f00..a152b98822a0bead2e9c337d927ca36d21a8fb02 100644 (file)
@@ -72,7 +72,7 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
     }
     Err(last_err.unwrap_or_else(|| {
         Error::new(ErrorKind::InvalidInput,
-                   "could not resolve to any addresses", None)
+                   "could not resolve to any addresses")
     }))
 }
 
index 869faa795f9c3fb1c0cd506578ac26cc67360bb4..04d1013af1faec67fd37be4cd91415bad249241f 100644 (file)
@@ -17,7 +17,7 @@
 use io;
 use net::{ToSocketAddrs, SocketAddr, Shutdown};
 use sys_common::net2 as net_imp;
-use sys_common::AsInner;
+use sys_common::{AsInner, FromInner};
 
 /// A structure which represents a TCP stream between a local socket and a
 /// remote socket.
@@ -100,13 +100,6 @@ pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         self.0.peer_addr()
     }
 
-    /// Returns the socket address of the local half of this TCP connection.
-    #[unstable(feature = "net")]
-    #[deprecated(since = "1.0.0", reason = "renamed to local_addr")]
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        self.0.socket_addr()
-    }
-
     /// Returns the socket address of the local half of this TCP connection.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
@@ -172,6 +165,10 @@ impl AsInner<net_imp::TcpStream> for TcpStream {
     fn as_inner(&self) -> &net_imp::TcpStream { &self.0 }
 }
 
+impl FromInner<net_imp::TcpStream> for TcpStream {
+    fn from_inner(inner: net_imp::TcpStream) -> TcpStream { TcpStream(inner) }
+}
+
 impl TcpListener {
     /// Creates a new `TcpListener` which will be bound to the specified
     /// address.
@@ -195,13 +192,6 @@ pub fn local_addr(&self) -> io::Result<SocketAddr> {
         self.0.socket_addr()
     }
 
-    /// Deprecated, renamed to local_addr
-    #[unstable(feature = "net")]
-    #[deprecated(since = "1.0.0", reason = "renamed to local_addr")]
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        self.0.socket_addr()
-    }
-
     /// Create a new independently owned handle to the underlying socket.
     ///
     /// The returned `TcpListener` is a reference to the same socket that this
@@ -245,6 +235,12 @@ impl AsInner<net_imp::TcpListener> for TcpListener {
     fn as_inner(&self) -> &net_imp::TcpListener { &self.0 }
 }
 
+impl FromInner<net_imp::TcpListener> for TcpListener {
+    fn from_inner(inner: net_imp::TcpListener) -> TcpListener {
+        TcpListener(inner)
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
@@ -349,7 +345,7 @@ fn smoke_test_ip6() {
             let _t = thread::spawn(move|| {
                 let mut stream = t!(TcpStream::connect(&addr));
                 t!(stream.write(&[99]));
-                tx.send(t!(stream.socket_addr())).unwrap();
+                tx.send(t!(stream.local_addr())).unwrap();
             });
 
             let (mut stream, addr) = t!(acceptor.accept());
@@ -499,7 +495,7 @@ fn connect(i: usize, addr: SocketAddr) {
     fn socket_and_peer_name_ip4() {
         each_ip(&mut |addr| {
             let listener = t!(TcpListener::bind(&addr));
-            let so_name = t!(listener.socket_addr());
+            let so_name = t!(listener.local_addr());
             assert_eq!(addr, so_name);
             let _t = thread::spawn(move|| {
                 t!(listener.accept());
@@ -525,7 +521,7 @@ fn partial_read() {
 
             let mut c = t!(TcpStream::connect(&addr));
             let mut b = [0; 10];
-            assert_eq!(c.read(&mut b), Ok(1));
+            assert_eq!(c.read(&mut b).unwrap(), 1);
             t!(c.write(&[1]));
             rx.recv().unwrap();
         })
@@ -570,7 +566,7 @@ fn tcp_clone_smoke() {
             let _t = thread::spawn(move|| {
                 let mut s = t!(TcpStream::connect(&addr));
                 let mut buf = [0, 0];
-                assert_eq!(s.read(&mut buf), Ok(1));
+                assert_eq!(s.read(&mut buf).unwrap(), 1);
                 assert_eq!(buf[0], 1);
                 t!(s.write(&[2]));
             });
@@ -588,7 +584,7 @@ fn tcp_clone_smoke() {
             });
             tx1.send(()).unwrap();
             let mut buf = [0, 0];
-            assert_eq!(s1.read(&mut buf), Ok(1));
+            assert_eq!(s1.read(&mut buf).unwrap(), 1);
             rx2.recv().unwrap();
         })
     }
@@ -661,7 +657,7 @@ fn shutdown_smoke() {
             let _t = thread::spawn(move|| {
                 let mut c = t!(a.accept()).0;
                 let mut b = [0];
-                assert_eq!(c.read(&mut b), Ok(0));
+                assert_eq!(c.read(&mut b).unwrap(), 0);
                 t!(c.write(&[1]));
             });
 
@@ -692,16 +688,16 @@ fn close_readwrite_smoke() {
             t!(s.shutdown(Shutdown::Write));
             assert!(s.write(&[0]).is_err());
             t!(s.shutdown(Shutdown::Read));
-            assert_eq!(s.read(&mut b), Ok(0));
+            assert_eq!(s.read(&mut b).unwrap(), 0);
 
             // closing should affect previous handles
             assert!(s2.write(&[0]).is_err());
-            assert_eq!(s2.read(&mut b), Ok(0));
+            assert_eq!(s2.read(&mut b).unwrap(), 0);
 
             // closing should affect new handles
             let mut s3 = t!(s.try_clone());
             assert!(s3.write(&[0]).is_err());
-            assert_eq!(s3.read(&mut b), Ok(0));
+            assert_eq!(s3.read(&mut b).unwrap(), 0);
 
             // make sure these don't die
             let _ = s2.shutdown(Shutdown::Read);
index 811511149628e640a2254600c7f301e3bc4e54c1..7b14e4dbea6788420954a43731d8853ddb154a66 100644 (file)
@@ -16,7 +16,7 @@
 use io::{self, Error, ErrorKind};
 use net::{ToSocketAddrs, SocketAddr, IpAddr};
 use sys_common::net2 as net_imp;
-use sys_common::AsInner;
+use sys_common::{AsInner, FromInner};
 
 /// A User Datagram Protocol socket.
 ///
@@ -76,17 +76,10 @@ pub fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], addr: A)
         match try!(addr.to_socket_addrs()).next() {
             Some(addr) => self.0.send_to(buf, &addr),
             None => Err(Error::new(ErrorKind::InvalidInput,
-                                   "no addresses to send data to", None)),
+                                   "no addresses to send data to")),
         }
     }
 
-    /// Returns the socket address that this socket was created from.
-    #[unstable(feature = "net")]
-    #[deprecated(since = "1.0.0", reason = "renamed to local_addr")]
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        self.0.socket_addr()
-    }
-
     /// Returns the socket address that this socket was created from.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
@@ -140,6 +133,10 @@ impl AsInner<net_imp::UdpSocket> for UdpSocket {
     fn as_inner(&self) -> &net_imp::UdpSocket { &self.0 }
 }
 
+impl FromInner<net_imp::UdpSocket> for UdpSocket {
+    fn from_inner(inner: net_imp::UdpSocket) -> UdpSocket { UdpSocket(inner) }
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
@@ -203,7 +200,7 @@ fn socket_smoke_test_ip4() {
     fn socket_name_ip4() {
         each_ip(&mut |addr, _| {
             let server = t!(UdpSocket::bind(&addr));
-            assert_eq!(addr, t!(server.socket_addr()));
+            assert_eq!(addr, t!(server.local_addr()));
         })
     }
 
@@ -215,7 +212,7 @@ fn udp_clone_smoke() {
 
             let _t = thread::spawn(move|| {
                 let mut buf = [0, 0];
-                assert_eq!(sock2.recv_from(&mut buf), Ok((1, addr1)));
+                assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
                 assert_eq!(buf[0], 1);
                 t!(sock2.send_to(&[2], &addr1));
             });
@@ -231,7 +228,7 @@ fn udp_clone_smoke() {
             });
             tx1.send(()).unwrap();
             let mut buf = [0, 0];
-            assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2)));
+            assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
             rx2.recv().unwrap();
         })
     }
index ad6cac621733b815472affd508d80c5210ddf09f..68aa7e4770f067e3cada0738e0256ac7381d242a 100644 (file)
@@ -548,7 +548,7 @@ fn test_buffered_writer_inner_flushes() {
         let mut w = BufferedWriter::with_capacity(3, Vec::new());
         w.write_all(&[0, 1]).unwrap();
         let a: &[_] = &[];
-        assert_eq!(a, &w.get_ref()[..]);
+        assert_eq!(&w.get_ref()[..], a);
         let w = w.into_inner();
         let a: &[_] = &[0, 1];
         assert_eq!(a, &w[..]);
index 0e5dd3aa4aac2862fca5478d305b3d7dc2304de1..73973d0db282d26c92c8adc059d46bb0f1c5dc96 100644 (file)
@@ -519,7 +519,8 @@ macro_rules! u64_from_be_bytes_bench_impl {
         ({
             use super::u64_from_be_bytes;
 
-            let data = (0..$stride*100+$start_index).collect::<Vec<_>>();
+            let len = ($stride as u8).wrapping_mul(100).wrapping_add($start_index);
+            let data = (0..len).collect::<Vec<_>>();
             let mut sum = 0;
             $b.iter(|| {
                 let mut i = $start_index;
index 6aa63c395c62501efb5620a33d9d34996f5a8728..bef6ea53e5085c2dc0f68c1055917dcaaba0237f 100644 (file)
@@ -951,7 +951,8 @@ fn drop(&mut self) {
     pub fn tmpdir() -> TempDir {
         use os;
         use rand;
-        let ret = os::tmpdir().join(format!("rust-{}", rand::random::<u32>()));
+        let temp = Path::new(::env::temp_dir().to_str().unwrap());
+        let ret = temp.join(format!("rust-{}", rand::random::<u32>()));
         check!(old_io::fs::mkdir(&ret, old_io::USER_RWX));
         TempDir(ret)
     }
@@ -1639,7 +1640,7 @@ fn binary_file() {
 
         check!(File::create(&tmpdir.join("test")).write(&bytes));
         let actual = check!(File::open(&tmpdir.join("test")).read_to_end());
-        assert!(actual == bytes.as_slice());
+        assert!(actual == &bytes[..]);
     }
 
     #[test]
index 64803191d4f14e7a51235d62c2de629665240385..c92e74fbc565e10b3a84aa46c67b86a630d816d8 100644 (file)
@@ -399,7 +399,7 @@ fn fill_buf(&mut self) -> IoResult<&[u8]> {
 mod test {
     extern crate test as test_crate;
     use old_io::{SeekSet, SeekCur, SeekEnd, Reader, Writer, Seek, Buffer};
-    use prelude::v1::{Ok, Err, Vec,  AsSlice};
+    use prelude::v1::{Ok, Err, Vec};
     use prelude::v1::Iterator;
     use old_io;
     use iter::repeat;
@@ -744,7 +744,7 @@ fn bench_buf_writer(b: &mut Bencher) {
                     wr.write(&[5; 10]).unwrap();
                 }
             }
-            assert_eq!(buf.as_slice(), [5; 100].as_slice());
+            assert_eq!(&buf[..], &[5; 100][..]);
         });
     }
 
index df8ac78f7e581c107d85d9c32f3a895788af72bb..9d7e1082d33b14fb42e76612a3b67debd55be8c6 100644 (file)
 use ops::FnOnce;
 use option::Option;
 use option::Option::{Some, None};
-use os;
+use sys::os;
 use boxed::Box;
 use result::Result;
 use result::Result::{Ok, Err};
index 26e1bb6550b7a152887e05d26a246f2dd1cb8b8f..099fe657f2602b761d74e3cffb955240b54a4434 100644 (file)
@@ -414,7 +414,7 @@ fn from_str(s: &str) -> Result<SocketAddr, ParseError> {
 /// Some examples:
 ///
 /// ```rust,no_run
-/// # #![feature(old_io, core)]
+/// # #![feature(old_io, core, convert)]
 /// # #![allow(unused_must_use)]
 ///
 /// use std::old_io::{TcpStream, TcpListener};
@@ -435,7 +435,7 @@ fn from_str(s: &str) -> Result<SocketAddr, ParseError> {
 ///     let tcp_l = TcpListener::bind("localhost:12345");
 ///
 ///     let mut udp_s = UdpSocket::bind(("127.0.0.1", 23451)).unwrap();
-///     udp_s.send_to([7, 7, 7].as_slice(), (Ipv4Addr(127, 0, 0, 1), 23451));
+///     udp_s.send_to([7, 7, 7].as_ref(), (Ipv4Addr(127, 0, 0, 1), 23451));
 /// }
 /// ```
 pub trait ToSocketAddr {
index 26f2460047982eb3223604cfc173e40eb1e522e8..fd1df49473e586d4bd6c40b8a497bf1a1937d963 100644 (file)
@@ -124,9 +124,9 @@ fn partial_read() {
         use os;
         use old_io::pipe::PipeStream;
 
-        let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
-        let out = PipeStream::open(writer);
-        let mut input = PipeStream::open(reader);
+        let (reader, writer) = unsafe { ::sys::os::pipe().unwrap() };
+        let out = PipeStream::open(writer.unwrap());
+        let mut input = PipeStream::open(reader.unwrap());
         let (tx, rx) = channel();
         let _t = thread::spawn(move|| {
             let mut out = out;
index 06940bf6860a409e8ebe3cf6a8ef865faa46eab7..ad2d5b4681978c99e5231f20cacdaad5eb4ee7c8 100644 (file)
@@ -246,7 +246,7 @@ fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap {
             None => {
                 // if the env is currently just inheriting from the parent's,
                 // materialize the parent's env into a hashtable.
-                self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
+                self.env = Some(::env::vars().map(|(k, v)| {
                     (EnvKey(CString::new(k).unwrap()),
                      CString::new(v).unwrap())
                 }).collect());
@@ -367,7 +367,7 @@ pub fn spawn(&self) -> IoResult<Process> {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(old_io, core)]
+    /// # #![feature(old_io, core, convert)]
     /// use std::old_io::Command;
     ///
     /// let output = match Command::new("cat").arg("foot.txt").output() {
@@ -376,8 +376,8 @@ pub fn spawn(&self) -> IoResult<Process> {
     /// };
     ///
     /// println!("status: {}", output.status);
-    /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice()));
-    /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice()));
+    /// println!("stdout: {}", String::from_utf8_lossy(output.output.as_ref()));
+    /// println!("stderr: {}", String::from_utf8_lossy(output.error.as_ref()));
     /// ```
     pub fn output(&self) -> IoResult<ProcessOutput> {
         self.spawn().and_then(|p| p.wait_with_output())
@@ -764,11 +764,9 @@ fn drop(&mut self) {
 
 #[cfg(test)]
 mod tests {
+    use prelude::v1::*;
     use old_io::{Truncate, Write, TimedOut, timer, process, FileNotFound};
     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::*;
@@ -1003,7 +1001,7 @@ fn test_keep_current_working_dir() {
         let prog = pwd_cmd().spawn().unwrap();
 
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
-        let parent_dir = os::getcwd().unwrap();
+        let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap());
         let child_dir = Path::new(output.trim());
 
         let parent_stat = parent_dir.stat().unwrap();
@@ -1018,7 +1016,7 @@ fn test_change_working_directory() {
         use os;
         // test changing to the parent of os::getcwd() because we know
         // the path exists (and os::getcwd() is not expected to be root)
-        let parent_dir = os::getcwd().unwrap().dir_path();
+        let parent_dir = Path::new(::env::current_dir().unwrap().to_str().unwrap());
         let prog = pwd_cmd().cwd(&parent_dir).spawn().unwrap();
 
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
@@ -1058,11 +1056,11 @@ fn test_inherit_env() {
         let prog = env_cmd().spawn().unwrap();
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
 
-        let r = os::env();
-        for &(ref k, ref v) in &r {
+        let r = ::env::vars();
+        for (k, v) in r {
             // don't check windows magical empty-named variables
             assert!(k.is_empty() ||
-                    output.contains(&format!("{}={}", *k, *v)),
+                    output.contains(&format!("{}={}", k, v)),
                     "output doesn't contain `{}={}`\n{}",
                     k, v, output);
         }
@@ -1076,16 +1074,12 @@ fn test_inherit_env() {
         let mut prog = env_cmd().spawn().unwrap();
         let output = String::from_utf8(prog.wait_with_output().unwrap().output).unwrap();
 
-        let r = os::env();
-        for &(ref k, ref v) in &r {
+        let r = ::env::vars();
+        for (k, v) in r {
             // don't check android RANDOM variables
-            if *k != "RANDOM".to_string() {
-                assert!(output.contains(&format!("{}={}",
-                                                 *k,
-                                                 *v)) ||
-                        output.contains(&format!("{}=\'{}\'",
-                                                 *k,
-                                                 *v)));
+            if k != "RANDOM".to_string() {
+                assert!(output.contains(&format!("{}={}", k, v)) ||
+                        output.contains(&format!("{}=\'{}\'", k, v)));
             }
         }
     }
@@ -1100,9 +1094,9 @@ fn test_override_env() {
         // PATH to our sub-process.
         let path_val: String;
         let mut new_env = vec![("RUN_TEST_NEW_ENV", "123")];
-        match os::getenv("PATH") {
-            None => {}
-            Some(val) => {
+        match ::env::var("PATH") {
+            Err(..) => {}
+            Ok(val) => {
                 path_val = val;
                 new_env.push(("PATH", &path_val))
             }
index 0a2cc517a0631096ed58ddc0b3a2e70fc0971b73..94faa5540bb30d538945a8e27b8c239a61345aee 100644 (file)
@@ -100,7 +100,8 @@ impl TempDir {
     #[allow(deprecated)]
     pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
         if !tmpdir.is_absolute() {
-            let cur_dir = try!(::os::getcwd());
+            let cur_dir = ::env::current_dir().unwrap();
+            let cur_dir = Path::new(cur_dir.to_str().unwrap());
             return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
         }
 
@@ -136,7 +137,8 @@ pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
     /// If no directory can be created, `Err` is returned.
     #[allow(deprecated)]
     pub fn new(prefix: &str) -> IoResult<TempDir> {
-        TempDir::new_in(&::os::tmpdir(), prefix)
+        let tmp = Path::new(::env::temp_dir().to_str().unwrap());
+        TempDir::new_in(&tmp, prefix)
     }
 
     /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
index db409ecde452612be8b1fedf2a55c22fc6dbfb63..312e1c814dc58e730c588e446da5dbcd877879ce 100644 (file)
@@ -43,7 +43,7 @@ fn next_test_unix_socket() -> String {
 pub fn next_test_unix() -> Path {
     let string = next_test_unix_socket();
     if cfg!(unix) {
-        ::os::tmpdir().join(string)
+        Path::new(::env::temp_dir().to_str().unwrap()).join(string)
     } else {
         Path::new(format!("{}{}", r"\\.\pipe\", string))
     }
@@ -141,7 +141,7 @@ pub unsafe fn raise_fd_limit() {
         // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
         use ptr::null_mut;
         use mem::size_of_val;
-        use os::last_os_error;
+        use io;
 
         // Fetch the kern.maxfilesperproc value
         let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
@@ -149,14 +149,14 @@ pub unsafe fn raise_fd_limit() {
         let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
         if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size,
                   null_mut(), 0) != 0 {
-            let err = last_os_error();
+            let err = io::Error::last_os_error();
             panic!("raise_fd_limit: error calling sysctl: {}", err);
         }
 
         // Fetch the current resource limits
         let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
         if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 {
-            let err = last_os_error();
+            let err = io::Error::last_os_error();
             panic!("raise_fd_limit: error calling getrlimit: {}", err);
         }
 
@@ -165,7 +165,7 @@ pub unsafe fn raise_fd_limit() {
 
         // Set our newly-increased resource limit
         if setrlimit(RLIMIT_NOFILE, &rlim) != 0 {
-            let err = last_os_error();
+            let err = io::Error::last_os_error();
             panic!("raise_fd_limit: error calling setrlimit: {}", err);
         }
     }
index 604099f117884a5126a821af919607d57e2269e3..a5ecb98334a81f1fc977e17f2ff4d021d7a7b261 100644 (file)
@@ -334,7 +334,7 @@ fn test_limit_reader_unlimited() {
         let mut r = MemReader::new(vec!(0, 1, 2));
         {
             let mut r = LimitReader::new(r.by_ref(), 4);
-            assert_eq!([0, 1, 2], r.read_to_end().unwrap());
+            assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]);
         }
     }
 
@@ -343,9 +343,9 @@ fn test_limit_reader_limited() {
         let mut r = MemReader::new(vec!(0, 1, 2));
         {
             let mut r = LimitReader::new(r.by_ref(), 2);
-            assert_eq!([0, 1], r.read_to_end().unwrap());
+            assert_eq!(r.read_to_end().unwrap(), [0, 1]);
         }
-        assert_eq!([2], r.read_to_end().unwrap());
+        assert_eq!(r.read_to_end().unwrap(), [2]);
     }
 
     #[test]
@@ -355,7 +355,7 @@ fn test_limit_reader_limit() {
         assert_eq!(3, r.limit());
         assert_eq!(0, r.read_byte().unwrap());
         assert_eq!(2, r.limit());
-        assert_eq!([1, 2], r.read_to_end().unwrap());
+        assert_eq!(r.read_to_end().unwrap(), [1, 2]);
         assert_eq!(0, r.limit());
     }
 
@@ -364,7 +364,7 @@ fn test_limit_reader_overlong_consume() {
         let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]);
         let mut r = LimitReader::new(r.by_ref(), 1);
         r.consume(2);
-        assert_eq!([], r.read_to_end().unwrap());
+        assert_eq!(r.read_to_end().unwrap(), []);
     }
 
     #[test]
@@ -380,7 +380,7 @@ fn test_zero_reader() {
         let mut s = ZeroReader;
         let mut buf = vec![1, 2, 3];
         assert_eq!(s.read(&mut buf), Ok(3));
-        assert_eq!([0, 0, 0], buf);
+        assert_eq!(buf, [0, 0, 0]);
     }
 
     #[test]
@@ -423,16 +423,16 @@ fn test_chained_reader() {
         let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()),
                       MemReader::new(vec!(2, 3)));
         let mut r = ChainedReader::new(rs.into_iter());
-        assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap());
+        assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]);
     }
 
     #[test]
     fn test_tee_reader() {
         let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
                                    Vec::new());
-        assert_eq!([0, 1, 2], r.read_to_end().unwrap());
+        assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]);
         let (_, w) = r.into_inner();
-        assert_eq!([0, 1, 2], w);
+        assert_eq!(w, [0, 1, 2]);
     }
 
     #[test]
@@ -440,7 +440,7 @@ fn test_copy() {
         let mut r = MemReader::new(vec!(0, 1, 2, 3, 4));
         let mut w = Vec::new();
         copy(&mut r, &mut w).unwrap();
-        assert_eq!([0, 1, 2, 3, 4], w);
+        assert_eq!(w, [0, 1, 2, 3, 4]);
     }
 
     #[test]
index c405df2824e818bc4736c3d8b4e264d923f048d3..9c88533d3bac605cb55b328b7265b8cb98a9ab5b 100644 (file)
 use core::marker::Sized;
 use ffi::CString;
 use clone::Clone;
+use borrow::Cow;
 use fmt;
 use iter::Iterator;
 use option::Option;
 use option::Option::{None, Some};
 use str;
-use string::{String, CowString};
+use string::String;
 use vec::Vec;
 
 /// Typedef for POSIX file paths.
@@ -907,7 +908,7 @@ impl<'a, P: GenericPath> Display<'a, P> {
     /// If the path is not UTF-8, invalid sequences will be replaced with the
     /// Unicode replacement char. This involves allocation.
     #[inline]
-    pub fn as_cow(&self) -> CowString<'a> {
+    pub fn as_cow(&self) -> Cow<'a, str> {
         String::from_utf8_lossy(if self.filename {
             match self.path.filename() {
                 None => {
index bbc1756bee6321004625b2bd4c14a0d3ede76859..c517fab257f9574678d813ff07b0e20c63da59f9 100644 (file)
@@ -20,7 +20,7 @@
 use marker::Sized;
 use option::Option::{self, Some, None};
 use result::Result::{self, Ok, Err};
-use slice::{AsSlice, Split, SliceConcatExt};
+use slice::{Split, SliceConcatExt};
 use str::{self, FromStr};
 use vec::Vec;
 
@@ -126,7 +126,7 @@ unsafe fn new_unchecked<T: BytesContainer>(path: T) -> Path {
     unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
         let filename = filename.container_as_bytes();
         match self.sepidx {
-            None if b".." == self.repr => {
+            None if self.repr == b".." => {
                 let mut v = Vec::with_capacity(3 + filename.len());
                 v.push_all(dot_dot_static);
                 v.push(SEP_BYTE);
@@ -186,7 +186,7 @@ fn into_vec(self) -> Vec<u8> {
 
     fn dirname<'a>(&'a self) -> &'a [u8] {
         match self.sepidx {
-            None if b".." == self.repr => &self.repr,
+            None if self.repr == b".." => &self.repr,
             None => dot_static,
             Some(0) => &self.repr[..1],
             Some(idx) if &self.repr[idx+1..] == b".." => &self.repr,
@@ -196,8 +196,7 @@ fn dirname<'a>(&'a self) -> &'a [u8] {
 
     fn filename<'a>(&'a self) -> Option<&'a [u8]> {
         match self.sepidx {
-            None if b"." == self.repr ||
-                b".." == self.repr => None,
+            None if self.repr == b"." || self.repr == b".." => None,
             None => Some(&self.repr),
             Some(idx) if &self.repr[idx+1..] == b".." => None,
             Some(0) if self.repr[1..].is_empty() => None,
@@ -207,13 +206,13 @@ fn filename<'a>(&'a self) -> Option<&'a [u8]> {
 
     fn pop(&mut self) -> bool {
         match self.sepidx {
-            None if b"." == self.repr => false,
+            None if self.repr == b"." => false,
             None => {
                 self.repr = vec![b'.'];
                 self.sepidx = None;
                 true
             }
-            Some(0) if b"/" == self.repr => false,
+            Some(0) if self.repr == b"/" => false,
             Some(idx) => {
                 if idx == 0 {
                     self.repr.truncate(idx+1);
@@ -245,7 +244,7 @@ fn is_ancestor_of(&self, other: &Path) -> bool {
         } else {
             let mut ita = self.components();
             let mut itb = other.components();
-            if b"." == self.repr {
+            if self.repr == b"." {
                 return match itb.next() {
                     None => true,
                     Some(b) => b != b".."
@@ -339,11 +338,11 @@ pub fn new_opt<T: BytesContainer>(path: T) -> Option<Path> {
 
     /// Returns a normalized byte vector representation of a path, by removing all empty
     /// components, and unnecessary . and .. components.
-    fn normalize<V: ?Sized + AsSlice<u8>>(v: &V) -> Vec<u8> {
+    fn normalize(v: &[u8]) -> Vec<u8> {
         // borrowck is being very picky
         let val = {
-            let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
-            let v_ = if is_abs { &v.as_slice()[1..] } else { v.as_slice() };
+            let is_abs = !v.is_empty() && v[0] == SEP_BYTE;
+            let v_ = if is_abs { &v[1..] } else { v };
             let comps = normalize_helper(v_, is_abs);
             match comps {
                 None => None,
@@ -371,7 +370,7 @@ fn normalize<V: ?Sized + AsSlice<u8>>(v: &V) -> Vec<u8> {
             }
         };
         match val {
-            None => v.as_slice().to_vec(),
+            None => v.to_vec(),
             Some(val) => val
         }
     }
@@ -446,8 +445,7 @@ mod tests {
     use clone::Clone;
     use option::Option::{self, Some, None};
     use old_path::GenericPath;
-    use slice::AsSlice;
-    use str::{self, Str};
+    use str;
     use string::ToString;
     use vec::Vec;
     use iter::Iterator;
index bd67855bf1b8c45fbbe4d4a6932844c4d8f072c1..0b88f368b3952aa9985839ec42636dc40e88f70c 100644 (file)
@@ -1129,8 +1129,6 @@ mod tests {
     use iter::Iterator;
     use option::Option::{self, Some, None};
     use old_path::GenericPath;
-    use slice::AsSlice;
-    use str::Str;
     use string::ToString;
     use vec::Vec;
 
index e19c734b8a3acc3646a8712c4ff83558d16389ea..ee0f04cb9911cc8ccf55bd53e262b8cf5d0ccebf 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Higher-level interfaces to libc::* functions and operating system services.
-//!
-//! In general these take and return rust types, use rust idioms (enums,
-//! closures, vectors) rather than C idioms, and do more extensive safety
-//! checks.
-//!
-//! This module is not meant to only contain 1:1 mappings to libc entries; any
-//! os-interface code that is reasonably useful and broadly applicable can go
-//! here. Including utility routines that merely build on other os code.
-//!
-//! We assume the general case is that users do not care, and do not want to be
-//! made to care, which operating system they are on. While they may want to
-//! special case various special cases -- and so we will not _hide_ the facts of
-//! which OS the user is on -- they should be given the opportunity to write
-//! OS-ignorant code by default.
+//! OS-specific functionality
 
-#![unstable(feature = "os")]
-#![deprecated(since = "1.0.0", reason = "replaced with std::env APIs")]
-
-#![allow(missing_docs)]
-#![allow(non_snake_case)]
-#![allow(unused_imports)]
-#![allow(deprecated)]
-
-use self::MemoryMapKind::*;
-use self::MapOption::*;
-use self::MapError::*;
-
-use boxed::Box;
-use clone::Clone;
-use convert::From;
-use env;
-use error::{FromError, Error};
-use ffi::{OsString, OsStr};
-use fmt;
-use iter::Iterator;
-use libc::{c_void, c_int, c_char};
-use libc;
-use marker::{Copy, Send};
-use old_io::{IoResult, IoError};
-use ops::{Drop, FnOnce};
-use option::Option::{Some, None};
-use option::Option;
-use old_path::{Path, GenericPath, BytesContainer};
-use path::{self, PathBuf};
-use ptr;
-use result::Result::{Err, Ok};
-use result::Result;
-use slice::AsSlice;
-use str::Str;
-use str;
-use string::{String, ToString};
-use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
-use sys::os as os_imp;
-use sys;
-use vec::Vec;
-
-#[cfg(unix)] use ffi::{self, CString};
+#![stable(feature = "os", since = "1.0.0")]
 
 #[cfg(unix)] pub use sys::ext as unix;
 #[cfg(windows)] pub use sys::ext as windows;
-
-fn err2old(new: ::io::Error) -> IoError {
-    IoError {
-        kind: ::old_io::OtherIoError,
-        desc: "os error",
-        detail: Some(new.to_string()),
-    }
-}
-
-#[cfg(windows)]
-fn path2new(path: &Path) -> PathBuf {
-    PathBuf::from(path.as_str().unwrap())
-}
-#[cfg(unix)]
-fn path2new(path: &Path) -> PathBuf {
-    use os::unix::prelude::*;
-    PathBuf::from(<OsStr as OsStrExt>::from_bytes(path.as_vec()))
-}
-
-#[cfg(unix)]
-fn path2old(path: &path::Path) -> Path {
-    use os::unix::prelude::*;
-    use ffi::AsOsStr;
-    Path::new(path.as_os_str().as_bytes())
-}
-#[cfg(windows)]
-fn path2old(path: &path::Path) -> Path {
-    Path::new(path.to_str().unwrap())
-}
-
-/// Get the number of cores available
-pub fn num_cpus() -> usize {
-    unsafe {
-        return rust_get_num_cpus() as usize;
-    }
-
-    extern {
-        fn rust_get_num_cpus() -> libc::uintptr_t;
-    }
-}
-
-pub const TMPBUF_SZ : usize = 1000;
-
-/// Returns the current working directory as a `Path`.
-///
-/// # Errors
-///
-/// Returns an `Err` if the current working directory value is invalid.
-/// Possible cases:
-///
-/// * Current directory does not exist.
-/// * There are insufficient permissions to access the current directory.
-/// * The internal buffer is not large enough to hold the path.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_path)]
-/// 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();
-/// println!("The current directory is {:?}", current_working_directory.display());
-/// ```
-#[unstable(feature = "os")]
-pub fn getcwd() -> IoResult<Path> {
-    env::current_dir().map_err(err2old).map(|s| path2old(&s))
-}
-
-/// Returns a vector of (variable, value) pairs, for all the environment
-/// variables of the current process.
-///
-/// Invalid UTF-8 bytes are replaced with \uFFFD. See `String::from_utf8_lossy()`
-/// for details.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os)]
-/// use std::os;
-///
-/// // We will iterate through the references to the element returned by os::env();
-/// for &(ref key, ref value) in os::env().iter() {
-///     println!("'{}': '{}'", key, value );
-/// }
-/// ```
-#[deprecated(since = "1.0.0", reason = "use env::vars instead")]
-#[unstable(feature = "os")]
-pub fn env() -> Vec<(String,String)> {
-    env::vars_os().map(|(k, v)| {
-        (k.to_string_lossy().into_owned(), v.to_string_lossy().into_owned())
-    }).collect()
-}
-
-/// Returns a vector of (variable, value) byte-vector pairs for all the
-/// environment variables of the current process.
-#[deprecated(since = "1.0.0", reason = "use env::vars_os instead")]
-#[unstable(feature = "os")]
-pub fn env_as_bytes() -> Vec<(Vec<u8>, Vec<u8>)> {
-    env::vars_os().map(|(k, v)| (byteify(k), byteify(v))).collect()
-}
-
-/// Fetches the environment variable `n` from the current process, returning
-/// None if the variable isn't set.
-///
-/// Any invalid UTF-8 bytes in the value are replaced by \uFFFD. See
-/// `String::from_utf8_lossy()` for details.
-///
-/// # Panics
-///
-/// Panics if `n` has any interior NULs.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os)]
-/// use std::os;
-///
-/// let key = "HOME";
-/// match os::getenv(key) {
-///     Some(val) => println!("{}: {}", key, val),
-///     None => println!("{} is not defined in the environment.", key)
-/// }
-/// ```
-#[deprecated(since = "1.0.0", reason = "use env::var instead")]
-#[unstable(feature = "os")]
-pub fn getenv(n: &str) -> Option<String> {
-    env::var(n).ok()
-}
-
-/// Fetches the environment variable `n` byte vector from the current process,
-/// returning None if the variable isn't set.
-///
-/// # Panics
-///
-/// Panics if `n` has any interior NULs.
-#[deprecated(since = "1.0.0", reason = "use env::var_os instead")]
-#[unstable(feature = "os")]
-pub fn getenv_as_bytes(n: &str) -> Option<Vec<u8>> {
-    env::var_os(n).map(byteify)
-}
-
-#[cfg(unix)]
-fn byteify(s: OsString) -> Vec<u8> {
-    use os::unix::prelude::*;
-    s.into_vec()
-}
-#[cfg(windows)]
-fn byteify(s: OsString) -> Vec<u8> {
-    s.to_string_lossy().as_bytes().to_vec()
-}
-
-/// Sets the environment variable `n` to the value `v` for the currently running
-/// process.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os)]
-/// use std::os;
-///
-/// let key = "KEY";
-/// os::setenv(key, "VALUE");
-/// match os::getenv(key) {
-///     Some(ref val) => println!("{}: {}", key, val),
-///     None => println!("{} is not defined in the environment.", key)
-/// }
-/// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::set_var")]
-#[unstable(feature = "os")]
-pub fn setenv<T: BytesContainer>(n: &str, v: T) {
-    #[cfg(unix)]
-    fn _setenv(n: &str, v: &[u8]) {
-        use os::unix::prelude::*;
-        let v: OsString = OsStringExt::from_vec(v.to_vec());
-        env::set_var(n, &v)
-    }
-
-    #[cfg(windows)]
-    fn _setenv(n: &str, v: &[u8]) {
-        let v = str::from_utf8(v).unwrap();
-        env::set_var(n, v)
-    }
-
-    _setenv(n, v.container_as_bytes())
-}
-
-/// Remove a variable from the environment entirely.
-#[deprecated(since = "1.0.0", reason = "renamed to env::remove_var")]
-#[unstable(feature = "os")]
-pub fn unsetenv(n: &str) {
-    env::remove_var(n)
-}
-
-/// Parses input according to platform conventions for the `PATH`
-/// environment variable.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(old_path, os)]
-/// use std::os;
-/// use std::old_path::{Path, GenericPath};
-///
-/// let key = "PATH";
-/// match os::getenv_as_bytes(key) {
-///     Some(paths) => {
-///         for path in os::split_paths(paths).iter() {
-///             println!("'{}'", path.display());
-///         }
-///     }
-///     None => println!("{} is not defined in the environment.", key)
-/// }
-/// ```
-#[unstable(feature = "os")]
-pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
-    let b = unparsed.container_as_bytes();
-    let s = str::from_utf8(b).unwrap();
-    env::split_paths(s).map(|s| path2old(&s)).collect()
-}
-
-/// Joins a collection of `Path`s appropriately for the `PATH`
-/// environment variable.
-///
-/// Returns a `Vec<u8>` on success, since `Path`s are not utf-8
-/// encoded on all platforms.
-///
-/// Returns an `Err` (containing an error message) if one of the input
-/// `Path`s contains an invalid character for constructing the `PATH`
-/// variable (a double quote on Windows or a colon on Unix).
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_path, core)]
-/// use std::os;
-/// use std::old_path::Path;
-///
-/// let key = "PATH";
-/// let mut paths = os::getenv_as_bytes(key).map_or(Vec::new(), os::split_paths);
-/// paths.push(Path::new("/home/xyz/bin"));
-/// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
-/// ```
-#[unstable(feature = "os")]
-pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
-    env::join_paths(paths.iter().map(|s| {
-        str::from_utf8(s.container_as_bytes()).unwrap()
-    })).map(|s| {
-        s.to_string_lossy().into_owned().into_bytes()
-    }).map_err(|_| "failed to join paths")
-}
-
-/// A low-level OS in-memory pipe.
-#[derive(Copy)]
-pub struct Pipe {
-    /// A file descriptor representing the reading end of the pipe. Data written
-    /// on the `out` file descriptor can be read from this file descriptor.
-    pub reader: c_int,
-    /// A file descriptor representing the write end of the pipe. Data written
-    /// to this file descriptor can be read from the `input` file descriptor.
-    pub writer: c_int,
-}
-
-/// Creates a new low-level OS in-memory pipe.
-///
-/// This function can fail to succeed if there are no more resources available
-/// to allocate a pipe.
-///
-/// This function is also unsafe as there is no destructor associated with the
-/// `Pipe` structure will return. If it is not arranged for the returned file
-/// descriptors to be closed, the file descriptors will leak. For safe handling
-/// of this scenario, use `std::old_io::PipeStream` instead.
-pub unsafe fn pipe() -> IoResult<Pipe> {
-    let (reader, writer) = try!(sys::os::pipe());
-    Ok(Pipe {
-        reader: reader.unwrap(),
-        writer: writer.unwrap(),
-    })
-}
-
-/// Returns the proper dll filename for the given basename of a file
-/// as a String.
-#[cfg(not(target_os="ios"))]
-#[deprecated(since = "1.0.0", reason = "this function will be removed, use the constants directly")]
-#[unstable(feature = "os")]
-#[allow(deprecated)]
-pub fn dll_filename(base: &str) -> String {
-    format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX)
-}
-
-/// Optionally returns the filesystem path to the current executable which is
-/// running but with the executable name.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_path)]
-/// 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()),
-///     None => println!("Unable to get the path of this executable!")
-/// };
-/// ```
-#[unstable(feature = "os")]
-pub fn self_exe_name() -> Option<Path> {
-    env::current_exe().ok().map(|p| path2old(&p))
-}
-
-/// Optionally returns the filesystem path to the current executable which is
-/// running.
-///
-/// Like self_exe_name() but without the binary's name.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_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()),
-///     None => println!("Impossible to fetch the path of this executable.")
-/// };
-/// ```
-#[unstable(feature = "os")]
-pub fn self_exe_path() -> Option<Path> {
-    env::current_exe().ok().map(|p| { let mut p = path2old(&p); p.pop(); p })
-}
-
-/// Optionally returns the path to the current user's home directory if known.
-///
-/// # Unix
-///
-/// Returns the value of the 'HOME' environment variable if it is set
-/// and not equal to the empty string.
-///
-/// # Windows
-///
-/// Returns the value of the 'HOME' environment variable if it is
-/// set and not equal to the empty string. Otherwise, returns the value of the
-/// 'USERPROFILE' environment variable if it is set and not equal to the empty
-/// string.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_path)]
-/// use std::os;
-/// use std::old_path::{Path, GenericPath};
-///
-/// match os::homedir() {
-///     Some(ref p) => println!("{}", p.display()),
-///     None => println!("Impossible to get your home dir!")
-/// }
-/// ```
-#[unstable(feature = "os")]
-#[allow(deprecated)]
-pub fn homedir() -> Option<Path> {
-    #[inline]
-    #[cfg(unix)]
-    fn _homedir() -> Option<Path> {
-        aux_homedir("HOME")
-    }
-
-    #[inline]
-    #[cfg(windows)]
-    fn _homedir() -> Option<Path> {
-        aux_homedir("HOME").or(aux_homedir("USERPROFILE"))
-    }
-
-    #[inline]
-    fn aux_homedir(home_name: &str) -> Option<Path> {
-        match getenv_as_bytes(home_name) {
-            Some(p)  => {
-                if p.is_empty() { None } else { Path::new_opt(p) }
-            },
-            _ => None
-        }
-    }
-    _homedir()
-}
-
-/// Returns the path to a temporary directory.
-///
-/// On Unix, returns the value of the 'TMPDIR' environment variable if it is
-/// set, otherwise for non-Android it returns '/tmp'. If Android, since there
-/// is no global temporary folder (it is usually allocated per-app), we return
-/// '/data/local/tmp'.
-///
-/// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
-/// 'USERPROFILE' environment variable  if any are set and not the empty
-/// string. Otherwise, tmpdir returns the path to the Windows directory.
-#[unstable(feature = "os")]
-#[allow(deprecated)]
-pub fn tmpdir() -> Path {
-    return lookup();
-
-    fn getenv_nonempty(v: &str) -> Option<Path> {
-        match getenv(v) {
-            Some(x) =>
-                if x.is_empty() {
-                    None
-                } else {
-                    Path::new_opt(x)
-                },
-            _ => None
-        }
-    }
-
-    #[cfg(unix)]
-    fn lookup() -> Path {
-        let default = if cfg!(target_os = "android") {
-            Path::new("/data/local/tmp")
-        } else {
-            Path::new("/tmp")
-        };
-
-        getenv_nonempty("TMPDIR").unwrap_or(default)
-    }
-
-    #[cfg(windows)]
-    fn lookup() -> Path {
-        getenv_nonempty("TMP").or(
-            getenv_nonempty("TEMP").or(
-                getenv_nonempty("USERPROFILE").or(
-                   getenv_nonempty("WINDIR")))).unwrap_or(Path::new("C:\\Windows"))
-    }
-}
-
-/// Convert a relative path to an absolute path
-///
-/// If the given path is relative, return it prepended with the current working
-/// directory. If the given path is already an absolute path, return it
-/// as is.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_path)]
-/// use std::os;
-/// use std::old_path::{Path, GenericPath};
-///
-/// // Assume we're in a path like /home/someuser
-/// let rel_path = Path::new("..");
-/// let abs_path = os::make_absolute(&rel_path).unwrap();
-/// println!("The absolute path is {}", abs_path.display());
-/// // Prints "The absolute path is /home"
-/// ```
-// NB: this is here rather than in path because it is a form of environment
-// querying; what it does depends on the process working directory, not just
-// the input paths.
-#[deprecated(since = "1.0.0", reason = "use env::current_dir + .join directly")]
-#[unstable(feature = "os")]
-pub fn make_absolute(p: &Path) -> IoResult<Path> {
-    if p.is_absolute() {
-        Ok(p.clone())
-    } else {
-        env::current_dir().map_err(err2old).map(|cwd| {
-            let mut cwd = path2old(&cwd);
-            cwd.push(p);
-            cwd
-        })
-    }
-}
-
-/// Changes the current working directory to the specified path, returning
-/// whether the change was completed successfully or not.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os, old_path)]
-/// use std::os;
-/// use std::old_path::{Path, GenericPath};
-///
-/// let root = Path::new("/");
-/// assert!(os::change_dir(&root).is_ok());
-/// println!("Successfully changed working directory to {}!", root.display());
-/// ```
-#[unstable(feature = "os")]
-pub fn change_dir(p: &Path) -> IoResult<()> {
-    sys::os::chdir(&path2new(p)).map_err(err2old)
-}
-
-/// Returns the platform-specific value of errno
-pub fn errno() -> i32 {
-    sys::os::errno() as i32
-}
-
-/// Return the string corresponding to an `errno()` value of `errnum`.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(os)]
-/// use std::os;
-///
-/// // Same as println!("{}", last_os_error());
-/// println!("{}", os::error_string(os::errno() as i32));
-/// ```
-pub fn error_string(errnum: i32) -> String {
-    return sys::os::error_string(errnum);
-}
-
-/// Get a string representing the platform-dependent last error
-pub fn last_os_error() -> String {
-    error_string(errno())
-}
-
-/// Sets the process exit code
-///
-/// Sets the exit code returned by the process if all supervised tasks
-/// terminate successfully (without panicking). If the current root task panics
-/// and is supervised by the scheduler then any user-specified exit status is
-/// ignored and the process exits with the default panic status.
-///
-/// Note that this is not synchronized against modifications of other threads.
-#[deprecated(since = "1.0.0", reason = "renamed to env::set_exit_status")]
-#[unstable(feature = "os")]
-pub fn set_exit_status(code: isize) {
-    env::set_exit_status(code as i32)
-}
-
-/// Fetches the process's current exit code. This defaults to 0 and can change
-/// by calling `set_exit_status`.
-#[deprecated(since = "1.0.0", reason = "renamed to env::get_exit_status")]
-#[unstable(feature = "os")]
-pub fn get_exit_status() -> isize {
-    env::get_exit_status() as isize
-}
-
-#[cfg(target_os = "macos")]
-unsafe fn load_argc_and_argv(argc: isize,
-                             argv: *const *const c_char) -> Vec<Vec<u8>> {
-    use ffi::CStr;
-
-    (0..argc).map(|i| {
-        CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec()
-    }).collect()
-}
-
-/// Returns the command line arguments
-///
-/// Returns a list of the command line arguments.
-#[cfg(target_os = "macos")]
-fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    unsafe {
-        let (argc, argv) = (*_NSGetArgc() as isize,
-                            *_NSGetArgv() as *const *const c_char);
-        load_argc_and_argv(argc, argv)
-    }
-}
-
-// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
-// and use underscores in their names - they're most probably
-// are considered private and therefore should be avoided
-// Here is another way to get arguments using Objective C
-// runtime
-//
-// In general it looks like:
-// res = Vec::new()
-// let args = [[NSProcessInfo processInfo] arguments]
-// for i in 0..[args count]
-//      res.push([args objectAtIndex:i])
-// res
-#[cfg(target_os = "ios")]
-fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    use ffi::CStr;
-    use iter::range;
-    use mem;
-
-    #[link(name = "objc")]
-    extern {
-        fn sel_registerName(name: *const libc::c_uchar) -> Sel;
-        fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
-        fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
-    }
-
-    #[link(name = "Foundation", kind = "framework")]
-    extern {}
-
-    type Sel = *const libc::c_void;
-    type NsId = *const libc::c_void;
-
-    let mut res = Vec::new();
-
-    unsafe {
-        let processInfoSel = sel_registerName("processInfo\0".as_ptr());
-        let argumentsSel = sel_registerName("arguments\0".as_ptr());
-        let utf8Sel = sel_registerName("UTF8String\0".as_ptr());
-        let countSel = sel_registerName("count\0".as_ptr());
-        let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr());
-
-        let klass = objc_getClass("NSProcessInfo\0".as_ptr());
-        let info = objc_msgSend(klass, processInfoSel);
-        let args = objc_msgSend(info, argumentsSel);
-
-        let cnt: isize = mem::transmute(objc_msgSend(args, countSel));
-        for i in 0..cnt {
-            let tmp = objc_msgSend(args, objectAtSel, i);
-            let utf_c_str: *const libc::c_char =
-                mem::transmute(objc_msgSend(tmp, utf8Sel));
-            res.push(CStr::from_ptr(utf_c_str).to_bytes().to_vec());
-        }
-    }
-
-    res
-}
-
-#[cfg(any(target_os = "linux",
-          target_os = "android",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "openbsd"))]
-fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    use rt;
-    rt::args::clone().unwrap_or_else(|| vec![])
-}
-
-#[cfg(not(windows))]
-fn real_args() -> Vec<String> {
-    real_args_as_bytes().into_iter()
-                        .map(|v| {
-                            String::from_utf8_lossy(&v).into_owned()
-                        }).collect()
-}
-
-#[cfg(windows)]
-fn real_args() -> Vec<String> {
-    use slice;
-    use iter::range;
-
-    let mut nArgs: c_int = 0;
-    let lpArgCount: *mut c_int = &mut nArgs;
-    let lpCmdLine = unsafe { GetCommandLineW() };
-    let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) };
-
-    let args: Vec<_> = (0..nArgs as usize).map(|i| unsafe {
-        // Determine the length of this argument.
-        let ptr = *szArgList.offset(i as isize);
-        let mut len = 0;
-        while *ptr.offset(len as isize) != 0 { len += 1; }
-
-        // Push it onto the list.
-        let ptr = ptr as *const u16;
-        let buf = slice::from_raw_parts(ptr, len);
-        let opt_s = String::from_utf16(sys::truncate_utf16_at_nul(buf));
-        opt_s.ok().expect("CommandLineToArgvW returned invalid UTF-16")
-    }).collect();
-
-    unsafe {
-        LocalFree(szArgList as *mut c_void);
-    }
-
-    return args
-}
-
-#[cfg(windows)]
-fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    real_args().into_iter().map(|s| s.into_bytes()).collect()
-}
-
-type LPCWSTR = *const u16;
-
-#[cfg(windows)]
-#[link_name="kernel32"]
-extern "system" {
-    fn GetCommandLineW() -> LPCWSTR;
-    fn LocalFree(ptr: *mut c_void);
-}
-
-#[cfg(windows)]
-#[link_name="shell32"]
-extern "system" {
-    fn CommandLineToArgvW(lpCmdLine: LPCWSTR,
-                          pNumArgs: *mut c_int) -> *mut *mut u16;
-}
-
-/// Returns the arguments which this program was started with (normally passed
-/// via the command line).
-///
-/// The first element is traditionally the path to the executable, but it can be
-/// set to arbitrary text, and it may not even exist, so this property should not
-/// be relied upon for security purposes.
-///
-/// The arguments are interpreted as utf-8, with invalid bytes replaced with \uFFFD.
-/// See `String::from_utf8_lossy` for details.
-/// # Examples
-///
-/// ```
-/// # #![feature(os)]
-/// use std::os;
-///
-/// // Prints each argument on a separate line
-/// for argument in os::args().iter() {
-///     println!("{}", argument);
-/// }
-/// ```
-#[deprecated(since = "1.0.0", reason = "use std::env::args() instead")]
-#[unstable(feature = "os")]
-pub fn args() -> Vec<String> {
-    real_args()
-}
-
-/// Returns the arguments which this program was started with (normally passed
-/// via the command line) as byte vectors.
-#[deprecated(since = "1.0.0", reason = "use env::args_os instead")]
-#[unstable(feature = "os")]
-pub fn args_as_bytes() -> Vec<Vec<u8>> {
-    real_args_as_bytes()
-}
-
-#[cfg(target_os = "macos")]
-extern {
-    // These functions are in crt_externs.h.
-    fn _NSGetArgc() -> *mut c_int;
-    fn _NSGetArgv() -> *mut *mut *mut c_char;
-}
-
-/// Returns the page size of the current architecture in bytes.
-#[deprecated(since = "1.0.0", reason = "renamed to env::page_size")]
-#[unstable(feature = "os")]
-pub fn page_size() -> usize {
-    sys::os::page_size()
-}
-
-/// A memory mapped file or chunk of memory. This is a very system-specific
-/// interface to the OS's memory mapping facilities (`mmap` on POSIX,
-/// `VirtualAlloc`/`CreateFileMapping` on Windows). It makes no attempt at
-/// abstracting platform differences, besides in error values returned. Consider
-/// yourself warned.
-///
-/// The memory map is released (unmapped) when the destructor is run, so don't
-/// let it leave scope by accident if you want it to stick around.
-pub struct MemoryMap {
-    data: *mut u8,
-    len: usize,
-    kind: MemoryMapKind,
-}
-
-/// Type of memory map
-#[allow(raw_pointer_derive)]
-#[derive(Copy)]
-pub enum MemoryMapKind {
-    /// Virtual memory map. Usually used to change the permissions of a given
-    /// chunk of memory.  Corresponds to `VirtualAlloc` on Windows.
-    MapFile(*const u8),
-    /// Virtual memory map. Usually used to change the permissions of a given
-    /// chunk of memory, or for allocation. Corresponds to `VirtualAlloc` on
-    /// Windows.
-    MapVirtual
-}
-
-/// Options the memory map is created with
-#[allow(raw_pointer_derive)]
-#[derive(Copy)]
-pub enum MapOption {
-    /// The memory should be readable
-    MapReadable,
-    /// The memory should be writable
-    MapWritable,
-    /// The memory should be executable
-    MapExecutable,
-    /// Create a map for a specific address range. Corresponds to `MAP_FIXED` on
-    /// POSIX.
-    MapAddr(*const u8),
-    /// Create a memory mapping for a file with a given HANDLE.
-    #[cfg(windows)]
-    MapFd(libc::HANDLE),
-    /// Create a memory mapping for a file with a given fd.
-    #[cfg(not(windows))]
-    MapFd(c_int),
-    /// When using `MapFd`, the start of the map is `usize` bytes from the start
-    /// of the file.
-    MapOffset(usize),
-    /// On POSIX, this can be used to specify the default flags passed to
-    /// `mmap`. By default it uses `MAP_PRIVATE` and, if not using `MapFd`,
-    /// `MAP_ANON`. This will override both of those. This is platform-specific
-    /// (the exact values used) and ignored on Windows.
-    MapNonStandardFlags(c_int),
-}
-
-/// Possible errors when creating a map.
-#[derive(Copy, Debug)]
-pub enum MapError {
-    /// # The following are POSIX-specific
-    ///
-    /// fd was not open for reading or, if using `MapWritable`, was not open for
-    /// writing.
-    ErrFdNotAvail,
-    /// fd was not valid
-    ErrInvalidFd,
-    /// Either the address given by `MapAddr` or offset given by `MapOffset` was
-    /// not a multiple of `MemoryMap::granularity` (unaligned to page size).
-    ErrUnaligned,
-    /// With `MapFd`, the fd does not support mapping.
-    ErrNoMapSupport,
-    /// If using `MapAddr`, the address + `min_len` was outside of the process's
-    /// address space. If using `MapFd`, the target of the fd didn't have enough
-    /// resources to fulfill the request.
-    ErrNoMem,
-    /// A zero-length map was requested. This is invalid according to
-    /// [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html).
-    /// Not all platforms obey this, but this wrapper does.
-    ErrZeroLength,
-    /// Unrecognized error. The inner value is the unrecognized errno.
-    ErrUnknown(isize),
-    /// # The following are Windows-specific
-    ///
-    /// Unsupported combination of protection flags
-    /// (`MapReadable`/`MapWritable`/`MapExecutable`).
-    ErrUnsupProt,
-    /// When using `MapFd`, `MapOffset` was given (Windows does not support this
-    /// at all)
-    ErrUnsupOffset,
-    /// When using `MapFd`, there was already a mapping to the file.
-    ErrAlreadyExists,
-    /// Unrecognized error from `VirtualAlloc`. The inner value is the return
-    /// value of GetLastError.
-    ErrVirtualAlloc(i32),
-    /// Unrecognized error from `CreateFileMapping`. The inner value is the
-    /// return value of `GetLastError`.
-    ErrCreateFileMappingW(i32),
-    /// Unrecognized error from `MapViewOfFile`. The inner value is the return
-    /// value of `GetLastError`.
-    ErrMapViewOfFile(i32)
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for MapError {
-    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
-        let str = match *self {
-            ErrFdNotAvail => "fd not available for reading or writing",
-            ErrInvalidFd => "Invalid fd",
-            ErrUnaligned => {
-                "Unaligned address, invalid flags, negative length or \
-                 unaligned offset"
-            }
-            ErrNoMapSupport=> "File doesn't support mapping",
-            ErrNoMem => "Invalid address, or not enough available memory",
-            ErrUnsupProt => "Protection mode unsupported",
-            ErrUnsupOffset => "Offset in virtual memory mode is unsupported",
-            ErrAlreadyExists => "File mapping for specified file already exists",
-            ErrZeroLength => "Zero-length mapping not allowed",
-            ErrUnknown(code) => {
-                return write!(out, "Unknown error = {}", code)
-            },
-            ErrVirtualAlloc(code) => {
-                return write!(out, "VirtualAlloc failure = {}", code)
-            },
-            ErrCreateFileMappingW(code) => {
-                return write!(out, "CreateFileMappingW failure = {}", code)
-            },
-            ErrMapViewOfFile(code) => {
-                return write!(out, "MapViewOfFile failure = {}", code)
-            }
-        };
-        write!(out, "{}", str)
-    }
-}
-
-impl Error for MapError {
-    fn description(&self) -> &str { "memory map error" }
-}
-
-// Round up `from` to be divisible by `to`
-fn round_up(from: usize, to: usize) -> usize {
-    let r = if from % to == 0 {
-        from
-    } else {
-        from + to - (from % to)
-    };
-    if r == 0 {
-        to
-    } else {
-        r
-    }
-}
-
-#[cfg(unix)]
-impl MemoryMap {
-    /// Create a new mapping with the given `options`, at least `min_len` bytes
-    /// long. `min_len` must be greater than zero; see the note on
-    /// `ErrZeroLength`.
-    pub fn new(min_len: usize, options: &[MapOption]) -> Result<MemoryMap, MapError> {
-        use libc::off_t;
-
-        if min_len == 0 {
-            return Err(ErrZeroLength)
-        }
-        let mut addr: *const u8 = ptr::null();
-        let mut prot = 0;
-        let mut flags = libc::MAP_PRIVATE;
-        let mut fd = -1;
-        let mut offset = 0;
-        let mut custom_flags = false;
-        let len = round_up(min_len, env::page_size());
-
-        for &o in options {
-            match o {
-                MapReadable => { prot |= libc::PROT_READ; },
-                MapWritable => { prot |= libc::PROT_WRITE; },
-                MapExecutable => { prot |= libc::PROT_EXEC; },
-                MapAddr(addr_) => {
-                    flags |= libc::MAP_FIXED;
-                    addr = addr_;
-                },
-                MapFd(fd_) => {
-                    flags |= libc::MAP_FILE;
-                    fd = fd_;
-                },
-                MapOffset(offset_) => { offset = offset_ as off_t; },
-                MapNonStandardFlags(f) => { custom_flags = true; flags = f },
-            }
-        }
-        if fd == -1 && !custom_flags { flags |= libc::MAP_ANON; }
-
-        let r = unsafe {
-            libc::mmap(addr as *mut c_void, len as libc::size_t, prot, flags,
-                       fd, offset)
-        };
-        if r == libc::MAP_FAILED {
-            Err(match errno() as c_int {
-                libc::EACCES => ErrFdNotAvail,
-                libc::EBADF => ErrInvalidFd,
-                libc::EINVAL => ErrUnaligned,
-                libc::ENODEV => ErrNoMapSupport,
-                libc::ENOMEM => ErrNoMem,
-                code => ErrUnknown(code as isize)
-            })
-        } else {
-            Ok(MemoryMap {
-               data: r as *mut u8,
-               len: len,
-               kind: if fd == -1 {
-                   MapVirtual
-               } else {
-                   MapFile(ptr::null())
-               }
-            })
-        }
-    }
-
-    /// Granularity that the offset or address must be for `MapOffset` and
-    /// `MapAddr` respectively.
-    pub fn granularity() -> usize {
-        env::page_size()
-    }
-}
-
-#[cfg(unix)]
-impl Drop for MemoryMap {
-    /// Unmap the mapping. Panics the task if `munmap` panics.
-    fn drop(&mut self) {
-        if self.len == 0 { /* workaround for dummy_stack */ return; }
-
-        unsafe {
-            // `munmap` only panics due to logic errors
-            libc::munmap(self.data as *mut c_void, self.len as libc::size_t);
-        }
-    }
-}
-
-#[cfg(windows)]
-impl MemoryMap {
-    /// Create a new mapping with the given `options`, at least `min_len` bytes long.
-    pub fn new(min_len: usize, options: &[MapOption]) -> Result<MemoryMap, MapError> {
-        use libc::types::os::arch::extra::{LPVOID, DWORD, SIZE_T, HANDLE};
-
-        let mut lpAddress: LPVOID = ptr::null_mut();
-        let mut readable = false;
-        let mut writable = false;
-        let mut executable = false;
-        let mut handle: HANDLE = libc::INVALID_HANDLE_VALUE;
-        let mut offset: usize = 0;
-        let len = round_up(min_len, env::page_size());
-
-        for &o in options {
-            match o {
-                MapReadable => { readable = true; },
-                MapWritable => { writable = true; },
-                MapExecutable => { executable = true; }
-                MapAddr(addr_) => { lpAddress = addr_ as LPVOID; },
-                MapFd(handle_) => { handle = handle_; },
-                MapOffset(offset_) => { offset = offset_; },
-                MapNonStandardFlags(..) => {}
-            }
-        }
-
-        let flProtect = match (executable, readable, writable) {
-            (false, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_NOACCESS,
-            (false, true, false) => libc::PAGE_READONLY,
-            (false, true, true) => libc::PAGE_READWRITE,
-            (true, false, false) if handle == libc::INVALID_HANDLE_VALUE => libc::PAGE_EXECUTE,
-            (true, true, false) => libc::PAGE_EXECUTE_READ,
-            (true, true, true) => libc::PAGE_EXECUTE_READWRITE,
-            _ => return Err(ErrUnsupProt)
-        };
-
-        if handle == libc::INVALID_HANDLE_VALUE {
-            if offset != 0 {
-                return Err(ErrUnsupOffset);
-            }
-            let r = unsafe {
-                libc::VirtualAlloc(lpAddress,
-                                   len as SIZE_T,
-                                   libc::MEM_COMMIT | libc::MEM_RESERVE,
-                                   flProtect)
-            };
-            match r as usize {
-                0 => Err(ErrVirtualAlloc(errno())),
-                _ => Ok(MemoryMap {
-                   data: r as *mut u8,
-                   len: len,
-                   kind: MapVirtual
-                })
-            }
-        } else {
-            let dwDesiredAccess = match (executable, readable, writable) {
-                (false, true, false) => libc::FILE_MAP_READ,
-                (false, true, true) => libc::FILE_MAP_WRITE,
-                (true, true, false) => libc::FILE_MAP_READ | libc::FILE_MAP_EXECUTE,
-                (true, true, true) => libc::FILE_MAP_WRITE | libc::FILE_MAP_EXECUTE,
-                _ => return Err(ErrUnsupProt) // Actually, because of the check above,
-                                              // we should never get here.
-            };
-            unsafe {
-                let hFile = handle;
-                let mapping = libc::CreateFileMappingW(hFile,
-                                                       ptr::null_mut(),
-                                                       flProtect,
-                                                       0,
-                                                       0,
-                                                       ptr::null());
-                if mapping == ptr::null_mut() {
-                    return Err(ErrCreateFileMappingW(errno()));
-                }
-                if errno() as c_int == libc::ERROR_ALREADY_EXISTS {
-                    return Err(ErrAlreadyExists);
-                }
-                let r = libc::MapViewOfFile(mapping,
-                                            dwDesiredAccess,
-                                            ((len as u64) >> 32) as DWORD,
-                                            (offset & 0xffff_ffff) as DWORD,
-                                            0);
-                match r as usize {
-                    0 => Err(ErrMapViewOfFile(errno())),
-                    _ => Ok(MemoryMap {
-                       data: r as *mut u8,
-                       len: len,
-                       kind: MapFile(mapping as *const u8)
-                    })
-                }
-            }
-        }
-    }
-
-    /// Granularity of MapAddr() and MapOffset() parameter values.
-    /// This may be greater than the value returned by page_size().
-    pub fn granularity() -> usize {
-        use mem;
-        unsafe {
-            let mut info = mem::zeroed();
-            libc::GetSystemInfo(&mut info);
-
-            return info.dwAllocationGranularity as usize;
-        }
-    }
-}
-
-#[cfg(windows)]
-impl Drop for MemoryMap {
-    /// Unmap the mapping. Panics the task if any of `VirtualFree`,
-    /// `UnmapViewOfFile`, or `CloseHandle` fail.
-    fn drop(&mut self) {
-        use libc::types::os::arch::extra::{LPCVOID, HANDLE};
-        use libc::consts::os::extra::FALSE;
-        if self.len == 0 { return }
-
-        unsafe {
-            match self.kind {
-                MapVirtual => {
-                    if libc::VirtualFree(self.data as *mut c_void, 0,
-                                         libc::MEM_RELEASE) == 0 {
-                        println!("VirtualFree failed: {}", errno());
-                    }
-                },
-                MapFile(mapping) => {
-                    if libc::UnmapViewOfFile(self.data as LPCVOID) == FALSE {
-                        println!("UnmapViewOfFile failed: {}", errno());
-                    }
-                    if libc::CloseHandle(mapping as HANDLE) == FALSE {
-                        println!("CloseHandle failed: {}", errno());
-                    }
-                }
-            }
-        }
-    }
-}
-
-impl MemoryMap {
-    /// Returns the pointer to the memory created or modified by this map.
-    pub fn data(&self) -> *mut u8 { self.data }
-    /// Returns the number of bytes this map applies to.
-    pub fn len(&self) -> usize { self.len }
-    /// Returns the type of mapping this represents.
-    pub fn kind(&self) -> MemoryMapKind { self.kind }
-}
-
-#[cfg(target_os = "linux")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `linux`.
-    pub const SYSNAME: &'static str = "linux";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.so`.
-    pub const DLL_SUFFIX: &'static str = ".so";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `so`.
-    pub const DLL_EXTENSION: &'static str = "so";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "macos")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `macos`.
-    pub const SYSNAME: &'static str = "macos";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.dylib`.
-    pub const DLL_SUFFIX: &'static str = ".dylib";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `dylib`.
-    pub const DLL_EXTENSION: &'static str = "dylib";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "ios")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `ios`.
-    pub const SYSNAME: &'static str = "ios";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "freebsd")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `freebsd`.
-    pub const SYSNAME: &'static str = "freebsd";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.so`.
-    pub const DLL_SUFFIX: &'static str = ".so";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `so`.
-    pub const DLL_EXTENSION: &'static str = "so";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "dragonfly")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `dragonfly`.
-    pub const SYSNAME: &'static str = "dragonfly";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.so`.
-    pub const DLL_SUFFIX: &'static str = ".so";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `so`.
-    pub const DLL_EXTENSION: &'static str = "so";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "bitrig")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `bitrig`.
-    pub const SYSNAME: &'static str = "bitrig";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.so`.
-    pub const DLL_SUFFIX: &'static str = ".so";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `so`.
-    pub const DLL_EXTENSION: &'static str = "so";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "openbsd")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `openbsd`.
-    pub const SYSNAME: &'static str = "openbsd";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.so`.
-    pub const DLL_SUFFIX: &'static str = ".so";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `so`.
-    pub const DLL_EXTENSION: &'static str = "so";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "android")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "unix";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `android`.
-    pub const SYSNAME: &'static str = "android";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, `lib`.
-    pub const DLL_PREFIX: &'static str = "lib";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.so`.
-    pub const DLL_SUFFIX: &'static str = ".so";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `so`.
-    pub const DLL_EXTENSION: &'static str = "so";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, the empty string.
-    pub const EXE_SUFFIX: &'static str = "";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, the empty string.
-    pub const EXE_EXTENSION: &'static str = "";
-}
-
-#[cfg(target_os = "windows")]
-#[deprecated(since = "1.0.0", reason = "renamed to env::consts")]
-#[unstable(feature = "os")]
-pub mod consts {
-    pub use os::arch_consts::ARCH;
-
-    pub const FAMILY: &'static str = "windows";
-
-    /// A string describing the specific operating system in use: in this
-    /// case, `windows`.
-    pub const SYSNAME: &'static str = "windows";
-
-    /// Specifies the filename prefix used for shared libraries on this
-    /// platform: in this case, the empty string.
-    pub const DLL_PREFIX: &'static str = "";
-
-    /// Specifies the filename suffix used for shared libraries on this
-    /// platform: in this case, `.dll`.
-    pub const DLL_SUFFIX: &'static str = ".dll";
-
-    /// Specifies the file extension used for shared libraries on this
-    /// platform that goes after the dot: in this case, `dll`.
-    pub const DLL_EXTENSION: &'static str = "dll";
-
-    /// Specifies the filename suffix used for executable binaries on this
-    /// platform: in this case, `.exe`.
-    pub const EXE_SUFFIX: &'static str = ".exe";
-
-    /// Specifies the file extension, if any, used for executable binaries
-    /// on this platform: in this case, `exe`.
-    pub const EXE_EXTENSION: &'static str = "exe";
-}
-
-#[cfg(target_arch = "x86")]
-mod arch_consts {
-    pub const ARCH: &'static str = "x86";
-}
-
-#[cfg(target_arch = "x86_64")]
-mod arch_consts {
-    pub const ARCH: &'static str = "x86_64";
-}
-
-#[cfg(target_arch = "arm")]
-mod arch_consts {
-    pub const ARCH: &'static str = "arm";
-}
-
-#[cfg(target_arch = "aarch64")]
-mod arch_consts {
-    pub const ARCH: &'static str = "aarch64";
-}
-
-#[cfg(target_arch = "mips")]
-mod arch_consts {
-    pub const ARCH: &'static str = "mips";
-}
-
-#[cfg(target_arch = "mipsel")]
-mod arch_consts {
-    pub const ARCH: &'static str = "mipsel";
-}
-
-#[cfg(target_arch = "powerpc")]
-mod arch_consts {
-    pub const ARCH: &'static str = "powerpc";
-}
-
-#[cfg(test)]
-mod tests {
-    #![allow(deprecated)] // rand
-
-    use prelude::v1::*;
-
-    use iter::repeat;
-    use os::{env, getcwd, getenv, make_absolute};
-    use os::{split_paths, join_paths, setenv, unsetenv};
-    use os;
-    use rand::Rng;
-    use rand;
-    use old_path::{Path, GenericPath};
-    use old_io::{Reader, Writer, Seek};
-
-    #[test]
-    pub fn last_os_error() {
-        debug!("{}", os::last_os_error());
-    }
-
-    fn make_rand_name() -> String {
-        let mut rng = rand::thread_rng();
-        let n = format!("TEST{}", rng.gen_ascii_chars().take(10)
-                                     .collect::<String>());
-        assert!(getenv(&n).is_none());
-        n
-    }
-
-    #[test]
-    fn test_num_cpus() {
-        assert!(os::num_cpus() > 0);
-    }
-
-    #[test]
-    fn test_setenv() {
-        let n = make_rand_name();
-        setenv(&n, "VALUE");
-        assert_eq!(getenv(&n), Some("VALUE".to_string()));
-    }
-
-    #[test]
-    fn test_unsetenv() {
-        let n = make_rand_name();
-        setenv(&n, "VALUE");
-        unsetenv(&n);
-        assert_eq!(getenv(&n), None);
-    }
-
-    #[test]
-    #[ignore]
-    fn test_setenv_overwrite() {
-        let n = make_rand_name();
-        setenv(&n, "1");
-        setenv(&n, "2");
-        assert_eq!(getenv(&n), Some("2".to_string()));
-        setenv(&n, "");
-        assert_eq!(getenv(&n), Some("".to_string()));
-    }
-
-    // Windows GetEnvironmentVariable requires some extra work to make sure
-    // the buffer the variable is copied into is the right size
-    #[test]
-    #[ignore]
-    fn test_getenv_big() {
-        let mut s = "".to_string();
-        let mut i = 0;
-        while i < 100 {
-            s.push_str("aaaaaaaaaa");
-            i += 1;
-        }
-        let n = make_rand_name();
-        setenv(&n, &s);
-        debug!("{}", s.clone());
-        assert_eq!(getenv(&n), Some(s));
-    }
-
-    #[test]
-    fn test_self_exe_name() {
-        let path = os::self_exe_name();
-        assert!(path.is_some());
-        let path = path.unwrap();
-        debug!("{}", path.display());
-
-        // Hard to test this function
-        assert!(path.is_absolute());
-    }
-
-    #[test]
-    fn test_self_exe_path() {
-        let path = os::self_exe_path();
-        assert!(path.is_some());
-        let path = path.unwrap();
-        debug!("{}", path.display());
-
-        // Hard to test this function
-        assert!(path.is_absolute());
-    }
-
-    #[test]
-    #[ignore]
-    fn test_env_getenv() {
-        let e = env();
-        assert!(e.len() > 0);
-        for p in &e {
-            let (n, v) = (*p).clone();
-            debug!("{}", n);
-            let v2 = getenv(&n);
-            // MingW seems to set some funky environment variables like
-            // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
-            // from env() but not visible from getenv().
-            assert!(v2.is_none() || v2 == Some(v));
-        }
-    }
-
-    #[test]
-    fn test_env_set_get_huge() {
-        let n = make_rand_name();
-        let s = repeat("x").take(10000).collect::<String>();
-        setenv(&n, &s);
-        assert_eq!(getenv(&n), Some(s));
-        unsetenv(&n);
-        assert_eq!(getenv(&n), None);
-    }
-
-    #[test]
-    fn test_env_setenv() {
-        let n = make_rand_name();
-
-        let mut e = env();
-        setenv(&n, "VALUE");
-        assert!(!e.contains(&(n.clone(), "VALUE".to_string())));
-
-        e = env();
-        assert!(e.contains(&(n, "VALUE".to_string())));
-    }
-
-    #[test]
-    fn test() {
-        assert!((!Path::new("test-path").is_absolute()));
-
-        let cwd = getcwd().unwrap();
-        debug!("Current working directory: {}", cwd.display());
-
-        debug!("{}", make_absolute(&Path::new("test-path")).unwrap().display());
-        debug!("{}", make_absolute(&Path::new("/usr/bin")).unwrap().display());
-    }
-
-    #[test]
-    #[cfg(unix)]
-    fn homedir() {
-        let oldhome = getenv("HOME");
-
-        setenv("HOME", "/home/MountainView");
-        assert!(os::homedir() == Some(Path::new("/home/MountainView")));
-
-        setenv("HOME", "");
-        assert!(os::homedir().is_none());
-
-        if let Some(s) = oldhome {
-            setenv("HOME", s);
-        }
-    }
-
-    #[test]
-    #[cfg(windows)]
-    fn homedir() {
-
-        let oldhome = getenv("HOME");
-        let olduserprofile = getenv("USERPROFILE");
-
-        setenv("HOME", "");
-        setenv("USERPROFILE", "");
-
-        assert!(os::homedir().is_none());
-
-        setenv("HOME", "/home/MountainView");
-        assert!(os::homedir() == Some(Path::new("/home/MountainView")));
-
-        setenv("HOME", "");
-
-        setenv("USERPROFILE", "/home/MountainView");
-        assert!(os::homedir() == Some(Path::new("/home/MountainView")));
-
-        setenv("HOME", "/home/MountainView");
-        setenv("USERPROFILE", "/home/PaloAlto");
-        assert!(os::homedir() == Some(Path::new("/home/MountainView")));
-
-        if let Some(s) = oldhome {
-            setenv("HOME", &s);
-        }
-        if let Some(s) = olduserprofile {
-            setenv("USERPROFILE", &s);
-        }
-    }
-
-    #[test]
-    fn memory_map_rw() {
-        use result::Result::{Ok, Err};
-
-        let chunk = match os::MemoryMap::new(16, &[
-            os::MapOption::MapReadable,
-            os::MapOption::MapWritable
-        ]) {
-            Ok(chunk) => chunk,
-            Err(msg) => panic!("{:?}", msg)
-        };
-        assert!(chunk.len >= 16);
-
-        unsafe {
-            *chunk.data = 0xBE;
-            assert!(*chunk.data == 0xBE);
-        }
-    }
-
-    #[test]
-    fn memory_map_file() {
-        use libc;
-        use os::*;
-        use old_io::fs::{File, unlink};
-        use old_io::SeekStyle::SeekSet;
-        use old_io::FileMode::Open;
-        use old_io::FileAccess::ReadWrite;
-
-        #[cfg(not(windows))]
-        fn get_fd(file: &File) -> libc::c_int {
-            use os::unix::prelude::*;
-            file.as_raw_fd()
-        }
-
-        #[cfg(windows)]
-        fn get_fd(file: &File) -> libc::HANDLE {
-            use os::windows::prelude::*;
-            file.as_raw_handle()
-        }
-
-        let mut path = tmpdir();
-        path.push("mmap_file.tmp");
-        let size = MemoryMap::granularity() * 2;
-        let mut file = File::open_mode(&path, Open, ReadWrite).unwrap();
-        file.seek(size as i64, SeekSet).unwrap();
-        file.write_u8(0).unwrap();
-
-        let chunk = MemoryMap::new(size / 2, &[
-            MapOption::MapReadable,
-            MapOption::MapWritable,
-            MapOption::MapFd(get_fd(&file)),
-            MapOption::MapOffset(size / 2)
-        ]).unwrap();
-        assert!(chunk.len > 0);
-
-        unsafe {
-            *chunk.data = 0xbe;
-            assert!(*chunk.data == 0xbe);
-        }
-        drop(chunk);
-
-        unlink(&path).unwrap();
-    }
-
-    #[test]
-    #[cfg(windows)]
-    fn split_paths_windows() {
-        fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
-            split_paths(unparsed) ==
-                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
-        }
-
-        assert!(check_parse("", &mut [""]));
-        assert!(check_parse(r#""""#, &mut [""]));
-        assert!(check_parse(";;", &mut ["", "", ""]));
-        assert!(check_parse(r"c:\", &mut [r"c:\"]));
-        assert!(check_parse(r"c:\;", &mut [r"c:\", ""]));
-        assert!(check_parse(r"c:\;c:\Program Files\",
-                            &mut [r"c:\", r"c:\Program Files\"]));
-        assert!(check_parse(r#"c:\;c:\"foo"\"#, &mut [r"c:\", r"c:\foo\"]));
-        assert!(check_parse(r#"c:\;c:\"foo;bar"\;c:\baz"#,
-                            &mut [r"c:\", r"c:\foo;bar\", r"c:\baz"]));
-    }
-
-    #[test]
-    #[cfg(unix)]
-    fn split_paths_unix() {
-        fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
-            split_paths(unparsed) ==
-                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
-        }
-
-        assert!(check_parse("", &mut [""]));
-        assert!(check_parse("::", &mut ["", "", ""]));
-        assert!(check_parse("/", &mut ["/"]));
-        assert!(check_parse("/:", &mut ["/", ""]));
-        assert!(check_parse("/:/usr/local", &mut ["/", "/usr/local"]));
-    }
-
-    #[test]
-    #[cfg(unix)]
-    fn join_paths_unix() {
-        fn test_eq(input: &[&str], output: &str) -> bool {
-            join_paths(input).unwrap() == output.as_bytes()
-        }
-
-        assert!(test_eq(&[], ""));
-        assert!(test_eq(&["/bin", "/usr/bin", "/usr/local/bin"],
-                         "/bin:/usr/bin:/usr/local/bin"));
-        assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
-                         ":/bin:::/usr/bin:"));
-        assert!(join_paths(&["/te:st"]).is_err());
-    }
-
-    #[test]
-    #[cfg(windows)]
-    fn join_paths_windows() {
-        fn test_eq(input: &[&str], output: &str) -> bool {
-            join_paths(input).unwrap() == output.as_bytes()
-        }
-
-        assert!(test_eq(&[], ""));
-        assert!(test_eq(&[r"c:\windows", r"c:\"],
-                        r"c:\windows;c:\"));
-        assert!(test_eq(&["", r"c:\windows", "", "", r"c:\", ""],
-                        r";c:\windows;;;c:\;"));
-        assert!(test_eq(&[r"c:\te;st", r"c:\"],
-                        r#""c:\te;st";c:\"#));
-        assert!(join_paths(&[r#"c:\te"st"#]).is_err());
-    }
-
-    // More recursive_mkdir tests are in extra::tempfile
-}
index df0b3842b7a349ccedac1cf265bf53dea571b2b0..889381da28e92c74f3d438d5a93e1e84b60c45fd 100644 (file)
@@ -35,7 +35,6 @@
 //! To build or modify paths, use `PathBuf`:
 //!
 //! ```rust
-//! # #![feature(convert)]
 //! use std::path::PathBuf;
 //!
 //! let mut path = PathBuf::from("c:\\");
@@ -530,9 +529,9 @@ impl<'a> Component<'a> {
     pub fn as_os_str(self) -> &'a OsStr {
         match self {
             Component::Prefix(p) => p.as_os_str(),
-            Component::RootDir => OsStr::from_str(MAIN_SEP_STR),
-            Component::CurDir => OsStr::from_str("."),
-            Component::ParentDir => OsStr::from_str(".."),
+            Component::RootDir => OsStr::new(MAIN_SEP_STR),
+            Component::CurDir => OsStr::new("."),
+            Component::ParentDir => OsStr::new(".."),
             Component::Normal(path) => path,
         }
     }
@@ -924,7 +923,6 @@ fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
 /// # Examples
 ///
 /// ```
-/// # #![feature(convert)]
 /// use std::path::PathBuf;
 ///
 /// let mut path = PathBuf::from("c:\\");
@@ -949,6 +947,12 @@ pub fn new() -> PathBuf {
         PathBuf { inner: OsString::new() }
     }
 
+    /// Coerce to a `Path` slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn as_path(&self) -> &Path {
+        self
+    }
+
     /// Extend `self` with `path`.
     ///
     /// If `path` is absolute, it replaces the current path.
@@ -1016,7 +1020,6 @@ pub fn pop(&mut self) -> bool {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(convert)]
     /// use std::path::PathBuf;
     ///
     /// let mut buf = PathBuf::from("/");
@@ -1427,7 +1430,7 @@ pub fn parent(&self) -> Option<&Path> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn file_name(&self) -> Option<&OsStr> {
         self.components().next_back().and_then(|p| match p {
-            Component::Normal(p) => Some(p.as_os_str()),
+            Component::Normal(p) => Some(p.as_ref()),
             _ => None
         })
     }
index 297eccb9f769831da5a804e564c328b932f63cec..84a450867675c814c96eff49d0873a0735ffc338 100644 (file)
 #[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;
+#[doc(no_inline)] pub use slice::SliceConcatExt;
 #[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;
+
+#[allow(deprecated)] pub use slice::AsSlice;
+#[allow(deprecated)] pub use str::Str;
index b4bd513e8f027ce7c7514ce3ce0c3e613970fbb2..52f5965db809a76c5168a5d8985d006569e1aaf6 100644 (file)
 use prelude::v1::*;
 use io::prelude::*;
 
-use ffi::AsOsStr;
+use ffi::OsStr;
 use fmt;
 use io::{self, Error, ErrorKind};
 use libc;
 use path;
 use sync::mpsc::{channel, Receiver};
 use sys::pipe2::{self, AnonPipe};
-use sys::process2::Process as ProcessImp;
 use sys::process2::Command as CommandImp;
+use sys::process2::Process as ProcessImp;
 use sys::process2::ExitStatus as ExitStatusImp;
 use sys_common::{AsInner, AsInnerMut};
 use thread;
@@ -147,9 +147,9 @@ impl Command {
     /// Builder methods are provided to change these defaults and
     /// otherwise configure the process.
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn new<S: AsOsStr>(program: S) -> Command {
+    pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
         Command {
-            inner: CommandImp::new(program.as_os_str()),
+            inner: CommandImp::new(program.as_ref()),
             stdin: None,
             stdout: None,
             stderr: None,
@@ -158,15 +158,15 @@ pub fn new<S: AsOsStr>(program: S) -> Command {
 
     /// Add an argument to pass to the program.
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn arg<S: AsOsStr>(&mut self, arg: S) -> &mut Command {
-        self.inner.arg(arg.as_os_str());
+    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command {
+        self.inner.arg(arg.as_ref());
         self
     }
 
     /// Add multiple arguments to pass to the program.
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn args<S: AsOsStr>(&mut self, args: &[S]) -> &mut Command {
-        self.inner.args(args.iter().map(AsOsStr::as_os_str));
+    pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> &mut Command {
+        self.inner.args(args.iter().map(AsRef::as_ref));
         self
     }
 
@@ -176,16 +176,16 @@ pub fn args<S: AsOsStr>(&mut self, args: &[S]) -> &mut Command {
     /// and case-sensitive on all other platforms.
     #[stable(feature = "process", since = "1.0.0")]
     pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
-        where K: AsOsStr, V: AsOsStr
+        where K: AsRef<OsStr>, V: AsRef<OsStr>
     {
-        self.inner.env(key.as_os_str(), val.as_os_str());
+        self.inner.env(key.as_ref(), val.as_ref());
         self
     }
 
     /// Removes an environment variable mapping.
     #[stable(feature = "process", since = "1.0.0")]
-    pub fn env_remove<K: AsOsStr>(&mut self, key: K) -> &mut Command {
-        self.inner.env_remove(key.as_os_str());
+    pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command {
+        self.inner.env_remove(key.as_ref());
         self
     }
 
@@ -199,7 +199,7 @@ 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: AsRef<path::Path>>(&mut self, dir: P) -> &mut Command {
-        self.inner.cwd(dir.as_ref().as_os_str());
+        self.inner.cwd(dir.as_ref().as_ref());
         self
     }
 
@@ -378,11 +378,6 @@ enum StdioImp {
 }
 
 impl Stdio {
-    /// A new pipe should be arranged to connect the parent and child processes.
-    #[unstable(feature = "process_capture")]
-    #[deprecated(since = "1.0.0", reason = "renamed to `Stdio::piped`")]
-    pub fn capture() -> Stdio { Stdio::piped() }
-
     /// A new pipe should be arranged to connect the parent and child processes.
     #[stable(feature = "process", since = "1.0.0")]
     pub fn piped() -> Stdio { Stdio(StdioImp::Piped) }
@@ -461,7 +456,6 @@ pub fn kill(&mut self) -> io::Result<()> {
             return Err(Error::new(
                 ErrorKind::InvalidInput,
                 "invalid argument: can't kill an exited process",
-                None
             ))
         }
 
@@ -527,13 +521,28 @@ fn read<T: Read + Send + 'static>(stream: Option<T>) -> Receiver<io::Result<Vec<
     }
 }
 
+/// Terminates the current process with the specified exit code.
+///
+/// This function will never return and will immediately terminate the current
+/// process. The exit code is passed through to the underlying OS and will be
+/// available for consumption by another process.
+///
+/// Note that because this function never returns, and that it terminates the
+/// process, no destructors on the current stack or any other thread's stack
+/// will be run. If a clean shutdown is needed it is recommended to only call
+/// this function at a known point where there are no more destructors left
+/// to run.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn exit(code: i32) -> ! {
+    ::sys::os::exit(code)
+}
+
 #[cfg(test)]
 mod tests {
-    use io::ErrorKind;
+    use prelude::v1::*;
     use io::prelude::*;
-    use prelude::v1::{Ok, Err, drop, Some, Vec};
-    use prelude::v1::{String, Clone};
-    use prelude::v1::{Str, AsSlice, ToString};
+
+    use io::ErrorKind;
     use old_path::{self, GenericPath};
     use old_io::fs::PathExtensions;
     use rt::running_on_valgrind;
@@ -567,7 +576,7 @@ fn exit_reported_right() {
         assert!(p.is_ok());
         let mut p = p.unwrap();
         assert!(p.wait().unwrap().code() == Some(1));
-        drop(p.wait().clone());
+        drop(p.wait());
     }
 
     #[cfg(all(unix, not(target_os="android")))]
@@ -678,7 +687,7 @@ fn test_process_output_fail_to_start() {
     fn test_process_output_output() {
         let Output {status, stdout, stderr}
              = Command::new("echo").arg("hello").output().unwrap();
-        let output_str = str::from_utf8(stdout.as_slice()).unwrap();
+        let output_str = str::from_utf8(&stdout).unwrap();
 
         assert!(status.success());
         assert_eq!(output_str.trim().to_string(), "hello");
@@ -720,7 +729,7 @@ fn test_wait_with_output_once() {
         let prog = Command::new("echo").arg("hello").stdout(Stdio::piped())
             .spawn().unwrap();
         let Output {status, stdout, stderr} = prog.wait_with_output().unwrap();
-        let output_str = str::from_utf8(stdout.as_slice()).unwrap();
+        let output_str = str::from_utf8(&stdout).unwrap();
 
         assert!(status.success());
         assert_eq!(output_str.trim().to_string(), "hello");
@@ -755,7 +764,8 @@ fn test_keep_current_working_dir() {
         let prog = pwd_cmd().spawn().unwrap();
 
         let output = String::from_utf8(prog.wait_with_output().unwrap().stdout).unwrap();
-        let parent_dir = os::getcwd().unwrap();
+        let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string();
+        let parent_dir = old_path::Path::new(parent_dir);
         let child_dir = old_path::Path::new(output.trim());
 
         let parent_stat = parent_dir.stat().unwrap();
@@ -770,7 +780,8 @@ fn test_change_working_directory() {
         use os;
         // test changing to the parent of os::getcwd() because we know
         // the path exists (and os::getcwd() is not expected to be root)
-        let parent_dir = os::getcwd().unwrap().dir_path();
+        let parent_dir = ::env::current_dir().unwrap().to_str().unwrap().to_string();
+        let parent_dir = old_path::Path::new(parent_dir).dir_path();
         let result = pwd_cmd().current_dir(parent_dir.as_str().unwrap()).output().unwrap();
 
         let output = String::from_utf8(result.stdout).unwrap();
@@ -821,14 +832,13 @@ fn test_inherit_env() {
     #[cfg(target_os="android")]
     #[test]
     fn test_inherit_env() {
-        use os;
+        use std::env;
         if running_on_valgrind() { return; }
 
         let mut result = env_cmd().output().unwrap();
         let output = String::from_utf8(result.stdout).unwrap();
 
-        let r = os::env();
-        for &(ref k, ref v) in &r {
+        for (ref k, ref v) in env::vars() {
             // don't check android RANDOM variables
             if *k != "RANDOM".to_string() {
                 assert!(output.contains(&format!("{}={}",
@@ -855,7 +865,7 @@ fn test_override_env() {
             cmd.env("PATH", &p);
         }
         let result = cmd.output().unwrap();
-        let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string();
+        let output = String::from_utf8_lossy(&result.stdout).to_string();
 
         assert!(output.contains("RUN_TEST_NEW_ENV=123"),
                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
@@ -864,7 +874,7 @@ fn test_override_env() {
     #[test]
     fn test_add_to_env() {
         let result = env_cmd().env("RUN_TEST_NEW_ENV", "123").output().unwrap();
-        let output = String::from_utf8_lossy(result.stdout.as_slice()).to_string();
+        let output = String::from_utf8_lossy(&result.stdout).to_string();
 
         assert!(output.contains("RUN_TEST_NEW_ENV=123"),
                 "didn't find RUN_TEST_NEW_ENV inside of:\n\n{}", output);
index 51b6045cf16f8b0302008694ef4d558cc5fda08d..7aba40dc6be89908d07accb551d74aa20469cd0e 100644 (file)
 
 #[cfg(all(unix, not(target_os = "ios")))]
 mod imp {
-    extern crate libc;
-
+    use prelude::v1::*;
     use self::OsRngInner::*;
 
+    use libc;
+    use mem;
     use old_io::{IoResult, File};
     use old_path::Path;
     use rand::Rng;
     use rand::reader::ReaderRng;
-    use result::Result::Ok;
-    use mem;
-    use os::errno;
+    use sys::os::errno;
 
     #[cfg(all(target_os = "linux",
               any(target_arch = "x86_64",
@@ -184,14 +183,13 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
 
 #[cfg(target_os = "ios")]
 mod imp {
-    extern crate libc;
+    use prelude::v1::*;
 
-    use old_io::{IoResult};
+    use old_io::IoResult;
     use mem;
     use os;
     use rand::Rng;
-    use result::Result::{Ok};
-    use self::libc::{c_int, size_t};
+    use libc::{c_int, size_t};
 
     /// A random number generator that retrieves randomness straight from
     /// the operating system. Platform sources:
@@ -251,16 +249,14 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
 
 #[cfg(windows)]
 mod imp {
-    extern crate libc;
+    use prelude::v1::*;
 
-    use old_io::{IoResult, IoError};
+    use io;
     use mem;
-    use ops::Drop;
-    use os;
+    use old_io::{IoResult, IoError};
     use rand::Rng;
-    use result::Result::{Ok, Err};
-    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
-    use self::libc::types::os::arch::extra::{LONG_PTR};
+    use libc::types::os::arch::extra::{LONG_PTR};
+    use libc::{DWORD, BYTE, LPCSTR, BOOL};
 
     type HCRYPTPROV = LONG_PTR;
 
@@ -330,7 +326,8 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
                                v.as_mut_ptr())
             };
             if ret == 0 {
-                panic!("couldn't generate random bytes: {}", os::last_os_error());
+                panic!("couldn't generate random bytes: {}",
+                       io::Error::last_os_error());
             }
         }
     }
@@ -341,7 +338,8 @@ fn drop(&mut self) {
                 CryptReleaseContext(self.hcryptprov, 0)
             };
             if ret == 0 {
-                panic!("couldn't release context: {}", os::last_os_error());
+                panic!("couldn't release context: {}",
+                       io::Error::last_os_error());
             }
         }
     }
index 428bcaa49f7d918d2c0f8f25c763a5e11b866fe5..2329861f29bc06dc6b7428d8ecb9fc560720a573 100644 (file)
@@ -108,7 +108,6 @@ unsafe fn load_argc_and_argv(argc: isize,
     #[cfg(test)]
     mod tests {
         use prelude::v1::*;
-        use finally::Finally;
 
         use super::*;
 
@@ -127,14 +126,11 @@ fn smoke_test() {
             assert!(take() == Some(expected.clone()));
             assert!(take() == None);
 
-            (|| {
-            }).finally(|| {
-                // Restore the actual global state.
-                match saved_value {
-                    Some(ref args) => put(args.clone()),
-                    None => ()
-                }
-            })
+            // Restore the actual global state.
+            match saved_value {
+                Some(ref args) => put(args.clone()),
+                None => ()
+            }
         }
     }
 }
index 68137601c405c84876ee746a0b8d302300cd2b03..a5259a00390f55369a7e737781fe0f6c00f52e34 100644 (file)
@@ -31,8 +31,6 @@
 pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
 
 pub use self::future::Future;
-#[allow(deprecated)]
-pub use self::task_pool::TaskPool;
 
 pub mod mpsc;
 
@@ -44,4 +42,3 @@
 mod poison;
 mod rwlock;
 mod semaphore;
-mod task_pool;
index b2b87bb6c44a757bcbd2014da07a40d7921e3b44..e14f32865fa10fe8dc6453503aadb50d3c563415 100644 (file)
 //! ```
 //!
 //! Reading from a channel with a timeout requires to use a Timer together
-//! with the channel. You can use the select! macro to select either and
+//! with the channel. You can use the `select!` macro to select either and
 //! handle the timeout case. This first example will break out of the loop
 //! after 10 seconds no matter what:
 //!
index c07c83d37f48881b041966d9c9cfbf48d82f5d8a..347cd0b464ed95892e74b13adafdb30a3013e532 100644 (file)
@@ -11,7 +11,7 @@
 use prelude::v1::*;
 
 use cell::UnsafeCell;
-use error::{Error, FromError};
+use error::{Error};
 use fmt;
 use thread;
 
@@ -122,12 +122,6 @@ pub fn new(guard: T) -> PoisonError<T> {
         PoisonError { guard: guard }
     }
 
-    /// Consumes this error indicating that a lock is poisoned, returning the
-    /// underlying guard to allow access regardless.
-    #[unstable(feature = "std_misc")]
-    #[deprecated(since = "1.0.0", reason = "renamed to into_inner")]
-    pub fn into_guard(self) -> T { self.guard }
-
     /// Consumes this error indicating that a lock is poisoned, returning the
     /// underlying guard to allow access regardless.
     #[unstable(feature = "std_misc")]
@@ -144,8 +138,8 @@ pub fn get_ref(&self) -> &T { &self.guard }
     pub fn get_mut(&mut self) -> &mut T { &mut self.guard }
 }
 
-impl<T> FromError<PoisonError<T>> for TryLockError<T> {
-    fn from_error(err: PoisonError<T>) -> TryLockError<T> {
+impl<T> From<PoisonError<T>> for TryLockError<T> {
+    fn from(err: PoisonError<T>) -> TryLockError<T> {
         TryLockError::Poisoned(err)
     }
 }
diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs
deleted file mode 100644 (file)
index 51cf70e..0000000
+++ /dev/null
@@ -1,217 +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.
-
-//! Abstraction of a thread pool for basic parallelism.
-
-#![deprecated(since = "1.0.0",
-              reason = "This kind of API needs some time to bake in \
-                        crates.io. This functionality is available through \
-                        https://crates.io/crates/threadpool")]
-#![unstable(feature = "std_misc")]
-
-#![allow(deprecated)]
-
-use core::prelude::*;
-
-use sync::{Arc, Mutex};
-use sync::mpsc::{channel, Sender, Receiver};
-use thread;
-use thunk::Thunk;
-
-struct Sentinel<'a> {
-    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
-    active: bool
-}
-
-impl<'a> Sentinel<'a> {
-    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
-        Sentinel {
-            jobs: jobs,
-            active: true
-        }
-    }
-
-    // Cancel and destroy this sentinel.
-    fn cancel(mut self) {
-        self.active = false;
-    }
-}
-
-#[unsafe_destructor]
-impl<'a> Drop for Sentinel<'a> {
-    fn drop(&mut self) {
-        if self.active {
-            spawn_in_pool(self.jobs.clone())
-        }
-    }
-}
-
-/// A thread pool used to execute functions in parallel.
-///
-/// Spawns `n` worker threads and replenishes the pool if any worker threads
-/// panic.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(std_misc, core)]
-/// use std::sync::TaskPool;
-/// use std::iter::AdditiveIterator;
-/// use std::sync::mpsc::channel;
-///
-/// let pool = TaskPool::new(4);
-///
-/// let (tx, rx) = channel();
-/// for _ in 0..8 {
-///     let tx = tx.clone();
-///     pool.execute(move|| {
-///         tx.send(1_u32).unwrap();
-///     });
-/// }
-///
-/// assert_eq!(rx.iter().take(8).sum(), 8);
-/// ```
-pub struct TaskPool {
-    // How the threadpool communicates with subthreads.
-    //
-    // This is the only such Sender, so when it is dropped all subthreads will
-    // quit.
-    jobs: Sender<Thunk<'static>>
-}
-
-impl TaskPool {
-    /// Spawns a new thread pool with `threads` threads.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `threads` is 0.
-    pub fn new(threads: usize) -> TaskPool {
-        assert!(threads >= 1);
-
-        let (tx, rx) = channel::<Thunk>();
-        let rx = Arc::new(Mutex::new(rx));
-
-        // Threadpool threads
-        for _ in 0..threads {
-            spawn_in_pool(rx.clone());
-        }
-
-        TaskPool { jobs: tx }
-    }
-
-    /// Executes the function `job` on a thread in the pool.
-    pub fn execute<F>(&self, job: F)
-        where F : FnOnce(), F : Send + 'static
-    {
-        self.jobs.send(Thunk::new(job)).unwrap();
-    }
-}
-
-fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
-    thread::spawn(move || {
-        // Will spawn a new thread on panic unless it is cancelled.
-        let sentinel = Sentinel::new(&jobs);
-
-        loop {
-            let message = {
-                // Only lock jobs for the time it takes
-                // to get a job, not run it.
-                let lock = jobs.lock().unwrap();
-                lock.recv()
-            };
-
-            match message {
-                Ok(job) => job.invoke(()),
-
-                // The Taskpool was dropped.
-                Err(..) => break
-            }
-        }
-
-        sentinel.cancel();
-    });
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::v1::*;
-    use super::*;
-    use sync::mpsc::channel;
-
-    const TEST_TASKS: usize = 4;
-
-    #[test]
-    fn test_works() {
-        use iter::AdditiveIterator;
-
-        let pool = TaskPool::new(TEST_TASKS);
-
-        let (tx, rx) = channel();
-        for _ in 0..TEST_TASKS {
-            let tx = tx.clone();
-            pool.execute(move|| {
-                tx.send(1).unwrap();
-            });
-        }
-
-        assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
-    }
-
-    #[test]
-    #[should_panic]
-    fn test_zero_tasks_panic() {
-        TaskPool::new(0);
-    }
-
-    #[test]
-    fn test_recovery_from_subtask_panic() {
-        use iter::AdditiveIterator;
-
-        let pool = TaskPool::new(TEST_TASKS);
-
-        // Panic all the existing threads.
-        for _ in 0..TEST_TASKS {
-            pool.execute(move|| -> () { panic!() });
-        }
-
-        // Ensure new threads were spawned to compensate.
-        let (tx, rx) = channel();
-        for _ in 0..TEST_TASKS {
-            let tx = tx.clone();
-            pool.execute(move|| {
-                tx.send(1).unwrap();
-            });
-        }
-
-        assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
-    }
-
-    #[test]
-    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {
-        use sync::{Arc, Barrier};
-
-        let pool = TaskPool::new(TEST_TASKS);
-        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));
-
-        // Panic all the existing threads in a bit.
-        for _ in 0..TEST_TASKS {
-            let waiter = waiter.clone();
-            pool.execute(move|| {
-                waiter.wait();
-                panic!();
-            });
-        }
-
-        drop(pool);
-
-        // Kick off the failure.
-        waiter.wait();
-    }
-}
index a8ee40639e32ee3fcda50ff9acdd78c0ef6290ba..7d42d65d360f548db50943439b54c8908ffd6854 100644 (file)
@@ -75,7 +75,7 @@ fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
             })))
         }
         _ => {
-            Err(Error::new(ErrorKind::InvalidInput, "invalid argument", None))
+            Err(Error::new(ErrorKind::InvalidInput, "invalid argument"))
         }
     }
 }
@@ -158,8 +158,7 @@ pub fn lookup_addr(addr: &IpAddr) -> io::Result<String> {
     match from_utf8(data.to_bytes()) {
         Ok(name) => Ok(name.to_string()),
         Err(_) => Err(io::Error::new(io::ErrorKind::Other,
-                                     "failed to lookup address information",
-                                     Some("invalid host name".to_string())))
+                                     "failed to lookup address information"))
     }
 }
 
@@ -259,6 +258,12 @@ pub fn duplicate(&self) -> io::Result<TcpStream> {
     }
 }
 
+impl FromInner<Socket> for TcpStream {
+    fn from_inner(socket: Socket) -> TcpStream {
+        TcpStream { inner: socket }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // TCP listeners
 ////////////////////////////////////////////////////////////////////////////////
@@ -312,6 +317,12 @@ pub fn duplicate(&self) -> io::Result<TcpListener> {
     }
 }
 
+impl FromInner<Socket> for TcpListener {
+    fn from_inner(socket: Socket) -> TcpListener {
+        TcpListener { inner: socket }
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // UDP
 ////////////////////////////////////////////////////////////////////////////////
@@ -424,3 +435,9 @@ pub fn duplicate(&self) -> io::Result<UdpSocket> {
         self.inner.duplicate().map(|s| UdpSocket { inner: s })
     }
 }
+
+impl FromInner<Socket> for UdpSocket {
+    fn from_inner(socket: Socket) -> UdpSocket {
+        UdpSocket { inner: socket }
+    }
+}
index 99a554a835f9fbc6cc7179d3757bae03892646c6..ca805ad02422ad6cda891f3a561bda0301dfebbf 100644 (file)
@@ -251,7 +251,6 @@ fn dladdr(addr: *const libc::c_void,
 fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void,
          symaddr: *mut libc::c_void) -> io::Result<()> {
     use env;
-    use ffi::AsOsStr;
     use os::unix::prelude::*;
     use ptr;
 
index 0805949d5602193272bfdce4d0a5933cf4b357ae..fbfbb40701fd9f5887a841ba7e50dde90ed36479 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 /// Unix-specific extensions to general I/O primitives
-#[unstable(feature = "io_ext",
-           reason = "may want a slightly different organization or a more \
-                     general file descriptor primitive")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod io {
     #[allow(deprecated)] use old_io;
     use fs;
     use libc;
     use net;
-    use sys_common::AsInner;
+    use sys_common::{net2, AsInner, FromInner};
+    use sys;
 
     /// Raw file descriptors.
-    pub type Fd = libc::c_int;
-
-    /// Extract raw file descriptor
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub type RawFd = libc::c_int;
+
+    /// A trait to extract the raw unix file descriptor from an underlying
+    /// object.
+    ///
+    /// This is only available on unix platforms and must be imported in order
+    /// to call the method. Windows platforms have a corresponding `AsRawHandle`
+    /// and `AsRawSocket` set of traits.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub trait AsRawFd {
-        /// Extract the raw file descriptor, without taking any ownership.
-        fn as_raw_fd(&self) -> Fd;
+        /// Extract the raw file descriptor.
+        ///
+        /// This method does **not** pass ownership of the raw file descriptor
+        /// to the caller. The descriptor is only guarantee to be valid while
+        /// the original object has not yet been destroyed.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn as_raw_fd(&self) -> RawFd;
+    }
+
+    /// A trait to express the ability to construct an object from a raw file
+    /// descriptor.
+    #[unstable(feature = "from_raw_os",
+               reason = "recent addition to std::os::unix::io")]
+    pub trait FromRawFd {
+        /// Constructs a new instances of `Self` from the given raw file
+        /// descriptor.
+        ///
+        /// This function **consumes ownership** of the specified file
+        /// descriptor. The returned object will take responsibility for closing
+        /// it when the object goes out of scope.
+        ///
+        /// Callers should normally only pass in a valid file descriptor to this
+        /// method or otherwise methods will return errors.
+        fn from_raw_fd(fd: RawFd) -> Self;
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for old_io::fs::File {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for fs::File {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd().raw()
         }
     }
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawFd for fs::File {
+        fn from_raw_fd(fd: RawFd) -> fs::File {
+            fs::File::from_inner(sys::fs2::File::from_inner(fd))
+        }
+    }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for old_io::pipe::PipeStream {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for old_io::net::pipe::UnixStream {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for old_io::net::pipe::UnixListener {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for old_io::net::pipe::UnixAcceptor {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     impl AsRawFd for old_io::net::tcp::TcpStream {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     impl AsRawFd for old_io::net::tcp::TcpListener {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     impl AsRawFd for old_io::net::tcp::TcpAcceptor {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for old_io::net::udp::UdpSocket {
-        fn as_raw_fd(&self) -> Fd {
+        fn as_raw_fd(&self) -> RawFd {
             self.as_inner().fd()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for net::TcpStream {
-        fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() }
+        fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
     }
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for net::TcpListener {
-        fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() }
+        fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
     }
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawFd for net::UdpSocket {
-        fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() }
+        fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+    }
+
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawFd for net::TcpStream {
+        fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+            let socket = sys::net::Socket::from_inner(fd);
+            net::TcpStream::from_inner(net2::TcpStream::from_inner(socket))
+        }
+    }
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawFd for net::TcpListener {
+        fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+            let socket = sys::net::Socket::from_inner(fd);
+            net::TcpListener::from_inner(net2::TcpListener::from_inner(socket))
+        }
+    }
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawFd for net::UdpSocket {
+        fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+            let socket = sys::net::Socket::from_inner(fd);
+            net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket))
+        }
     }
 }
 
@@ -138,7 +207,7 @@ fn as_raw_fd(&self) -> Fd { *self.as_inner().socket().as_inner() }
 /// Unix-specific extension to the primitives in the `std::ffi` module
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod ffi {
-    use ffi::{CString, NulError, OsStr, OsString};
+    use ffi::{OsStr, OsString};
     use mem;
     use prelude::v1::*;
     use sys::os_str::Buf;
@@ -175,10 +244,6 @@ pub trait OsStrExt {
         /// Get the underlying byte view of the `OsStr` slice.
         #[stable(feature = "rust1", since = "1.0.0")]
         fn as_bytes(&self) -> &[u8];
-
-        /// Convert the `OsStr` slice into a `CString`.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn to_cstring(&self) -> Result<CString, NulError>;
     }
 
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -189,9 +254,6 @@ fn from_bytes(slice: &[u8]) -> &OsStr {
         fn as_bytes(&self) -> &[u8] {
             &self.as_inner().inner
         }
-        fn to_cstring(&self) -> Result<CString, NulError> {
-            CString::new(self.as_bytes())
-        }
     }
 }
 
@@ -302,7 +364,7 @@ fn signal(&self) -> Option<i32> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod prelude {
     #[doc(no_inline)]
-    pub use super::io::{Fd, AsRawFd};
+    pub use super::io::{RawFd, AsRawFd};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::ffi::{OsStrExt, OsStringExt};
     #[doc(no_inline)]
index 2569653811f11e2892900a3ca710551becb07b22..6b085c8eb7a85fc90b41b2239c4410e29118c5f4 100644 (file)
@@ -388,9 +388,7 @@ mod tests {
     fn test_file_desc() {
         // Run this test with some pipes so we don't have to mess around with
         // opening or closing files.
-        let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
-        let mut reader = FileDesc::new(reader, true);
-        let mut writer = FileDesc::new(writer, true);
+        let (mut reader, mut writer) = unsafe { ::sys::os::pipe().unwrap() };
 
         writer.write(b"test").unwrap();
         let mut buf = [0; 4];
index 202e5ddaec42bd01c77eda25d11acdba21c902fd..c0426af051be372061b45cae94f907247ae57298 100644 (file)
@@ -12,7 +12,7 @@
 use io::prelude::*;
 use os::unix::prelude::*;
 
-use ffi::{CString, CStr, OsString, AsOsStr, OsStr};
+use ffi::{CString, CStr, OsString, OsStr};
 use io::{self, Error, SeekFrom};
 use libc::{self, c_int, size_t, off_t, c_char, mode_t};
 use mem;
@@ -276,8 +276,14 @@ pub fn fd(&self) -> &FileDesc { &self.0 }
 }
 
 fn cstr(path: &Path) -> io::Result<CString> {
-    let cstring = try!(path.as_os_str().to_cstring());
-    Ok(cstring)
+    path.as_os_str().to_cstring().ok_or(
+        io::Error::new(io::ErrorKind::InvalidInput, "path contained a null"))
+}
+
+impl FromInner<c_int> for File {
+    fn from_inner(fd: c_int) -> File {
+        File(FileDesc::new(fd))
+    }
 }
 
 pub fn mkdir(p: &Path) -> io::Result<()> {
index 17c8b21f8b3bcf51cc6861253fd19bd7b67fc91c..fe0ede80fc663cbda1451a8cfffecb65aaecb178 100644 (file)
 #![allow(deprecated)]
 
 use libc;
-use os;
+use sys::os;
 
 use sys::fs::FileDesc;
 
 pub type signal = libc::c_int;
 
 pub fn new() -> (signal, signal) {
-    let os::Pipe { reader, writer } = unsafe { os::pipe().unwrap() };
-    (reader, writer)
+    let (a, b) = unsafe { os::pipe().unwrap() };
+    (a.unwrap(), b.unwrap())
 }
 
 pub fn signal(fd: libc::c_int) {
index b22fa33e5624a3ca7a2e1754f57b65b2b027ac7c..908136a42ab00a96723bc902d863def68d5f26ef 100644 (file)
@@ -17,7 +17,7 @@
 use sys::c;
 use net::SocketAddr;
 use sys::fd::FileDesc;
-use sys_common::AsInner;
+use sys_common::{AsInner, FromInner};
 
 pub use sys::{cvt, cvt_r};
 
@@ -35,7 +35,8 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> {
             .to_string()
     };
     Err(io::Error::new(io::ErrorKind::Other,
-                       "failed to lookup address information", Some(detail)))
+                       &format!("failed to lookup address information: {}",
+                                detail)[..]))
 }
 
 impl Socket {
@@ -72,3 +73,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
 impl AsInner<c_int> for Socket {
     fn as_inner(&self) -> &c_int { self.0.as_inner() }
 }
+
+impl FromInner<c_int> for Socket {
+    fn from_inner(fd: c_int) -> Socket { Socket(FileDesc::new(fd)) }
+}
index fab443feebd0bd08f1c5fe8bd7ab963e6d2f80da..7b13e951b9b3315203bdf294a51bb1172828d084 100644 (file)
@@ -16,7 +16,7 @@
 use os::unix::prelude::*;
 
 use error::Error as StdError;
-use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
+use ffi::{CString, CStr, OsString, OsStr};
 use fmt;
 use io;
 use iter;
@@ -125,7 +125,8 @@ pub fn getcwd() -> io::Result<PathBuf> {
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
-    let p = try!(CString::new(p.as_os_str().as_bytes()));
+    let p: &OsStr = p.as_ref();
+    let p = try!(CString::new(p.as_bytes()));
     unsafe {
         match libc::chdir(p.as_ptr()) == (0 as c_int) {
             true => Ok(()),
@@ -158,13 +159,13 @@ fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 pub struct JoinPathsError;
 
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
-    where I: Iterator<Item=T>, T: AsOsStr
+    where I: Iterator<Item=T>, T: AsRef<OsStr>
 {
     let mut joined = Vec::new();
     let sep = b':';
 
     for (i, path) in paths.enumerate() {
-        let path = path.as_os_str().as_bytes();
+        let path = path.as_ref().as_bytes();
         if i > 0 { joined.push(sep) }
         if path.contains(&sep) {
             return Err(JoinPathsError)
@@ -464,7 +465,7 @@ pub fn page_size() -> usize {
 }
 
 pub fn temp_dir() -> PathBuf {
-    getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| {
+    getenv("TMPDIR".as_ref()).map(os2path).unwrap_or_else(|| {
         if cfg!(target_os = "android") {
             PathBuf::from("/data/local/tmp")
         } else {
@@ -474,7 +475,7 @@ pub fn temp_dir() -> PathBuf {
 }
 
 pub fn home_dir() -> Option<PathBuf> {
-    return getenv("HOME".as_os_str()).or_else(|| unsafe {
+    return getenv("HOME".as_ref()).or_else(|| unsafe {
         fallback()
     }).map(os2path);
 
@@ -505,3 +506,7 @@ unsafe fn fallback() -> Option<OsString> {
         }
     }
 }
+
+pub fn exit(code: i32) -> ! {
+    unsafe { libc::exit(code as c_int) }
+}
index 0d35ace185d844b86bf874ee5a1420ffa8338a17..8095325f83d1faf553220784814a6e2f84b102a7 100644 (file)
@@ -19,8 +19,9 @@
 use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
 use old_io::{IoResult, EndOfFile};
 use libc::{self, pid_t, c_void, c_int};
+use io;
 use mem;
-use os;
+use sys::os;
 use old_path::BytesContainer;
 use ptr;
 use sync::mpsc::{channel, Sender, Receiver};
@@ -496,7 +497,8 @@ fn drain(fd: libc::c_int) -> bool {
                     n if n > 0 => { ret = true; }
                     0 => return true,
                     -1 if wouldblock() => return ret,
-                    n => panic!("bad read {:?} ({:?})", os::last_os_error(), n),
+                    n => panic!("bad read {} ({})",
+                                io::Error::last_os_error(), n),
                 }
             }
         }
index 20c409154b82428e1d175f5b6691f9c6c1c57fe5..c2a8b26aef4ebb63306fa9f6b947f9c3df15e99e 100644 (file)
@@ -54,7 +54,7 @@ pub fn arg(&mut self, arg: &OsStr) {
         self.args.push(arg.to_cstring().unwrap())
     }
     pub fn args<'a, I: Iterator<Item = &'a OsStr>>(&mut self, args: I) {
-        self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap()))
+        self.args.extend(args.map(|s| s.to_cstring().unwrap()))
     }
     fn init_env_map(&mut self) {
         if self.env.is_none() {
index d9a162302fc1cc28c1bd0c0756c0c4a20c76b02d..9309147b15c44f6bd14ae38417bf04ef010fcda2 100644 (file)
@@ -54,7 +54,8 @@
 use old_io::IoResult;
 use libc;
 use mem;
-use os;
+use sys::os;
+use io;
 use ptr;
 use sync::atomic::{self, Ordering};
 use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
@@ -209,7 +210,7 @@ fn signal(active: &mut Vec<Box<Inner>>,
 
             -1 if os::errno() == libc::EINTR as i32 => {}
             n => panic!("helper thread failed in select() with error: {} ({})",
-                       n, os::last_os_error())
+                       n, io::Error::last_os_error())
         }
     }
 }
index b9be4eb6bf52b2c2405d502deeeb44867ef51f84..e74de595f9750db33072c5396a74e3f7c3ab1119 100644 (file)
@@ -433,6 +433,7 @@ pub fn OpenProcessToken(ProcessHandle: libc::HANDLE,
                             TokenHandle: *mut libc::HANDLE) -> libc::BOOL;
     pub fn GetCurrentProcess() -> libc::HANDLE;
     pub fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
+    pub fn ExitProcess(uExitCode: libc::c_uint) -> !;
 }
 
 #[link(name = "userenv")]
index 7955397892b7726fc1d1891b26231a03e140c447..2dd61861bd6dc8c78299ffb2b7c9065f3aef29c9 100644 (file)
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-#[unstable(feature = "io_ext",
-           reason = "organization may change slightly and the primitives \
-                     provided may be tweaked")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub mod io {
     use fs;
     use libc;
     use net;
-    use sys_common::AsInner;
+    use sys_common::{net2, AsInner, FromInner};
+    use sys;
 
     #[allow(deprecated)]
     use old_io;
 
     /// Raw HANDLEs.
-    pub type Handle = libc::HANDLE;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub type RawHandle = libc::HANDLE;
 
     /// Raw SOCKETs.
-    pub type Socket = libc::SOCKET;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub type RawSocket = libc::SOCKET;
 
     /// Extract raw handles.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub trait AsRawHandle {
         /// Extract the raw handle, without taking any ownership.
-        fn as_raw_handle(&self) -> Handle;
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn as_raw_handle(&self) -> RawHandle;
+    }
+
+    /// Construct I/O objects from raw handles.
+    #[unstable(feature = "from_raw_os",
+               reason = "recent addition to the std::os::windows::io module")]
+    pub trait FromRawHandle {
+        /// Construct a new I/O object from the specified raw handle.
+        ///
+        /// This function will **consume ownership** of the handle given,
+        /// passing responsibility for closing the handle to the returned
+        /// object.
+        fn from_raw_handle(handle: RawHandle) -> Self;
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawHandle for old_io::fs::File {
-        fn as_raw_handle(&self) -> Handle {
+        fn as_raw_handle(&self) -> RawHandle {
             self.as_inner().handle()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawHandle for fs::File {
-        fn as_raw_handle(&self) -> Handle {
+        fn as_raw_handle(&self) -> RawHandle {
             self.as_inner().handle().raw()
         }
     }
 
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawHandle for fs::File {
+        fn from_raw_handle(handle: RawHandle) -> fs::File {
+            fs::File::from_inner(sys::fs2::File::from_inner(handle))
+        }
+    }
+
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawHandle for old_io::pipe::PipeStream {
-        fn as_raw_handle(&self) -> Handle {
+        fn as_raw_handle(&self) -> RawHandle {
             self.as_inner().handle()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawHandle for old_io::net::pipe::UnixStream {
-        fn as_raw_handle(&self) -> Handle {
+        fn as_raw_handle(&self) -> RawHandle {
             self.as_inner().handle()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawHandle for old_io::net::pipe::UnixListener {
-        fn as_raw_handle(&self) -> Handle {
+        fn as_raw_handle(&self) -> RawHandle {
             self.as_inner().handle()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawHandle for old_io::net::pipe::UnixAcceptor {
-        fn as_raw_handle(&self) -> Handle {
+        fn as_raw_handle(&self) -> RawHandle {
             self.as_inner().handle()
         }
     }
 
     /// Extract raw sockets.
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub trait AsRawSocket {
-        fn as_raw_socket(&self) -> Socket;
+        /// Extract the underlying raw socket from this object.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        fn as_raw_socket(&self) -> RawSocket;
+    }
+
+    /// Create I/O objects from raw sockets.
+    #[unstable(feature = "from_raw_os", reason = "recent addition to module")]
+    pub trait FromRawSocket {
+        /// Creates a new I/O object from the given raw socket.
+        ///
+        /// This function will **consume ownership** of the socket provided and
+        /// it will be closed when the returned object goes out of scope.
+        fn from_raw_socket(sock: RawSocket) -> Self;
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for old_io::net::tcp::TcpStream {
-        fn as_raw_socket(&self) -> Socket {
+        fn as_raw_socket(&self) -> RawSocket {
             self.as_inner().fd()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for old_io::net::tcp::TcpListener {
-        fn as_raw_socket(&self) -> Socket {
+        fn as_raw_socket(&self) -> RawSocket {
             self.as_inner().socket()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for old_io::net::tcp::TcpAcceptor {
-        fn as_raw_socket(&self) -> Socket {
+        fn as_raw_socket(&self) -> RawSocket {
             self.as_inner().socket()
         }
     }
 
     #[allow(deprecated)]
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for old_io::net::udp::UdpSocket {
-        fn as_raw_socket(&self) -> Socket {
+        fn as_raw_socket(&self) -> RawSocket {
             self.as_inner().fd()
         }
     }
 
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for net::TcpStream {
-        fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() }
+        fn as_raw_socket(&self) -> RawSocket {
+            *self.as_inner().socket().as_inner()
+        }
     }
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for net::TcpListener {
-        fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() }
+        fn as_raw_socket(&self) -> RawSocket {
+            *self.as_inner().socket().as_inner()
+        }
     }
+    #[stable(feature = "rust1", since = "1.0.0")]
     impl AsRawSocket for net::UdpSocket {
-        fn as_raw_socket(&self) -> Socket { *self.as_inner().socket().as_inner() }
+        fn as_raw_socket(&self) -> RawSocket {
+            *self.as_inner().socket().as_inner()
+        }
+    }
+
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawSocket for net::TcpStream {
+        fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
+            let sock = sys::net::Socket::from_inner(sock);
+            net::TcpStream::from_inner(net2::TcpStream::from_inner(sock))
+        }
+    }
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawSocket for net::TcpListener {
+        fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
+            let sock = sys::net::Socket::from_inner(sock);
+            net::TcpListener::from_inner(net2::TcpListener::from_inner(sock))
+        }
+    }
+    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+    impl FromRawSocket for net::UdpSocket {
+        fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
+            let sock = sys::net::Socket::from_inner(sock);
+            net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock))
+        }
     }
 }
 
@@ -230,7 +306,7 @@ fn share_mode(&mut self, access: i32) -> &mut OpenOptions {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub mod prelude {
     #[doc(no_inline)]
-    pub use super::io::{Socket, Handle, AsRawSocket, AsRawHandle};
+    pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::ffi::{OsStrExt, OsStringExt};
     #[doc(no_inline)]
index 3330130c7700207fab3279f53768b9d311af9fdd..0bbb1a9e92752c09c39f81adbcb6b53335b23baf 100644 (file)
@@ -136,7 +136,7 @@ pub fn fstat(&self) -> IoResult<old_io::FileStat> {
         }
     }
 
-    /// Extract the actual filedescriptor without closing it.
+    #[allow(dead_code)]
     pub fn unwrap(self) -> fd_t {
         let fd = self.fd;
         unsafe { mem::forget(self) };
index 998352651117bcbe99b5f9c3f54cc69b2ef3d88f..d03e45649ed05e3a8a3daec584b453eb32fbc4da 100644 (file)
 use path::{Path, PathBuf};
 use ptr;
 use sync::Arc;
-use sys::handle::Handle as RawHandle;
+use sys::handle::Handle;
 use sys::{c, cvt};
+use sys_common::FromInner;
 use vec::Vec;
 
-pub struct File { handle: RawHandle }
+pub struct File { handle: Handle }
 pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
 
 pub struct ReadDir {
@@ -192,7 +193,7 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
         if handle == libc::INVALID_HANDLE_VALUE {
             Err(Error::last_os_error())
         } else {
-            Ok(File { handle: RawHandle::new(handle) })
+            Ok(File { handle: Handle::new(handle) })
         }
     }
 
@@ -260,7 +261,13 @@ pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
         Ok(newpos as u64)
     }
 
-    pub fn handle(&self) -> &RawHandle { &self.handle }
+    pub fn handle(&self) -> &Handle { &self.handle }
+}
+
+impl FromInner<libc::HANDLE> for File {
+    fn from_inner(handle: libc::HANDLE) -> File {
+        File { handle: Handle::new(handle) }
+    }
 }
 
 pub fn to_utf16(s: &Path) -> Vec<u16> {
index 88d043de479bbe68ce50b27e4ff02ff3d6c6f821..12a8ef99d764adc3a9d70b6eea9c66bb71787ca0 100644 (file)
@@ -20,7 +20,7 @@
 use rt;
 use sync::{Once, ONCE_INIT};
 use sys::c;
-use sys_common::AsInner;
+use sys_common::{AsInner, FromInner};
 
 pub type wrlen_t = i32;
 
@@ -126,10 +126,14 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
 
 impl Drop for Socket {
     fn drop(&mut self) {
-        unsafe { cvt(libc::closesocket(self.0)).unwrap(); }
+        let _ = unsafe { libc::closesocket(self.0) };
     }
 }
 
 impl AsInner<libc::SOCKET> for Socket {
     fn as_inner(&self) -> &libc::SOCKET { &self.0 }
 }
+
+impl FromInner<libc::SOCKET> for Socket {
+    fn from_inner(sock: libc::SOCKET) -> Socket { Socket(sock) }
+}
index 167db1e8ac2d790b056c05af6bd78b8bdb8cdb86..d5843a2f9987b153b67543303530eb44dc9af436 100644 (file)
@@ -16,7 +16,7 @@
 use os::windows::prelude::*;
 
 use error::Error as StdError;
-use ffi::{OsString, OsStr, AsOsStr};
+use ffi::{OsString, OsStr};
 use fmt;
 use io;
 use libc::types::os::arch::extra::LPWCH;
@@ -31,7 +31,7 @@
 use slice;
 use sys::c;
 use sys::fs::FileDesc;
-use sys::handle::Handle as RawHandle;
+use sys::handle::Handle;
 
 use libc::funcs::extra::kernel32::{
     GetEnvironmentStringsW,
@@ -199,13 +199,13 @@ fn next(&mut self) -> Option<PathBuf> {
 pub struct JoinPathsError;
 
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
-    where I: Iterator<Item=T>, T: AsOsStr
+    where I: Iterator<Item=T>, T: AsRef<OsStr>
 {
     let mut joined = Vec::new();
     let sep = b';' as u16;
 
     for (i, path) in paths.enumerate() {
-        let path = path.as_os_str();
+        let path = path.as_ref();
         if i > 0 { joined.push(sep) }
         let v = path.encode_wide().collect::<Vec<u16>>();
         if v.contains(&(b'"' as u16)) {
@@ -245,7 +245,8 @@ pub fn getcwd() -> io::Result<PathBuf> {
 }
 
 pub fn chdir(p: &path::Path) -> io::Result<()> {
-    let mut p = p.as_os_str().encode_wide().collect::<Vec<_>>();
+    let p: &OsStr = p.as_ref();
+    let mut p = p.encode_wide().collect::<Vec<_>>();
     p.push(0);
 
     unsafe {
@@ -361,15 +362,15 @@ pub fn temp_dir() -> PathBuf {
 }
 
 pub fn home_dir() -> Option<PathBuf> {
-    getenv("HOME".as_os_str()).or_else(|| {
-        getenv("USERPROFILE".as_os_str())
+    getenv("HOME".as_ref()).or_else(|| {
+        getenv("USERPROFILE".as_ref())
     }).map(PathBuf::from).or_else(|| unsafe {
         let me = c::GetCurrentProcess();
         let mut token = ptr::null_mut();
         if c::OpenProcessToken(me, c::TOKEN_READ, &mut token) == 0 {
             return None
         }
-        let _handle = RawHandle::new(token);
+        let _handle = Handle::new(token);
         super::fill_utf16_buf_new(|buf, mut sz| {
             match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
                 0 if libc::GetLastError() != 0 => 0,
@@ -379,3 +380,7 @@ pub fn home_dir() -> Option<PathBuf> {
         }, super::os2path).ok()
     })
 }
+
+pub fn exit(code: i32) -> ! {
+    unsafe { c::ExitProcess(code as libc::c_uint) }
+}
index 297f6e173abdc9f48d3b6872ab2c712f54fe4e2d..b10042090ddc8d634a89d875cb10334ea07cf52e 100644 (file)
@@ -23,7 +23,7 @@
 use old_io::process::{ProcessExit, ExitStatus};
 use old_io::{IoResult, IoError};
 use old_io;
-use os;
+use fs::PathExt;
 use old_path::{BytesContainer, GenericPath};
 use ptr;
 use str;
@@ -142,14 +142,19 @@ pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
         let program = cfg.env().and_then(|env| {
             for (key, v) in env {
                 if b"PATH" != key.container_as_bytes() { continue }
+                let v = match ::str::from_utf8(v.container_as_bytes()) {
+                    Ok(s) => s,
+                    Err(..) => continue,
+                };
 
                 // Split the value and test each path to see if the
                 // program exists.
-                for path in os::split_paths(v.container_as_bytes()) {
-                    let path = path.join(cfg.program().as_bytes())
+                for path in ::env::split_paths(v) {
+                    let program = str::from_utf8(cfg.program().as_bytes()).unwrap();
+                    let path = path.join(program)
                                    .with_extension(env::consts::EXE_EXTENSION);
                     if path.exists() {
-                        return Some(CString::from_slice(path.as_vec()))
+                        return Some(CString::new(path.to_str().unwrap()).unwrap())
                     }
                 }
                 break
@@ -482,9 +487,9 @@ mod tests {
     #[test]
     fn test_make_command_line() {
         fn test_wrapper(prog: &str, args: &[&str]) -> String {
-            make_command_line(&CString::from_slice(prog.as_bytes()),
+            make_command_line(&CString::new(prog).unwrap(),
                               &args.iter()
-                                   .map(|a| CString::from_slice(a.as_bytes()))
+                                   .map(|a| CString::new(*a).unwrap())
                                    .collect::<Vec<CString>>())
         }
 
index 9e9bb86446e7c11b1f395ed598c888a89764ea4e..7e832b6384dee46ce09686ccd483c7c4008928b3 100644 (file)
@@ -445,10 +445,9 @@ fn test_make_command_line() {
         fn test_wrapper(prog: &str, args: &[&str]) -> String {
             String::from_utf16(
                 &make_command_line(OsStr::from_str(prog),
-                                   args.iter()
-                                       .map(|a| OsString::from_str(a))
-                                       .collect::<Vec<OsString>>()
-                                       .as_slice())).unwrap()
+                                   &args.iter()
+                                        .map(|a| OsString::from(a))
+                                        .collect::<Vec<OsString>>())).unwrap()
         }
 
         assert_eq!(
index d1bff0e135dd697aa2c7f2eb1139200ffd7b903c..91f6f328ff6e0a9eb7038dbfe21e7c4babca885a 100644 (file)
@@ -41,7 +41,7 @@ fn get(handle: libc::DWORD) -> io::Result<Output> {
         Err(io::Error::last_os_error())
     } else if handle.is_null() {
         Err(io::Error::new(io::ErrorKind::Other,
-                           "no stdio handle available for this process", None))
+                           "no stdio handle available for this process"))
     } else {
         let ret = NoClose::new(handle);
         let mut out = 0;
@@ -160,6 +160,5 @@ fn drop(&mut self) {
 }
 
 fn invalid_encoding() -> io::Error {
-    io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode",
-                   None)
+    io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode")
 }
index a2b824bb016ffa401255a488249e480e0d56eaf8..b9cbd01bed180120895dc28c1e3085a85b39b377 100644 (file)
@@ -294,12 +294,6 @@ pub fn state(&'static self) -> LocalKeyState {
             }
         }
     }
-
-    /// 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")))]
index 074030bd07bdb7853f1f9e4d70a61836d3044043..1202b353317cdb4c28cd7ac2cb6b0f7900c65d5d 100644 (file)
 use thunk::Thunk;
 use time::Duration;
 
-#[allow(deprecated)] use old_io::Writer;
-
 ////////////////////////////////////////////////////////////////////////////////
 // Thread-local storage
 ////////////////////////////////////////////////////////////////////////////////
@@ -243,28 +241,6 @@ pub fn stack_size(mut self, size: usize) -> Builder {
         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
@@ -568,71 +544,6 @@ fn new(name: Option<String>) -> Thread {
         }
     }
 
-    /// 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.
@@ -762,8 +673,8 @@ pub fn thread(&self) -> &Thread {
         &self.inner.thread
     }
 
-    /// Wait for the associated thread to finish, returning the result of the thread's
-    /// calculation.
+    /// Wait for the associated thread to finish, returning the result of the
+    /// thread's calculation.
     ///
     /// # Panics
     ///
@@ -777,17 +688,6 @@ pub fn join(mut self) -> T {
     }
 }
 
-#[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> {
@@ -810,7 +710,6 @@ mod test {
 
     use any::Any;
     use sync::mpsc::{channel, Sender};
-    use boxed::BoxAny;
     use result;
     use std::old_io::{ChanReader, ChanWriter};
     use super::{Builder};
index 48bb044cb1854cafba113fd3a9b56ff1c3aa3ec9..2b5cb7076f463c8e4da518d5a5dcf17f32e9fd06 100644 (file)
@@ -53,18 +53,29 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[derive(Clone)]
-struct LinkedPathNode<'a> {
+pub struct LinkedPathNode<'a> {
     node: PathElem,
     next: LinkedPath<'a>,
 }
 
-type LinkedPath<'a> = Option<&'a LinkedPathNode<'a>>;
+#[derive(Copy, Clone)]
+pub struct LinkedPath<'a>(Option<&'a LinkedPathNode<'a>>);
+
+impl<'a> LinkedPath<'a> {
+    pub fn empty() -> LinkedPath<'a> {
+        LinkedPath(None)
+    }
+
+    pub fn from(node: &'a LinkedPathNode) -> LinkedPath<'a> {
+        LinkedPath(Some(node))
+    }
+}
 
 impl<'a> Iterator for LinkedPath<'a> {
     type Item = PathElem;
 
     fn next(&mut self) -> Option<PathElem> {
-        match *self {
+        match self.0 {
             Some(node) => {
                 *self = node.next;
                 Some(node.node)
@@ -384,7 +395,7 @@ pub fn get_path_elem(&self, id: NodeId) -> PathElem {
     pub fn with_path<T, F>(&self, id: NodeId, f: F) -> T where
         F: FnOnce(PathElems) -> T,
     {
-        self.with_path_next(id, None, f)
+        self.with_path_next(id, LinkedPath::empty(), f)
     }
 
     pub fn path_to_string(&self, id: NodeId) -> String {
@@ -422,7 +433,7 @@ fn with_path_next<T, F>(&self, id: NodeId, next: LinkedPath, f: F) -> T where
                 _ => f([].iter().cloned().chain(next))
             }
         } else {
-            self.with_path_next(parent, Some(&LinkedPathNode {
+            self.with_path_next(parent, LinkedPath::from(&LinkedPathNode {
                 node: self.get_path_elem(id),
                 next: next
             }), f)
index 1b03a18072011a2c1f5acf0bbcf306369af6fe28..113827a3b402f2bb4f2353d3895705627037ad61 100644 (file)
     ("start", "1.0.0", Active),
     ("main", "1.0.0", Active),
 
+    ("fundamental", "1.0.0", Active),
+
     // Deprecate after snapshot
-    // SNAP a923278
+    // SNAP 5520801
     ("unsafe_destructor", "1.0.0", Active),
 
     // A temporary feature gate used to enable parser extensions needed
     // A way to temporarily opt out of opt in copy. This will *never* be accepted.
     ("opt_out_copy", "1.0.0", Removed),
 
-    // A way to temporarily opt out of the new orphan rules. This will *never* be accepted.
-    ("old_orphan_check", "1.0.0", Deprecated),
-
     // OIBIT specific features
     ("optin_builtin_traits", "1.0.0", Active),
 
@@ -161,10 +160,6 @@ enum Status {
     /// currently being considered for addition/removal.
     Active,
 
-    /// Represents a feature gate that is temporarily enabling deprecated behavior.
-    /// This gate will never be accepted.
-    Deprecated,
-
     /// Represents a feature which has since been removed (it was once Active)
     Removed,
 
@@ -244,6 +239,10 @@ enum Status {
     ("allow_internal_unstable", Gated("allow_internal_unstable",
                                       EXPLAIN_ALLOW_INTERNAL_UNSTABLE)),
 
+    ("fundamental", Gated("fundamental",
+                          "the `#[fundamental]` attribute \
+                           is an experimental feature")),
+
     // FIXME: #14408 whitelist docs since rustdoc looks at them
     ("doc", Whitelisted),
 
@@ -277,9 +276,6 @@ enum Status {
     ("stable", Whitelisted),
     ("unstable", Whitelisted),
 
-    // FIXME: #19470 this shouldn't be needed forever
-    ("old_orphan_check", Whitelisted),
-
     ("rustc_paren_sugar", Gated("unboxed_closures",
                                 "unboxed_closures are still evolving")),
     ("rustc_reflect_like", Gated("reflect",
@@ -327,7 +323,6 @@ pub struct Features {
     pub allow_trace_macros: bool,
     pub allow_internal_unstable: bool,
     pub allow_custom_derive: bool,
-    pub old_orphan_check: bool,
     pub simd_ffi: bool,
     pub unmarked_api: bool,
     /// spans of #![feature] attrs for stable language features. for error reporting
@@ -349,7 +344,6 @@ pub fn new() -> Features {
             allow_trace_macros: false,
             allow_internal_unstable: false,
             allow_custom_derive: false,
-            old_orphan_check: false,
             simd_ffi: false,
             unmarked_api: false,
             declared_stable_lang_features: Vec::new(),
@@ -573,14 +567,6 @@ fn visit_item(&mut self, i: &ast::Item) {
                     },
                     _ => {}
                 }
-
-                if attr::contains_name(&i.attrs[..],
-                                       "old_orphan_check") {
-                    self.gate_feature(
-                        "old_orphan_check",
-                        i.span,
-                        "the new orphan check rules will eventually be strictly enforced");
-                }
             }
 
             _ => {}
@@ -699,13 +685,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
                         Some(&(name, _, Active)) => {
                             cx.features.push(name);
                         }
-                        Some(&(name, _, Deprecated)) => {
-                            cx.features.push(name);
-                            span_handler.span_warn(
-                                mi.span,
-                                "feature is deprecated and will only be available \
-                                 for a limited time, please rewrite code that relies on it");
-                        }
                         Some(&(_, _, Removed)) => {
                             span_handler.span_err(mi.span, "feature has been removed");
                         }
@@ -737,7 +716,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         allow_trace_macros: cx.has_feature("trace_macros"),
         allow_internal_unstable: cx.has_feature("allow_internal_unstable"),
         allow_custom_derive: cx.has_feature("custom_derive"),
-        old_orphan_check: cx.has_feature("old_orphan_check"),
         simd_ffi: cx.has_feature("simd_ffi"),
         unmarked_api: cx.has_feature("unmarked_api"),
         declared_stable_lang_features: accepted_features,
index c471d9e31792212cbcdf3b9dcd7ead5324d1d260..0980acd3433dcc427dcf3da5833b856ccdaa3f60 100644 (file)
@@ -37,7 +37,6 @@
 #![feature(unicode)]
 #![feature(path_ext)]
 #![feature(str_char)]
-#![feature(convert)]
 #![feature(into_cow)]
 #![feature(slice_patterns)]
 
index bcb265af9265527d85a78e209683456d1d156601..78470f002072ddf6f724c21e6d1858ae68f1f92a 100644 (file)
@@ -620,8 +620,8 @@ fn bump_expecting_char<'a,D:fmt::Debug>(r: &mut StringReader<'a>,
         let base = 10;
 
         // find the integer representing the name
-        self.scan_digits(base);
-        let encoded_name: u32 = self.with_str_from(start_bpos, |s| {
+        self.scan_digits(base, base);
+        let encoded_name : u32 = self.with_str_from(start_bpos, |s| {
             u32::from_str_radix(s, 10).unwrap_or_else(|_| {
                 panic!("expected digits representing a name, got {:?}, {}, range [{:?},{:?}]",
                       s, whence, start_bpos, self.last_pos);
@@ -638,7 +638,7 @@ fn bump_expecting_char<'a,D:fmt::Debug>(r: &mut StringReader<'a>,
 
         // find the integer representing the ctxt
         let start_bpos = self.last_pos;
-        self.scan_digits(base);
+        self.scan_digits(base, base);
         let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| {
             u32::from_str_radix(s, 10).unwrap_or_else(|_| {
                 panic!("expected digits representing a ctxt, got {:?}, {}", s, whence);
@@ -652,16 +652,28 @@ fn bump_expecting_char<'a,D:fmt::Debug>(r: &mut StringReader<'a>,
                      ctxt: encoded_ctxt, }
     }
 
-    /// Scan through any digits (base `radix`) or underscores, and return how
-    /// many digits there were.
-    fn scan_digits(&mut self, radix: u32) -> usize {
+    /// Scan through any digits (base `scan_radix`) or underscores,
+    /// and return how many digits there were.
+    ///
+    /// `real_radix` represents the true radix of the number we're
+    /// interested in, and errors will be emitted for any digits
+    /// between `real_radix` and `scan_radix`.
+    fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
+        assert!(real_radix <= scan_radix);
         let mut len = 0;
         loop {
             let c = self.curr;
             if c == Some('_') { debug!("skipping a _"); self.bump(); continue; }
-            match c.and_then(|cc| cc.to_digit(radix)) {
+            match c.and_then(|cc| cc.to_digit(scan_radix)) {
                 Some(_) => {
                     debug!("{:?} in scan_digits", c);
+                    // check that the hypothetical digit is actually
+                    // in range for the true radix
+                    if c.unwrap().to_digit(real_radix).is_none() {
+                        self.err_span_(self.last_pos, self.pos,
+                                       &format!("invalid digit for a base {} literal",
+                                                real_radix));
+                    }
                     len += 1;
                     self.bump();
                 }
@@ -680,11 +692,11 @@ fn scan_number(&mut self, c: char) -> token::Lit {
 
         if c == '0' {
             match self.curr.unwrap_or('\0') {
-                'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2); }
-                'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8); }
-                'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16); }
+                'b' => { self.bump(); base = 2; num_digits = self.scan_digits(2, 10); }
+                'o' => { self.bump(); base = 8; num_digits = self.scan_digits(8, 10); }
+                'x' => { self.bump(); base = 16; num_digits = self.scan_digits(16, 16); }
                 '0'...'9' | '_' | '.' => {
-                    num_digits = self.scan_digits(10) + 1;
+                    num_digits = self.scan_digits(10, 10) + 1;
                 }
                 _ => {
                     // just a 0
@@ -692,7 +704,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
                 }
             }
         } else if c.is_digit(10) {
-            num_digits = self.scan_digits(10) + 1;
+            num_digits = self.scan_digits(10, 10) + 1;
         } else {
             num_digits = 0;
         }
@@ -711,7 +723,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
             // with a number
             self.bump();
             if self.curr.unwrap_or('\0').is_digit(10) {
-                self.scan_digits(10);
+                self.scan_digits(10, 10);
                 self.scan_float_exponent();
             }
             let last_pos = self.last_pos;
@@ -934,7 +946,7 @@ fn scan_float_exponent(&mut self) {
             if self.curr_is('-') || self.curr_is('+') {
                 self.bump();
             }
-            if self.scan_digits(10) == 0 {
+            if self.scan_digits(10, 10) == 0 {
                 self.err_span_(self.last_pos, self.pos, "expected at least one digit in exponent")
             }
         }
index 544862a374a4e9e9ff52e6d59711f141f2278477..f59e1d8214a5a632d32651e824d04dd9ef9eebff 100644 (file)
@@ -736,7 +736,20 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) ->
 
     let res = match u64::from_str_radix(s, base).ok() {
         Some(r) => r,
-        None => { sd.span_err(sp, "int literal is too large"); 0 }
+        None => {
+            // small bases are lexed as if they were base 10, e.g, the string
+            // might be `0b10201`. This will cause the conversion above to fail,
+            // but these cases have errors in the lexer: we don't want to emit
+            // two errors, and we especially don't want to emit this error since
+            // it isn't necessarily true.
+            let already_errored = base < 10 &&
+                s.chars().any(|c| c.to_digit(10).map_or(false, |d| d >= base));
+
+            if !already_errored {
+                sd.span_err(sp, "int literal is too large");
+            }
+            0
+        }
     };
 
     // adjust the sign
index da1b7a7bdde50e93ec50a11aac7702b4db45b759..c2f323f98afc56d5a3808ac1db1bdf3ff1b0482d 100644 (file)
@@ -37,6 +37,7 @@ pub enum AnnNode<'a> {
     NodeName(&'a ast::Name),
     NodeBlock(&'a ast::Block),
     NodeItem(&'a ast::Item),
+    NodeSubItem(ast::NodeId),
     NodeExpr(&'a ast::Expr),
     NodePat(&'a ast::Pat),
 }
@@ -1264,6 +1265,7 @@ pub fn print_method_sig(&mut self,
 
     pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                             -> io::Result<()> {
+        try!(self.ann.pre(self, NodeSubItem(ti.id)));
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(ti.span.lo));
         try!(self.print_outer_attributes(&ti.attrs));
@@ -1275,19 +1277,21 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                 try!(self.print_method_sig(ti.ident, sig, ast::Inherited));
                 if let Some(ref body) = *body {
                     try!(self.nbsp());
-                    self.print_block_with_attrs(body, &ti.attrs)
+                    try!(self.print_block_with_attrs(body, &ti.attrs));
                 } else {
-                    word(&mut self.s, ";")
+                    try!(word(&mut self.s, ";"));
                 }
             }
             ast::TypeTraitItem(ref bounds, ref default) => {
-                self.print_associated_type(ti.ident, Some(bounds),
-                                           default.as_ref().map(|ty| &**ty))
+                try!(self.print_associated_type(ti.ident, Some(bounds),
+                                                default.as_ref().map(|ty| &**ty)));
             }
         }
+        self.ann.post(self, NodeSubItem(ti.id))
     }
 
     pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
+        try!(self.ann.pre(self, NodeSubItem(ii.id)));
         try!(self.hardbreak_if_not_bol());
         try!(self.maybe_print_comment(ii.span.lo));
         try!(self.print_outer_attributes(&ii.attrs));
@@ -1296,10 +1300,10 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
                 try!(self.head(""));
                 try!(self.print_method_sig(ii.ident, sig, ii.vis));
                 try!(self.nbsp());
-                self.print_block_with_attrs(body, &ii.attrs)
+                try!(self.print_block_with_attrs(body, &ii.attrs));
             }
             ast::TypeImplItem(ref ty) => {
-                self.print_associated_type(ii.ident, None, Some(ty))
+                try!(self.print_associated_type(ii.ident, None, Some(ty)));
             }
             ast::MacImplItem(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
                                                 ..}) => {
@@ -1311,9 +1315,10 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
                 try!(self.print_tts(&tts[..]));
                 try!(self.pclose());
                 try!(word(&mut self.s, ";"));
-                self.end()
+                try!(self.end())
             }
         }
+        self.ann.post(self, NodeSubItem(ii.id))
     }
 
     pub fn print_outer_attributes(&mut self,
index 5bd6591cfb097c770cf1aa658e8e495ad91f4e97..1649934f4b10e5d4628d20e9ed26370bb9e5a7f6 100644 (file)
@@ -226,13 +226,13 @@ fn test_from_iter() {
     fn test_move_iter() {
         let v = SmallVector::zero();
         let v: Vec<isize> = v.into_iter().collect();
-        assert_eq!(Vec::new(), v);
+        assert_eq!(v, Vec::new());
 
         let v = SmallVector::one(1);
-        assert_eq!([1], v.into_iter().collect::<Vec<_>>());
+        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1]);
 
         let v = SmallVector::many(vec![1, 2, 3]);
-        assert_eq!([1, 2, 3], v.into_iter().collect::<Vec<_>>());
+        assert_eq!(v.into_iter().collect::<Vec<_>>(), [1, 2, 3]);
     }
 
     #[test]
index ed2d00d6ad788ad00008e3a6fb868745f4a1df84..38d58f042b94167fd7ff9ed5d2bd6378d3656bd8 100644 (file)
@@ -62,7 +62,6 @@
 #![feature(std_misc)]
 #![feature(str_char)]
 #![feature(path_ext)]
-#![feature(convert)]
 #![cfg_attr(windows, feature(libc))]
 
 #[macro_use] extern crate log;
index ee0d190d729eb30f9ab1445368a64ea596733a48..f7e5c9f1deedc1ef21634c3a5adbb47540ad8d44 100644 (file)
@@ -43,8 +43,6 @@
 #![feature(std_misc)]
 #![feature(libc)]
 #![feature(set_stdio)]
-#![feature(os)]
-#![feature(convert)]
 #![cfg_attr(test, feature(old_io))]
 
 extern crate getopts;
@@ -857,7 +855,8 @@ fn get_concurrency() -> usize {
             if std::rt::util::limit_thread_creation_due_to_osx_and_valgrind() {
                 1
             } else {
-                std::os::num_cpus()
+                extern { fn rust_get_num_cpus() -> libc::uintptr_t; }
+                unsafe { rust_get_num_cpus() as usize }
             }
         }
     }
index 4a652f846ed58bd0112c54e609a64737c8dad74f..09fcd518c1e7e3998f32851738559f36840d845d 100644 (file)
@@ -15,7 +15,6 @@
 #![feature(rustdoc)]
 #![feature(rustc_private)]
 #![feature(path_relative_from)]
-#![feature(convert)]
 
 extern crate rustdoc;
 extern crate rustc_back;
index 8b05f7c895527887e68a2a8169c6d44e14110214..74d8b222c541f72e323869415049d304486b2f3d 100644 (file)
@@ -1,3 +1,13 @@
+S 2015-03-27 5520801
+  bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163
+  freebsd-x86_64 0910bbad35e213f679d0433884fd51398eb3bc8d
+  linux-i386 1ef82402ed16f5a6d2f87a9a62eaa83170e249ec
+  linux-x86_64 ef2154372e97a3cb687897d027fd51c8f2c5f349
+  macos-i386 0310b1a970f2da7e61770fd14dbbbdca3b518234
+  macos-x86_64 5f35d9c920b8083a7420ef8cf5b00d5ef3085dfa
+  winnt-i386 808b7961f85872f04ec15ad0d3e9e23ae9bc0c3b
+  winnt-x86_64 903a99a58f57a9bd9848cc68a2445dda881f1ee8
+
 S 2015-03-25 a923278
   bitrig-x86_64 41de2c7a69a1ac648d3fa3b65e96a29bdc122163
   freebsd-x86_64 cd02c86a9218da73b2a45aff293787010d33bf3e
diff --git a/src/test/auxiliary/coherence_copy_like_lib.rs b/src/test/auxiliary/coherence_copy_like_lib.rs
new file mode 100644 (file)
index 0000000..a1e1b48
--- /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.
+
+#![crate_type = "rlib"]
+#![feature(fundamental)]
+
+use std::marker::MarkerTrait;
+
+pub trait MyCopy : MarkerTrait { }
+impl MyCopy for i32 { }
+
+pub struct MyStruct<T>(T);
+
+#[fundamental]
+pub struct MyFundamentalStruct<T>(T);
index 64c3872213780beefc05796991c918f900bc4bd9..ce050cc73235dfd76aced3df5d7b3fff0aeb4690 100644 (file)
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#![feature(rustc_private, core)]
+#![feature(rustc_private, core, step_by)]
 
 extern crate arena;
 
-use std::iter::range_step;
 use std::thread;
 use arena::TypedArena;
 
@@ -109,7 +108,7 @@ fn main() {
     let long_lived_arena = TypedArena::new();
     let long_lived_tree = bottom_up_tree(&long_lived_arena, 0, max_depth);
 
-    let messages = range_step(min_depth, max_depth + 1, 2).map(|depth| {
+    let messages = (min_depth..max_depth + 1).step_by(2).map(|depth| {
         use std::num::Int;
         let iterations = 2.pow((max_depth - depth + min_depth) as u32);
         thread::scoped(move || inner(depth, iterations))
index 3a1da4c32af4c1ce5d265a8ab98275a2ad0a83a1..af9ef80e609bac36aff6e39eeeffa7fb3687a2f4 100644 (file)
@@ -38,9 +38,9 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
-#![feature(core)]
+#![feature(step_by)]
 
-use std::{cmp, iter, mem};
+use std::{cmp, mem};
 use std::thread;
 
 fn rotate(x: &mut [i32]) {
@@ -163,7 +163,7 @@ fn fannkuch(n: i32) -> (i32, i32) {
     let mut futures = vec![];
     let k = perm.max() / N;
 
-    for (_, j) in (0..N).zip(iter::count(0, k)) {
+    for (_, j) in (0..N).zip((0..).step_by(k)) {
         let max = cmp::min(j+k, perm.max());
 
         futures.push(thread::scoped(move|| {
index de1d0103657e02485824039d78c741febf742072..c190641bfbff02e468df6396c064805ad47139e9 100644 (file)
@@ -193,7 +193,7 @@ fn main() {
 
            // start processing if this is the one
            ('>', false) => {
-               match line[1..].find_str("THREE") {
+               match line[1..].find("THREE") {
                    Some(_) => { proc_mode = true; }
                    None    => { }
                }
index cd89b822035c22180771bd378421fcee7abee341..c0268e816cf3e537b9c2b7653a4c89680fbebb66 100644 (file)
@@ -118,7 +118,9 @@ fn dot(v: &[f64], u: &[f64]) -> f64 {
 fn parallel<'a,T, F>(v: &mut [T], ref f: F)
                   where T: Send + Sync + 'a,
                         F: Fn(usize, &mut [T]) + Sync + 'a {
-    let size = v.len() / os::num_cpus() + 1;
+    // FIXME: pick a more appropriate parallel factor
+    let parallelism = 4;
+    let size = v.len() / parallelism + 1;
     v.chunks_mut(size).enumerate().map(|(i, chunk)| {
         thread::scoped(move|| {
             f(i * size, chunk)
diff --git a/src/test/compile-fail/coherence-cow-1.rs b/src/test/compile-fail/coherence-cow-1.rs
new file mode 100644 (file)
index 0000000..530bbf5
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+// aux-build:coherence_lib.rs
+
+// pretty-expanded FIXME #23616
+
+// Test that the `Pair` type reports an error if it contains type
+// parameters, even when they are covered by local types. This test
+// was originally intended to test the opposite, but the rules changed
+// with RFC 1023 and this became illegal.
+
+extern crate coherence_lib as lib;
+use lib::{Remote,Pair};
+
+pub struct Cover<T>(T);
+
+impl<T> Remote for Pair<T,Cover<T>> { }
+//~^ ERROR E0210
+
+fn main() { }
diff --git a/src/test/compile-fail/coherence-cow-2.rs b/src/test/compile-fail/coherence-cow-2.rs
new file mode 100644 (file)
index 0000000..52abcea
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+// aux-build:coherence_lib.rs
+
+// Test that the `Pair` type reports an error if it contains type
+// parameters, even when they are covered by local types. This test
+// was originally intended to test the opposite, but the rules changed
+// with RFC 1023 and this became illegal.
+
+// pretty-expanded FIXME #23616
+
+extern crate coherence_lib as lib;
+use lib::{Remote,Pair};
+
+pub struct Cover<T>(T);
+
+impl<T> Remote for Pair<Cover<T>,T> { } //~ ERROR E0210
+
+fn main() { }
index 475d7df1fdb4f7acb5ce91f7b5640f359813c5bd..cd32e797ae9bf0a8d237c6b067fc5a82ffd1ce2b 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:coherence_lib.rs
 
-// Test that it's not ok for U to appear uncovered
+// Test that it's not ok for T to appear uncovered
 
 extern crate coherence_lib as lib;
 use lib::{Remote,Pair};
@@ -18,6 +18,6 @@
 pub struct Cover<T>(T);
 
 impl<T,U> Remote for Pair<Cover<T>,U> { }
-//~^ ERROR type parameter `U` must be used as the type parameter for some local type
+//~^ ERROR type parameter `T` must be used as the type parameter for some local type
 
 fn main() { }
index 3034be177ca68110a3523bd118d9c503b6b3e552..b99b2e1205b9bfd26c3f93f1fc5af331a8a1dafc 100644 (file)
@@ -23,17 +23,24 @@ impl !Sync for NotSync {}
 
 impl Copy for TestE {}
 impl Copy for MyType {}
+
+impl Copy for &'static mut MyType {}
+//~^ ERROR E0206
+
 impl Copy for (MyType, MyType) {}
 //~^ ERROR E0206
+//~| ERROR E0117
 
 impl Copy for &'static NotSync {}
 //~^ ERROR E0206
 
 impl Copy for [MyType] {}
 //~^ ERROR E0206
+//~| ERROR E0117
 
 impl Copy for &'static [NotSync] {}
 //~^ ERROR E0206
+//~| ERROR E0117
 
 fn main() {
 }
index b05c1ff0f0b7265d62fe90db7dbf8980f7517d52..f130a9353516f527462a79183cb49b4436ad7257 100644 (file)
@@ -24,17 +24,17 @@ impl !Sync for NotSync {}
 unsafe impl Send for TestE {}
 unsafe impl Send for MyType {}
 unsafe impl Send for (MyType, MyType) {}
-//~^ ERROR E0321
+//~^ ERROR E0117
 
 unsafe impl Send for &'static NotSync {}
 //~^ ERROR E0321
 
 unsafe impl Send for [MyType] {}
-//~^ ERROR E0321
+//~^ ERROR E0117
 
 unsafe impl Send for &'static [NotSync] {}
-//~^ ERROR E0321
-//~| ERROR conflicting implementations
+//~^ ERROR E0117
+//~| ERROR E0119
 
 fn main() {
 }
index a9a3ebaffb75abff44bfc810ac3ca74544b24b5b..2ac4bb0492b1f6f4df24a1454829c785aaf66e0f 100644 (file)
@@ -22,12 +22,17 @@ enum TestE {
 impl !Sync for NotSync {}
 
 impl Sized for TestE {} //~ ERROR E0322
+
 impl Sized for MyType {} //~ ERROR E0322
-impl Sized for (MyType, MyType) {} //~ ERROR E0322
+
+impl Sized for (MyType, MyType) {} //~ ERROR E0117
+
 impl Sized for &'static NotSync {} //~ ERROR E0322
-impl Sized for [MyType] {} //~ ERROR E0322
+
+impl Sized for [MyType] {} //~ ERROR E0117
 //~^ ERROR E0277
-impl Sized for &'static [NotSync] {} //~ ERROR E0322
+
+impl Sized for &'static [NotSync] {} //~ ERROR E0117
 
 fn main() {
 }
diff --git a/src/test/compile-fail/coherence-overlap-issue-23516.rs b/src/test/compile-fail/coherence-overlap-issue-23516.rs
new file mode 100644 (file)
index 0000000..d7f060a
--- /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.
+
+// Tests that we consider `Box<U>: !Sugar` to be ambiguous, even
+// though we see no impl of `Sugar` for `Box`. Therefore, an overlap
+// error is reported for the following pair of impls (#23516).
+
+pub trait Sugar { fn dummy(&self) { } }
+pub trait Sweet { fn dummy(&self) { } }
+impl<T:Sugar> Sweet for T { } //~ ERROR E0119
+impl<U:Sugar> Sweet for Box<U> { }
+fn main() { }
diff --git a/src/test/compile-fail/coherence-vec-local-2.rs b/src/test/compile-fail/coherence-vec-local-2.rs
new file mode 100644 (file)
index 0000000..5f0b56a
--- /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.
+
+// Test that a local, generic type appearing within a
+// *non-fundamental* remote type like `Vec` is not considered local.
+
+// aux-build:coherence_lib.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate coherence_lib as lib;
+use lib::Remote;
+
+struct Local<T>(T);
+
+impl<T> Remote for Vec<Local<T>> { } //~ ERROR E0210
+
+fn main() { }
diff --git a/src/test/compile-fail/coherence-vec-local.rs b/src/test/compile-fail/coherence-vec-local.rs
new file mode 100644 (file)
index 0000000..c354caa
--- /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.
+
+// Test that a local type (with no type parameters) appearing within a
+// *non-fundamental* remote type like `Vec` is not considered local.
+
+// aux-build:coherence_lib.rs
+
+// pretty-expanded FIXME #23616
+
+extern crate coherence_lib as lib;
+use lib::Remote;
+
+struct Local;
+
+impl Remote for Vec<Local> { } //~ ERROR E0117
+
+fn main() { }
diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct.rs
new file mode 100644 (file)
index 0000000..f13175c
--- /dev/null
@@ -0,0 +1,36 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+use std::marker::MarkerTrait;
+
+struct MyType { x: i32 }
+
+trait MyTrait : MarkerTrait { }
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// `MyFundamentalStruct` is declared fundamental, so we can test that
+//
+//    MyFundamentalStruct<MyTrait>: !MyTrait
+//
+// Huzzah.
+impl MyTrait for lib::MyFundamentalStruct<MyType> { }
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_ref.rs
new file mode 100644 (file)
index 0000000..ae3d242
--- /dev/null
@@ -0,0 +1,36 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+use std::marker::MarkerTrait;
+
+struct MyType { x: i32 }
+
+trait MyTrait : MarkerTrait { }
+impl<T: lib::MyCopy> MyTrait for T { }
+
+// `MyFundamentalStruct` is declared fundamental, so we can test that
+//
+//    MyFundamentalStruct<&MyTrait>: !MyTrait
+//
+// Huzzah.
+impl<'a> MyTrait for lib::MyFundamentalStruct<&'a MyType> { }
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
diff --git a/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_fundamental_struct_tuple.rs
new file mode 100644 (file)
index 0000000..c4e95e7
--- /dev/null
@@ -0,0 +1,32 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+
+extern crate coherence_copy_like_lib as lib;
+
+use std::marker::MarkerTrait;
+
+struct MyType { x: i32 }
+
+trait MyTrait : MarkerTrait { }
+
+impl<T: lib::MyCopy> MyTrait for T { } //~ ERROR E0119
+
+// Tuples are not fundamental.
+impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
+
+#[rustc_error]
+fn main() { }
diff --git a/src/test/compile-fail/coherence_copy_like_err_struct.rs b/src/test/compile-fail/coherence_copy_like_err_struct.rs
new file mode 100644 (file)
index 0000000..f768a47
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+// aux-build:coherence_copy_like_lib.rs
+
+// Test that we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+extern crate coherence_copy_like_lib as lib;
+
+use std::marker::MarkerTrait;
+
+struct MyType { x: i32 }
+
+trait MyTrait : MarkerTrait { }
+impl<T: lib::MyCopy> MyTrait for T { } //~ ERROR E0119
+
+// `MyStruct` is not declared fundamental, therefore this would
+// require that
+//
+//     MyStruct<MyType>: !MyTrait
+//
+// which we cannot approve.
+impl MyTrait for lib::MyStruct<MyType> { }
+
+fn main() { }
diff --git a/src/test/compile-fail/coherence_copy_like_err_tuple.rs b/src/test/compile-fail/coherence_copy_like_err_tuple.rs
new file mode 100644 (file)
index 0000000..0c78fff
--- /dev/null
@@ -0,0 +1,32 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+extern crate coherence_copy_like_lib as lib;
+
+use std::marker::MarkerTrait;
+
+struct MyType { x: i32 }
+
+trait MyTrait : MarkerTrait { }
+impl<T: lib::MyCopy> MyTrait for T { } //~ ERROR E0119
+
+// Tuples are not fundamental, therefore this would require that
+//
+//     (MyType,): !MyTrait
+//
+// which we cannot approve.
+impl MyTrait for (MyType,) { }
+
+fn main() { }
diff --git a/src/test/compile-fail/coherence_local.rs b/src/test/compile-fail/coherence_local.rs
new file mode 100644 (file)
index 0000000..551577b
--- /dev/null
@@ -0,0 +1,33 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// These are all legal because they are all fundamental types:
+
+impl lib::MyCopy for MyType { }
+impl<'a> lib::MyCopy for &'a MyType { }
+impl<'a> lib::MyCopy for &'a Box<MyType> { }
+impl lib::MyCopy for Box<MyType> { }
+impl lib::MyCopy for lib::MyFundamentalStruct<MyType> { }
+impl lib::MyCopy for lib::MyFundamentalStruct<Box<MyType>> { }
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
diff --git a/src/test/compile-fail/coherence_local_err_struct.rs b/src/test/compile-fail/coherence_local_err_struct.rs
new file mode 100644 (file)
index 0000000..01f4c1c
--- /dev/null
@@ -0,0 +1,29 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// These are all legal because they are all fundamental types:
+
+// MyStruct is not fundamental.
+impl lib::MyCopy for lib::MyStruct<MyType> { } //~ ERROR E0117
+
+#[rustc_error]
+fn main() { }
diff --git a/src/test/compile-fail/coherence_local_err_tuple.rs b/src/test/compile-fail/coherence_local_err_tuple.rs
new file mode 100644 (file)
index 0000000..590f68c
--- /dev/null
@@ -0,0 +1,29 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// These are all legal because they are all fundamental types:
+
+// Tuples are not fundamental, so this is not a local impl.
+impl lib::MyCopy for (MyType,) { } //~ ERROR E0117
+
+#[rustc_error]
+fn main() { }
diff --git a/src/test/compile-fail/coherence_local_ref.rs b/src/test/compile-fail/coherence_local_ref.rs
new file mode 100644 (file)
index 0000000..f6e1aab
--- /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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+extern crate coherence_copy_like_lib as lib;
+
+struct MyType { x: i32 }
+
+// naturally, legal
+impl lib::MyCopy for MyType { }
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
diff --git a/src/test/compile-fail/const-eval-overflow-2.rs b/src/test/compile-fail/const-eval-overflow-2.rs
new file mode 100644 (file)
index 0000000..be04bc9
--- /dev/null
@@ -0,0 +1,30 @@
+// 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.
+
+// Evaluation of constants in refutable patterns goes through
+// different compiler control-flow paths.
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const NEG_128: i8 = -128;
+const NEG_NEG_128: i8 = -NEG_128;
+//~^ ERROR constant evaluation error: attempted to negate with overflow
+//~| ERROR attempted to negate with overflow
+
+fn main() {
+    match -128i8 {
+        NEG_NEG_128 => println!("A"),
+        _ => println!("B"),
+    }
+}
diff --git a/src/test/compile-fail/const-eval-overflow-3.rs b/src/test/compile-fail/const-eval-overflow-3.rs
new file mode 100644 (file)
index 0000000..c2bc5b2
--- /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.
+
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array expression.
+
+// FIXME (#23926): the error output is not consistent between a
+// self-hosted and a cross-compiled setup; therefore resorting to
+// error-pattern for now.
+
+// error-pattern: expected constant integer for repeat count, but attempted to add with overflow
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_I
+    : [u32; (i8::MAX as usize) + 1]
+    = [0; (i8::MAX + 1) as usize];
+
+fn main() {
+    foo(&A_I8_I[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
+
diff --git a/src/test/compile-fail/const-eval-overflow-3b.rs b/src/test/compile-fail/const-eval-overflow-3b.rs
new file mode 100644 (file)
index 0000000..719b210
--- /dev/null
@@ -0,0 +1,43 @@
+// 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.
+
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array expression.
+//
+// This is a variation of another such test, but in this case the
+// types for the left- and right-hand sides of the addition do not
+// match (as well as overflow).
+
+// FIXME (#23926): the error output is not consistent between a
+// self-hosted and a cross-compiled setup; therefore resorting to
+// error-pattern for now.
+
+// error-pattern: mismatched types
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_I
+    : [u32; (i8::MAX as usize) + 1]
+    = [0; (i8::MAX + 1u8) as usize];
+
+fn main() {
+    foo(&A_I8_I[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
+
diff --git a/src/test/compile-fail/const-eval-overflow-4.rs b/src/test/compile-fail/const-eval-overflow-4.rs
new file mode 100644 (file)
index 0000000..f1f125a
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+// ignore-test this should fail to compile (#23833)
+
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array type.
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_T
+    : [u32; (i8::MAX as i8 + 1i8) as usize]
+    //~^ ERROR error evaluating count: attempted to add with overflow
+    = [0; (i8::MAX as usize) + 1];
+
+fn main() {
+    foo(&A_I8_T[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
+
diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs
new file mode 100644 (file)
index 0000000..6322b56
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.
+
+// Evaluation of constants in array-elem count goes through different
+// compiler control-flow paths.
+//
+// This test is checking the count in an array type.
+
+#![allow(unused_imports)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const A_I8_T
+    : [u32; (i8::MAX as i8 + 1u8) as usize]
+    //~^ ERROR mismatched types
+    //~| the trait `core::ops::Add<u8>` is not implemented for the type `i8`
+    //~| the trait `core::ops::Add<u8>` is not implemented for the type `i8`
+    = [0; (i8::MAX as usize) + 1];
+
+fn main() {
+    foo(&A_I8_T[..]);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
+
diff --git a/src/test/compile-fail/const-eval-overflow.rs b/src/test/compile-fail/const-eval-overflow.rs
new file mode 100644 (file)
index 0000000..f647c43
--- /dev/null
@@ -0,0 +1,129 @@
+// 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.
+
+#![allow(unused_imports)]
+
+// Note: the relevant lint pass here runs before some of the constant
+// evaluation below (e.g. that performed by trans and llvm), so if you
+// change this warn to a deny, then the compiler will exit before
+// those errors are detected.
+#![warn(unsigned_negation)]
+
+use std::fmt;
+use std::{i8, i16, i32, i64, isize};
+use std::{u8, u16, u32, u64, usize};
+
+const VALS_I8: (i8, i8, i8, i8) =
+    (-i8::MIN,
+     //~^ ERROR attempted to negate with overflow
+     i8::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     i8::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     i8::MIN * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_I16: (i16, i16, i16, i16) =
+    (-i16::MIN,
+     //~^ ERROR attempted to negate with overflow
+     i16::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     i16::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     i16::MIN * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_I32: (i32, i32, i32, i32) =
+    (-i32::MIN,
+     //~^ ERROR attempted to negate with overflow
+     i32::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     i32::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     i32::MIN * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_I64: (i64, i64, i64, i64) =
+    (-i64::MIN,
+     //~^ ERROR attempted to negate with overflow
+     i64::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     i64::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     i64::MAX * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_U8: (u8, u8, u8, u8) =
+    (-u8::MIN,
+     //~^ WARNING negation of unsigned int variable may be unintentional
+     // (The above is separately linted; unsigned negation is defined to be !x+1.)
+     u8::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     u8::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     u8::MAX * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_U16: (u16, u16, u16, u16) =
+    (-u16::MIN,
+     //~^ WARNING negation of unsigned int variable may be unintentional
+     // (The above is separately linted; unsigned negation is defined to be !x+1.)
+     u16::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     u16::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     u16::MAX * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_U32: (u32, u32, u32, u32) =
+    (-u32::MIN,
+     //~^ WARNING negation of unsigned int variable may be unintentional
+     // (The above is separately linted; unsigned negation is defined to be !x+1.)
+     u32::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     u32::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     u32::MAX * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+const VALS_U64: (u64, u64, u64, u64) =
+    (-u64::MIN,
+     //~^ WARNING negation of unsigned int variable may be unintentional
+     // (The above is separately linted; unsigned negation is defined to be !x+1.)
+     u64::MIN - 1,
+     //~^ ERROR attempted to sub with overflow
+     u64::MAX + 1,
+     //~^ ERROR attempted to add with overflow
+     u64::MAX * 2,
+     //~^ ERROR attempted to mul with overflow
+     );
+
+fn main() {
+    foo(VALS_I8);
+    foo(VALS_I16);
+    foo(VALS_I32);
+    foo(VALS_I64);
+
+    foo(VALS_U8);
+    foo(VALS_U16);
+    foo(VALS_U32);
+    foo(VALS_U64);
+}
+
+fn foo<T:fmt::Debug>(x: T) {
+    println!("{:?}", x);
+}
diff --git a/src/test/compile-fail/discrim-ill-typed.rs b/src/test/compile-fail/discrim-ill-typed.rs
new file mode 100644 (file)
index 0000000..23106c9
--- /dev/null
@@ -0,0 +1,118 @@
+// 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.
+
+// When explicit discriminant value has
+// a type that does not match the representation
+// type, rustc should fail gracefully.
+
+// See also run-pass/discrim-explicit-23030.rs where the input types
+// are correct.
+
+#![allow(dead_code, unused_variables, unused_imports)]
+
+use std::{i8,u8,i16,u16,i32,u32,i64, u64};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo = 0_u8,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo = 0_i8,
+        //~^  ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo = 0_u16,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo = 0_i16,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo = 0_u32,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo = 0_i32,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo = 0_u64,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo = 0_i64,
+        //~^ ERROR mismatched types
+    }
+
+    let x = A::Ok;
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/discrim-overflow-2.rs b/src/test/compile-fail/discrim-overflow-2.rs
new file mode 100644 (file)
index 0000000..76378d5
--- /dev/null
@@ -0,0 +1,94 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Issue 23030: Detect overflowing discriminant
+//
+// Check that we detect the overflow even if enum is not used.
+
+// See also run-pass/discrim-explicit-23030.rs where the suggested
+// workaround is tested.
+
+use std::{i8,u8,i16,u16,i32,u32,i64, u64};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome
+    }
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome
+    }
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/discrim-overflow.rs b/src/test/compile-fail/discrim-overflow.rs
new file mode 100644 (file)
index 0000000..5d7e61e
--- /dev/null
@@ -0,0 +1,108 @@
+// 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.
+
+// ignore-tidy-linelength
+
+// Issue 23030: Detect overflowing discriminant
+
+// See also run-pass/discrim-explicit-23030.rs where the suggested
+// workaround is tested.
+
+use std::{i8,u8,i16,u16,i32,u32,i64, u64};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed on value after 127: i8; set explicitly via OhNo = -128 if that is desired outcome
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed on value after 255: u8; set explicitly via OhNo = 0 if that is desired outcome
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+
+    let x = A::Ok;
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+
+    let x = A::Ok;
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo, //~ ERROR enum discriminant overflowed
+    }
+
+    let x = A::Ok;
+}
+
+fn main() { }
index 3aa2fae282693fd3b42bdfe69ae64e7012c6f11a..40d992fe21f207abe22984110f44735c61fcced7 100644 (file)
@@ -20,9 +20,9 @@
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
-    static S_COUNT: AtomicUint = ATOMIC_UINT_INIT;
+    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index 74e3c724b676daa75bec403ad02e31762476faed..9488882ca94a51421a5bf04d89d7ab0d5eb35df6 100644 (file)
@@ -27,9 +27,9 @@
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
-    static S_COUNT: AtomicUint = ATOMIC_UINT_INIT;
+    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index 3f69c7d1a9c3ee1755f3bb3682fcf9b5be7ba572..9d92552244f28e651f83b1d03a639f68ce11cd32 100644 (file)
@@ -19,9 +19,9 @@
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
-    static S_COUNT: AtomicUint = ATOMIC_UINT_INIT;
+    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
 
     pub fn next_count() -> usize {
         S_COUNT.fetch_add(1, Ordering::SeqCst) + 1
index ddc929017718d02b6729740f3386812063fef3bd..2d87345db2245f5c71701480ad892e3cceda4f61 100644 (file)
@@ -23,10 +23,6 @@ pub fn main() {
     let f2: &Fat<[isize; 3]> = &f1;
     let f3: &Fat<[usize]> = f2;
     //~^ ERROR mismatched types
-    //~| expected `&Fat<[usize]>`
-    //~| found `&Fat<[isize; 3]>`
-    //~| expected usize
-    //~| found isize
 
     // With a trait.
     let f1 = Fat { ptr: Foo };
index 6e64e01d7410d2858315a2e6e3f4d462f8abe5f3..b5c6db0cea9e32767687133e5330509b1f5b3bdb 100644 (file)
@@ -18,7 +18,7 @@ fn has_uniq(x: String) {
 
 fn has_slice(x: &str) {
    wants_uniq(x); //~ ERROR mismatched types
-   wants_slice(x.as_slice());
+   wants_slice(x);
 }
 
 fn main() {
index 105f885f2875f4934aa01ecddc3c5bb66d5c0231..54340cf7ac414f17d922749321a2814c7997f5e1 100644 (file)
@@ -8,9 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: too big for the current
+// FIXME (#23926): the error output is not consistent between a
+// self-hosted and a cross-compiled setup. Skipping for now.
+
+// ignore-test FIXME(#23926)
+
 #![allow(exceeding_bitshifts)]
 
 fn main() {
-   let fat : [u8; (1<<61)+(1<<31)] = [0; (1u64<<61) as usize +(1u64<<31) as usize];
+    let _fat : [u8; (1<<61)+(1<<31)] =
+        [0; (1u64<<61) as usize +(1u64<<31) as usize];
 }
index 50c4ac94d903267b8d07b2c90f9a878bf5293ae0..8886dd80be5039bed56eb68650bcf347efd7d6b9 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::iter::{Range,range};
+use std::ops::Range;
 
 trait Itble<'r, T, I: Iterator<Item=T>> { fn iter(&'r self) -> I; }
 
 impl<'r> Itble<'r, usize, Range<usize>> for (usize, usize) {
     fn iter(&'r self) -> Range<usize> {
         let &(min, max) = self;
-        range(min, max)
+        min..max
     }
 }
 
index 8ebf80a8db0dc5be49c5d6fc655d30a5dbaefce0..9e49abc463f15491906c9a402f844437ebdb980f 100644 (file)
@@ -13,6 +13,6 @@
 
 fn main() {
     // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-    (|| Box::new(*[0].as_slice()))();
+    (|| Box::new(*(&[0][..])))();
     //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `[_]`
 }
index 0a8e4514b4334294289cafd117bfa309e3ae7a28..d2d0dbf3e981fe3fa32a24d7eb7d9bd32b8cbac4 100644 (file)
 
 // ignore-tidy-linelength
 
-use std::iter::{Range,range};
+use std::ops::Range;
 
 trait Itble<'r, T, I: Iterator<Item=T>> { fn iter(&'r self) -> I; }
 
 impl<'r> Itble<'r, usize, Range<usize>> for (usize, usize) {
     fn iter(&'r self) -> Range<usize> {
         let &(min, max) = self;
-        range(min, max)
+        min..max
     }
 }
 
index 0212adff305d0d53e2df9a4253ce1e2ad3154971..a7cabae16be1b8f39be0f84ae8f66a090bbfbdad 100644 (file)
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Note: This test is checking that we forbid a coding pattern that
+// Issue #5873 explicitly wants to allow.
+
 enum State { ST_NULL, ST_WHITESPACE }
 
 fn main() {
     [State::ST_NULL; (State::ST_WHITESPACE as usize)];
-    //~^ ERROR expected constant integer for repeat count, found non-constant expression
+    //~^ ERROR expected constant integer for repeat count, but non-constant path
 }
index 26528543b435a253fa7f00f0ce4c478733c7a7eb..3ce206ff7fb2c0c13b1a5a7b1079aa2e65e9a16d 100644 (file)
@@ -12,6 +12,7 @@
 
 fn main() {
     fn bar(n: usize) {
-        let _x = [0; n]; //~ ERROR expected constant integer for repeat count, found variable
+        let _x = [0; n];
+        //~^ ERROR expected constant integer for repeat count, found variable
     }
 }
index 0077d10e6ca826e4a8312615a66b3837817c0fae..4fba45e2a66c589f61ff74396997e632b30088ae 100644 (file)
@@ -81,8 +81,8 @@ fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
     // which fails to type check.
 
     ss
-        //~^ ERROR cannot infer
-        //~| ERROR mismatched types
+        //~^ ERROR lifetime of the source pointer does not outlive lifetime bound
+        //~| ERROR cannot infer
 }
 
 fn main() {
index 70752cbfda19f11396ec29a6c288a365e1da3336..7fae530984f898e36b8781d30e7eb577fee63bd4 100644 (file)
@@ -25,7 +25,7 @@ fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
     // is illegal.
 
-    ss.r //~ ERROR mismatched types
+    ss.r //~ ERROR lifetime of the source pointer does not outlive lifetime bound
 }
 
 fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
@@ -38,7 +38,7 @@ fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
 fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
     // Here we override the lifetimes explicitly, and so naturally we get an error.
 
-    ss.r = b; //~ ERROR mismatched types
+    ss.r = b; //~ ERROR lifetime of the source pointer does not outlive lifetime bound
 }
 
 fn main() {
index 0f8bc6d684f12ab05df4fe4ea7f79f9b42e100db..10b883d4dc830b8568e8eb3391d5ffe0a0f3e0fc 100644 (file)
@@ -27,7 +27,7 @@ fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
 
 fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
     // A outlives 'a AND 'b...but not 'c.
-    box v as Box<SomeTrait+'a> //~ ERROR mismatched types
+    box v as Box<SomeTrait+'a> //~ ERROR lifetime of the source pointer does not outlive
 }
 
 fn main() {
index 8d05cb67e77b10dbc4afe722306bec6138ba0174..f3722690ef8959f27e0e158d3e2329cb7f0b01fd 100644 (file)
@@ -22,7 +22,7 @@ fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
 
 fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
     // Without knowing 'a:'b, we can't coerce
-    x //~ ERROR mismatched types
+    x //~ ERROR lifetime of the source pointer does not outlive
      //~^ ERROR cannot infer
 }
 
index 7d25c04882f24e0a459ab38aaabaf73c2e6edabe..b1febae76803608b861d36212c623c964e92400e 100644 (file)
 use lib::DefaultedTrait;
 
 struct A;
-impl DefaultedTrait for (A,) { } //~ ERROR E0321
+impl DefaultedTrait for (A,) { } //~ ERROR E0117
 
 struct B;
-impl !DefaultedTrait for (B,) { } //~ ERROR E0321
+impl !DefaultedTrait for (B,) { } //~ ERROR E0117
 
 struct C;
 struct D<T>(T);
 impl DefaultedTrait for Box<C> { } //~ ERROR E0321
-impl DefaultedTrait for lib::Something<C> { } //~ ERROR E0321
+impl DefaultedTrait for lib::Something<C> { } //~ ERROR E0117
 impl DefaultedTrait for D<C> { } // OK
 
 fn main() { }
diff --git a/src/test/compile-fail/variance-deprecated-markers.rs b/src/test/compile-fail/variance-deprecated-markers.rs
deleted file mode 100644 (file)
index 8f9d24c..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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 deprecated markers still have their old effect.
-
-#![feature(rustc_attrs)]
-
-use std::marker;
-
-#[rustc_variance]
-struct A<T>(marker::CovariantType<T>); //~ ERROR types=[[+];[];[]]
-
-#[rustc_variance]
-struct B<T>(marker::ContravariantType<T>); //~ ERROR types=[[-];[];[]]
-
-#[rustc_variance]
-struct C<T>(marker::InvariantType<T>); //~ ERROR types=[[o];[];[]]
-
-#[rustc_variance]
-struct D<'a>(marker::CovariantLifetime<'a>); //~ ERROR regions=[[+];[];[]]
-
-#[rustc_variance]
-struct E<'a>(marker::ContravariantLifetime<'a>); //~ ERROR regions=[[-];[];[]]
-
-#[rustc_variance]
-struct F<'a>(marker::InvariantLifetime<'a>); //~ ERROR regions=[[o];[];[]]
-
-fn main() { }
index 6aaf51278afd8ac1d1c77294b8789f617b90d83f..44a3f716e3eea4a3602cc43a5d8928d8faa9a71e 100644 (file)
@@ -30,9 +30,9 @@
 
 mod s {
     #![allow(unstable)]
-    use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+    use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
-    static S_COUNT: AtomicUint = ATOMIC_UINT_INIT;
+    static S_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
 
     /// generates globally unique count (global across the current
     /// process, that is)
index a191b3e56c41754fd3274c0be3ecca3cb7c63e54..0025449a3dbb7f93b2ae5bfb94675b1825ac9ddb 100644 (file)
@@ -27,5 +27,5 @@ fn main() {
     v.push(&x); //~ ERROR `x` does not live long enough
     v.push(&y); //~ ERROR `y` does not live long enough
 
-    assert_eq!(v.as_slice(), [&3, &4]);
+    assert_eq!(v, [&3, &4]);
 }
index 309848d6cedc9b400e00b9ba55b43cfc543a27c8..63536b1383475be0889ea6b93bb21a572f6ccb74 100644 (file)
@@ -26,6 +26,22 @@ fn after_return() {
         (a, ref b) => {}
     }
     for a in &[111i32] {}
+    let test = if some_predicate() { 1 } else { 2 };
+    while some_predicate() {
+        let abc = !some_predicate();
+    }
+    loop {
+        let abc = !some_predicate();
+        break;
+    }
+    // nested block
+    {
+        let abc = !some_predicate();
+
+        {
+            let def = !some_predicate();
+        }
+    }
 }
 
 fn after_panic() {
@@ -36,6 +52,22 @@ fn after_panic() {
         (a, ref b) => {}
     }
     for a in &[111i32] {}
+    let test = if some_predicate() { 1 } else { 2 };
+    while some_predicate() {
+        let abc = !some_predicate();
+    }
+    loop {
+        let abc = !some_predicate();
+        break;
+    }
+    // nested block
+    {
+        let abc = !some_predicate();
+
+        {
+            let def = !some_predicate();
+        }
+    }
 }
 
 fn after_diverging_function() {
@@ -46,6 +78,22 @@ fn after_diverging_function() {
         (a, ref b) => {}
     }
     for a in &[111i32] {}
+    let test = if some_predicate() { 1 } else { 2 };
+    while some_predicate() {
+        let abc = !some_predicate();
+    }
+    loop {
+        let abc = !some_predicate();
+        break;
+    }
+    // nested block
+    {
+        let abc = !some_predicate();
+
+        {
+            let def = !some_predicate();
+        }
+    }
 }
 
 fn after_break() {
@@ -57,18 +105,50 @@ fn after_break() {
             (a, ref b) => {}
         }
         for a in &[111i32] {}
+        let test = if some_predicate() { 1 } else { 2 };
+        while some_predicate() {
+            let abc = !some_predicate();
+        }
+        loop {
+            let abc = !some_predicate();
+            break;
+        }
+        // nested block
+        {
+            let abc = !some_predicate();
+
+            {
+                let def = !some_predicate();
+            }
+        }
     }
 }
 
 fn after_continue() {
     for _ in 0..10i32 {
-        break;
+        continue;
         let x = "0";
         let (ref y,z) = (1i32, 2u32);
         match (20i32, 'c') {
             (a, ref b) => {}
         }
         for a in &[111i32] {}
+        let test = if some_predicate() { 1 } else { 2 };
+        while some_predicate() {
+            let abc = !some_predicate();
+        }
+        loop {
+            let abc = !some_predicate();
+            break;
+        }
+        // nested block
+        {
+            let abc = !some_predicate();
+
+            {
+                let def = !some_predicate();
+            }
+        }
     }
 }
 
@@ -83,3 +163,6 @@ fn main() {
 fn diverge() -> ! {
     panic!();
 }
+
+fn some_predicate() -> bool { true || false }
+
index 8ce99f517c48af568cd611a0b2ec3c3747a3a83a..00fb2808faa95124227431a325a22660525b0f8b 100644 (file)
@@ -10,5 +10,5 @@
 
 // error-pattern:no valid digits found for number
 fn main() {
-    log(error, 0b42);
+    log(error, 0b);
 }
diff --git a/src/test/parse-fail/lex-bad-binary-literal.rs b/src/test/parse-fail/lex-bad-binary-literal.rs
new file mode 100644 (file)
index 0000000..e92000c
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+fn main() {
+    0b121; //~ ERROR invalid digit for a base 2 literal
+    0b10_10301; //~ ERROR invalid digit for a base 2 literal
+    0b30; //~ ERROR invalid digit for a base 2 literal
+    0b41; //~ ERROR invalid digit for a base 2 literal
+    0b5; //~ ERROR invalid digit for a base 2 literal
+    0b6; //~ ERROR invalid digit for a base 2 literal
+    0b7; //~ ERROR invalid digit for a base 2 literal
+    0b8; //~ ERROR invalid digit for a base 2 literal
+    0b9; //~ ERROR invalid digit for a base 2 literal
+}
diff --git a/src/test/parse-fail/lex-bad-octal-literal.rs b/src/test/parse-fail/lex-bad-octal-literal.rs
new file mode 100644 (file)
index 0000000..bf9880c
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+fn main() {
+    0o18; //~ ERROR invalid digit for a base 8 literal
+    0o1234_9_5670;  //~ ERROR invalid digit for a base 8 literal
+}
index fd6d69efb4f6e018664bdbe38fc43ff311e30c82..0b35062b186e9227bebbbb35c022fa4454f9df5a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:assertion failed: `(left == right) && (right == left)` (left: `14`, right: `15`)
+// error-pattern:assertion failed: `(left == right)` (left: `14`, right: `15`)
 
 fn main() {
     assert_eq!(14,15);
index 0e72ab22dc8f9822af338157534d1b744d1d2d06..249e2e1ac2d64938594f638ccbc8186a405e1bfd 100644 (file)
 
 // error-pattern:whatever
 
-#![feature(os, rustc_private)]
+#![feature(exit_status, rustc_private)]
 
 #[macro_use] extern crate log;
-use std::os;
+use std::env;
 
 fn main() {
     error!("whatever");
     // Setting the exit status only works when the scheduler terminates
     // normally. In this case we're going to panic, so instead of
     // returning 50 the process will return the typical rt failure code.
-    os::set_exit_status(50);
+    env::set_exit_status(50);
     panic!();
 }
index a71ce9ebab59ba0025e6b520455af41234e73217..fddff3c5a9f4fea67ab205b483e7f34a8b17720c 100644 (file)
 
 // error-pattern:whatever
 
-#![feature(os, rustc_private)]
+#![feature(exit_status, rustc_private)]
 
 #[macro_use] extern crate log;
-use std::os;
+use std::env;
 use std::thread;
 
 struct r {
@@ -25,7 +25,7 @@ struct r {
 // runtime's exit code
 impl Drop for r {
     fn drop(&mut self) {
-        os::set_exit_status(50);
+        env::set_exit_status(50);
     }
 }
 
index 9425a1b1902b51aa3683b3637d9a37d6ad0340e4..c33a8d2d03227027c976a20bb5d8782b9d4e1e4d 100644 (file)
 
 // error-pattern:whatever
 
-#![feature(rustc_private, os)]
+#![feature(rustc_private, exit_status)]
 
 #[macro_use] extern crate log;
-use std::os;
+use std::env;
 
 fn main() {
     error!("whatever");
     // 101 is the code the runtime uses on task panic and the value
     // compiletest expects run-fail tests to return.
-    os::set_exit_status(101);
+    env::set_exit_status(101);
 }
index b1576ccd48e9f04af52a43c2923438141a198a90..c1787eb03f5925a67ececa5b076df9828345c957 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(libc, os)]
+#![feature(libc, exit_status)]
 
 extern crate libc;
 
@@ -23,6 +23,6 @@ fn main() {
     };
 
     if result != 1 {
-        std::os::set_exit_status(255);
+        std::env::set_exit_status(255);
     }
 }
index ebf3226334cc6573635b0a8c1a96ff94bcb63c3f..a70a160076520aca44acdf60aa98baea8d2542dc 100644 (file)
@@ -95,10 +95,10 @@ fn main() {
     let expected_span = format!("\n{}^{}\n",
                                 repeat(" ").take(offset + 7).collect::<String>(),
                                 repeat("~").take(8).collect::<String>());
-    assert!(err.contains(expected_span.as_slice()));
+    assert!(err.contains(&expected_span));
     // Second snake is 8 ~s long, with 36 preceding spaces
     let expected_span = format!("\n{}^{}\n",
                                 repeat(" ").take(offset + 36).collect::<String>(),
                                 repeat("~").take(8).collect::<String>());
-    assert!(err.contains(expected_span.as_slice()));
+    assert!(err.contains(&expected_span));
 }
index 7a3c32a45f912c6388b8d1279338c8d4885d4cf5..4bacde0aadf3fc67fed7a79fbef5e90361342828 100644 (file)
@@ -77,6 +77,6 @@ fn main() {
     let mut tc = TestCalls { count: 1 };
     // we should never get use this filename, but lets make sure they are valid args.
     let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
-    rustc_driver::run_compiler(args.as_slice(), &mut tc);
+    rustc_driver::run_compiler(&args, &mut tc);
     assert!(tc.count == 30);
 }
diff --git a/src/test/run-pass-fulldeps/create-dir-all-bare.rs b/src/test/run-pass-fulldeps/create-dir-all-bare.rs
new file mode 100644 (file)
index 0000000..e4fb7c1
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+// ignore-android
+
+#![feature(rustc_private)]
+
+extern crate rustc_back;
+
+use std::env;
+use std::fs;
+use rustc_back::tempdir::TempDir;
+
+fn main() {
+    let td = TempDir::new("create-dir-all-bare").unwrap();
+    env::set_current_dir(td.path()).unwrap();
+    fs::create_dir_all("create-dir-all-bare").unwrap();
+}
diff --git a/src/test/run-pass-fulldeps/rename-directory.rs b/src/test/run-pass-fulldeps/rename-directory.rs
new file mode 100644 (file)
index 0000000..a1e016b
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2013-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.
+
+// This test can't be a unit test in std,
+// because it needs TempDir, which is in extra
+
+// ignore-android
+// pretty-expanded FIXME #23616
+
+#![feature(rustc_private, path_ext)]
+
+extern crate rustc_back;
+
+use std::ffi::CString;
+use std::fs::{self, File, PathExt};
+use rustc_back::tempdir::TempDir;
+
+fn rename_directory() {
+    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() }
index 226a7c12df9ab4a1d6689fec169a2b7eeb1ab231..14d8bce061f5aed20699783b800cd333377a08d9 100644 (file)
@@ -80,9 +80,9 @@ fn runtest(me: &str) {
     let s = str::from_utf8(&out.error).unwrap();
     let mut i = 0;
     for _ in 0..2 {
-        i += s[i + 10..].find_str("stack backtrace").unwrap() + 10;
+        i += s[i + 10..].find("stack backtrace").unwrap() + 10;
     }
-    assert!(s[i + 10..].find_str("stack backtrace").is_none(),
+    assert!(s[i + 10..].find("stack backtrace").is_none(),
             "bad output4: {}", s);
 }
 
index 09746380ebab029d90d75a79276e7f3edaab56d6..b73eac0c7140fa230f64ee7d40296cf6065a75df 100644 (file)
 
 // pretty-expanded FIXME #23616
 
+#![feature(core)]
+
+// Catch mistakes in the overflowing literals lint.
+#![deny(overflowing_literals)]
+
 pub fn main() {
     assert_eq!(0xffffffff, (-1 as u32));
     assert_eq!(4294967295, (-1 as u32));
     assert_eq!(0xffffffffffffffff, (-1 as u64));
     assert_eq!(18446744073709551615, (-1 as u64));
 
-    assert_eq!(-2147483648 - 1, 2147483647);
+    assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647);
 }
index b20de7113ec5db60bba85cfeacb3012efbd8c6f4..f9b429a935a6a676a553f031f29023c050cdbc5f 100644 (file)
@@ -22,7 +22,7 @@
 use std::sync::mpsc::channel;
 use std::fmt;
 use std::old_io::{ChanReader, ChanWriter, Reader, Writer};
-use std::thread::Thread;
+use std::thread;
 
 struct MyWriter(ChanWriter);
 
@@ -36,7 +36,7 @@ fn log(&mut self, record: &LogRecord) {
 fn main() {
     let (tx, rx) = channel();
     let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         set_logger(box MyWriter(w) as Box<Logger+Send>);
         debug!("debug");
         info!("info");
index 64642e51c094b3a23bca35d846aef9e8484db65f..7da1416602f6daec46d6961d456da65febc39cc8 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 fn child2(_s: String) { }
 
 pub fn main() {
-    let _x = Thread::spawn(move|| child2("hi".to_string()));
+    let _x = thread::spawn(move|| child2("hi".to_string()));
 }
index fa663105ccdaf0367d5c74d37a31be4c2380c485..16efceb9d7e0e1db35803a9620b0c2639889f30c 100644 (file)
@@ -13,7 +13,7 @@
 #![allow(unknown_features)]
 #![feature(box_syntax, std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 struct Pair {
     a: isize,
@@ -23,7 +23,7 @@ struct Pair {
 pub fn main() {
     let z: Box<_> = box Pair { a : 10, b : 12};
 
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         assert_eq!(z.a, 10);
         assert_eq!(z.b, 12);
     });
diff --git a/src/test/run-pass/coherence-cow-1.rs b/src/test/run-pass/coherence-cow-1.rs
deleted file mode 100644 (file)
index 31f6c9a..0000000
+++ /dev/null
@@ -1,25 +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.
-
-// aux-build:coherence_lib.rs
-
-// Test that it's ok for T to appear first in the self-type, as long
-// as it's covered somewhere.
-
-// pretty-expanded FIXME #23616
-
-extern crate coherence_lib as lib;
-use lib::{Remote,Pair};
-
-pub struct Cover<T>(T);
-
-impl<T> Remote for Pair<T,Cover<T>> { }
-
-fn main() { }
diff --git a/src/test/run-pass/coherence-cow-2.rs b/src/test/run-pass/coherence-cow-2.rs
deleted file mode 100644 (file)
index ccda844..0000000
+++ /dev/null
@@ -1,25 +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.
-
-// aux-build:coherence_lib.rs
-
-// Test that it's ok for T to appear second in the self-type, as long
-// as it's covered somewhere.
-
-// pretty-expanded FIXME #23616
-
-extern crate coherence_lib as lib;
-use lib::{Remote,Pair};
-
-pub struct Cover<T>(T);
-
-impl<T> Remote for Pair<Cover<T>,T> { }
-
-fn main() { }
diff --git a/src/test/run-pass/coherence-local-1.rs b/src/test/run-pass/coherence-local-1.rs
deleted file mode 100644 (file)
index 21faa30..0000000
+++ /dev/null
@@ -1,22 +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.
-
-// aux-build:coherence_lib.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate coherence_lib as lib;
-use lib::Remote;
-
-struct Local;
-
-impl Remote for Vec<Local> { }
-
-fn main() { }
diff --git a/src/test/run-pass/coherence-local-2.rs b/src/test/run-pass/coherence-local-2.rs
deleted file mode 100644 (file)
index 5fd3e8c..0000000
+++ /dev/null
@@ -1,22 +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.
-
-// aux-build:coherence_lib.rs
-
-// pretty-expanded FIXME #23616
-
-extern crate coherence_lib as lib;
-use lib::Remote;
-
-struct Local<T>(T);
-
-impl<T> Remote for Vec<Local<T>> { }
-
-fn main() { }
diff --git a/src/test/run-pass/coherence_copy_like.rs b/src/test/run-pass/coherence_copy_like.rs
new file mode 100644 (file)
index 0000000..db98936
--- /dev/null
@@ -0,0 +1,29 @@
+// 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 we are able to introduce a negative constraint that
+// `MyType: !MyTrait` along with other "fundamental" wrappers.
+
+// aux-build:coherence_copy_like_lib.rs
+
+extern crate coherence_copy_like_lib as lib;
+
+use std::marker::MarkerTrait;
+
+struct MyType { x: i32 }
+
+trait MyTrait : MarkerTrait { }
+impl<T: lib::MyCopy> MyTrait for T { }
+impl MyTrait for MyType { }
+impl<'a> MyTrait for &'a MyType { }
+impl MyTrait for Box<MyType> { }
+impl<'a> MyTrait for &'a Box<MyType> { }
+
+fn main() { }
index 43f10cfd060022b2485cc1c71eb740baeb4a0ead..859599596ae7bc114ad03a74968137ae96717d6a 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _t = Thread::spawn(move|| { child(&tx) });
+    let _t = thread::scoped(move|| { child(&tx) });
     let y = rx.recv().unwrap();
     println!("received");
     println!("{}", y);
index a969f6911545fcf6ac5810a8a33013de1e8d7fa4..03bf3851257dfa10c1644e751d1e55acdb7d335b 100644 (file)
@@ -24,7 +24,7 @@
 use std::time::Duration;
 use std::str;
 use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
 
 macro_rules! succeed { ($e:expr) => (
     match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) }
@@ -86,7 +86,7 @@ pub fn test_destroy_actually_kills(force: bool) {
     let (tx, rx1) = channel();
     let mut t = timer::Timer::new().unwrap();
     let rx2 = t.oneshot(Duration::milliseconds(1000));
-    Thread::spawn(move|| {
+    thread::spawn(move|| {
         select! {
             _ = rx2.recv() => unsafe { libc::exit(1) },
             _ = rx1.recv() => {}
diff --git a/src/test/run-pass/create-dir-all-bare.rs b/src/test/run-pass/create-dir-all-bare.rs
deleted file mode 100644 (file)
index 475df62..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-// 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(tempdir)]
-
-use std::env;
-use std::fs::{self, TempDir};
-
-fn main() {
-    let td = TempDir::new("create-dir-all-bare").unwrap();
-    env::set_current_dir(td.path()).unwrap();
-    fs::create_dir_all("create-dir-all-bare").unwrap();
-}
index 17f4d93e24c1712ee207de428fffe1721a97d7fb..6ccedb0ad982f129982a87ef47925557c59eadd3 100644 (file)
@@ -12,7 +12,7 @@
 
 #![allow(unknown_features)]
 #![feature(box_syntax)]
-#![feature(old_orphan_check, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate serialize;
 
index d116c2dfc2ac2aee3ac892f1f2fe6afed9880a7d..d216062bb2da362c3c7369f79fc237a365e8cecc 100644 (file)
@@ -13,7 +13,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(old_orphan_check, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate serialize;
 
index 2ca34e91b62a1958d4dc9858be776c6c56e75951..105d421b4041567c49497d14b41adde4f2ce4fde 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(old_orphan_check, rand, rustc_private)]
+#![feature(rand, rustc_private)]
 
 extern crate serialize;
 extern crate rand;
diff --git a/src/test/run-pass/discrim-explicit-23030.rs b/src/test/run-pass/discrim-explicit-23030.rs
new file mode 100644 (file)
index 0000000..aed7b15
--- /dev/null
@@ -0,0 +1,156 @@
+// 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.
+
+// Issue 23030: Workaround overflowing discriminant
+// with explicit assignments.
+
+// See also compile-fail/overflow-discrim.rs, which shows what
+// happens if you leave the OhNo explicit cases out here.
+
+use std::{i8,u8,i16,u16,i32,u32,i64,u64,isize,usize};
+
+fn f_i8() {
+    #[repr(i8)]
+    enum A {
+        Ok = i8::MAX - 1,
+        Ok2,
+        OhNo = i8::MIN,
+        NotTheEnd = -1,
+        Zero,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+    let z = (A::NotTheEnd, A::Zero).1 as i8;
+    assert_eq!(z, 0);
+}
+
+fn f_u8() {
+    #[repr(u8)]
+    enum A {
+        Ok = u8::MAX - 1,
+        Ok2,
+        OhNo = u8::MIN,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+}
+
+fn f_i16() {
+    #[repr(i16)]
+    enum A {
+        Ok = i16::MAX - 1,
+        Ok2,
+        OhNo = i16::MIN,
+        NotTheEnd = -1,
+        Zero,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+    let z = (A::NotTheEnd, A::Zero).1 as i16;
+    assert_eq!(z, 0);
+}
+
+fn f_u16() {
+    #[repr(u16)]
+    enum A {
+        Ok = u16::MAX - 1,
+        Ok2,
+        OhNo = u16::MIN,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+}
+
+fn f_i32() {
+    #[repr(i32)]
+    enum A {
+        Ok = i32::MAX - 1,
+        Ok2,
+        OhNo = i32::MIN,
+        NotTheEnd = -1,
+        Zero,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+    let z = (A::NotTheEnd, A::Zero).1 as i32;
+    assert_eq!(z, 0);
+}
+
+fn f_u32() {
+    #[repr(u32)]
+    enum A {
+        Ok = u32::MAX - 1,
+        Ok2,
+        OhNo = u32::MIN,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+}
+
+fn f_i64() {
+    #[repr(i64)]
+    enum A {
+        Ok = i64::MAX - 1,
+        Ok2,
+        OhNo = i64::MIN,
+        NotTheEnd = -1,
+        Zero,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+    let z = (A::NotTheEnd, A::Zero).1 as i64;
+    assert_eq!(z, 0);
+}
+
+fn f_u64() {
+    #[repr(u64)]
+    enum A {
+        Ok = u64::MAX - 1,
+        Ok2,
+        OhNo = u64::MIN,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+}
+
+fn f_isize() {
+    #[repr(isize)]
+    enum A {
+        Ok = isize::MAX - 1,
+        Ok2,
+        OhNo = isize::MIN,
+        NotTheEnd = -1,
+        Zero,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+    let z = (A::NotTheEnd, A::Zero).1 as isize;
+    assert_eq!(z, 0);
+}
+
+fn f_usize() {
+    #[repr(usize)]
+    enum A {
+        Ok = usize::MAX - 1,
+        Ok2,
+        OhNo = usize::MIN,
+    }
+
+    let _x = (A::Ok, A::Ok2, A::OhNo);
+}
+
+fn main() {
+    f_i8(); f_u8();
+    f_i16(); f_u16();
+    f_i32(); f_u32();
+    f_i64(); f_u64();
+
+    f_isize(); f_usize();
+}
index ddfaf54493fb4211825df29f0af62f17ab42fc57..3d4af80e30bb57a98a3349b07eed10ef61e7b1fa 100644 (file)
@@ -14,7 +14,7 @@
 
 fn main() {
     let args = vec!("foobie", "asdf::asdf");
-    let arr: Vec<&str> = args[1].split_str("::").collect();
+    let arr: Vec<&str> = args[1].split("::").collect();
     assert_eq!(arr[0], "asdf");
     assert_eq!(arr[0], "asdf");
 }
index 2d0128ba89e325d579f34f75037288d290372e50..7fb96112125afaaae984810a19d6ad83bbfeff3e 100644 (file)
@@ -11,7 +11,6 @@
 // pretty-expanded FIXME #23616
 
 #![feature(path)]
-#![feature(convert)]
 
 use std::env::*;
 use std::path::PathBuf;
index 069ecd92a56d099bc8572fdcd1f46a80fbb90680..e8c9bc76335f7ab7500eed3b0ae0232535b22f82 100644 (file)
@@ -15,7 +15,7 @@
 #![feature(libc, std_misc)]
 
 extern crate libc;
-use std::thread::Thread;
+use std::thread;
 
 mod rustrt {
     extern crate libc;
@@ -46,7 +46,7 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t {
 pub fn main() {
     // Make sure we're on a task with small Rust stacks (main currently
     // has a large stack)
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         let result = count(12);
         println!("result = {}", result);
         assert_eq!(result, 2048);
index 3d1b74438a845ddaa6f9b85fa0f15ff11f06a6c6..5c96aaf4bd8902365862e4a14066d048d35ff374 100644 (file)
@@ -25,7 +25,7 @@ mod map_reduce {
     use std::collections::HashMap;
     use std::sync::mpsc::{channel, Sender};
     use std::str;
-    use std::thread::Thread;
+    use std::thread;
 
     pub type putter<'a> = Box<FnMut(String, String) + 'a>;
 
@@ -37,7 +37,7 @@ fn start_mappers(ctrl: Sender<ctrl_proto>, inputs: Vec<String>) {
         for i in &inputs {
             let ctrl = ctrl.clone();
             let i = i.clone();
-            Thread::spawn(move|| map_task(ctrl.clone(), i.clone()) );
+            thread::spawn(move|| map_task(ctrl.clone(), i.clone()) );
         }
     }
 
index ca4dba4198c036d801986731ec7b8a2e195b53af..26d58d34b9dea1e4dc373adcaeaff2057590b4c9 100644 (file)
@@ -16,7 +16,7 @@
 
 #![feature(intrinsics, std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 extern "rust-intrinsic" {
     pub fn init<T>() -> T;
@@ -26,7 +26,7 @@
 
 fn main() {
     // do the test in a new thread to avoid (spurious?) stack overflows
-    let _ = Thread::scoped(|| {
+    let _ = thread::scoped(|| {
         let _memory: [u8; SIZE] = unsafe { init() };
     }).join();
 }
index 811926826dd12a0746cf69250b5a166d2c6748da..35c25b33a9764c2976889ffdf7877dfc4f24a030 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(old_orphan_check, rustc_private, old_io)]
+#![feature(rustc_private, old_io)]
 
 extern crate rbml;
 extern crate serialize;
index 876b329998e08539c188436f364d25f547b2768b..c260aa95b57f1d556bdf83f77826ba120ab0ea7c 100644 (file)
@@ -29,8 +29,8 @@ fn main() {
 fn parent() {
     let args: Vec<String> = env::args().collect();
     let mut p = Command::new(&args[0]).arg("child")
-                        .stdout(Stdio::capture())
-                        .stdin(Stdio::capture())
+                        .stdout(Stdio::piped())
+                        .stdin(Stdio::piped())
                         .spawn().unwrap();
     p.stdin.as_mut().unwrap().write_all(b"test1\ntest2\ntest3").unwrap();
     let out = p.wait_with_output().unwrap();
index 6159edbfe1ee4c27150602868faf79785726ad5c..d1b1647de7881244887f8011abd854374a4ce71a 100644 (file)
@@ -16,7 +16,7 @@
 #![feature(std_misc)]
 
 use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread::Thread;
+use std::thread;
 
 fn helper(rx: Receiver<Sender<()>>) {
     for tx in rx.iter() {
@@ -26,7 +26,7 @@ fn helper(rx: Receiver<Sender<()>>) {
 
 fn main() {
     let (tx, rx) = channel();
-    let _t = Thread::spawn(move|| { helper(rx) });
+    let _t = thread::scoped(move|| { helper(rx) });
     let (snd, rcv) = channel::<isize>();
     for _ in 1..100000 {
         snd.send(1).unwrap();
@@ -37,4 +37,5 @@ fn main() {
             _ = rcv.recv() => ()
         }
     }
+    drop(tx);
 }
index e773f03f21217f3609e9194392365ec721b74b9c..907967d115d583ec7ecc67ce5e7e6ddc6fede761 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(old_orphan_check, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate serialize;
 
index f897b00ceffef9f8f519e5f33d3673b224e605e8..ab9633ca1fe90e0ba46d921e66b16264792c5279 100644 (file)
@@ -38,9 +38,9 @@ fn child() {
 fn test() {
     let args: Vec<String> = env::args().collect();
     let mut p = Command::new(&args[0]).arg("child")
-                                     .stdin(Stdio::capture())
-                                     .stdout(Stdio::capture())
-                                     .stderr(Stdio::capture())
+                                     .stdin(Stdio::piped())
+                                     .stdout(Stdio::piped())
+                                     .stderr(Stdio::piped())
                                      .spawn().unwrap();
     assert!(p.wait().unwrap().success());
 }
index d058cb737117730d75fe9ee6cd103165593142c2..67ce6a1c44f0db4b2866889bdbaaec565dd92f43 100644 (file)
@@ -13,7 +13,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(old_orphan_check, core)]
+#![feature(core)]
 
 use std::ops::Index;
 
index 0dac3295c1bf615761864e61b1a4a2325db07568..6e93194647ad2c8aea38bbfa4e80361f5100b485 100644 (file)
 
 #![feature(core)]
 
+trait Str { fn foo(&self) {} }
+impl Str for str {}
+impl<'a, S: ?Sized> Str for &'a S where S: Str {}
+
 fn main() {
     let _: &Str = &"x";
 }
diff --git a/src/test/run-pass/issue-17746.rs b/src/test/run-pass/issue-17746.rs
new file mode 100644 (file)
index 0000000..a66d5e1
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+// Regression test for #17746
+
+fn main() {}
+
+struct A;
+
+impl A {
+    fn b(&mut self) {
+        self.a()
+    }
+}
+
+trait Foo {
+    fn dummy(&self) {}
+}
+trait Bar {
+    fn a(&self);
+}
+
+impl Foo for A {}
+impl<T> Bar for T where T: Foo {
+    fn a(&self) {}
+}
index 0e3d4e0e40d67d5adc98c9912f63a25c36d7ee27..d527d9519cfbc4eee484caa8bca030b6f3c492d4 100644 (file)
 
 use std::thread;
 
-fn main() {
-    thread::Thread::spawn(move || { // no need for -> ()
+fn _foo() {
+    let _t = thread::scoped(move || { // no need for -> ()
         loop {
             println!("hello");
         }
     });
 }
+
+fn main() {}
index d0720ec593fa4a2e97884820a3bf67366356cbb7..45d31d4a7f168ffa987e9a9cfcc65adad1adf636 100644 (file)
@@ -12,8 +12,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(convert)]
-
 use std::default::Default;
 use std::io;
 use std::fs;
index a47c844e1994a3e032b35c6aef6ce6f222c0c5e0..2c4141b0bd37939a88ef3c827b9271532792d262 100644 (file)
 use std::{fs, net};
 
 fn assert_both<T: Send + Sync>() {}
+fn assert_send<T: Send>() {}
 
 fn main() {
     assert_both::<fs::File>();
     assert_both::<fs::Metadata>();
     assert_both::<fs::ReadDir>();
     assert_both::<fs::DirEntry>();
-    assert_both::<fs::WalkDir>();
+    assert_send::<fs::WalkDir>();
     assert_both::<fs::OpenOptions>();
     assert_both::<fs::Permissions>();
 
index 7842bcb7dd1ec16637826896a28389a191fbc68a..71d1439dd2bc8f3f14d197137c50853a27e506fe 100644 (file)
@@ -21,7 +21,7 @@ pub mod pipes {
     use std::mem::{forget, transmute};
     use std::mem::{replace, swap};
     use std::mem;
-    use std::thread::Thread;
+    use std::thread;
     use std::marker::Send;
 
     pub struct Stuff<T> {
@@ -115,7 +115,7 @@ pub fn recv<T:Send>(mut p: recv_packet<T>) -> Option<T> {
             let old_state = swap_state_acq(&mut (*p).state,
                                            blocked);
             match old_state {
-              empty | blocked => { Thread::yield_now(); }
+              empty | blocked => { thread::yield_now(); }
               full => {
                 let payload = replace(&mut p.payload, None);
                 return Some(payload.unwrap())
index 2bd56e8168787d279a6f9450cbfcdbb933677860..45eb21374e2981aab7a5b84bdfc5e93f966587f0 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(unknown_features)]
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::Sender;
 use std::thunk::Invoke;
 
@@ -24,7 +24,7 @@ enum Msg
 }
 
 fn foo(name: String, samples_chan: Sender<Msg>) {
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         let mut samples_chan = samples_chan;
 
         // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
index 03699ff8d60369d7657c9ecad9b6ea00f0f9086f..7f66b6b25b8d2860c112edfb97bdc98bec046ede 100644 (file)
@@ -10,7 +10,6 @@
 
 // If `Mul` used an associated type for its output, this test would
 // work more smoothly.
-#![feature(old_orphan_check)]
 
 use std::ops::Mul;
 
index 4e1ff84291eb129f0d2e21b5fbdaa126aaa67d7a..280311af6fbd12ea94121129cc608f6f9a8f12f2 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Receiver};
 
 fn periodical(n: isize) -> Receiver<bool> {
     let (chan, port) = channel();
-    Thread::spawn(move|| {
+    thread::spawn(move|| {
         loop {
             for _ in 1..n {
                 match chan.send(false) {
@@ -34,7 +34,7 @@ fn periodical(n: isize) -> Receiver<bool> {
 
 fn integers() -> Receiver<isize> {
     let (chan, port) = channel();
-    Thread::spawn(move|| {
+    thread::spawn(move|| {
         let mut i = 1;
         loop {
             match chan.send(i) {
index aeba6889f49e8ae25b0e271330bda2c2a10bba15..bfaf060e43c30ac41d25f856663c430cbe8166c4 100644 (file)
 
 use std::sync::mpsc::{TryRecvError, channel};
 use std::old_io::timer::Timer;
-use std::thread::Thread;
+use std::thread;
 use std::time::Duration;
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _t = Thread::scoped(move||{
+    let _t = thread::scoped(move||{
         let mut timer = Timer::new().unwrap();
         timer.sleep(Duration::milliseconds(10));
         tx.send(()).unwrap();
index d5138f6fdbc5968afe4a942accd3fd7441acd70a..8ae084dce8c37793a928b9deb41101647062325a 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 fn producer(tx: &Sender<Vec<u8>>) {
@@ -23,7 +23,7 @@ fn producer(tx: &Sender<Vec<u8>>) {
 
 pub fn main() {
     let (tx, rx) = channel::<Vec<u8>>();
-    let _prod = Thread::spawn(move|| {
+    let _prod = thread::scoped(move|| {
         producer(&tx)
     });
 
index 4645e8ff3924a0ad1706f497b18a4818d9e3711f..11b1d70137deffe7046b5bf791b05bf8b3c83cfd 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 fn user(_i: isize) {}
 
@@ -18,7 +18,7 @@ fn foo() {
     // Here, i is *copied* into the proc (heap closure).
     // Requires allocation.  The proc's copy is not mutable.
     let mut i = 0;
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         user(i);
         println!("spawned {}", i)
     });
@@ -31,7 +31,7 @@ fn bar() {
     // mutable outside of the proc.
     let mut i = 0;
     while i < 10 {
-        let _t = Thread::spawn(move|| {
+        let _t = thread::scoped(move|| {
             user(i);
         });
         i += 1;
@@ -42,7 +42,7 @@ fn car() {
     // Here, i must be shadowed in the proc to be mutable.
     let mut i = 0;
     while i < 10 {
-        let _t = Thread::spawn(move|| {
+        let _t = thread::scoped(move|| {
             let mut i = i;
             i += 1;
             user(i);
index 80a3b8c9eddeeccdaf4f3b0291aa04bd83d8dcc6..4881a5ab647ec0996efde72f97ad3c368aae8120 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 macro_rules! expr { ($e: expr) => { $e } }
 
 macro_rules! spawn {
     ($($code: tt)*) => {
-        expr!(Thread::spawn(move|| {$($code)*}))
+        expr!(thread::spawn(move|| {$($code)*}))
     }
 }
 
index d87ed03e94e01816f2936c09138128aafae3d3bd..2ceff22adb9eb4da6e5d204d9b00c8c6711056e1 100644 (file)
@@ -8,13 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Test that we pick which version of `Foo` to run based on whether
-// the type we (ultimately) inferred for `x` is copyable or not.
-//
-// In this case, the two versions are both impls of same trait, and
-// hence we we can resolve method even without knowing yet which
-// version will run (note that the `push` occurs after the call to
-// `foo()`).
+// Test that when we write `x.foo()`, we do nothave to know the
+// complete type of `x` in order to type-check the method call. In
+// this case, we know that `x: Vec<_1>`, but we don't know what type
+// `_1` is (because the call to `push` comes later). To pick between
+// the impls, we would have to know `_1`, since we have to know
+// whether `_1: MyCopy` or `_1 == Box<i32>`.  However (and this is the
+// point of the test), we don't have to pick between the two impls --
+// it is enough to know that `foo` comes from the `Foo` trait. We can
+// translate the call as `Foo::foo(&x)` and let the specific impl get
+// chosen later.
 
 // pretty-expanded FIXME #23616
 
@@ -25,25 +28,29 @@ trait Foo {
     fn foo(&self) -> isize;
 }
 
-impl<T:Copy> Foo for Vec<T> {
+trait MyCopy { fn foo(&self) { } }
+impl MyCopy for i32 { }
+
+impl<T:MyCopy> Foo for Vec<T> {
     fn foo(&self) -> isize {1}
 }
 
-impl<T> Foo for Vec<Box<T>> {
+impl Foo for Vec<Box<i32>> {
     fn foo(&self) -> isize {2}
 }
 
 fn call_foo_copy() -> isize {
     let mut x = Vec::new();
     let y = x.foo();
-    x.push(0_usize);
+    x.push(0_i32);
     y
 }
 
 fn call_foo_other() -> isize {
-    let mut x: Vec<Box<_>> = Vec::new();
+    let mut x: Vec<_> = Vec::new();
     let y = x.foo();
-    x.push(box 0);
+    let z: Box<i32> = box 0;
+    x.push(z);
     y
 }
 
index 329b77776b6394e8b2624b0bd4eaa78e66dd6941..77072bdec905190cb483a1cacd74e29c7fa49c36 100644 (file)
@@ -33,6 +33,6 @@ fn foo(self) {}
 
 fn main() {
     let x: [isize; 4] = [1,2,3,4];
-    let xptr = x.as_slice() as *const [isize];
+    let xptr = &x[..] as *const [isize];
     xptr.foo();
 }
diff --git a/src/test/run-pass/minmax-stability-issue-23687.rs b/src/test/run-pass/minmax-stability-issue-23687.rs
new file mode 100644 (file)
index 0000000..86dd1a0
--- /dev/null
@@ -0,0 +1,83 @@
+// 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)]
+use std::fmt::Debug;
+use std::cmp::{self, PartialOrd, Ordering};
+use std::iter::MinMaxResult::MinMax;
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+struct Foo {
+    n: u8,
+    name: &'static str
+}
+
+impl PartialOrd for Foo {
+    fn partial_cmp(&self, other: &Foo) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Foo {
+    fn cmp(&self, other: &Foo) -> Ordering {
+        self.n.cmp(&other.n)
+    }
+}
+
+fn main() {
+    let a = Foo { n: 4, name: "a" };
+    let b = Foo { n: 4, name: "b" };
+    let c = Foo { n: 8, name: "c" };
+    let d = Foo { n: 8, name: "d" };
+    let e = Foo { n: 22, name: "e" };
+    let f = Foo { n: 22, name: "f" };
+
+    let data = [a, b, c, d, e, f];
+
+    // `min` should return the left when the values are equal
+    assert_eq!(data.iter().min(), Some(&a));
+    assert_eq!(data.iter().min_by(|a| a.n), Some(&a));
+    assert_eq!(cmp::min(a, b), a);
+    assert_eq!(cmp::min(b, a), b);
+    assert_eq!(cmp::partial_min(a, b), Some(a));
+    assert_eq!(cmp::partial_min(b, a), Some(b));
+
+    // `max` should return the right when the values are equal
+    assert_eq!(data.iter().max(), Some(&f));
+    assert_eq!(data.iter().max_by(|a| a.n), Some(&f));
+    assert_eq!(cmp::max(e, f), f);
+    assert_eq!(cmp::max(f, e), e);
+    assert_eq!(cmp::partial_max(e, f), Some(f));
+    assert_eq!(cmp::partial_max(f, e), Some(e));
+
+    // Similar for `min_max`
+    assert_eq!(data.iter().min_max(), MinMax(&a, &f));
+    assert_eq!(data[1..5].iter().min_max(), MinMax(&b, &e));
+    assert_eq!(data[2..4].iter().min_max(), MinMax(&c, &d));
+
+    let mut presorted = data.to_vec();
+    presorted.sort();
+    assert_stable(&presorted);
+
+    let mut presorted = data.to_vec();
+    presorted.sort_by(|a, b| a.cmp(b));
+    assert_stable(&presorted);
+
+    // Assert that sorted and min/max are the same
+    fn assert_stable<T: Ord + Debug>(presorted: &[T]) {
+        for slice in presorted.windows(2) {
+            let a = &slice[0];
+            let b = &slice[1];
+
+            assert_eq!(a, cmp::min(a, b));
+            assert_eq!(b, cmp::max(a, b));
+        }
+    }
+}
index f0eba366e711763d7f4dc6ec40fc6826b37991b9..b6509d280366a2e295b2998a27c9be2eed7a9464 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() {
     let x = "Hello world!".to_string();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         println!("{}", x);
     });
 }
index 8f5a5e8ece75dbb0cd22735b2d74fa8db681256d..03ba6097cd9297ad6d120e223b749912966abfbe 100644 (file)
@@ -12,7 +12,7 @@
 
 pub fn main() {
     let thing = "{{ f }}";
-    let f = thing.find_str("{{");
+    let f = thing.find("{{");
 
     if f.is_none() {
         println!("None!");
index 3c322f72b75b699f95cc6a3dd668da9ac337c255..f08ed6e7f9cdc06cee25fd99c63689cf8488a0d2 100644 (file)
@@ -18,7 +18,7 @@
 
 use std::old_io::process::Command;
 use std::env;
-use std::thread::Thread;
+use std::thread;
 
 // lifted from the test module
 // Inlining to avoid llvm turning the recursive functions into tail calls,
@@ -37,7 +37,7 @@ fn recurse() {
 fn main() {
     let args: Vec<String> = env::args().collect();
     if args.len() > 1 && args[1] == "recurse" {
-        let _t = Thread::scoped(recurse);
+        let _t = thread::scoped(recurse);
     } else {
         let recurse = Command::new(&args[0]).arg("recurse").output().unwrap();
         assert!(!recurse.status.success());
diff --git a/src/test/run-pass/process-exit.rs b/src/test/run-pass/process-exit.rs
new file mode 100644 (file)
index 0000000..9ef66ff
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+use std::env;
+use std::process::{self, Command, Stdio};
+
+fn main() {
+    let args: Vec<String> = env::args().collect();
+    if args.len() > 1 && args[1] == "child" {
+        child();
+    } else {
+        parent();
+    }
+}
+
+fn parent() {
+    let args: Vec<String> = env::args().collect();
+    let status = Command::new(&args[0]).arg("child").status().unwrap();
+    assert_eq!(status.code(), Some(2));
+}
+
+fn child() -> i32 {
+    process::exit(2);
+}
index febf5f92ef6ea70eb055ffa3f4a28b140bdc0f06..63525b36206a419d1b78fb4e9259a531bca3876f 100644 (file)
@@ -29,7 +29,7 @@ fn foo<'a>(map: RefCell<HashMap<&'static str, &'a [u8]>>) {
 // supposed to match the lifetime `'a`) ...
 fn foo<'a>(map: RefCell<HashMap<&'static str, &'a [u8]>>) {
     let one = [1];
-    assert_eq!(map.borrow().get("one"), Some(&one.as_slice()));
+    assert_eq!(map.borrow().get("one"), Some(&&one[..]));
 }
 
 #[cfg(all(not(cannot_use_this_yet),not(cannot_use_this_yet_either)))]
diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs
deleted file mode 100644 (file)
index f149a70..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013-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.
-
-// This test can't be a unit test in std,
-// because it needs TempDir, which is in extra
-
-// pretty-expanded FIXME #23616
-
-#![feature(tempdir, path_ext)]
-
-use std::ffi::CString;
-use std::fs::{self, TempDir, File, PathExt};
-
-fn rename_directory() {
-    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() }
index c5b59e6c6e071f08f93fc1a4bca8ecfe9ca88d81..abad08c7ac6b31bc57593547184b2134c7349323 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(start, os, std_misc, old_io)]
 
-use std::ffi;
+use std::ffi::CStr;
 use std::old_io::process::{Command, ProcessOutput};
 use std::os;
 use std::rt::unwind::try;
@@ -38,7 +38,7 @@ fn start(argc: isize, argv: *const *const u8) -> isize {
     let args = unsafe {
         (0..argc as usize).map(|i| {
             let ptr = *argv.offset(i as isize) as *const _;
-            ffi::c_str_to_bytes(&ptr).to_vec()
+            CStr::from_ptr(ptr).to_bytes().to_vec()
         }).collect::<Vec<_>>()
     };
     let me = &*args[0];
index bc379f1a76f7f382b5d9517bc34e0f9c329b42ad..660b1e2036d3311dcd838ef12d5f25d2b37c44b6 100644 (file)
@@ -19,7 +19,7 @@
 extern crate log;
 
 use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread::Thread;
+use std::thread;
 
 pub struct ChannelLogger {
     tx: Sender<String>
@@ -41,7 +41,7 @@ fn log(&mut self, record: &log::LogRecord) {
 pub fn main() {
     let (logger, rx) = ChannelLogger::new();
 
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         log::set_logger(logger);
 
         info!("foo");
index 5815eaa01ea822ec18ef01e196675df4541794aa..99ae3b7c7d87c63cf54479adf99bfc0473d3431f 100644 (file)
@@ -11,7 +11,7 @@
 // pretty-expanded FIXME #23616
 
 #![feature(core, std_misc)]
-use std::thread::Thread;
+use std::thread;
 use std::sync::Mutex;
 
 fn par_for<I, F>(iter: I, f: F)
@@ -21,7 +21,7 @@ fn par_for<I, F>(iter: I, f: F)
 {
     let f = &f;
     let _guards: Vec<_> = iter.map(|elem| {
-        Thread::scoped(move || {
+        thread::scoped(move || {
             f(elem)
         })
     }).collect();
index 2c897c48a33c9da89e53d5dca7c659f8a5b4477b..3f64b2adb639538f490fc5a3c601606e99854175 100644 (file)
@@ -12,7 +12,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::channel;
 
 struct test {
@@ -32,7 +32,7 @@ fn test(f: isize) -> test {
 pub fn main() {
     let (tx, rx) = channel();
 
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         let (tx2, rx2) = channel();
         tx.send(tx2).unwrap();
 
index 0d26b75c2ad7f6ded6febd04e81a04bb5fecc7f1..9f7b78e4e3354fae1e16d0bd6978e673f61e5e57 100644 (file)
@@ -32,6 +32,7 @@ pub fn main() {
     assert!(eq_u32x4(u32x4(1, 2, 3, 4) + u32x4(4, 3, 2, 1), u32x4(5, 5, 5, 5)));
     assert!(eq_u32x4(u32x4(4, 5, 6, 7) - u32x4(4, 3, 2, 1), u32x4(0, 2, 4, 6)));
     assert!(eq_u32x4(u32x4(1, 2, 3, 4) * u32x4(4, 3, 2, 1), u32x4(4, 6, 6, 4)));
+    assert!(eq_u32x4(u32x4(1, 2, 3, 4) / u32x4(4, 3, 2, 1), u32x4(0, 0, 1, 4)));
     assert!(eq_u32x4(u32x4(1, 2, 3, 4) & u32x4(4, 3, 2, 1), u32x4(0, 2, 2, 0)));
     assert!(eq_u32x4(u32x4(1, 2, 3, 4) | u32x4(4, 3, 2, 1), u32x4(5, 3, 3, 5)));
     assert!(eq_u32x4(u32x4(1, 2, 3, 4) ^ u32x4(4, 3, 2, 1), u32x4(5, 1, 1, 5)));
@@ -41,6 +42,7 @@ pub fn main() {
     assert!(eq_i32x4(i32x4(1, 2, 3, 4) + i32x4(4, 3, 2, 1), i32x4(5, 5, 5, 5)));
     assert!(eq_i32x4(i32x4(1, 2, 3, 4) - i32x4(4, 3, 2, 1), i32x4(-3, -1, 1, 3)));
     assert!(eq_i32x4(i32x4(1, 2, 3, 4) * i32x4(4, 3, 2, 1), i32x4(4, 6, 6, 4)));
+    assert!(eq_i32x4(i32x4(1, 2, 3, 4) / i32x4(4, 3, 2, 1), i32x4(0, 0, 1, 4)));
     assert!(eq_i32x4(i32x4(1, 2, 3, 4) & i32x4(4, 3, 2, 1), i32x4(0, 2, 2, 0)));
     assert!(eq_i32x4(i32x4(1, 2, 3, 4) | i32x4(4, 3, 2, 1), i32x4(5, 3, 3, 5)));
     assert!(eq_i32x4(i32x4(1, 2, 3, 4) ^ i32x4(4, 3, 2, 1), i32x4(5, 1, 1, 5)));
index df204065d163e6a76769dc5993a4a9b599e58be5..a87a3072c8adbcbd1d04495b8da91c8b35068507 100644 (file)
@@ -10,6 +10,9 @@
 
 // pretty-expanded FIXME #23616
 
+// this is for the wrapping_add call below.
+#![feature(core)]
+
 /*!
  * Tests the range assertion wraparound case in trans::middle::adt::load_discr.
  */
@@ -29,8 +32,8 @@ enum Es { Ls = -128, Hs = 127 }
 static CHs: Es = Es::Hs;
 
 pub fn main() {
-    assert_eq!((Eu::Hu as u8) + 1, Eu::Lu as u8);
-    assert_eq!((Es::Hs as i8) + 1, Es::Ls as i8);
+    assert_eq!((Eu::Hu as u8).wrapping_add(1), Eu::Lu as u8);
+    assert_eq!((Es::Hs as i8).wrapping_add(1), Es::Ls as i8);
     assert_eq!(CLu as u8, Eu::Lu as u8);
     assert_eq!(CHu as u8, Eu::Hu as u8);
     assert_eq!(CLs as i8, Es::Ls as i8);
diff --git a/src/test/run-pass/stat.rs b/src/test/run-pass/stat.rs
deleted file mode 100644 (file)
index c453f92..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2012-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.
-
-// pretty-expanded FIXME #23616
-
-#![feature(tempdir, path_ext)]
-
-use std::fs::{File, TempDir};
-use std::io::prelude::*;
-
-pub fn main() {
-    let dir = TempDir::new_in(".", "").unwrap();
-    let path = dir.path().join("file");
-
-    {
-        match File::create(&path) {
-            Err(..) => unreachable!(),
-            Ok(f) => {
-                let mut f = f;
-                for _ in 0..1000 {
-                    f.write(&[0]);
-                }
-            }
-        }
-    }
-
-    assert!(path.exists());
-    assert_eq!(path.metadata().unwrap().len(), 1000);
-}
index b3f503aad3444e808a128cf2e3135a07c5704621..8834fd39d1d8845f135e14abf1bd9f56d1587e17 100644 (file)
@@ -36,7 +36,6 @@ pub fn main() {
     assert!(
         include_str!("syntax-extension-source-utils-files/includeme.\
                       fragment").to_string()
-        .as_slice()
         .starts_with("/* this is for "));
     assert!(
         include_bytes!("syntax-extension-source-utils-files/includeme.fragment")
@@ -44,8 +43,5 @@ pub fn main() {
     // The Windows tests are wrapped in an extra module for some reason
     assert!((m1::m2::where_am_i().ends_with("m1::m2")));
 
-    assert!(match (47, "( 2 * 3 ) + 5") {
-        (line!(), stringify!((2*3) + 5)) => true,
-        _ => false
-    })
+    assert_eq!((46, "( 2 * 3 ) + 5"), (line!(), stringify!((2*3) + 5)));
 }
index 05197cd6a3d896605684525fa6ee8a46ee8df929..786dd2c76123e4a02e7975ccfd26fee519593f79 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 pub fn main() { test05(); }
@@ -26,7 +26,7 @@ fn test05_start(tx : &Sender<isize>) {
 
 fn test05() {
     let (tx, rx) = channel();
-    let _t = Thread::spawn(move|| { test05_start(&tx) });
+    let _t = thread::scoped(move|| { test05_start(&tx) });
     let mut value: isize = rx.recv().unwrap();
     println!("{}", value);
     value = rx.recv().unwrap();
index e882d8506fc6598b954121f6cc86ac2bbfa5628b..9c3466f162b03f365e1dd824689c590c30cabaea 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() { test00(); }
 
 fn start() { println!("Started / Finished task."); }
 
 fn test00() {
-    let _ = Thread::scoped(move|| start() ).join();
+    let _ = thread::scoped(move|| start() ).join();
     println!("Completing.");
 }
index 99eebdb601a29316b0b836434bd12a1007efd0df..f25bb3ff71ae8fe9803c9b58f73e4775460a5404 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 fn start(tx: &Sender<Sender<String>>) {
@@ -29,10 +29,10 @@ fn start(tx: &Sender<Sender<String>>) {
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _child = Thread::spawn(move|| { start(&tx) });
+    let _child = thread::scoped(move|| { start(&tx) });
 
     let mut c = rx.recv().unwrap();
     c.send("A".to_string()).unwrap();
     c.send("B".to_string()).unwrap();
-    Thread::yield_now();
+    thread::yield_now();
 }
index 9ef5afab2e0919c3a1d2ba62b887af6c0a579ee1..ec9ed53c1dca0cb21dc6c3b9ddced2b97554c6cf 100644 (file)
@@ -13,7 +13,7 @@
 #![feature(std_misc)]
 
 use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
 
 fn start(tx: &Sender<Sender<isize>>) {
     let (tx2, _rx) = channel();
@@ -22,7 +22,7 @@ fn start(tx: &Sender<Sender<isize>>) {
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _child = Thread::spawn(move|| {
+    let _child = thread::scoped(move|| {
         start(&tx)
     });
     let _tx = rx.recv().unwrap();
index 8921529c6bea3884887b3a5bb548059ef832c48b..03305091a2d074cddcece5ee5185786f1b15e3ef 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() { test00(); }
 
 
 fn test00() {
     let i: isize = 0;
-    let mut result = Thread::scoped(move|| {
+    let mut result = thread::scoped(move|| {
         start(i)
     });
 
     // Sleep long enough for the task to finish.
     let mut i = 0_usize;
     while i < 10000 {
-        Thread::yield_now();
+        thread::yield_now();
         i += 1;
     }
 
index 3a0757548e8c6e0aad5fade48fba4052d5a29cc5..15ceacd672f8bb8a16a4d91f78762762227367f5 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(std_misc)]
 
 use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
 
 fn start(tx: &Sender<isize>, start: isize, number_of_messages: isize) {
     let mut i: isize = 0;
@@ -21,6 +21,6 @@ fn start(tx: &Sender<isize>, start: isize, number_of_messages: isize) {
 pub fn main() {
     println!("Check that we don't deadlock.");
     let (tx, rx) = channel();
-    let _ = Thread::scoped(move|| { start(&tx, 0, 10) }).join();
+    let _t = thread::scoped(move|| { start(&tx, 0, 10) }).join();
     println!("Joined task");
 }
index 2ef09cdcf874d8502f56f268b5ad9e3fc7bd21ea..1e2d9fe52df154f1869fc1abc873c1e42737fd48 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(std_misc)]
 
 use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() {
     let (tx, rx) = channel();
@@ -21,7 +21,7 @@ pub fn main() {
     while (i > 0) {
         println!("{}", i);
         let tx = tx.clone();
-        Thread::spawn({let i = i; move|| { child(i, &tx) }});
+        thread::scoped({let i = i; move|| { child(i, &tx) }});
         i = i - 1;
     }
 
index 605900495b50cca0c944d3f633c0919d314eae4f..2663595aecfa18570c0130436313f578ee290e65 100644 (file)
@@ -13,7 +13,7 @@
 #![feature(std_misc)]
 
 use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
 
 fn start(tx: &Sender<isize>, i0: isize) {
     let mut i = i0;
@@ -29,7 +29,7 @@ pub fn main() {
     // the child's point of view the receiver may die. We should
     // drop messages on the floor in this case, and not crash!
     let (tx, rx) = channel();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         start(&tx, 10)
     });
     rx.recv();
index 6c27292d19d598cce5daa4764f9e5480293db4d6..de334c77aa310e5b947c83581f14245043648314 100644 (file)
 
 // This test is specifically about spawning temporary closures.
 
-use std::thread::Thread;
+use std::thread;
 
 fn f() {
 }
 
 pub fn main() {
-    let _t = Thread::scoped(move|| f() ).join();
+    let _t = thread::scoped(move|| f() ).join();
 }
index d742b7bb11ab6122a6d1b8ed8a133c96a612fbe5..254ad653c48132ba6a676270774d9a60c4dea121 100644 (file)
@@ -12,7 +12,7 @@
 
 // no-pretty-expanded FIXME #15189
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); }
@@ -42,7 +42,7 @@ fn test00() {
     let mut results = Vec::new();
     while i < number_of_tasks {
         let tx = tx.clone();
-        results.push(Thread::scoped({
+        results.push(thread::scoped({
             let i = i;
             move|| {
                 test00_start(&tx, i, number_of_messages)
index 82e8fe0af417eaf144ac1a8b9f2bc6d25a0efc3b..b05e36552a24c16b849168c61ad775e921829f99 100644 (file)
@@ -14,7 +14,7 @@
 #![allow(dead_assignment)]
 
 use std::sync::mpsc::{channel, Sender};
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() { test00(); }
 
@@ -31,19 +31,19 @@ fn test00() {
     let number_of_messages: isize = 10;
 
     let tx2 = tx.clone();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         test00_start(&tx2, number_of_messages * 0, number_of_messages);
     });
     let tx2 = tx.clone();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         test00_start(&tx2, number_of_messages * 1, number_of_messages);
     });
     let tx2 = tx.clone();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         test00_start(&tx2, number_of_messages * 2, number_of_messages);
     });
     let tx2 = tx.clone();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         test00_start(&tx2, number_of_messages * 3, number_of_messages);
     });
 
index 3e4a75b8e220f3da0cfe910b9f29ce5dde44d056..758764aa9fdcca766ee17564cda123e36303d244 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::{channel, Sender};
 
 pub fn main() { test00(); }
@@ -26,7 +26,7 @@ fn test00() {
     let (tx, rx) = channel();
     let number_of_messages: isize = 10;
 
-    let result = Thread::scoped(move|| {
+    let result = thread::scoped(move|| {
         test00_start(&tx, number_of_messages);
     });
 
index 7da7a1afb9af89cb480634d0c4698685427a4fc0..b97f4355b3ee08bb297b0d2d4f4a458628830b9a 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() {
-    let _t = Thread::spawn(move|| child("Hello".to_string()) );
+    let _t = thread::scoped(move|| child("Hello".to_string()) );
 }
 
 fn child(_s: String) {
index 637f564f72649edcbc9b96d65fa45941a3c11f86..aa7b61bf112f90627cd4516e53d3d63ecd7d200a 100644 (file)
@@ -13,7 +13,7 @@
 #![allow(unknown_features)]
 #![feature(box_syntax, std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::channel;
 
 pub fn main() {
@@ -22,7 +22,7 @@ pub fn main() {
     let x: Box<isize> = box 1;
     let x_in_parent = &(*x) as *const isize as usize;
 
-    let _t = Thread::spawn(move || {
+    let _t = thread::scoped(move || {
         let x_in_child = &(*x) as *const isize as usize;
         tx.send(x_in_child).unwrap();
     });
index 99d36a179aaf5b93ddcdf1d1306f3f31ccfba538..00467e563347a32174c7cb5a693448d75a7b68dc 100644 (file)
@@ -19,7 +19,7 @@
 use std::sync::Arc;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
 
 static N: usize = 8;
 static M: usize = 20;
@@ -40,7 +40,7 @@ fn test() {
         let a = a.clone();
         let cnt = cnt.clone();
         let srv_tx = srv_tx.clone();
-        Thread::scoped(move|| {
+        thread::scoped(move|| {
             let mut a = a;
             loop {
                 match a.accept() {
@@ -59,7 +59,7 @@ fn test() {
 
     let _t = (0..N).map(|_| {
         let cli_tx = cli_tx.clone();
-        Thread::scoped(move|| {
+        thread::scoped(move|| {
             for _ in 0..M {
                 let _s = TcpStream::connect(addr).unwrap();
             }
index a9a16cd72dff7dbf48ba6761188986581aa7712a..64f07a60b3503858390cadc58b92687422f0c8d9 100644 (file)
@@ -26,7 +26,7 @@
 use std::old_io;
 use std::time::Duration;
 use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
 
 #[cfg_attr(target_os = "freebsd", ignore)]
 fn eventual_timeout() {
@@ -34,7 +34,7 @@ fn eventual_timeout() {
 
     let (tx1, rx1) = channel();
     let (_tx2, rx2) = channel::<()>();
-    let _t = Thread::spawn(move|| {
+    let _t = thread::scoped(move|| {
         let _l = TcpListener::bind(addr).unwrap().listen();
         tx1.send(()).unwrap();
         let _ = rx2.recv();
index 489abf163c0b2d80cc9d9ab9a28527d8c5e03c0a..4209d5986ba506c8fc3d1a69180273bfa94ca4c5 100644 (file)
 use std::sync::mpsc::channel;
 use std::old_io::net::tcp::{TcpListener, TcpStream};
 use std::old_io::{Acceptor, Listener, Reader, Writer};
-use std::thread::{Builder, Thread};
+use std::thread::{self, Builder};
 use std::time::Duration;
 
 fn main() {
     // This test has a chance to time out, try to not let it time out
-    Thread::spawn(move|| -> () {
+    thread::spawn(move|| -> () {
         use std::old_io::timer;
         timer::sleep(Duration::milliseconds(30 * 1000));
         println!("timed out!");
@@ -36,7 +36,7 @@ fn main() {
     });
 
     let (tx, rx) = channel();
-    Thread::spawn(move || -> () {
+    thread::spawn(move || -> () {
         let mut listener = TcpListener::bind("127.0.0.1:0").unwrap();
         tx.send(listener.socket_name().unwrap()).unwrap();
         let mut acceptor = listener.listen();
index 74290518364d08b6776b1b84be23314c67f09cd5..49fac24d0b3a5b7e921233856ad3dff79776f99a 100644 (file)
@@ -24,7 +24,7 @@
 use std::old_io::fs::PathExtensions;
 use std::old_io::{fs, TempDir};
 use std::old_io;
-use std::os;
+use std::env;
 use std::sync::mpsc::channel;
 use std::thread;
 
@@ -129,7 +129,7 @@ fn test_rm_tempdir_close() {
 // to depend on std
 fn recursive_mkdir_rel() {
     let path = Path::new("frob");
-    let cwd = os::getcwd().unwrap();
+    let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap());
     println!("recursive_mkdir_rel: Making: {} in cwd {} [{}]", path.display(),
            cwd.display(), path.exists());
     fs::mkdir_recursive(&path, old_io::USER_RWX);
@@ -147,7 +147,7 @@ fn recursive_mkdir_dot() {
 
 fn recursive_mkdir_rel_2() {
     let path = Path::new("./frob/baz");
-    let cwd = os::getcwd().unwrap();
+    let cwd = Path::new(env::current_dir().unwrap().to_str().unwrap());
     println!("recursive_mkdir_rel_2: Making: {} in cwd {} [{}]", path.display(),
            cwd.display(), path.exists());
     fs::mkdir_recursive(&path, old_io::USER_RWX);
@@ -196,7 +196,7 @@ pub fn dont_double_panic() {
 
 fn in_tmpdir<F>(f: F) where F: FnOnce() {
     let tmpdir = TempDir::new("test").ok().expect("can't make tmpdir");
-    assert!(os::change_dir(tmpdir.path()).is_ok());
+    assert!(env::set_current_dir(tmpdir.path().as_str().unwrap()).is_ok());
 
     f();
 }
index 4fc0995290493499ab93d283f5454768ddc19d52..969a42a6f8715624ad3543688927b7cbcd057e08 100644 (file)
 
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 
 pub fn main() {
     let mut i = 10;
     while i > 0 {
-        Thread::scoped({let i = i; move|| child(i)});
+        thread::scoped({let i = i; move|| child(i)});
         i = i - 1;
     }
     println!("main thread exiting");
index 2d97633771e61739ae7a22f4955acfa157aaf238..02ea7037056051a5e2d1a1f79049f327c142f388 100644 (file)
@@ -19,7 +19,7 @@
 
 use std::sync::Arc;
 use std::sync::mpsc::channel;
-use std::thread::Thread;
+use std::thread;
 
 trait Pet {
     fn name(&self, blk: Box<FnMut(&str)>);
@@ -83,13 +83,13 @@ pub fn main() {
                             box dogge2 as Box<Pet+Sync+Send>));
     let (tx1, rx1) = channel();
     let arc1 = arc.clone();
-    let _t1 = Thread::spawn(move|| { check_legs(arc1); tx1.send(()); });
+    let _t1 = thread::scoped(move|| { check_legs(arc1); tx1.send(()); });
     let (tx2, rx2) = channel();
     let arc2 = arc.clone();
-    let _t2 = Thread::spawn(move|| { check_names(arc2); tx2.send(()); });
+    let _t2 = thread::scoped(move|| { check_names(arc2); tx2.send(()); });
     let (tx3, rx3) = channel();
     let arc3 = arc.clone();
-    let _t3 = Thread::spawn(move|| { check_pedigree(arc3); tx3.send(()); });
+    let _t3 = thread::scoped(move|| { check_pedigree(arc3); tx3.send(()); });
     rx1.recv();
     rx2.recv();
     rx3.recv();
index 5edd3dfbc9ef5e1b474a1ad10a435668ed69a4c6..0190b7b7b9628370a408733e302da67757825e24 100644 (file)
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
+use std::marker::MarkerTrait;
+
 trait Get {
     fn get(&self) -> Self;
 }
 
-impl<T:Copy> Get for T {
-    fn get(&self) -> T { *self }
+trait MyCopy : MarkerTrait { fn copy(&self) -> Self; }
+impl MyCopy for u16 { fn copy(&self) -> Self { *self } }
+impl MyCopy for u32 { fn copy(&self) -> Self { *self } }
+impl MyCopy for i32 { fn copy(&self) -> Self { *self } }
+impl<T:Copy> MyCopy for Option<T> { fn copy(&self) -> Self { *self } }
+
+impl<T:MyCopy> Get for T {
+    fn get(&self) -> T { self.copy() }
 }
 
-impl<T:Get> Get for Box<T> {
-    fn get(&self) -> Box<T> { box get_it(&**self) }
+impl Get for Box<i32> {
+    fn get(&self) -> Box<i32> { box get_it(&**self) }
 }
 
 fn get_it<T:Get>(t: &T) -> T {
diff --git a/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs b/src/test/run-pass/unboxed-closures-blanket-fn-mut.rs
new file mode 100644 (file)
index 0000000..37dccca
--- /dev/null
@@ -0,0 +1,37 @@
+// 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 you can supply `&F` where `F: FnMut()`.
+
+// pretty-expanded FIXME #23616
+
+#![feature(lang_items, unboxed_closures)]
+
+fn a<F:FnMut() -> i32>(mut f: F) -> i32 {
+    f()
+}
+
+fn b(f: &mut FnMut() -> i32) -> i32 {
+    a(f)
+}
+
+fn c<F:FnMut() -> i32>(f: &mut F) -> i32 {
+    a(f)
+}
+
+fn main() {
+    let z: isize = 7;
+
+    let x = b(&mut || 22);
+    assert_eq!(x, 22);
+
+    let x = c(&mut || 22);
+    assert_eq!(x, 22);
+}
diff --git a/src/test/run-pass/unboxed-closures-blanket-fn.rs b/src/test/run-pass/unboxed-closures-blanket-fn.rs
new file mode 100644 (file)
index 0000000..0f93966
--- /dev/null
@@ -0,0 +1,37 @@
+// 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 you can supply `&F` where `F: Fn()`.
+
+// pretty-expanded FIXME #23616
+
+#![feature(lang_items, unboxed_closures)]
+
+fn a<F:Fn() -> i32>(f: F) -> i32 {
+    f()
+}
+
+fn b(f: &Fn() -> i32) -> i32 {
+    a(f)
+}
+
+fn c<F:Fn() -> i32>(f: &F) -> i32 {
+    a(f)
+}
+
+fn main() {
+    let z: isize = 7;
+
+    let x = b(&|| 22);
+    assert_eq!(x, 22);
+
+    let x = c(&|| 22);
+    assert_eq!(x, 22);
+}
index 9e1ced364024f3487799f5f75f1702684c179ed4..c2db63ed251a5c72420d8189102f54cb230d5895 100644 (file)
@@ -14,7 +14,6 @@
 
 #![feature(alloc)]
 
-use std::boxed::BoxAny;
 use std::thread;
 
 struct Foo;
index 1688482ca37606b1ace3552e43312cf91ffb69fe..d81dc3afcd7af05d03d7ba52212eba2edeac57da 100644 (file)
@@ -14,7 +14,7 @@
 
 extern crate libc;
 
-use std::ffi::{self, CString};
+use std::ffi::{CStr, CString};
 use libc::{c_char, c_int};
 
 
@@ -25,7 +25,7 @@
 unsafe fn check<T, F>(expected: &str, f: F) where F: FnOnce(*mut c_char) -> T {
     let mut x = [0 as c_char; 50];
     f(&mut x[0] as *mut c_char);
-    assert_eq!(expected.as_bytes(), ffi::c_str_to_bytes(&x.as_ptr()));
+    assert_eq!(expected.as_bytes(), CStr::from_ptr(x.as_ptr()).to_bytes());
 }
 
 pub fn main() {