]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #23934 - lfairy:write-no-deref, r=alexcrichton
authorbors <bors@rust-lang.org>
Fri, 3 Apr 2015 07:13:51 +0000 (07:13 +0000)
committerbors <bors@rust-lang.org>
Fri, 3 Apr 2015 07:13:51 +0000 (07:13 +0000)
This means passing in e.g. a `Vec<u8>` or `String` will work as
intended, rather than deref-ing to `&mut [u8]` or `&mut str`.

[breaking-change]

Closes #23768

609 files changed:
RELEASES.md
src/compiletest/compiletest.rs
src/compiletest/header.rs
src/doc/reference.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/benchmark-tests.md [new file with mode: 0644]
src/doc/trpl/box-syntax-and-patterns.md [new file with mode: 0644]
src/doc/trpl/closures.md
src/doc/trpl/concurrency.md
src/doc/trpl/error-handling.md
src/doc/trpl/iterators.md
src/doc/trpl/macros.md
src/doc/trpl/ownership.md
src/doc/trpl/pointers.md
src/doc/trpl/testing.md
src/doc/trpl/traits.md
src/etc/rustup.sh
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/boxed_test.rs
src/liballoc/lib.rs
src/libcollections/binary_heap.rs
src/libcollections/bit.rs
src/libcollections/borrow.rs
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/enum_set.rs
src/libcollections/fmt.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/bit/vec.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 [deleted file]
src/libcore/finally.rs [deleted file]
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/fmt/rt/v1.rs
src/libcore/hash/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/int_macros.rs
src/libcore/num/mod.rs
src/libcore/num/uint_macros.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/simd.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/fmt/num.rs
src/libcoretest/iter.rs
src/libcoretest/lib.rs
src/libcoretest/mem.rs
src/libcoretest/num/int_macros.rs
src/libcoretest/num/uint_macros.rs
src/libcoretest/str.rs
src/libfmt_macros/lib.rs
src/libgetopts/lib.rs
src/libgraphviz/lib.rs
src/liblibc/lib.rs
src/liblog/lib.rs
src/librand/chacha.rs
src/librand/distributions/exponential.rs
src/librand/distributions/mod.rs
src/librand/distributions/normal.rs
src/librand/lib.rs
src/librand/reseeding.rs
src/librbml/lib.rs
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/mod.rs
src/librustc/metadata/common.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/tydecode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/cfg/mod.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_loop.rs
src/librustc/middle/check_match.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/def.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/graph.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/type_variable.rs
src/librustc/middle/infer/unify.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.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/session/config.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_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/graphviz.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/diagnostic.rs
src/librustc_llvm/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/save/recorder.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/basic_block.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/cleanup.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/context.rs
src/librustc_trans/trans/controlflow.rs
src/librustc_trans/trans/datum.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/mod.rs
src/librustc_trans/trans/tvec.rs
src/librustc_trans/trans/value.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/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wf.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/rscope.rs
src/librustc_typeck/variance.rs
src/librustdoc/clean/mod.rs
src/librustdoc/flock.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/stability_summary.rs
src/librustdoc/test.rs
src/libserialize/hex.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/error.rs [new file with mode: 0644]
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/num/strconv.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/addrinfo.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/rt/at_exit_imp.rs
src/libstd/rt/libunwind.rs
src/libstd/rt/mod.rs
src/libstd/rt/unwind.rs
src/libstd/sync/condvar.rs
src/libstd/sync/future.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/poison.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/task_pool.rs [deleted file]
src/libstd/sys/common/net.rs
src/libstd/sys/common/net2.rs
src/libstd/sys/common/thread.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/c.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/sys/windows/tcp.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd/thunk.rs
src/libsyntax/abi.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/blocks.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/ast_util.rs
src/libsyntax/attr.rs
src/libsyntax/codemap.rs
src/libsyntax/diagnostic.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/mtwt.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pp.rs
src/libsyntax/print/pprust.rs
src/libsyntax/util/small_vector.rs
src/libsyntax/visit.rs
src/libterm/lib.rs
src/libterm/terminfo/parm.rs
src/libterm/win.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/auxiliary/issue-14422.rs
src/test/auxiliary/issue13213aux.rs
src/test/auxiliary/method_self_arg1.rs
src/test/auxiliary/method_self_arg2.rs
src/test/auxiliary/struct_variant_xc_aux.rs
src/test/auxiliary/xcrate_unit_struct.rs
src/test/bench/noise.rs
src/test/bench/shootout-binarytrees.rs
src/test/bench/shootout-chameneos-redux.rs
src/test/bench/shootout-fannkuch-redux.rs
src/test/bench/shootout-fasta-redux.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-k-nucleotide.rs
src/test/bench/shootout-nbody.rs
src/test/bench/shootout-spectralnorm.rs
src/test/compile-fail-fulldeps/gated-macro-reexports.rs
src/test/compile-fail/borrowck-borrow-from-owned-ptr.rs
src/test/compile-fail/borrowck-borrow-from-stack-variable.rs
src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
src/test/compile-fail/borrowck-use-mut-borrow.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/dst-index.rs
src/test/compile-fail/enum-discrim-too-small.rs
src/test/compile-fail/estr-subtyping.rs
src/test/compile-fail/exclusive-drop-and-copy.rs
src/test/compile-fail/feature-gate-rust-call.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-simd-ffi.rs
src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs
src/test/compile-fail/gated-box-patterns.rs
src/test/compile-fail/gated-box-syntax.rs
src/test/compile-fail/gated-link-args.rs
src/test/compile-fail/gated-link-llvm-intrinsics.rs
src/test/compile-fail/gated-plugin_registrar.rs
src/test/compile-fail/gated-simd-ffi.rs
src/test/compile-fail/gated-unsafe-destructor.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/kindck-copy.rs
src/test/compile-fail/kindck-inherited-copy-bound.rs
src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-2.rs
src/test/compile-fail/lint-exceeding-bitshifts.rs
src/test/compile-fail/lint-type-limits.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/opt-in-copy.rs
src/test/compile-fail/pub-method-macro.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/unsendable-class.rs [deleted file]
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/c-style-enum.rs
src/test/debuginfo/generic-method-on-generic-struct.rs
src/test/debuginfo/method-on-enum.rs
src/test/debuginfo/method-on-generic-struct.rs
src/test/debuginfo/method-on-struct.rs
src/test/debuginfo/method-on-trait.rs
src/test/debuginfo/method-on-tuple-struct.rs
src/test/debuginfo/self-in-default-method.rs
src/test/debuginfo/self-in-generic-default-method.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/pretty/block-disambig.rs
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/allow-non-lint-warnings-cmdline/foo.rs
src/test/run-make/extern-fn-with-packed-struct/test.rs
src/test/run-make/link-path-order/main.rs
src/test/run-make/rustdoc-extern-method/bar.rs
src/test/run-make/rustdoc-extern-method/foo.rs
src/test/run-make/save-analysis/foo.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/associated-types-normalize-unifield-struct.rs
src/test/run-pass/backtrace.rs
src/test/run-pass/big-literals.rs
src/test/run-pass/binops-issue-22743.rs
src/test/run-pass/bitwise.rs
src/test/run-pass/borrowck-univariant-enum.rs
src/test/run-pass/builtin-superkinds-in-metadata.rs
src/test/run-pass/capturing-logging.rs
src/test/run-pass/child-outlives-parent.rs
src/test/run-pass/class-impl-very-parameterized-trait.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-impl-in-fn.rs
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/const-nullary-univariant-enum.rs
src/test/run-pass/copy-out-of-array-1.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-bounds.rs
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/dst-struct-sole.rs
src/test/run-pass/dst-struct.rs
src/test/run-pass/dst-trait.rs
src/test/run-pass/empty-tag.rs
src/test/run-pass/enum-discrim-width-stuff.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/explicit-self-generic.rs
src/test/run-pass/expr-copy.rs
src/test/run-pass/expr-if-struct.rs
src/test/run-pass/expr-match-struct.rs
src/test/run-pass/exterior.rs
src/test/run-pass/extern-call-scrub.rs
src/test/run-pass/extern-pass-TwoU16s.rs
src/test/run-pass/extern-pass-TwoU32s.rs
src/test/run-pass/extern-pass-TwoU64s.rs
src/test/run-pass/extern-pass-TwoU8s.rs
src/test/run-pass/foreign-fn-with-byval.rs
src/test/run-pass/generic-fn.rs
src/test/run-pass/guards-not-exhaustive.rs
src/test/run-pass/guards.rs
src/test/run-pass/hashmap-memory.rs
src/test/run-pass/hrtb-opt-in-copy.rs
src/test/run-pass/init-large-type.rs
src/test/run-pass/intrinsics-integer.rs
src/test/run-pass/issue-11709.rs
src/test/run-pass/issue-11881.rs
src/test/run-pass/issue-11958.rs
src/test/run-pass/issue-12860.rs
src/test/run-pass/issue-13264.rs
src/test/run-pass/issue-13304.rs
src/test/run-pass/issue-13494.rs
src/test/run-pass/issue-13763.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-17074.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-17897.rs
src/test/run-pass/issue-18188.rs
src/test/run-pass/issue-19100.rs
src/test/run-pass/issue-20454.rs
src/test/run-pass/issue-20797.rs
src/test/run-pass/issue-21296.rs
src/test/run-pass/issue-2190-1.rs
src/test/run-pass/issue-22536-copy-mustnt-zero.rs
src/test/run-pass/issue-22577.rs
src/test/run-pass/issue-2288.rs
src/test/run-pass/issue-23550.rs
src/test/run-pass/issue-2633.rs
src/test/run-pass/issue-2718.rs
src/test/run-pass/issue-3121.rs
src/test/run-pass/issue-3563-3.rs
src/test/run-pass/issue-3609.rs
src/test/run-pass/issue-3743.rs
src/test/run-pass/issue-3753.rs
src/test/run-pass/issue-5688.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/match-arm-statics.rs
src/test/run-pass/method-self-arg-trait.rs
src/test/run-pass/method-self-arg.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/monomorphize-abi-alignment.rs
src/test/run-pass/moves-based-on-type-capture-clause.rs
src/test/run-pass/multidispatch1.rs
src/test/run-pass/multidispatch2.rs
src/test/run-pass/newtype.rs
src/test/run-pass/operator-overloading.rs
src/test/run-pass/option-ext.rs
src/test/run-pass/out-of-stack-new-thread-no-split.rs
src/test/run-pass/out-pointer-aliasing.rs
src/test/run-pass/overloaded-autoderef-order.rs
src/test/run-pass/packed-struct-vec.rs
src/test/run-pass/process-exit.rs [new file with mode: 0644]
src/test/run-pass/rec-tup.rs
src/test/run-pass/rec.rs
src/test/run-pass/regions-dependent-addr-of.rs
src/test/run-pass/regions-early-bound-used-in-bound-method.rs
src/test/run-pass/regions-early-bound-used-in-bound.rs
src/test/run-pass/regions-early-bound-used-in-type-param.rs
src/test/run-pass/regions-mock-tcx.rs
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/self-in-mut-slot-immediate-value.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/simd-generics.rs
src/test/run-pass/small-enum-range-edge.rs
src/test/run-pass/stat.rs [deleted file]
src/test/run-pass/struct-return.rs
src/test/run-pass/structured-compare.rs
src/test/run-pass/sync-send-iterators-in-libcollections.rs
src/test/run-pass/syntax-extension-source-utils.rs
src/test/run-pass/tag-variant-disr-val.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/trait-coercion-generic.rs
src/test/run-pass/trait-coercion.rs
src/test/run-pass/traits-conditional-dispatch.rs
src/test/run-pass/ufcs-explicit-self.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
src/test/run-pass/vector-sort-panic-safe.rs

index 69b804cf24c40ab16e1d9fe431614a9ce6bb3c99..7da73afb4111f4f7f221b6ef90eb907023e2bc4a 100644 (file)
@@ -1,3 +1,102 @@
+Version 1.0.0-beta (April 2015)
+-------------------------------------
+
+* ~1100 changes, numerous bugfixes
+
+* Highlights
+
+    * The big news is that the vast majority of the standard library
+      is now `#[stable]` -- 75% of the non-deprecated API surface at
+      last count. Numerous crates are now running on stable
+      Rust. Starting with this release, it is not possible to use
+      unstable features on a stable build.
+    * Arithmetic on basic integer types now
+      [checks for overflow in debug builds][overflow].
+
+* Language
+
+    * [`Send` no longer implies `'static`][send-rfc], which made
+      possible the [`thread::scoped` API][scoped]. Scoped threads can
+      borrow data from their parent's stack frame -- safely!
+    * [UFCS now supports trait-less associated paths][moar-ufcs] like
+      `MyType::default()`.
+    * Primitive types [now have inherent methods][prim-inherent],
+      obviating the need for extension traits like `SliceExt`.
+    * Methods with `Self: Sized` in their `where` clause are
+      [considered object-safe][self-sized], allowing many extension
+      traits like `IteratorExt` to be merged into the traits they
+      extended.
+    * You can now [refer to associated types][assoc-where] whose
+      corresponding trait bounds appear only in a `where` clause.
+    * The final bits of [OIBIT landed][oibit-final], meaning that
+      traits like `Send` and `Sync` are now library-defined.
+    * A [Reflect trait][reflect] was introduced, which means that
+      downcasting via the `Any` trait is effectively limited to
+      concrete types. This helps retain the potentially-important
+      "parametricity" property: generic code cannot behave differently
+      for different type arguments except in minor ways.
+    * The `unsafe_destructor` feature is now deprecated in favor of
+      the [new `dropck`][dropck]. This change is a major reduction in
+      unsafe code.
+    * Trait coherence was [revised again][fundamental], this time with
+      an eye toward API evolution over time.
+
+* Libraries
+
+    * The new path and IO modules are complete and `#[stable]`. This
+      was the major library focus for this cycle.
+    * The path API was [revised][path-normalize] to normalize `.`,
+      adjusting the tradeoffs in favor of the most common usage.
+    * A large number of remaining APIs in `std` were also stabilized
+      during this cycle; about 75% of the non-deprecated API surface
+      is now stable.
+    * The new [string pattern API][string-pattern] landed, which makes
+      the string slice API much more internally consistent and flexible.
+    * A shiny [framework for Debug implementations][debug-builder] landed.
+      This makes it possible to opt in to "pretty-printed" debugging output.
+    * A new set of [generic conversion traits][conversion] replaced
+      many existing ad hoc traits.
+    * Generic numeric traits were
+      [completely removed][num-traits]. This was made possible thanks
+      to inherent methods for primitive types, and the removal gives
+      maximal flexibility for designing a numeric hierarchy in the future.
+    * The `Fn` traits are now related via [inheritance][fn-inherit]
+      and provide ergonomic [blanket implementations][fn-blanket].
+    * The `Index` and `IndexMut` traits were changed to
+      [take the index by value][index-value], enabling code like
+      `hash_map["string"]` to work.
+    * `Copy` now [inherits][copy-clone] from `Clone`, meaning that all
+      `Copy` data is known to be `Clone` as well.
+
+* Infrastructure
+
+    * Metadata was tuned, shrinking binaries [by 27%][metadata-shrink].
+    * Much headway was made on ecosystem-wide CI, making it possible
+      to [compare builds for breakage][ci-compare].
+
+[send-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0458-send-improvements.md
+[scoped]: http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html
+[moar-ufcs]: https://github.com/rust-lang/rust/pull/22172
+[prim-inherent]: https://github.com/rust-lang/rust/pull/23104
+[overflow]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
+[metadata-shrink]: https://github.com/rust-lang/rust/pull/22971
+[self-sized]: https://github.com/rust-lang/rust/pull/22301
+[assoc-where]: https://github.com/rust-lang/rust/pull/22512
+[string-pattern]: https://github.com/rust-lang/rust/pull/22466
+[oibit-final]: https://github.com/rust-lang/rust/pull/21689
+[reflect]: https://github.com/rust-lang/rust/pull/23712
+[debug-builder]: https://github.com/rust-lang/rfcs/blob/master/text/0640-debug-improvements.md
+[conversion]: https://github.com/rust-lang/rfcs/pull/529
+[num-traits]: https://github.com/rust-lang/rust/pull/23549
+[index-value]: https://github.com/rust-lang/rust/pull/23601
+[dropck]: https://github.com/rust-lang/rfcs/pull/769
+[fundamental]: https://github.com/rust-lang/rfcs/pull/1023
+[ci-compare]: https://gist.github.com/brson/a30a77836fbec057cbee
+[fn-inherit]: https://github.com/rust-lang/rust/pull/23282
+[fn-blanket]: https://github.com/rust-lang/rust/pull/23895
+[copy-clone]: https://github.com/rust-lang/rust/pull/23860
+[path-normalize]: https://github.com/rust-lang/rust/pull/23229
+
 Version 1.0.0-alpha.2 (February 2015)
 -------------------------------------
 
index f0aacc1460b3fa7b372b6919e632ece9921aea36..f00ff9bcbe5e5c4bec3ad7fbbd4336a72f1a2c55 100644 (file)
@@ -18,7 +18,6 @@
 #![feature(std_misc)]
 #![feature(test)]
 #![feature(path_ext)]
-#![feature(convert)]
 #![feature(str_char)]
 
 #![deny(warnings)]
@@ -32,7 +31,6 @@
 use std::env;
 use std::fs;
 use std::path::{Path, PathBuf};
-use std::thunk::Thunk;
 use getopts::{optopt, optflag, reqopt};
 use common::Config;
 use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen};
@@ -352,7 +350,7 @@ fn shorten(path: &Path) -> String {
 pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn {
     let config = (*config).clone();
     let testfile = testfile.to_path_buf();
-    test::DynTestFn(Thunk::new(move || {
+    test::DynTestFn(Box::new(move || {
         runtest::run(config, &testfile)
     }))
 }
index 9612c0e06a34d7b311fb08db18b5181e7ac2fe7f..f5505b6e83a6738dd073b68513a4ef5755a339e4 100644 (file)
@@ -311,7 +311,7 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> {
     parse_name_value_directive(line, "exec-env").map(|nv| {
         // nv is either FOO or FOO=BAR
         let mut strs: Vec<String> = nv
-                                      .splitn(1, '=')
+                                      .splitn(2, '=')
                                       .map(|s| s.to_string())
                                       .collect();
 
index 0bc4414999d74e320e6968e410e3211a39237e01..cc90a69fd2ae7d2b1f1147565abdddd73f64c0d1 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]);
@@ -1652,7 +1648,7 @@ specific type.
 Implementations are defined with the keyword `impl`.
 
 ```
-# #[derive(Copy)]
+# #[derive(Copy, Clone)]
 # struct Point {x: f64, y: f64};
 # type Surface = i32;
 # struct BoundingBox {x: f64, y: f64, width: f64, height: f64};
@@ -1665,6 +1661,10 @@ struct Circle {
 
 impl Copy for Circle {}
 
+impl Clone for Circle {
+    fn clone(&self) -> Circle { *self }
+}
+
 impl Shape for Circle {
     fn draw(&self, s: Surface) { do_draw_circle(s, *self); }
     fn bounding_box(&self) -> BoundingBox {
index d31348d667b57e56e996ca86e2e64e4505f8fdde..11e62aff42f3fd6132c1d4df5280aaa74a134ba2 100644 (file)
@@ -42,5 +42,7 @@
     * [Intrinsics](intrinsics.md)
     * [Lang items](lang-items.md)
     * [Link args](link-args.md)
+    * [Benchmark Tests](benchmark-tests.md)
+    * [Box Syntax and Patterns](box-syntax-and-patterns.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.
diff --git a/src/doc/trpl/box-syntax-and-patterns.md b/src/doc/trpl/box-syntax-and-patterns.md
new file mode 100644 (file)
index 0000000..839f07d
--- /dev/null
@@ -0,0 +1,100 @@
+%  Box Syntax and Patterns
+
+Currently the only stable way to create a `Box` is via the `Box::new` method.
+Also it is not possible in stable Rust to destructure a `Box` in a match
+pattern. The unstable `box` keyword can be used to both create and destructure
+a `Box`. An example usage would be:
+
+```
+#![feature(box_syntax, box_patterns)]
+
+fn main() {
+    let b = Some(box 5);
+    match b {
+        Some(box n) if n < 0 => {
+            println!("Box contains negative number {}", n);
+        },
+        Some(box n) if n >= 0 => {
+            println!("Box contains non-negative number {}", n);
+        },
+        None => {
+            println!("No box");
+        },
+        _ => unreachable!()
+    }
+}
+```
+
+Note that these features are currently hidden behind the `box_syntax` (box
+creation) and `box_patterns` (destructuring and pattern matching) gates
+because the syntax may still change in the future.
+
+# Returning Pointers
+
+In many languages with pointers, you'd return a pointer from a function
+so as to avoid copying a large data structure. For example:
+
+```{rust}
+struct BigStruct {
+    one: i32,
+    two: i32,
+    // etc
+    one_hundred: i32,
+}
+
+fn foo(x: Box<BigStruct>) -> Box<BigStruct> {
+    Box::new(*x)
+}
+
+fn main() {
+    let x = Box::new(BigStruct {
+        one: 1,
+        two: 2,
+        one_hundred: 100,
+    });
+
+    let y = foo(x);
+}
+```
+
+The idea is that by passing around a box, you're only copying a pointer, rather
+than the hundred `int`s that make up the `BigStruct`.
+
+This is an antipattern in Rust. Instead, write this:
+
+```rust
+#![feature(box_syntax)]
+
+struct BigStruct {
+    one: i32,
+    two: i32,
+    // etc
+    one_hundred: i32,
+}
+
+fn foo(x: Box<BigStruct>) -> BigStruct {
+    *x
+}
+
+fn main() {
+    let x = Box::new(BigStruct {
+        one: 1,
+        two: 2,
+        one_hundred: 100,
+    });
+
+    let y: Box<BigStruct> = box foo(x);
+}
+```
+
+This gives you flexibility without sacrificing performance.
+
+You may think that this gives us terrible performance: return a value and then
+immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is
+smarter than that. There is no copy in this code. `main` allocates enough room
+for the `box`, passes a pointer to that memory into `foo` as `x`, and then
+`foo` writes the value straight into the `Box<T>`.
+
+This is important enough that it bears repeating: pointers are not for
+optimizing returning values from your code. Allow the caller to choose how they
+want to use your output.
index bf4c2d903570beb740a577f35be0c5612c65d10d..01b8163ffd372b89c75843e419dcc9bc968546e8 100644 (file)
 % Closures
 
-So far, we've made lots of functions in Rust, but we've given them all names.
-Rust also allows us to create anonymous functions. Rust's anonymous
-functions are called *closures*. By themselves, closures aren't all that
-interesting, but when you combine them with functions that take closures as
-arguments, really powerful things are possible.
+Rust not only has named functions, but anonymous functions as well. Anonymous
+functions that have an associated environment are called 'closures', because they
+close over an environment. Rust has a really great implementation of them, as
+we'll see.
 
-Let's make a closure:
+# Syntax
 
-```{rust}
-let add_one = |x| { 1 + x };
+Closures look like this:
 
-println!("The sum of 5 plus 1 is {}.", add_one(5));
+```rust
+let plus_one = |x: i32| x + 1;
+
+assert_eq!(2, plus_one(1));
+```
+
+We create a binding, `plus_one`, and assign it to a closure. The closure's
+arguments go between the pipes (`|`), and the body is an expression, in this
+case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
+closures too:
+
+```rust
+let plus_two = |x| {
+    let mut result: i32 = x;
+
+    result += 1;
+    result += 1;
+
+    result
+};
+
+assert_eq!(4, plus_two(2));
+```
+
+You'll notice a few things about closures that are a bit different than regular
+functions defined with `fn`. The first of which is that we did not need to
+annotate the types of arguments the closure takes or the values it returns. We
+can:
+
+```rust
+let plus_one = |x: i32| -> i32 { x + 1 };
+
+assert_eq!(2, plus_one(1));
+```
+
+But we don't have to. Why is this? Basically, it was chosen for ergonomic reasons.
+While specifying the full type for named functions is helpful with things like
+documentation and type inference, the types of closures are rarely documented
+since they’re anonymous, and they don’t cause the kinds of error-at-a-distance
+that inferring named function types can.
+
+The second is that the syntax is similar, but a bit different. I've added spaces
+here to make them look a little closer:
+
+```rust
+fn  plus_one_v1 (  x: i32 ) -> i32 { x + 1 }
+let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
+let plus_one_v3 = |x: i32 |          x + 1  ;
 ```
 
-We create a closure using the `|...| { ... }` syntax, and then we create a
-binding so we can use it later. Note that we call the function using the
-binding name and two parentheses, just like we would for a named function.
+Small differences, but they're similar in ways.
 
-Let's compare syntax. The two are pretty close:
+# Closures and their environment
 
-```{rust}
-let add_one = |x: i32| -> i32 { 1 + x };
-fn  add_one   (x: i32) -> i32 { 1 + x }
+Closures are called such because they 'close over their environment.' It
+looks like this:
+
+```rust
+let num = 5;
+let plus_num = |x: i32| x + num;
+
+assert_eq!(10, plus_num(5));
 ```
 
-As you may have noticed, closures infer their argument and return types, so you
-don't need to declare one. This is different from named functions, which
-default to returning unit (`()`).
+This closure, `plus_num`, refers to a `let` binding in its scope: `num`. More
+specifically, it borrows the binding. If we do something that would conflict
+with that binding, we get an error. Like this one:
+
+```rust,ignore
+let mut num = 5;
+let plus_num = |x: i32| x + num;
 
-There's one big difference between a closure and named functions, and it's in
-the name: a closure "closes over its environment." What does that mean? It means
-this:
+let y = &mut num;
+```
 
-```{rust}
+Which errors with:
+
+```text
+error: cannot borrow `num` as mutable because it is also borrowed as immutable
+    let y = &mut num;
+                 ^~~
+note: previous borrow of `num` occurs here due to use in closure; the immutable
+  borrow prevents subsequent moves or mutable borrows of `num` until the borrow
+  ends
+    let plus_num = |x| x + num;
+                   ^~~~~~~~~~~
+note: previous borrow ends here
 fn main() {
-    let x: i32 = 5;
+    let mut num = 5;
+    let plus_num = |x| x + num;
+    
+    let y = &mut num;
+}
+^
+```
+
+A verbose yet helpful error message! As it says, we can't take a mutable borrow
+on `num` because the closure is already borrowing it. If we let the closure go
+out of scope, we can:
+
+```rust
+let mut num = 5;
+{
+    let plus_num = |x: i32| x + num;
+
+} // plus_num goes out of scope, borrow of num ends
 
-    let printer = || { println!("x is: {}", x); };
+let y = &mut num;
+```
+
+If your closure requires it, however, Rust will take ownership and move
+the environment instead:
+
+```rust,ignore
+let nums = vec![1, 2, 3];
+
+let takes_nums = || nums;
+
+println!("{:?}", nums);
+```
+
+This gives us:
+
+```text
+note: `nums` moved into closure environment here because it has type
+  `[closure(()) -> collections::vec::Vec<i32>]`, which is non-copyable
+let takes_nums = || nums;
+                    ^~~~~~~
+```
+
+`Vec<T>` has ownership over its contents, and therefore, when we refer to it
+in our closure, we have to take ownership of `nums`. It's the same as if we'd
+passed `nums` to a function that took ownership of it.
+
+## `move` closures
+
+We can force our closure to take ownership of its environment with the `move`
+keyword:
 
-    printer(); // prints "x is: 5"
+```rust
+let num = 5;
+
+let owns_num = move |x: i32| x + num;
+```
+
+Now, even though the keyword is `move`, the variables follow normal move semantics.
+In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
+of `num`. So what's the difference?
+
+```rust
+let mut num = 5;
+
+{ 
+    let mut add_num = |x: i32| num += x;
+
+    add_num(5);
 }
+
+assert_eq!(10, num);
 ```
 
-The `||` syntax means this is an anonymous closure that takes no arguments.
-Without it, we'd just have a block of code in `{}`s.
+So in this case, our closure took a mutable reference to `num`, and then when
+we called `add_num`, it mutated the underlying value, as we'd expect. We also
+needed to declare `add_num` as `mut` too, because we’re mutating its
+environment.
 
-In other words, a closure has access to variables in the scope where it's
-defined. The closure borrows any variables it uses, so this will error:
+We also had to declare `add_num` as mut, since we will be modifying its
+environment.
 
-```{rust,ignore}
-fn main() {
-    let mut x: i32 = 5;
+If we change to a `move` closure, it's different:
+
+```rust
+let mut num = 5;
 
-    let printer = || { println!("x is: {}", x); };
+{ 
+    let mut add_num = move |x: i32| num += x;
 
-    x = 6; // error: cannot assign to `x` because it is borrowed
+    add_num(5);
 }
+
+assert_eq!(5, num);
 ```
 
-## Moving closures
+We only get `5`. Rather than taking a mutable borrow out on our `num`, we took
+ownership of a copy.
+
+Another way to think about `move` closures: they give a closure its own stack
+frame.  Without `move`, a closure may be tied to the stack frame that created
+it, while a `move` closure is self-contained. This means that you cannot
+generally return a non-`move` closure from a function, for example.
+
+But before we talk about taking and returning closures, we should talk some more
+about the way that closures are implemented. As a systems language, Rust gives
+you tons of control over what your code does, and closures are no different.
 
-Rust has a second type of closure, called a *moving closure*. Moving
-closures are indicated using the `move` keyword (e.g., `move || x *
-x`). The difference between a moving closure and an ordinary closure
-is that a moving closure always takes ownership of all variables that
-it uses. Ordinary closures, in contrast, just create a reference into
-the enclosing stack frame. Moving closures are most useful with Rust's
-concurrency features, and so we'll just leave it at this for
-now. We'll talk about them more in the "Concurrency" chapter of the book.
+# Closure implementation
 
-## Accepting closures as arguments
+Rust's implementation of closures is a bit different than other languages. They
+are effectively syntax sugar for traits. You'll want to make sure to have read
+the [traits chapter][traits] before this one, as well as the chapter on [static
+and dynamic dispatch][dispatch], which talks about trait objects.
 
-Closures are most useful as an argument to another function. Here's an example:
+[traits]: traits.html
+[dispatch]: static-and-dynamic-dispatch.html
 
-```{rust}
-fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
-    f(x) + f(x)
+Got all that? Good.
+
+The key to understanding how closures work under the hood is something a bit
+strange: Using `()` to call a function, like `foo()`, is an overloadable
+operator. From this, everything else clicks into place. In Rust, we use the
+trait system to overload operators. Calling functions is no different. We have
+three separate traits to overload with:
+
+```rust
+# mod foo {
+pub trait Fn<Args> : FnMut<Args> {
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
-fn main() {
-    let square = |x: i32| { x * x };
+pub trait FnMut<Args> : FnOnce<Args> {
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
+pub trait FnOnce<Args> {
+    type Output;
 
-    twice(5, square); // evaluates to 50
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
+# }
 ```
 
-Let's break the example down, starting with `main`:
+You'll notice a few differences between these traits, but a big one is `self`:
+`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
+covers all three kinds of `self` via the usual method call syntax. But we've
+split them up into three traits, rather than having a single one. This gives us
+a large amount of control over what kind of closures we can take.
 
-```{rust}
-let square = |x: i32| { x * x };
-```
+The `|| {}` syntax for closures is sugar for these three traits. Rust will
+generate a struct for the environment, `impl` the appropriate trait, and then
+use it.
+
+# Taking closures as arguments
+
+Now that we know that closures are traits, we already know how to accept and
+return closures: just like any other trait!
+
+This also means that we can choose static vs dynamic dispatch as well. First,
+let's write a function which takes something callable, calls it, and returns
+the result:
+
+```rust
+fn call_with_one<F>(some_closure: F) -> i32
+    where F : Fn(i32) -> i32 {
+
+    some_closure(1)
+}
 
-We've seen this before. We make a closure that takes an integer, and returns
-its square.
+let answer = call_with_one(|x| x + 2);
 
-```{rust}
-# fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 { f(x) + f(x) }
-# let square = |x: i32| { x * x };
-twice(5, square); // evaluates to 50
+assert_eq!(3, answer);
 ```
 
-This line is more interesting. Here, we call our function, `twice`, and we pass
-it two arguments: an integer, `5`, and our closure, `square`. This is just like
-passing any other two variable bindings to a function, but if you've never
-worked with closures before, it can seem a little complex. Just think: "I'm
-passing two variables: one is an i32, and one is a function."
+We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
+suggests: it calls the closure, giving it `1` as an argument.
 
-Next, let's look at how `twice` is defined:
+Let's examine the signature of `call_with_one` in more depth:
 
-```{rust,ignore}
-fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
+```rust
+fn call_with_one<F>(some_closure: F) -> i32
+#    where F : Fn(i32) -> i32 {
+#    some_closure(1) }
 ```
 
-`twice` takes two arguments, `x` and `f`. That's why we called it with two
-arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
-though, and that function takes an `i32` and returns an `i32`. This is
-what the requirement `Fn(i32) -> i32` for the type parameter `F` says.
-Now `F` represents *any* function that takes an `i32` and returns an `i32`.
+We take one parameter, and it has the type `F`. We also return a `i32`. This part
+isn't interesting. The next part is:
 
-This is the most complicated function signature we've seen yet! Give it a read
-a few times until you can see how it works. It takes a teeny bit of practice, and
-then it's easy. The good news is that this kind of passing a closure around
-can be very efficient. With all the type information available at compile-time
-the compiler can do wonders.
+```rust
+# fn call_with_one<F>(some_closure: F) -> i32
+    where F : Fn(i32) -> i32 {
+#   some_closure(1) }
+```
+
+Because `Fn` is a trait, we can bound our generic with it. In this case, our closure
+takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
+is `Fn(i32) -> i32`.
 
-Finally, `twice` returns an `i32` as well.
+There's one other key point here: because we're bounding a generic with a
+trait, this will get monomorphized, and therefore, we'll be doing static
+dispatch into the closure. That's pretty neat. In many langauges, closures are
+inherently heap allocated, and will always involve dynamic dispatch. In Rust,
+we can stack allocate our closure environment, and statically dispatch the
+call. This happens quite often with iterators and their adapters, which often
+take closures as arguments.
 
-Okay, let's look at the body of `twice`:
+Of course, if we want dynamic dispatch, we can get that too. A trait object
+handles this case, as usual:
 
-```{rust}
-fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
-  f(x) + f(x)
+```rust
+fn call_with_one(some_closure: &Fn(i32) -> i32) -> i32 {
+    some_closure(1)
 }
+
+let answer = call_with_one(&|x| x + 2);
+
+assert_eq!(3, answer);
 ```
 
-Since our closure is named `f`, we can call it just like we called our closures
-before, and we pass in our `x` argument to each one, hence the name `twice`.
+Now we take a trait object, a `&Fn`. And we have to make a reference
+to our closure when we pass it to `call_with_one`, so we use `&||`.
 
-If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get.
+# Returning closures
 
-Play around with this concept until you're comfortable with it. Rust's standard
-library uses lots of closures where appropriate, so you'll be using
-this technique a lot.
+It’s very common for functional-style code to return closures in various
+situations. If you try to return a closure, you may run into an error. At
+first, it may seem strange, but we'll figure it out. Here's how you'd probably
+try to return a closure from a function:
 
-If we didn't want to give `square` a name, we could just define it inline.
-This example is the same as the previous one:
+```rust,ignore
+fn factory() -> (Fn(i32) -> Vec<i32>) {
+    let vec = vec![1, 2, 3];
 
-```{rust}
-fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
-    f(x) + f(x)
+    |n| vec.push(n)
 }
 
-fn main() {
-    twice(5, |x: i32| { x * x }); // evaluates to 50
-}
+let f = factory();
+
+let answer = f(4);
+assert_eq!(vec![1, 2, 3, 4], answer);
 ```
 
-A named function's name can be used wherever you'd use a closure. Another
-way of writing the previous example:
+This gives us these long, related errors:
+
+```text
+error: the trait `core::marker::Sized` is not implemented for the type
+`core::ops::Fn(i32) -> collections::vec::Vec<i32>` [E0277]
+f = factory();
+^
+note: `core::ops::Fn(i32) -> collections::vec::Vec<i32>` does not have a
+constant size known at compile-time
+f = factory();
+^
+error: the trait `core::marker::Sized` is not implemented for the type
+`core::ops::Fn(i32) -> collections::vec::Vec<i32>` [E0277]
+factory() -> (Fn(i32) -> Vec<i32>) {
+             ^~~~~~~~~~~~~~~~~~~~~
+note: `core::ops::Fn(i32) -> collections::vec::Vec<i32>` does not have a constant size known at compile-time
+fa ctory() -> (Fn(i32) -> Vec<i32>) {
+              ^~~~~~~~~~~~~~~~~~~~~
 
-```{rust}
-fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
-    f(x) + f(x)
-}
+```
 
-fn square(x: i32) -> i32 { x * x }
+In order to return something from a function, Rust needs to know what
+size the return type is. But since `Fn` is a trait, it could be various
+things of various sizes: many different types can implement `Fn`. An easy
+way to give something a size is to take a reference to it, as references
+have a known size. So we'd write this:
 
-fn main() {
-    twice(5, square); // evaluates to 50
+```rust,ignore
+fn factory() -> &(Fn(i32) -> Vec<i32>) {
+    let vec = vec![1, 2, 3];
+
+    |n| vec.push(n)
 }
+
+let f = factory();
+
+let answer = f(4);
+assert_eq!(vec![1, 2, 3, 4], answer);
+```
+
+But we get another error:
+
+```text
+error: missing lifetime specifier [E0106]
+fn factory() -> &(Fn(i32) -> i32) {
+                ^~~~~~~~~~~~~~~~~
 ```
 
-Doing this is not particularly common, but it's useful every once in a while.
+Right. Because we have a reference, we need to give it a lifetime. But
+our `factory()` function takes no arguments, so elision doesn't kick in
+here. What lifetime can we choose? `'static`:
 
-Before we move on, let us look at a function that accepts two closures.
+```rust,ignore
+fn factory() -> &'static (Fn(i32) -> i32) {
+    let num = 5;
 
-```{rust}
-fn compose<F, G>(x: i32, f: F, g: G) -> i32
-    where F: Fn(i32) -> i32, G: Fn(i32) -> i32 {
-    g(f(x))
+    |x| x + num
 }
 
-fn main() {
-    compose(5,
-            |n: i32| { n + 42 },
-            |n: i32| { n * 2 }); // evaluates to 94
+let f = factory();
+
+let answer = f(1);
+assert_eq!(6, answer);
+```
+
+But we get another error:
+
+```text
+error: mismatched types:
+ expected `&'static core::ops::Fn(i32) -> i32`,
+    found `[closure <anon>:7:9: 7:20]`
+(expected &-ptr,
+    found closure) [E0308]
+         |x| x + num
+         ^~~~~~~~~~~
+
+```
+
+This error is letting us know that we don't have a `&'static Fn(i32) -> i32`,
+we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
+
+Because each closure generates its own environment `struct` and implementation
+of `Fn` and friends, these types are anonymous. They exist just solely for
+this closure. So Rust shows them as `closure <anon>`, rather than some
+autogenerated name.
+
+But why doesn't our closure implement `&'static Fn`? Well, as we discussed before,
+closures borrow their environment. And in this case, our environment is based
+on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
+of the stack frame. So if we returned this closure, the function call would be
+over, the stack frame would go away, and our closure is capturing an environment
+of garbage memory!
+
+So what to do? This _almost_ works:
+
+```rust,ignore
+fn factory() -> Box<Fn(i32) -> i32> {
+    let num = 5;
+
+    Box::new(|x| x + num)
 }
+# fn main() {
+let f = factory();
+
+let answer = f(1);
+assert_eq!(6, answer);
+# }
 ```
 
-You might ask yourself: why do we need to introduce two type
-parameters `F` and `G` here?  Evidently, both `f` and `g` have the
-same signature: `Fn(i32) -> i32`.
+We use a trait object, by `Box`ing up the `Fn`. There's just one last problem:
 
-That is because in Rust each closure has its own unique type.
-So, not only do closures with different signatures have different types,
-but different closures with the *same* signature have *different*
-types, as well!
+```text
+error: `num` does not live long enough
+Box::new(|x| x + num)
+         ^~~~~~~~~~~
+```
+
+We still have a reference to the parent stack frame. With one last fix, we can
+make this work:
 
-You can think of it this way: the behavior of a closure is part of its
-type.  Therefore, using a single type parameter for both closures
-will accept the first of them, rejecting the second. The distinct
-type of the second closure does not allow it to be represented by the
-same type parameter as that of the first.  We acknowledge this, and
-use two different type parameters `F` and `G`.
+```rust
+fn factory() -> Box<Fn(i32) -> i32> {
+    let num = 5;
 
-This also introduces the `where` clause, which lets us describe type
-parameters in a more flexible manner.
+    Box::new(move |x| x + num)
+}
+# fn main() {
+let f = factory();
+
+let answer = f(1);
+assert_eq!(6, answer);
+# }
+```
 
-That's all you need to get the hang of closures! Closures are a little bit
-strange at first, but once you're used to them, you'll miss them
-in other languages. Passing functions to other functions is
-incredibly powerful, as you will see in the following chapter about iterators.
+By making the inner closure a `move Fn`, we create a new stack frame for our
+closure. By `Box`ing it up, we've given it a known size, and allowing it to
+escape our stack frame.
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 cf60bd88c542be85ff5f6c90d20c5cd599a9827d..b9e7bd78c5b2fa26dd200d632ce8875b1da846e4 100644 (file)
@@ -200,15 +200,15 @@ Because these kinds of situations are relatively rare, use panics sparingly.
 # Upgrading failures to panics
 
 In certain circumstances, even though a function may fail, we may want to treat
-it as a panic instead. For example, `io::stdin().read_line()` returns an
-`IoResult<String>`, a form of `Result`, when there is an error reading the
-line. This allows us to handle and possibly recover from this sort of error.
+it as a panic instead. For example, `io::stdin().read_line(&mut buffer)` returns
+an `Result<usize>`, when there is an error reading the line. This allows us to
+handle and possibly recover from error.
 
 If we don't want to handle this error, and would rather just abort the program,
 we can use the `unwrap()` method:
 
 ```{rust,ignore}
-io::stdin().read_line().unwrap();
+io::stdin().read_line(&mut buffer).unwrap();
 ```
 
 `unwrap()` will `panic!` if the `Option` is `None`. This basically says "Give
@@ -219,12 +219,13 @@ shorter. Sometimes, just crashing is appropriate.
 There's another way of doing this that's a bit nicer than `unwrap()`:
 
 ```{rust,ignore}
-let input = io::stdin().read_line()
+let mut buffer = String::new();
+let input = io::stdin().read_line(&mut buffer)
                        .ok()
                        .expect("Failed to read line");
 ```
 
-`ok()` converts the `IoResult` into an `Option`, and `expect()` does the same
+`ok()` converts the `Result` into an `Option`, and `expect()` does the same
 thing as `unwrap()`, but takes a message. This message is passed along to the
 underlying `panic!`, providing a better error message if the code errors.
 
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 107d7d979a09cc8c2db3457aabb28e458f04fc5c..1b3f2a5b7734cc2dcdc44fd10e678dea53f5817b 100644 (file)
@@ -574,7 +574,7 @@ fn main() {
 ```
 
 We can mutably borrow `x` multiple times, but only if x itself is mutable, and
-it may not be *simultaneously* borrowed: 
+it may not be *simultaneously* borrowed:
 
 ```{rust,ignore}
 fn increment(x: &mut i32) {
@@ -595,8 +595,7 @@ Notice the signature of `increment()` requests a mutable reference.
 
 ## Best practices
 
-Boxes are appropriate to use in two situations: Recursive data structures,
-and occasionally, when returning data.
+Boxes are most appropriate to use when defining recursive data structures.
 
 ### Recursive data structures
 
@@ -630,14 +629,6 @@ we don't know the size, and therefore, we need to heap allocate our list.
 Working with recursive or other unknown-sized data structures is the primary
 use-case for boxes.
 
-### Returning data
-
-This is important enough to have its own section entirely. The TL;DR is this:
-you don't want to return pointers, even when you might in a language like C or
-C++.
-
-See [Returning Pointers](#returning-pointers) below for more.
-
 # Rc and Arc
 
 This part is coming soon.
@@ -654,79 +645,6 @@ This part is coming soon.
 
 This part is coming soon.
 
-# Returning Pointers
-
-In many languages with pointers, you'd return a pointer from a function
-so as to avoid copying a large data structure. For example:
-
-```{rust}
-struct BigStruct {
-    one: i32,
-    two: i32,
-    // etc
-    one_hundred: i32,
-}
-
-fn foo(x: Box<BigStruct>) -> Box<BigStruct> {
-    Box::new(*x)
-}
-
-fn main() {
-    let x = Box::new(BigStruct {
-        one: 1,
-        two: 2,
-        one_hundred: 100,
-    });
-
-    let y = foo(x);
-}
-```
-
-The idea is that by passing around a box, you're only copying a pointer, rather
-than the hundred `int`s that make up the `BigStruct`.
-
-This is an antipattern in Rust. Instead, write this:
-
-```rust
-#![feature(box_syntax)]
-
-struct BigStruct {
-    one: i32,
-    two: i32,
-    // etc
-    one_hundred: i32,
-}
-
-fn foo(x: Box<BigStruct>) -> BigStruct {
-    *x
-}
-
-fn main() {
-    let x = Box::new(BigStruct {
-        one: 1,
-        two: 2,
-        one_hundred: 100,
-    });
-
-    let y: Box<BigStruct> = box foo(x);
-}
-```
-
-Note that this uses the `box_syntax` feature gate, so this syntax may change in
-the future.
-
-This gives you flexibility without sacrificing performance.
-
-You may think that this gives us terrible performance: return a value and then
-immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is
-smarter than that. There is no copy in this code. `main` allocates enough room
-for the `box`, passes a pointer to that memory into `foo` as `x`, and then
-`foo` writes the value straight into the `Box<T>`.
-
-This is important enough that it bears repeating: pointers are not for
-optimizing returning values from your code. Allow the caller to choose how they
-want to use your output.
-
 # Creating your own Pointers
 
 This part is coming soon.
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 47e64547eed3985bc34d1087df708f00a2ec0321..918c0c66f76df070b99848c2d53be8a5894ad6db 100755 (executable)
@@ -288,6 +288,7 @@ VAL_OPTIONS=""
 flag uninstall "only uninstall from the installation prefix"
 valopt prefix "" "set installation prefix"
 valopt date "" "use the YYYY-MM-DD nightly instead of the current nightly"
+valopt channel "beta" "use the selected release channel [beta]"
 flag save "save the downloaded nightlies to ~/.rustup"
 
 if [ $HELP -eq 1 ]
@@ -307,7 +308,7 @@ CFG_CPUTYPE=$(uname -m)
 
 if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
 then
-    # Darwin's `uname -s` lies and always returns i386. We have to use sysctl
+    # Darwin's `uname -m` lies and always returns i386. We have to use sysctl
     # instead.
     if sysctl hw.optional.x86_64 | grep -q ': 1'
     then
@@ -449,18 +450,28 @@ then
 fi
 
 RUST_URL="https://static.rust-lang.org/dist"
-RUST_PACKAGE_NAME=rust-nightly
+case "$CFG_CHANNEL" in
+    nightly)
+        # add a date suffix if we want a particular nightly.
+        if [ -n "${CFG_DATE}" ];
+        then
+            RUST_URL="${RUST_URL}/${CFG_DATE}"
+        fi
+
+        RUST_PACKAGE_NAME=rust-nightly
+        ;;
+    beta)
+        RUST_PACKAGE_NAME=rust-1.0.0-beta
+        ;;
+    *)
+        err "Currently 'beta' and 'nightly' are the only supported channels"
+esac
+
 RUST_PACKAGE_NAME_AND_TRIPLE="${RUST_PACKAGE_NAME}-${HOST_TRIPLE}"
 RUST_TARBALL_NAME="${RUST_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
 RUST_LOCAL_INSTALL_DIR="${CFG_TMP_DIR}/${RUST_PACKAGE_NAME_AND_TRIPLE}"
 RUST_LOCAL_INSTALL_SCRIPT="${RUST_LOCAL_INSTALL_DIR}/install.sh"
 
-# add a date suffix if we want a particular nighly.
-if [ -n "${CFG_DATE}" ];
-then
-    RUST_URL="${RUST_URL}/${CFG_DATE}"
-fi
-
 download_hash() {
     msg "Downloading ${remote_sha256}"
     remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"`
index 9b37ddc7ab53383136d86eee9ef4a44de7288917..8b884c56505b25ccec7d8ab4083d11adb8192eff 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,41 @@ 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)]
+/// extern crate alloc;
+/// # fn main() {
+/// use 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>`.
@@ -286,7 +321,7 @@ fn deref(&self) -> &T {
     }
 }
 
-impl<T: Send + Sync + Clone> Arc<T> {
+impl<T: Clone> Arc<T> {
     /// Make a mutable reference from the given `Arc<T>`.
     ///
     /// This is also referred to as a copy-on-write operation because the inner
@@ -312,11 +347,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
     }
@@ -433,7 +465,7 @@ fn inner(&self) -> &ArcInner<T> {
 
 #[unstable(feature = "alloc",
            reason = "Weak pointers may not belong in this module.")]
-impl<T: Sync + Send> Clone for Weak<T> {
+impl<T> Clone for Weak<T> {
     /// Makes a clone of the `Weak<T>`.
     ///
     /// This increases the weak reference count.
@@ -659,7 +691,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 +727,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..2801cf38cb75529d94912551a60a5eab51597235 100644 (file)
 use core::any::Any;
 use core::cmp::Ordering;
 use core::default::Default;
-use core::error::{Error, FromError};
 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::{Unique};
+use core::raw::{TraitObject};
 
 /// A value that represents the heap. This is the default place that the `box`
 /// keyword allocates into when no place is supplied.
@@ -84,6 +83,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 +233,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 +253,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 +275,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;
@@ -321,9 +300,74 @@ fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
 #[stable(feature = "rust1", since = "1.0.0")]
 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> {
-        Box::new(err)
+
+/// `FnBox` is a version of the `FnOnce` intended for use with boxed
+/// closure objects. The idea is that where one would normally store a
+/// `Box<FnOnce()>` in a data structure, you should use
+/// `Box<FnBox()>`. The two traits behave essentially the same, except
+/// that a `FnBox` closure can only be called if it is boxed. (Note
+/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
+/// closures become directly usable.)
+///
+/// ### Example
+///
+/// Here is a snippet of code which creates a hashmap full of boxed
+/// once closures and then removes them one by one, calling each
+/// closure as it is removed. Note that the type of the closures
+/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
+/// -> i32>`.
+///
+/// ```
+/// #![feature(core)]
+///
+/// use std::boxed::FnBox;
+/// use std::collections::HashMap;
+///
+/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
+///     let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
+///     map.insert(1, Box::new(|| 22));
+///     map.insert(2, Box::new(|| 44));
+///     map
+/// }
+///
+/// fn main() {
+///     let mut map = make_map();
+///     for i in &[1, 2] {
+///         let f = map.remove(&i).unwrap();
+///         assert_eq!(f(), i * 22);
+///     }
+/// }
+/// ```
+#[rustc_paren_sugar]
+#[unstable(feature = "core", reason = "Newly introduced")]
+pub trait FnBox<A> {
+    type Output;
+
+    fn call_box(self: Box<Self>, args: A) -> Self::Output;
+}
+
+impl<A,F> FnBox<A> for F
+    where F: FnOnce<A>
+{
+    type Output = F::Output;
+
+    fn call_box(self: Box<F>, args: A) -> F::Output {
+        self.call_once(args)
+    }
+}
+
+impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
+    type Output = R;
+
+    extern "rust-call" fn call_once(self, args: A) -> R {
+        self.call_box(args)
+    }
+}
+
+impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
+    type Output = R;
+
+    extern "rust-call" fn call_once(self, args: A) -> R {
+        self.call_box(args)
     }
 }
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 e4bc6a393c4918dc4110f4d619c76c8729061823..3804874a650f6c065e23c78043bbfc8b1c35a168 100644 (file)
@@ -30,7 +30,7 @@
 //! use std::collections::BinaryHeap;
 //! use std::usize;
 //!
-//! #[derive(Copy, Eq, PartialEq)]
+//! #[derive(Copy, Clone, Eq, PartialEq)]
 //! struct State {
 //!     cost: usize,
 //!     position: usize,
index 3ed8ca2bea98b1adb197c1654262df769ad138cb..d9255241af0e644415bb6fc04d25dc79f80d8756 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)
@@ -190,17 +190,17 @@ fn blocks_for_bits(bits: usize) -> usize {
     //
     // Note that we can technically avoid this branch with the expression
     // `(nbits + u32::BITS - 1) / 32::BITS`, but if nbits is almost usize::MAX this will overflow.
-    if bits % u32::BITS as usize == 0 {
-        bits / u32::BITS as usize
+    if bits % u32::BITS == 0 {
+        bits / u32::BITS
     } else {
-        bits / u32::BITS as usize + 1
+        bits / u32::BITS + 1
     }
 }
 
 /// Computes the bitmask for the final word of the vector
 fn mask_for_bits(bits: usize) -> u32 {
     // Note especially that a perfect multiple of u32::BITS should mask all 1s.
-    !0 >> (u32::BITS as usize - bits % u32::BITS as usize) % u32::BITS as usize
+    !0 >> (u32::BITS - bits % u32::BITS) % u32::BITS
 }
 
 impl BitVec {
@@ -238,7 +238,7 @@ fn blocks(&self) -> Blocks {
     /// An operation might screw up the unused bits in the last block of the
     /// `BitVec`. As per (3), it's assumed to be all 0s. This method fixes it up.
     fn fix_last_block(&mut self) {
-        let extra_bits = self.len() % u32::BITS as usize;
+        let extra_bits = self.len() % u32::BITS;
         if extra_bits > 0 {
             let mask = (1 << extra_bits) - 1;
             let storage_len = self.storage.len();
@@ -317,7 +317,7 @@ pub fn with_capacity(nbits: usize) -> BitVec {
     ///                     false, false, true, false]));
     /// ```
     pub fn from_bytes(bytes: &[u8]) -> BitVec {
-        let len = bytes.len().checked_mul(u8::BITS as usize).expect("capacity overflow");
+        let len = bytes.len().checked_mul(u8::BITS).expect("capacity overflow");
         let mut bit_vec = BitVec::with_capacity(len);
         let complete_words = bytes.len() / 4;
         let extra_bytes = bytes.len() % 4;
@@ -386,8 +386,8 @@ pub fn get(&self, i: usize) -> Option<bool> {
         if i >= self.nbits {
             return None;
         }
-        let w = i / u32::BITS as usize;
-        let b = i % u32::BITS as usize;
+        let w = i / u32::BITS;
+        let b = i % u32::BITS;
         self.storage.get(w).map(|&block|
             (block & (1 << b)) != 0
         )
@@ -414,8 +414,8 @@ pub fn get(&self, i: usize) -> Option<bool> {
                reason = "panic semantics are likely to change in the future")]
     pub fn set(&mut self, i: usize, x: bool) {
         assert!(i < self.nbits);
-        let w = i / u32::BITS as usize;
-        let b = i % u32::BITS as usize;
+        let w = i / u32::BITS;
+        let b = i % u32::BITS;
         let flag = 1 << b;
         let val = if x { self.storage[w] | flag }
                   else { self.storage[w] & !flag };
@@ -811,7 +811,7 @@ pub fn reserve_exact(&mut self, additional: usize) {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn capacity(&self) -> usize {
-        self.storage.capacity().checked_mul(u32::BITS as usize).unwrap_or(usize::MAX)
+        self.storage.capacity().checked_mul(u32::BITS).unwrap_or(usize::MAX)
     }
 
     /// Grows the `BitVec` in-place, adding `n` copies of `value` to the `BitVec`.
@@ -842,7 +842,7 @@ pub fn grow(&mut self, n: usize, value: bool) {
 
         // Correct the old tail word, setting or clearing formerly unused bits
         let num_cur_blocks = blocks_for_bits(self.nbits);
-        if self.nbits % u32::BITS as usize > 0 {
+        if self.nbits % u32::BITS > 0 {
             let mask = mask_for_bits(self.nbits);
             if value {
                 self.storage[num_cur_blocks - 1] |= !mask;
@@ -892,7 +892,7 @@ pub fn pop(&mut self) -> Option<bool> {
             // (3)
             self.set(i, false);
             self.nbits = i;
-            if self.nbits % u32::BITS as usize == 0 {
+            if self.nbits % u32::BITS == 0 {
                 // (2)
                 self.storage.pop();
             }
@@ -915,7 +915,7 @@ pub fn pop(&mut self) -> Option<bool> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, elem: bool) {
-        if self.nbits % u32::BITS as usize == 0 {
+        if self.nbits % u32::BITS == 0 {
             self.storage.push(0);
         }
         let insert_pos = self.nbits;
@@ -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.
     ///
@@ -1441,7 +1433,7 @@ pub fn shrink_to_fit(&mut self) {
         // Truncate
         let trunc_len = cmp::max(old_len - n, 1);
         bit_vec.storage.truncate(trunc_len);
-        bit_vec.nbits = trunc_len * u32::BITS as usize;
+        bit_vec.nbits = trunc_len * u32::BITS;
     }
 
     /// Iterator over each u32 stored in the `BitSet`.
@@ -1879,13 +1871,13 @@ impl<'a> Iterator for TwoBitPositions<'a> {
     fn next(&mut self) -> Option<usize> {
         while self.next_idx < self.set.bit_vec.len() ||
               self.next_idx < self.other.bit_vec.len() {
-            let bit_idx = self.next_idx % u32::BITS as usize;
+            let bit_idx = self.next_idx % u32::BITS;
             if bit_idx == 0 {
                 let s_bit_vec = &self.set.bit_vec;
                 let o_bit_vec = &self.other.bit_vec;
                 // Merging the two words is a bit of an awkward dance since
                 // one BitVec might be longer than the other
-                let word_idx = self.next_idx / u32::BITS as usize;
+                let word_idx = self.next_idx / u32::BITS;
                 let w1 = if word_idx < s_bit_vec.storage.len() {
                              s_bit_vec.storage[word_idx]
                          } else { 0 };
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 847ee7c19ce94d7b7f8329938a9267c7418a4b36..26c57256049cb87553ccb5a660893b81c6c8d4b1 100644 (file)
@@ -526,7 +526,7 @@ fn clone(&self) -> Node<K, V> {
 ///     println!("Uninitialized memory: {:?}", handle.into_kv());
 /// }
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Handle<NodeRef, Type, NodeType> {
     node: NodeRef,
     index: usize,
index 474b4de8123e1ce271c59e9a3166cf771b54081e..a3a266669b1bbb6787c97ebd505bcf8fe8a566a5 100644 (file)
@@ -21,7 +21,7 @@
 
 // FIXME(contentions): implement union family of methods? (general design may be wrong here)
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
 /// A specialized set implementation to use enum types.
 ///
 /// It is a logic error for an item to be modified in such a way that the transformation of the
@@ -37,6 +37,10 @@ pub struct EnumSet<E> {
 
 impl<E> Copy for EnumSet<E> {}
 
+impl<E> Clone for EnumSet<E> {
+    fn clone(&self) -> EnumSet<E> { *self }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<E:CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
@@ -82,7 +86,7 @@ pub trait CLike {
 fn bit<E:CLike>(e: &E) -> usize {
     use core::usize;
     let value = e.to_usize();
-    assert!(value < usize::BITS as usize,
+    assert!(value < usize::BITS,
             "EnumSet only supports up to {} variants.", usize::BITS - 1);
     1 << value
 }
index b106f4adbc708219524bf1a368cdac19211c7689..46b1ad2138bd8152a25c6f22cea5898c367abeed 100644 (file)
 //!         should always be printed.
 //! * '-' - Currently not used
 //! * '#' - This flag is indicates that the "alternate" form of printing should
-//!         be used. By default, this only applies to the integer formatting
-//!         traits and performs like:
-//!     * `x` - precedes the argument with a "0x"
-//!     * `X` - precedes the argument with a "0x"
-//!     * `t` - precedes the argument with a "0b"
-//!     * `o` - precedes the argument with a "0o"
+//!         be used.  For array slices, the alternate form omits the brackets.
+//!         For the integer formatting traits, the alternate forms are:
+//!     * `#x` - precedes the argument with a "0x"
+//!     * `#X` - precedes the argument with a "0x"
+//!     * `#t` - precedes the argument with a "0b"
+//!     * `#o` - precedes the argument with a "0o"
 //! * '0' - This is used to indicate for integer formats that the padding should
 //!         both be done with a `0` character as well as be sign-aware. A format
 //!         like `{:08}` would yield `00000001` for the integer `1`, while the
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..ff923fb19068fb0a8187ea5684d561fac6bfd182 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
@@ -358,9 +328,12 @@ pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool {
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to splitting at most `n` times.  The matched element is
+    /// `pred`, limited to returning at most `n` items.  The matched element is
     /// not contained in the subslices.
     ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
     /// # Examples
     ///
     /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
@@ -368,7 +341,7 @@ pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool {
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.splitn(1, |num| *num % 3 == 0) {
+    /// for group in v.splitn(2, |num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
     /// ```
@@ -379,10 +352,13 @@ pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) ->
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to splitting at most `n` times. This starts at the end of
+    /// `pred` limited to returning at most `n` items. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
     ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
     /// # Examples
     ///
     /// Print the slice split once, starting from the end, by numbers divisible
@@ -390,7 +366,7 @@ pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) ->
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.rsplitn(1, |num| *num % 3 == 0) {
+    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
     /// ```
@@ -557,7 +533,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 +586,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]
@@ -693,8 +632,11 @@ pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> where F: FnMut(&T) ->
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to splitting at most `n` times.  The matched element is
+    /// `pred`, limited to returning at most `n` items.  The matched element is
     /// not contained in the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
@@ -703,9 +645,12 @@ pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to splitting at most `n` times. This starts at the end of
+    /// `pred` limited to returning at most `n` items. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn rsplitn_mut<F>(&mut self,  n: usize, pred: F) -> RSplitNMut<T, F>
@@ -924,7 +869,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 +881,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
@@ -1198,7 +1135,7 @@ impl Iterator for ElementSwaps {
     // #[inline]
     fn next(&mut self) -> Option<(usize, usize)> {
         fn new_pos_wrapping(i: usize, s: Direction) -> usize {
-            i.wrapping_add(match s { Pos => 1, Neg => -1 })
+            i.wrapping_add(match s { Pos => 1, Neg => !0 /* aka -1 */ })
         }
 
         fn new_pos(i: usize, s: Direction) -> usize {
index 9ddf8988f1ee7ee643e03b65dcde77b9effa0f53..c22b6fb9286d192382c9dd8c7ec1f112677aaa6b 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
@@ -627,24 +610,27 @@ pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
         core_str::StrExt::split(&self[..], pat)
     }
 
-    /// An iterator over substrings of `self`, separated by characters matched by a pattern,
-    /// restricted to splitting at most `count` times.
+    /// An iterator over substrings of `self`, separated by characters matched
+    /// by a pattern, returning most `count` items.
     ///
     /// The pattern can be a simple `&str`, or a closure that determines
     /// the split.
     ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// string.
+    ///
     /// # Examples
     ///
     /// Simple `&str` patterns:
     ///
     /// ```
     /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
+    /// assert_eq!(v, ["Mary", "had a little lambda"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
-    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
+    /// assert_eq!(v, ["lion", "XtigerXleopard"]);
     ///
-    /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
+    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
     /// assert_eq!(v, ["abcXdef"]);
     ///
     /// let v: Vec<&str> = "".splitn(1, 'X').collect();
@@ -654,7 +640,7 @@ pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
     /// More complex patterns with a lambda:
     ///
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect();
+    /// let v: Vec<&str> = "abc1def2ghi".splitn(2, |c: char| c.is_numeric()).collect();
     /// assert_eq!(v, ["abc", "def2ghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -722,25 +708,28 @@ pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
     }
 
     /// An iterator over substrings of `self`, separated by a pattern,
-    /// starting from the end of the string, restricted to splitting
-    /// at most `count` times.
+    /// starting from the end of the string, restricted to returning
+    /// at most `count` items.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// string.
     ///
     /// # Examples
     ///
     /// Simple patterns:
     ///
     /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
     /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
     ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(1, "::").collect();
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
     /// assert_eq!(v, ["leopard", "lion::tiger"]);
     /// ```
     ///
     /// More complex patterns with a lambda:
     ///
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect();
+    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(2, |c: char| c.is_numeric()).collect();
     /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -778,25 +767,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 +818,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 +1251,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 +1394,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 +1417,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..7a7725320914f6fdba19cb1443d0d1e9c2da753b 100644 (file)
@@ -17,7 +17,6 @@
 use core::prelude::*;
 
 use core::default::Default;
-use core::error::Error;
 use core::fmt;
 use core::hash;
 use core::iter::{IntoIterator, FromIterator};
@@ -93,7 +92,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 +363,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
@@ -715,11 +722,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for FromUtf8Error {
-    fn description(&self) -> &str { "invalid utf-8" }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for FromUtf16Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -727,11 +729,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for FromUtf16Error {
-    fn description(&self) -> &str { "invalid utf-16" }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl FromIterator<char> for String {
     fn from_iter<I: IntoIterator<Item=char>>(iter: I) -> String {
@@ -848,7 +845,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 +1068,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..10c688c3b66338ceedcc2b76b27d1bee05967575 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);
@@ -408,7 +407,7 @@ fn bench_bit_vecset_small(b: &mut Bencher) {
         let mut bit_vec = BitSet::new();
         b.iter(|| {
             for _ in 0..100 {
-                bit_vec.insert((r.next_u32() as usize) % u32::BITS as usize);
+                bit_vec.insert((r.next_u32() as usize) % u32::BITS);
             }
             black_box(&bit_vec);
         });
index 3826974d1ad6b13ff374e8694fa86ea2255277ff..de3c0586ab728f3ccd8e8215e06633f78683c663 100644 (file)
@@ -541,43 +541,43 @@ fn test_big_bit_vec_tests() {
 
 #[test]
 fn test_bit_vec_push_pop() {
-    let mut s = BitVec::from_elem(5 * u32::BITS as usize - 2, false);
-    assert_eq!(s.len(), 5 * u32::BITS as usize - 2);
-    assert_eq!(s[5 * u32::BITS as usize - 3], false);
+    let mut s = BitVec::from_elem(5 * u32::BITS - 2, false);
+    assert_eq!(s.len(), 5 * u32::BITS - 2);
+    assert_eq!(s[5 * u32::BITS - 3], false);
     s.push(true);
     s.push(true);
-    assert_eq!(s[5 * u32::BITS as usize - 2], true);
-    assert_eq!(s[5 * u32::BITS as usize - 1], true);
+    assert_eq!(s[5 * u32::BITS - 2], true);
+    assert_eq!(s[5 * u32::BITS - 1], true);
     // Here the internal vector will need to be extended
     s.push(false);
-    assert_eq!(s[5 * u32::BITS as usize], false);
+    assert_eq!(s[5 * u32::BITS], false);
     s.push(false);
-    assert_eq!(s[5 * u32::BITS as usize + 1], false);
-    assert_eq!(s.len(), 5 * u32::BITS as usize + 2);
+    assert_eq!(s[5 * u32::BITS + 1], false);
+    assert_eq!(s.len(), 5 * u32::BITS + 2);
     // Pop it all off
     assert_eq!(s.pop(), Some(false));
     assert_eq!(s.pop(), Some(false));
     assert_eq!(s.pop(), Some(true));
     assert_eq!(s.pop(), Some(true));
-    assert_eq!(s.len(), 5 * u32::BITS as usize - 2);
+    assert_eq!(s.len(), 5 * u32::BITS - 2);
 }
 
 #[test]
 fn test_bit_vec_truncate() {
-    let mut s = BitVec::from_elem(5 * u32::BITS as usize, true);
+    let mut s = BitVec::from_elem(5 * u32::BITS, true);
 
-    assert_eq!(s, BitVec::from_elem(5 * u32::BITS as usize, true));
-    assert_eq!(s.len(), 5 * u32::BITS as usize);
-    s.truncate(4 * u32::BITS as usize);
-    assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true));
-    assert_eq!(s.len(), 4 * u32::BITS as usize);
+    assert_eq!(s, BitVec::from_elem(5 * u32::BITS, true));
+    assert_eq!(s.len(), 5 * u32::BITS);
+    s.truncate(4 * u32::BITS);
+    assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true));
+    assert_eq!(s.len(), 4 * u32::BITS);
     // Truncating to a size > s.len() should be a noop
-    s.truncate(5 * u32::BITS as usize);
-    assert_eq!(s, BitVec::from_elem(4 * u32::BITS as usize, true));
-    assert_eq!(s.len(), 4 * u32::BITS as usize);
-    s.truncate(3 * u32::BITS as usize - 10);
-    assert_eq!(s, BitVec::from_elem(3 * u32::BITS as usize - 10, true));
-    assert_eq!(s.len(), 3 * u32::BITS as usize - 10);
+    s.truncate(5 * u32::BITS);
+    assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true));
+    assert_eq!(s.len(), 4 * u32::BITS);
+    s.truncate(3 * u32::BITS - 10);
+    assert_eq!(s, BitVec::from_elem(3 * u32::BITS - 10, true));
+    assert_eq!(s.len(), 3 * u32::BITS - 10);
     s.truncate(0);
     assert_eq!(s, BitVec::from_elem(0, true));
     assert_eq!(s.len(), 0);
@@ -585,26 +585,26 @@ fn test_bit_vec_truncate() {
 
 #[test]
 fn test_bit_vec_reserve() {
-    let mut s = BitVec::from_elem(5 * u32::BITS as usize, true);
+    let mut s = BitVec::from_elem(5 * u32::BITS, true);
     // Check capacity
-    assert!(s.capacity() >= 5 * u32::BITS as usize);
-    s.reserve(2 * u32::BITS as usize);
-    assert!(s.capacity() >= 7 * u32::BITS as usize);
-    s.reserve(7 * u32::BITS as usize);
-    assert!(s.capacity() >= 12 * u32::BITS as usize);
-    s.reserve_exact(7 * u32::BITS as usize);
-    assert!(s.capacity() >= 12 * u32::BITS as usize);
-    s.reserve(7 * u32::BITS as usize + 1);
-    assert!(s.capacity() >= 12 * u32::BITS as usize + 1);
+    assert!(s.capacity() >= 5 * u32::BITS);
+    s.reserve(2 * u32::BITS);
+    assert!(s.capacity() >= 7 * u32::BITS);
+    s.reserve(7 * u32::BITS);
+    assert!(s.capacity() >= 12 * u32::BITS);
+    s.reserve_exact(7 * u32::BITS);
+    assert!(s.capacity() >= 12 * u32::BITS);
+    s.reserve(7 * u32::BITS + 1);
+    assert!(s.capacity() >= 12 * u32::BITS + 1);
     // Check that length hasn't changed
-    assert_eq!(s.len(), 5 * u32::BITS as usize);
+    assert_eq!(s.len(), 5 * u32::BITS);
     s.push(true);
     s.push(false);
     s.push(true);
-    assert_eq!(s[5 * u32::BITS as usize - 1], true);
-    assert_eq!(s[5 * u32::BITS as usize - 0], true);
-    assert_eq!(s[5 * u32::BITS as usize + 1], false);
-    assert_eq!(s[5 * u32::BITS as usize + 2], true);
+    assert_eq!(s[5 * u32::BITS - 1], true);
+    assert_eq!(s[5 * u32::BITS - 0], true);
+    assert_eq!(s[5 * u32::BITS + 1], false);
+    assert_eq!(s[5 * u32::BITS + 2], true);
 }
 
 #[test]
@@ -650,7 +650,7 @@ fn bench_usize_small(b: &mut Bencher) {
         let mut bit_vec = 0 as usize;
         b.iter(|| {
             for _ in 0..100 {
-                bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS as usize);
+                bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS);
             }
             black_box(&bit_vec);
         });
@@ -683,10 +683,10 @@ fn bench_bit_set_big_variable(b: &mut Bencher) {
     #[bench]
     fn bench_bit_set_small(b: &mut Bencher) {
         let mut r = rng();
-        let mut bit_vec = BitVec::from_elem(u32::BITS as usize, false);
+        let mut bit_vec = BitVec::from_elem(u32::BITS, false);
         b.iter(|| {
             for _ in 0..100 {
-                bit_vec.set((r.next_u32() as usize) % u32::BITS as usize, true);
+                bit_vec.set((r.next_u32() as usize) % u32::BITS, true);
             }
             black_box(&bit_vec);
         });
@@ -703,7 +703,7 @@ fn bench_bit_vec_big_union(b: &mut Bencher) {
 
     #[bench]
     fn bench_bit_vec_small_iter(b: &mut Bencher) {
-        let bit_vec = BitVec::from_elem(u32::BITS as usize, false);
+        let bit_vec = BitVec::from_elem(u32::BITS, false);
         b.iter(|| {
             let mut sum = 0;
             for _ in 0..10 {
index f04367147cb9d03377fc70bc45c84a0b95c3e2f8..0a1eb0bcfa8879cb801191d5e6532f65fda60f40 100644 (file)
@@ -14,7 +14,7 @@
 
 use self::Foo::*;
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 #[repr(usize)]
 enum Foo {
     A, B, C
@@ -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,42 +183,42 @@ 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]
 #[should_panic]
 fn test_overflow() {
     #[allow(dead_code)]
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     #[repr(usize)]
     enum Bar {
         V00, V01, V02, V03, V04, V05, V06, V07, V08, V09,
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..5b0aceb76d19cc4d54d8aa7d46fa00477634b58c 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);
@@ -867,18 +867,18 @@ fn test_splitnator() {
     let xs = &[1,2,3,4,5];
 
     let splits: &[&[_]] = &[&[1,2,3,4,5]];
-    assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[1], &[3,4,5]];
-    assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[], &[], &[], &[4,5]];
-    assert_eq!(xs.splitn(3, |_| true).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn(4, |_| true).collect::<Vec<_>>(),
                splits);
 
     let xs: &[i32] = &[];
     let splits: &[&[i32]] = &[&[]];
-    assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<_>>(), splits);
+    assert_eq!(xs.splitn(2, |x| *x == 5).collect::<Vec<_>>(), splits);
 }
 
 #[test]
@@ -886,18 +886,18 @@ fn test_splitnator_mut() {
     let xs = &mut [1,2,3,4,5];
 
     let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]];
-    assert_eq!(xs.splitn_mut(0, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]];
-    assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]];
-    assert_eq!(xs.splitn_mut(3, |_| true).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(4, |_| true).collect::<Vec<_>>(),
                splits);
 
     let xs: &mut [i32] = &mut [];
     let splits: &[&mut[i32]] = &[&mut []];
-    assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::<Vec<_>>(),
                splits);
 }
 
@@ -928,18 +928,19 @@ fn test_rsplitnator() {
     let xs = &[1,2,3,4,5];
 
     let splits: &[&[_]] = &[&[1,2,3,4,5]];
-    assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[5], &[1,2,3]];
-    assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[], &[], &[], &[1,2]];
-    assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<_>>(),
+    assert_eq!(xs.rsplitn(4, |_| true).collect::<Vec<_>>(),
                splits);
 
     let xs: &[i32]  = &[];
     let splits: &[&[i32]] = &[&[]];
-    assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+    assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+    assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none());
 }
 
 #[test]
@@ -1088,7 +1089,7 @@ fn test_bytes_set_memory() {
 #[should_panic]
 fn test_overflow_does_not_cause_segfault() {
     let mut v = vec![];
-    v.reserve_exact(-1);
+    v.reserve_exact(!0);
     v.push(1);
     v.push(2);
 }
@@ -1097,7 +1098,7 @@ fn test_overflow_does_not_cause_segfault() {
 #[should_panic]
 fn test_overflow_does_not_cause_segfault_managed() {
     let mut v = vec![Rc::new(1)];
-    v.reserve_exact(-1);
+    v.reserve_exact(!0);
     v.push(Rc::new(2));
 }
 
index 5cfa800905415dd855554be725c97731ac513448..495a961fa360e2564bb72cbf7a8d91e717c4f20e 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]
@@ -885,17 +885,17 @@ fn test_char_indices_revator() {
 fn test_splitn_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
-    let split: Vec<&str> = data.splitn(3, ' ').collect();
+    let split: Vec<&str> = data.splitn(4, ' ').collect();
     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
-    let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect();
+    let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
     // Unicode
-    let split: Vec<&str> = data.splitn(3, 'ä').collect();
+    let split: Vec<&str> = data.splitn(4, 'ä').collect();
     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
 
-    let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect();
+    let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
 }
 
@@ -928,13 +928,13 @@ fn test_rsplit() {
 fn test_rsplitn() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
-    let split: Vec<&str> = data.rsplitn(1, ' ').collect();
+    let split: Vec<&str> = data.rsplitn(2, ' ').collect();
     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
 
-    let split: Vec<&str> = data.rsplitn(1, "lämb").collect();
+    let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
 
-    let split: Vec<&str> = data.rsplitn(1, |c: char| c == 'ä').collect();
+    let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
 }
 
@@ -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..ed35e095492178479acf620e9acc579018dbb0a8 100644 (file)
@@ -122,7 +122,7 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 /// Rust's memory orderings are [the same as
 /// C++'s](http://gcc.gnu.org/wiki/Atomic/GCCMM/AtomicSync).
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Ordering {
     /// No ordering constraints, only atomic operations.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -161,7 +161,7 @@ pub enum Ordering {
         AtomicUsize { v: UnsafeCell { value: 0, } };
 
 // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
-const UINT_TRUE: usize = -1;
+const UINT_TRUE: usize = !0;
 
 impl AtomicBool {
     /// Creates a new `AtomicBool`.
@@ -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..76e09eedbdfa574a86f447041d47fed9099613d8 100644 (file)
@@ -287,7 +287,7 @@ pub enum BorrowState {
 // (will not outgrow its range since `usize` is the size of the address space)
 type BorrowFlag = usize;
 const UNUSED: BorrowFlag = 0;
-const WRITING: BorrowFlag = -1;
+const WRITING: BorrowFlag = !0;
 
 impl<T> RefCell<T> {
     /// Creates a new `RefCell` containing `value`.
@@ -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
diff --git a/src/libcore/error.rs b/src/libcore/error.rs
deleted file mode 100644 (file)
index 9430aa0..0000000
+++ /dev/null
@@ -1,115 +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.
-
-//! Traits for working with Errors.
-//!
-//! # The `Error` trait
-//!
-//! `Error` is a trait representing the basic expectations for error values,
-//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
-//! a description, but they may optionally provide additional detail (via
-//! `Display`) and cause chain information:
-//!
-//! ```
-//! use std::fmt::Display;
-//!
-//! trait Error: Display {
-//!     fn description(&self) -> &str;
-//!
-//!     fn cause(&self) -> Option<&Error> { None }
-//! }
-//! ```
-//!
-//! The `cause` method is generally used when errors cross "abstraction
-//! boundaries", i.e.  when a one module must report an error that is "caused"
-//! by an error from a lower-level module. This setup makes it possible for the
-//! 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")]
-
-use prelude::*;
-use fmt::{Debug, Display};
-
-/// Base functionality for all errors in Rust.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait Error: Debug + Display {
-    /// A short description of the error.
-    ///
-    /// The description should not contain newlines or sentence-ending
-    /// punctuation, to facilitate embedding in larger user-facing
-    /// strings.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn description(&self) -> &str;
-
-    /// The lower-level cause of this error, if any.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn cause(&self) -> Option<&Error> { None }
-}
-
-/// 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..be804327663e5b058196fd268b5d20d72f5f22eb 100644 (file)
@@ -12,9 +12,9 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-use any;
 use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
 use char::CharExt;
+use clone::Clone;
 use iter::Iterator;
 use marker::{Copy, PhantomData, Sized};
 use mem;
@@ -54,7 +54,7 @@ pub mod rt {
 /// occurred. Any extra information must be arranged to be transmitted through
 /// some other means.
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct Error;
 
 /// A collection of methods that are required to format a message into a stream.
@@ -141,6 +141,12 @@ pub struct ArgumentV1<'a> {
     formatter: fn(&Void, &mut Formatter) -> Result,
 }
 
+impl<'a> Clone for ArgumentV1<'a> {
+    fn clone(&self) -> ArgumentV1<'a> {
+        *self
+    }
+}
+
 impl<'a> ArgumentV1<'a> {
     #[inline(never)]
     fn show_usize(x: &usize, f: &mut Formatter) -> Result {
@@ -175,7 +181,7 @@ fn as_usize(&self) -> Option<usize> {
 }
 
 // flags available in the v1 format of format_args
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[allow(dead_code)] // SignMinus isn't currently used
 enum FlagV1 { SignPlus, SignMinus, Alternate, SignAwareZeroPad, }
 
@@ -222,7 +228,7 @@ pub fn new_v1_formatted(pieces: &'a [&'a str],
 /// macro validates the format string at compile-time so usage of the `write`
 /// and `format` functions can be safely performed.
 #[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Arguments<'a> {
     // Format string pieces to print.
     pieces: &'a [&'a str],
@@ -997,11 +1003,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 f3f5a0b70cb742117bd9cb3db937d653e16b5aba..76c975902aabb0df47a9b16b0611517b3e6b9b78 100644 (file)
@@ -139,7 +139,7 @@ fn digit(&self, x: u8) -> u8 {
 /// A helper type for formatting radixes.
 #[unstable(feature = "core",
            reason = "may be renamed or move to a different module")]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct RadixFmt<T, R>(T, R);
 
 /// Constructs a radix formatter in the range of `2..36`.
index 7f6dea905dafd45ec351f20d8e1a21de91356e29..d56ec6a74d4494b59c7d0fe758784d3f621379f0 100644 (file)
@@ -16,7 +16,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Argument {
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -25,7 +25,7 @@ pub struct Argument {
     pub format: FormatSpec,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct FormatSpec {
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -41,7 +41,7 @@ pub struct FormatSpec {
 }
 
 /// Possible alignments that can be requested as part of a formatting directive.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Alignment {
     /// Indication that contents should be left-aligned.
@@ -58,7 +58,7 @@ pub enum Alignment {
     Unknown,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Count {
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -71,7 +71,7 @@ pub enum Count {
     Implied,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Position {
     #[stable(feature = "rust1", since = "1.0.0")]
index 2375ae896500586799867ef4cd6ab5d23d76380a..553e0c0dfe6e45c3cf792d70cd0768a80c0a8990 100644 (file)
@@ -194,7 +194,7 @@ fn hash<H: Hasher>(&self, state: &mut H) {
                 fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
                     // FIXME(#23542) Replace with type ascription.
                     #![allow(trivial_casts)]
-                    let newlen = data.len() * ::$ty::BYTES as usize;
+                    let newlen = data.len() * ::$ty::BYTES;
                     let ptr = data.as_ptr() as *const u8;
                     state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
                 }
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..2189e2c3ad1baca6a42e615d71f4b3c26190f865 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;
 pub mod str;
 pub mod hash;
 pub mod fmt;
-pub mod error;
 
 #[doc(primitive = "bool")]
 mod bool {
index e867ed3efd908730d9a1da3a9c6c8701032148dc..c21898d088d669b82feb17075483a7078bd7d73e 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..619f983aee07173f3e1deadd9e1abbadc33d105c 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.
 }
@@ -75,7 +76,7 @@ pub trait Sized : MarkerTrait {
 ///
 /// ```
 /// // we can just derive a `Copy` implementation
-/// #[derive(Debug, Copy)]
+/// #[derive(Debug, Copy, Clone)]
 /// struct Foo;
 ///
 /// let x = Foo;
@@ -124,7 +125,7 @@ pub trait Sized : MarkerTrait {
 /// There are two ways to implement `Copy` on your type:
 ///
 /// ```
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct MyStruct;
 /// ```
 ///
@@ -133,6 +134,7 @@ pub trait Sized : MarkerTrait {
 /// ```
 /// struct MyStruct;
 /// impl Copy for MyStruct {}
+/// impl Clone for MyStruct { fn clone(&self) -> MyStruct { *self } }
 /// ```
 ///
 /// There is a small difference between the two: the `derive` strategy will also place a `Copy`
@@ -154,7 +156,7 @@ pub trait Sized : MarkerTrait {
 /// change: that second example would fail to compile if we made `Foo` non-`Copy`.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang="copy"]
-pub trait Copy : MarkerTrait {
+pub trait Copy : Clone {
     // Empty.
 }
 
@@ -346,17 +348,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 +398,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 +411,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 +447,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 fe0d6d13c4c06483649bdbf737fe89c68048cf43..3113521e0afff825ed7352ba894b73928686f8a3 100644 (file)
@@ -15,11 +15,11 @@ macro_rules! int_module { ($T:ty, $bits:expr) => (
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
 #[unstable(feature = "core")]
-pub const BITS : u32 = $bits;
+pub const BITS : usize = $bits;
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `mem::size_of` function.
 #[unstable(feature = "core")]
-pub const BYTES : u32 = ($bits / 8);
+pub const BYTES : usize = ($bits / 8);
 
 // FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
 // calling the `Bounded::min_value` function.
index 64f8e7055a57ae57b0ab0cbe93812b6fcf1859e4..28e0bcf13dd0911132938784bd5096d264a55a71 100644 (file)
@@ -20,7 +20,6 @@
 use char::CharExt;
 use clone::Clone;
 use cmp::{PartialEq, Eq, PartialOrd, Ord};
-use error::Error;
 use fmt;
 use intrinsics;
 use iter::Iterator;
@@ -46,7 +45,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;
@@ -517,7 +516,7 @@ fn one() -> $T { 1 }
             fn min_value() -> $T { 0 }
 
             #[inline]
-            fn max_value() -> $T { -1 }
+            fn max_value() -> $T { !0 }
 
             #[inline]
             fn count_ones(self) -> u32 {
@@ -820,6 +819,18 @@ macro_rules! int_impl {
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
+        /// Returns the smallest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn min_value() -> $T {
+            (-1 as $T) << ($BITS - 1)
+        }
+
+        /// Returns the largest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn max_value() -> $T {
+            let min: $T = Int::min_value(); !min
+        }
+
         /// Convert a string slice in a given base to an integer.
         ///
         /// Leading and trailing whitespace represent an error.
@@ -1330,6 +1341,14 @@ macro_rules! uint_impl {
      $add_with_overflow:path,
      $sub_with_overflow:path,
      $mul_with_overflow:path) => {
+        /// Returns the smallest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn min_value() -> $T { 0 }
+
+        /// Returns the largest value that can be represented by this integer type.
+        #[stable(feature = "rust1", since = "1.0.0")]
+        pub fn max_value() -> $T { !0 }
+
         /// Convert a string slice in a given base to an integer.
         ///
         /// Leading and trailing whitespace represent an error.
@@ -2425,7 +2444,7 @@ fn from<N: ToPrimitive>(n: N) -> Option<$T> {
 impl_num_cast! { f64,   to_f64 }
 
 /// Used for representing the classification of floating point numbers
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum FpCategory {
     /// "Not a Number", often obtained by dividing by zero
@@ -2948,16 +2967,9 @@ enum IntErrorKind {
     Underflow,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for ParseIntError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.description().fmt(f)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseIntError {
-    fn description(&self) -> &str {
+impl ParseIntError {
+    #[unstable(feature = "core", reason = "available through Error trait")]
+    pub fn description(&self) -> &str {
         match self.kind {
             IntErrorKind::Empty => "cannot parse integer from empty string",
             IntErrorKind::InvalidDigit => "invalid digit found in string",
@@ -2967,6 +2979,13 @@ fn description(&self) -> &str {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for ParseIntError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.description().fmt(f)
+    }
+}
+
 /// An error which can be returned when parsing a float.
 #[derive(Debug, Clone, PartialEq)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2978,19 +2997,19 @@ enum FloatErrorKind {
     Invalid,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Display for ParseFloatError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.description().fmt(f)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseFloatError {
-    fn description(&self) -> &str {
+impl ParseFloatError {
+    #[unstable(feature = "core", reason = "available through Error trait")]
+    pub fn description(&self) -> &str {
         match self.kind {
             FloatErrorKind::Empty => "cannot parse float from empty string",
             FloatErrorKind::Invalid => "invalid float literal",
         }
     }
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for ParseFloatError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.description().fmt(f)
+    }
+}
index d0c4885ad00b77ebbfaef418cb230976e6955f21..867829507455035e7eabbf74fd394efca5102cb4 100644 (file)
@@ -13,9 +13,9 @@
 macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
 
 #[unstable(feature = "core")]
-pub const BITS : u32 = $bits;
+pub const BITS : usize = $bits;
 #[unstable(feature = "core")]
-pub const BYTES : u32 = ($bits / 8);
+pub const BYTES : usize = ($bits / 8);
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MIN: $T = 0 as $T;
index bda05a3d9e885aff66f7929816cbe13a360ac0d3..28276d0bf0168b35677c43ea4b50f4d2d322f23b 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};
+
 #[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,7 +192,21 @@ fn bitand(self, other: Wrapping<$t>) -> Wrapping<$t> {
 
 wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
 
-macro_rules! overflowing_impl {
+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! signed_overflowing_impl {
     ($($t:ident)*) => ($(
         impl OverflowingOps for $t {
             #[inline(always)]
@@ -205,11 +227,85 @@ 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))
+            }
         }
     )*)
 }
 
-overflowing_impl! { u8 u16 u32 u64 i8 i16 i32 i64 }
+macro_rules! unsigned_overflowing_impl {
+    ($($t:ident)*) => ($(
+        impl OverflowingOps for $t {
+            #[inline(always)]
+            fn overflowing_add(self, rhs: $t) -> ($t, bool) {
+                unsafe {
+                    concat_idents!($t, _add_with_overflow)(self, rhs)
+                }
+            }
+            #[inline(always)]
+            fn overflowing_sub(self, rhs: $t) -> ($t, bool) {
+                unsafe {
+                    concat_idents!($t, _sub_with_overflow)(self, rhs)
+                }
+            }
+            #[inline(always)]
+            fn overflowing_mul(self, rhs: $t) -> ($t, bool) {
+                unsafe {
+                    concat_idents!($t, _mul_with_overflow)(self, rhs)
+                }
+            }
+
+            #[inline(always)]
+            fn overflowing_div(self, rhs: $t) -> ($t, bool) {
+                (self/rhs, false)
+            }
+            #[inline(always)]
+            fn overflowing_rem(self, rhs: $t) -> ($t, bool) {
+                (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))
+            }
+        }
+    )*)
+}
+
+signed_overflowing_impl! { i8 i16 i32 i64 }
+unsigned_overflowing_impl! { u8 u16 u32 u64 }
 
 #[cfg(target_pointer_width = "64")]
 impl OverflowingOps for usize {
@@ -234,6 +330,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 +375,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 +420,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 +465,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..faf305c6a13783e6965aaf061d5f46ffb8030790 100644 (file)
@@ -165,7 +165,7 @@ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
 /// ```
 /// use std::ops::Add;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Add for Foo {
@@ -219,7 +219,7 @@ fn add(self, other: $t) -> $t { self + other }
 /// ```
 /// use std::ops::Sub;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Sub for Foo {
@@ -273,7 +273,7 @@ fn sub(self, other: $t) -> $t { self - other }
 /// ```
 /// use std::ops::Mul;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Mul for Foo {
@@ -327,7 +327,7 @@ fn mul(self, other: $t) -> $t { self * other }
 /// ```
 /// use std::ops::Div;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Div for Foo {
@@ -381,7 +381,7 @@ fn div(self, other: $t) -> $t { self / other }
 /// ```
 /// use std::ops::Rem;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Rem for Foo {
@@ -454,7 +454,7 @@ fn rem(self, other: $t) -> $t {
 /// ```
 /// use std::ops::Neg;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Neg for Foo {
@@ -482,8 +482,10 @@ pub trait Neg {
     fn neg(self) -> Self::Output;
 }
 
-macro_rules! neg_impl {
-    ($($t:ty)*) => ($(
+
+
+macro_rules! neg_impl_core {
+    ($id:ident => $body:expr, $($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
         #[allow(unsigned_negation)]
         impl Neg for $t {
@@ -492,14 +494,28 @@ impl Neg for $t {
 
             #[inline]
             #[stable(feature = "rust1", since = "1.0.0")]
-            fn neg(self) -> $t { -self }
+            fn neg(self) -> $t { let $id = self; $body }
         }
 
         forward_ref_unop! { impl Neg, neg for $t }
     )*)
 }
 
-neg_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+macro_rules! neg_impl_numeric {
+    ($($t:ty)*) => { neg_impl_core!{ x => -x, $($t)*} }
+}
+
+macro_rules! neg_impl_unsigned {
+    ($($t:ty)*) => {
+        neg_impl_core!{ x => {
+            #[cfg(stage0)]
+            use ::num::wrapping::WrappingOps;
+            !x.wrapping_add(1)
+        }, $($t)*} }
+}
+
+// neg_impl_unsigned! { usize u8 u16 u32 u64 }
+neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 }
 
 /// The `Not` trait is used to specify the functionality of unary `!`.
 ///
@@ -511,7 +527,7 @@ fn neg(self) -> $t { -self }
 /// ```
 /// use std::ops::Not;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Not for Foo {
@@ -565,7 +581,7 @@ fn not(self) -> $t { !self }
 /// ```
 /// use std::ops::BitAnd;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl BitAnd for Foo {
@@ -619,7 +635,7 @@ fn bitand(self, rhs: $t) -> $t { self & rhs }
 /// ```
 /// use std::ops::BitOr;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl BitOr for Foo {
@@ -673,7 +689,7 @@ fn bitor(self, rhs: $t) -> $t { self | rhs }
 /// ```
 /// use std::ops::BitXor;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl BitXor for Foo {
@@ -727,7 +743,7 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
 /// ```
 /// use std::ops::Shl;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Shl<Foo> for Foo {
@@ -799,7 +815,7 @@ macro_rules! shl_impl_all {
 /// ```
 /// use std::ops::Shr;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 ///
 /// impl Shr<Foo> for Foo {
@@ -871,7 +887,7 @@ macro_rules! shr_impl_all {
 /// ```
 /// use std::ops::Index;
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 /// struct Bar;
 ///
@@ -912,7 +928,7 @@ pub trait Index<Idx: ?Sized> {
 /// ```
 /// use std::ops::{Index, IndexMut};
 ///
-/// #[derive(Copy)]
+/// #[derive(Copy, Clone)]
 /// struct Foo;
 /// struct Bar;
 ///
@@ -1117,6 +1133,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 +1143,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 +1153,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 +1161,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..ded52ff07785ebd100c3c251fda7999db367ed2c 100644 (file)
@@ -18,6 +18,7 @@
 //!
 //! Their definition should always match the ABI defined in `rustc::back::abi`.
 
+use clone::Clone;
 use marker::Copy;
 use mem;
 
@@ -63,18 +64,8 @@ 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 (),
+impl<T> Clone for Slice<T> {
+    fn clone(&self) -> Slice<T> { *self }
 }
 
 /// The representation of a trait object like `&SomeTrait`.
@@ -149,7 +140,7 @@ pub struct Closure {
 /// assert_eq!(synthesized.bar(), 457);
 /// ```
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct TraitObject {
     pub data: *mut (),
     pub vtable: *mut (),
index 21cff3021abea400af1831356fe2644b384e1bf0..7b55ba49a07f779e83766b417cc4b35861dbdafb 100644 (file)
@@ -38,7 +38,7 @@
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
                  pub i8, pub i8, pub i8, pub i8,
@@ -47,26 +47,26 @@ pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
                  pub i16, pub i16, pub i16, pub i16);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct i64x2(pub i64, pub i64);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
                  pub u8, pub u8, pub u8, pub u8,
@@ -75,31 +75,31 @@ pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
                  pub u16, pub u16, pub u16, pub u16);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct u64x2(pub u64, pub u64);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
 
 #[unstable(feature = "core")]
 #[simd]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[repr(C)]
 pub struct f64x2(pub f64, pub f64);
index 223a0bdae36cd8c3cebe763a4192e2950732c4e6..70e60adf64c2a3649b9d2256a7eadd8a46ff7346 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 {
@@ -1136,18 +1126,20 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        if self.count == 0 {
-            self.iter.finish()
-        } else {
-            self.count -= 1;
-            if self.invert { self.iter.next_back() } else { self.iter.next() }
+        match self.count {
+            0 => None,
+            1 => { self.count -= 1; self.iter.finish() }
+            _ => {
+                self.count -= 1;
+                if self.invert {self.iter.next_back()} else {self.iter.next()}
+            }
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (lower, upper_opt) = self.iter.size_hint();
-        (lower, upper_opt.map(|upper| cmp::min(self.count + 1, upper)))
+        (lower, upper_opt.map(|upper| cmp::min(self.count, upper)))
     }
 }
 
@@ -1502,54 +1494,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..dbb365c4e2357536c4ab7097ed435aedd4f3de9f 100644 (file)
 use clone::Clone;
 use cmp::{self, Eq};
 use default::Default;
-use error::Error;
 use fmt;
 use iter::ExactSizeIterator;
 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};
@@ -194,11 +191,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseBoolError {
-    fn description(&self) -> &str { "failed to parse bool" }
-}
-
 /*
 Section: Creating a string
 */
@@ -243,88 +235,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 {
-        match *self {
-            Utf8Error::TooShort => "invalid utf-8: not enough bytes",
-            Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents",
-        }
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Utf8Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -579,7 +489,7 @@ struct CharSplits<'a, P: Pattern<'a>> {
 /// splitting at most `count` times.
 struct CharSplitsN<'a, P: Pattern<'a>> {
     iter: CharSplits<'a, P>,
-    /// The number of splits remaining
+    /// The number of items remaining
     count: usize,
 }
 
@@ -686,11 +596,10 @@ impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P> {
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
-        if self.count != 0 {
-            self.count -= 1;
-            self.iter.next()
-        } else {
-            self.iter.get_end()
+        match self.count {
+            0 => None,
+            1 => { self.count = 0; self.iter.get_end() }
+            _ => { self.count -= 1; self.iter.next() }
         }
     }
 }
@@ -740,11 +649,10 @@ impl<'a, P: Pattern<'a>> Iterator for RCharSplitsN<'a, P>
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
-        if self.count != 0 {
-            self.count -= 1;
-            self.iter.next()
-        } else {
-            self.iter.get_remainder()
+        match self.count {
+            0 => None,
+            1 => { self.count -= 1; self.iter.get_remainder() }
+            _ => { self.count -= 1; self.iter.next() }
         }
     }
 }
@@ -947,7 +855,7 @@ fn next(&mut self, haystack: &[u8], needle: &[u8], long_period: bool)
     #[allow(dead_code)]
     #[allow(deprecated)]
     fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) {
-        let mut left: usize = -1; // Corresponds to i in the paper
+        let mut left: usize = !0; // Corresponds to i in the paper
         let mut right = 0; // Corresponds to j in the paper
         let mut offset = 1; // Corresponds to k in the paper
         let mut period = 1; // Corresponds to p in the paper
@@ -1047,22 +955,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)]
@@ -1213,7 +1105,7 @@ macro_rules! next { () => {
 /// Struct that contains a `char` and the index of the first byte of
 /// the next `char` in a string.  This can be used as a data structure
 /// for iterating over the UTF-8 bytes of a string.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[unstable(feature = "str_char",
            reason = "existence of this struct is uncertain as it is frequently \
                      able to be replaced with char.len_utf8() and/or \
@@ -1444,8 +1336,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 +1455,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 7db8db444ff20901b67040498155a4c2196a90a3..ba12ff306e9b89dba04c107666553b416f426694 100644 (file)
@@ -125,14 +125,14 @@ fn test_format_int_flags() {
     assert!(format!("{:>8x}", 10) == "       a");
     assert!(format!("{:#08x}", 10) == "0x00000a");
     assert!(format!("{:08}", -10) == "-0000010");
-    assert!(format!("{:x}", -1u8) == "ff");
-    assert!(format!("{:X}", -1u8) == "FF");
-    assert!(format!("{:b}", -1u8) == "11111111");
-    assert!(format!("{:o}", -1u8) == "377");
-    assert!(format!("{:#x}", -1u8) == "0xff");
-    assert!(format!("{:#X}", -1u8) == "0xFF");
-    assert!(format!("{:#b}", -1u8) == "0b11111111");
-    assert!(format!("{:#o}", -1u8) == "0o377");
+    assert!(format!("{:x}", !0u8) == "ff");
+    assert!(format!("{:X}", !0u8) == "FF");
+    assert!(format!("{:b}", !0u8) == "11111111");
+    assert!(format!("{:o}", !0u8) == "377");
+    assert!(format!("{:#x}", !0u8) == "0xff");
+    assert!(format!("{:#X}", !0u8) == "0xFF");
+    assert!(format!("{:#b}", !0u8) == "0b11111111");
+    assert!(format!("{:#o}", !0u8) == "0o377");
 }
 
 #[test]
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 fa41167cae8a6dda7742850facc156fa30f3e26d..cb2359873e9dc59ef8e19f09726c6647c1d6fc1e 100644 (file)
@@ -86,9 +86,9 @@ fn test_count_ones() {
 
     #[test]
     fn test_count_zeros() {
-        assert!(A.count_zeros() == BITS - 3);
-        assert!(B.count_zeros() == BITS - 2);
-        assert!(C.count_zeros() == BITS - 5);
+        assert!(A.count_zeros() == BITS as u32 - 3);
+        assert!(B.count_zeros() == BITS as u32 - 2);
+        assert!(C.count_zeros() == BITS as u32 - 5);
     }
 
     #[test]
index 39e41a4fad3b7d5092c834aa43c69a443b1018b7..5e00692766d90aa052029f70b013e444f12426df 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]
@@ -54,9 +54,9 @@ fn test_count_ones() {
 
     #[test]
     fn test_count_zeros() {
-        assert!(A.count_zeros() == BITS - 3);
-        assert!(B.count_zeros() == BITS - 2);
-        assert!(C.count_zeros() == BITS - 5);
+        assert!(A.count_zeros() == BITS as u32 - 3);
+        assert!(B.count_zeros() == BITS as u32 - 2);
+        assert!(C.count_zeros() == BITS as u32 - 5);
     }
 
     #[test]
index 38cab4f0e0942440063c16e0bd3b1a3813fd9451..5fce527d9798df979a3183c2d3a433f191d05234 100644 (file)
@@ -65,20 +65,20 @@ fn test_strslice_contains() {
 fn test_rsplitn_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
-    let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
-    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
     // Unicode
-    let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 
-    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 }
@@ -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..4cf93ab2645df79a91a9087f9c77c6c9a997925c 100644 (file)
@@ -40,7 +40,7 @@
 
 /// A piece is a portion of the format string which represents the next part
 /// to emit. These are emitted as a stream by the `Parser` class.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Piece<'a> {
     /// A literal string which should directly be emitted
     String(&'a str),
@@ -50,7 +50,7 @@ pub enum Piece<'a> {
 }
 
 /// Representation of an argument specification.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub struct Argument<'a> {
     /// Where to find this argument
     pub position: Position<'a>,
@@ -59,7 +59,7 @@ pub struct Argument<'a> {
 }
 
 /// Specification for the formatting of an argument in the format string.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub struct FormatSpec<'a> {
     /// Optionally specified character to fill alignment with
     pub fill: Option<char>,
@@ -78,7 +78,7 @@ pub struct FormatSpec<'a> {
 }
 
 /// Enum describing where an argument for a format can be located.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Position<'a> {
     /// The argument will be in the next position. This is the default.
     ArgumentNext,
@@ -89,7 +89,7 @@ pub enum Position<'a> {
 }
 
 /// Enum of alignments which are supported.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Alignment {
     /// The value will be aligned to the left.
     AlignLeft,
@@ -103,7 +103,7 @@ pub enum Alignment {
 
 /// Various flags which can be applied to format strings. The meaning of these
 /// flags is defined by the formatters themselves.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Flag {
     /// A `+` will be used to denote positive numbers.
     FlagSignPlus,
@@ -119,7 +119,7 @@ pub enum Flag {
 
 /// A count is used for the precision and width parameters of an integer, and
 /// can reference either an argument or a literal integer.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Count<'a> {
     /// The count is specified explicitly.
     CountIs(usize),
@@ -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 9a5dde8e45e2f92e91bb0c505f2778ab5967426d..5c10641e8515e288d083bc0f87a2ed56c63d5d4f 100644 (file)
@@ -213,7 +213,7 @@ pub enum Fail {
 }
 
 /// The type of failure that occurred.
-#[derive(Copy, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 #[allow(missing_docs)]
 pub enum FailType {
     ArgumentMissing_,
@@ -843,18 +843,18 @@ pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String {
     line
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum SplitWithinState {
     A,  // leading whitespace, initial state
     B,  // words
     C,  // internal and trailing whitespace
 }
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Whitespace {
     Ws, // current char is whitespace
     Cr  // current char is not whitespace
 }
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum LengthLimit {
     UnderLim, // current char makes current substring still fit in limit
     OverLim   // current char makes current substring no longer fit in limit
index b3a3f266a5ef33449a76658aeba5a9c4d77c6bd9..95b78e1cbfd039a1b4d1e5665a0e4d4b0dd12830 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 }
@@ -524,7 +524,7 @@ pub trait GraphWalk<'a, N, E> {
     fn target(&'a self, edge: &E) -> N;
 }
 
-#[derive(Copy, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum RenderOption {
     NoEdgeLabels,
     NoNodeLabels,
index b7162c4a177d6f0457bb30a40f729d19da2f7f38..040c9b011f32757d748afc48715db55f38e420eb 100644 (file)
@@ -227,7 +227,7 @@ pub mod posix01 {
                 pub type rlim_t = u64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct glob_t {
+                #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc: size_t,
                     pub gl_pathv: *mut *mut c_char,
                     pub gl_offs:  size_t,
@@ -240,23 +240,23 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timeval {
+                #[derive(Copy, Clone)] pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timespec {
+                #[derive(Copy, Clone)] pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
 
-                #[derive(Copy)] pub enum timezone {}
+                pub enum timezone {}
 
                 pub type sighandler_t = size_t;
 
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rlimit {
                     pub rlim_cur: rlim_t,
                     pub rlim_max: rlim_t,
@@ -269,7 +269,7 @@ pub mod bsd43 {
                 // This is also specified in POSIX 2001, but only has two fields. All implementors
                 // implement BSD 4.3 version.
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rusage {
                     pub ru_utime: timeval,
                     pub ru_stime: timeval,
@@ -299,7 +299,7 @@ pub mod bsd44 {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr {
+                #[derive(Copy, Clone)] pub struct sockaddr {
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
@@ -312,19 +312,22 @@ pub mod bsd44 {
                     #[cfg(target_pointer_width = "64")]
                     pub __ss_pad2: [u8; 128 - 2 * 8],
                 }
+                impl ::core::clone::Clone for sockaddr_storage {
+                    fn clone(&self) -> sockaddr_storage { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)] pub struct sockaddr_in {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in_addr {
+                #[derive(Copy, Clone)] pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
                     pub sin6_flowinfo: u32,
@@ -332,21 +335,21 @@ pub mod bsd44 {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in6_addr {
+                #[derive(Copy, Clone)] pub struct in6_addr {
                     pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip_mreq {
+                #[derive(Copy, Clone)] pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)] pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct addrinfo {
+                #[derive(Copy, Clone)] pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -372,9 +375,12 @@ pub mod bsd44 {
                     pub sun_family: sa_family_t,
                     pub sun_path: [c_char; 108]
                 }
+                impl ::core::clone::Clone for sockaddr_un {
+                    fn clone(&self) -> sockaddr_un { *self }
+                }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct ifaddrs {
+                #[derive(Copy, Clone)] pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
@@ -465,7 +471,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i32;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub __pad1: c_short,
                     pub st_ino: ino_t,
@@ -489,13 +495,13 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy, Clone)] pub struct pthread_attr_t {
                     pub __size: [u32; 9]
                 }
             }
@@ -510,7 +516,7 @@ pub mod posix01 {
                 pub type blkcnt_t = u32;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: c_ulonglong,
                     pub __pad0: [c_uchar; 4],
                     pub __st_ino: ino_t,
@@ -533,13 +539,13 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy, Clone)] pub struct pthread_attr_t {
                     pub __size: [u32; 9]
                 }
             }
@@ -556,7 +562,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i32;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: c_ulong,
                     pub st_pad1: [c_long; 3],
                     pub st_ino: ino_t,
@@ -580,13 +586,13 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy, Clone)] pub struct pthread_attr_t {
                     pub __size: [u32; 9]
                 }
             }
@@ -595,7 +601,7 @@ pub mod bsd44 {}
             pub mod extra {
                 use types::os::arch::c95::{c_ushort, c_int, c_uchar};
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_ll {
+                #[derive(Copy, Clone)] pub struct sockaddr_ll {
                     pub sll_family: c_ushort,
                     pub sll_protocol: c_ushort,
                     pub sll_ifindex: c_int,
@@ -667,7 +673,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_nlink: nlink_t,
@@ -689,13 +695,13 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy, Clone)] pub struct pthread_attr_t {
                     pub __size: [u64; 7]
                 }
             }
@@ -711,7 +717,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: mode_t,
@@ -734,13 +740,13 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct pthread_attr_t {
+                #[derive(Copy, Clone)] pub struct pthread_attr_t {
                     pub __size: [u64; 8]
                 }
             }
@@ -750,7 +756,7 @@ pub mod bsd44 {
             }
             pub mod extra {
                 use types::os::arch::c95::{c_ushort, c_int, c_uchar};
-                #[derive(Copy)] pub struct sockaddr_ll {
+                #[derive(Copy, Clone)] pub struct sockaddr_ll {
                     pub sll_family: c_ushort,
                     pub sll_protocol: c_ushort,
                     pub sll_ifindex: c_int,
@@ -777,7 +783,7 @@ pub mod posix01 {
                 pub type rlim_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct glob_t {
+                #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc:  size_t,
                     pub __unused1: size_t,
                     pub gl_offs:   size_t,
@@ -794,23 +800,23 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timeval {
+                #[derive(Copy, Clone)] pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timespec {
+                #[derive(Copy, Clone)] pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
 
-                #[derive(Copy)] pub enum timezone {}
+                pub enum timezone {}
 
                 pub type sighandler_t = size_t;
 
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rlimit {
                     pub rlim_cur: rlim_t,
                     pub rlim_max: rlim_t,
@@ -821,7 +827,7 @@ pub mod bsd43 {
                 use types::os::common::posix01::timeval;
                 use types::os::arch::c95::c_long;
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rusage {
                     pub ru_utime: timeval,
                     pub ru_stime: timeval,
@@ -851,7 +857,7 @@ pub mod bsd44 {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr {
+                #[derive(Copy, Clone)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
@@ -864,8 +870,11 @@ pub mod bsd44 {
                     pub __ss_align: i64,
                     pub __ss_pad2: [u8; 112],
                 }
+                impl ::core::clone::Clone for sockaddr_storage {
+                    fn clone(&self) -> sockaddr_storage { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)] pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -873,11 +882,11 @@ pub mod bsd44 {
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in_addr {
+                #[derive(Copy, Clone)] pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -886,21 +895,21 @@ pub mod bsd44 {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in6_addr {
+                #[derive(Copy, Clone)] pub struct in6_addr {
                     pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip_mreq {
+                #[derive(Copy, Clone)] pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)] pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct addrinfo {
+                #[derive(Copy, Clone)] pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -916,8 +925,11 @@ pub mod bsd44 {
                     pub sun_family: sa_family_t,
                     pub sun_path: [c_char; 104]
                 }
+                impl ::core::clone::Clone for sockaddr_un {
+                    fn clone(&self) -> sockaddr_un { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ifaddrs {
+                #[derive(Copy, Clone)] pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
@@ -984,7 +996,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i64;
                 pub type fflags_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: mode_t,
@@ -1010,7 +1022,7 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -1039,7 +1051,7 @@ pub mod posix01 {
                 pub type rlim_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct glob_t {
+                #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc:  size_t,
                     pub __unused1: size_t,
                     pub gl_offs:   size_t,
@@ -1056,23 +1068,23 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timeval {
+                #[derive(Copy, Clone)] pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timespec {
+                #[derive(Copy, Clone)] pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
 
-                #[derive(Copy)] pub enum timezone {}
+                pub enum timezone {}
 
                 pub type sighandler_t = size_t;
 
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rlimit {
                     pub rlim_cur: rlim_t,
                     pub rlim_max: rlim_t,
@@ -1083,7 +1095,7 @@ pub mod bsd43 {
                 use types::os::common::posix01::timeval;
                 use types::os::arch::c95::c_long;
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rusage {
                     pub ru_utime: timeval,
                     pub ru_stime: timeval,
@@ -1113,7 +1125,7 @@ pub mod bsd44 {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr {
+                #[derive(Copy, Clone)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
@@ -1126,8 +1138,11 @@ pub mod bsd44 {
                     pub __ss_align: i64,
                     pub __ss_pad2: [u8; 112],
                 }
+                impl ::core::clone::Clone for sockaddr_storage {
+                    fn clone(&self) -> sockaddr_storage { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)] pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -1135,11 +1150,11 @@ pub mod bsd44 {
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in_addr {
+                #[derive(Copy, Clone)] pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -1148,21 +1163,21 @@ pub mod bsd44 {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in6_addr {
+                #[derive(Copy, Clone)] pub struct in6_addr {
                     pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip_mreq {
+                #[derive(Copy, Clone)] pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)] pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct addrinfo {
+                #[derive(Copy, Clone)] pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -1178,8 +1193,11 @@ pub mod bsd44 {
                     pub sun_family: sa_family_t,
                     pub sun_path: [c_char; 104]
                 }
+                impl ::core::clone::Clone for sockaddr_un {
+                    fn clone(&self) -> sockaddr_un { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ifaddrs {
+                #[derive(Copy, Clone)] pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
@@ -1246,7 +1264,7 @@ pub mod posix01 {
                 pub type fflags_t = u32;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_ino: ino_t,
                     pub st_nlink: nlink_t,
                     pub st_dev: dev_t,
@@ -1271,7 +1289,7 @@ pub mod posix01 {
                     pub st_qspare2: int64_t,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -1301,7 +1319,7 @@ pub mod posix01 {
 
                 #[cfg(target_os = "bitrig")]
                 #[repr(C)]
-                #[derive(Copy)] pub struct glob_t {
+                #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc:  c_int,
                     pub gl_matchc: c_int,
                     pub gl_offs:   c_int,
@@ -1318,7 +1336,7 @@ pub mod posix01 {
 
                 #[cfg(target_os = "openbsd")]
                 #[repr(C)]
-                #[derive(Copy)] pub struct glob_t {
+                #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc:  c_int,
                     pub __unused1: c_int,
                     pub gl_offs:   c_int,
@@ -1336,23 +1354,23 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timeval {
+                #[derive(Copy, Clone)] pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timespec {
+                #[derive(Copy, Clone)] pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
 
-                #[derive(Copy)] pub enum timezone {}
+                pub enum timezone {}
 
                 pub type sighandler_t = size_t;
 
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rlimit {
                     pub rlim_cur: rlim_t,
                     pub rlim_max: rlim_t,
@@ -1363,7 +1381,7 @@ pub mod bsd43 {
                 use types::os::common::posix01::timeval;
                 use types::os::arch::c95::c_long;
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rusage {
                     pub ru_utime: timeval,
                     pub ru_stime: timeval,
@@ -1393,7 +1411,7 @@ pub mod bsd44 {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr {
+                #[derive(Copy, Clone)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
@@ -1406,8 +1424,11 @@ pub mod bsd44 {
                     pub __ss_pad2: i64,
                     pub __ss_pad3: [u8; 240],
                 }
+                impl ::core::clone::Clone for sockaddr_storage {
+                    fn clone(&self) -> sockaddr_storage { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)] pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -1415,11 +1436,11 @@ pub mod bsd44 {
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in_addr {
+                #[derive(Copy, Clone)] pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -1428,21 +1449,21 @@ pub mod bsd44 {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in6_addr {
+                #[derive(Copy, Clone)] pub struct in6_addr {
                     pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip_mreq {
+                #[derive(Copy, Clone)] pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)] pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct addrinfo {
+                #[derive(Copy, Clone)] pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -1458,8 +1479,11 @@ pub mod bsd44 {
                     pub sun_family: sa_family_t,
                     pub sun_path: [c_char; 104]
                 }
+                impl ::core::clone::Clone for sockaddr_un {
+                    fn clone(&self) -> sockaddr_un { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ifaddrs {
+                #[derive(Copy, Clone)] pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
@@ -1526,7 +1550,7 @@ pub mod posix01 {
                 pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_mode: mode_t,
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
@@ -1549,7 +1573,7 @@ pub mod posix01 {
                     pub st_birthtime_nsec: c_long,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -1576,7 +1600,7 @@ pub mod posix01 {
                 // pub Note: this is the struct called stat64 in Windows. Not stat,
                 // nor stati64.
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub st_ino: ino_t,
                     pub st_mode: u16,
@@ -1592,24 +1616,24 @@ pub mod posix01 {
 
                 // note that this is called utimbuf64 in Windows
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time64_t,
                     pub modtime: time64_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timeval {
+                #[derive(Copy, Clone)] pub struct timeval {
                     pub tv_sec: c_long,
                     pub tv_usec: c_long,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timespec {
+                #[derive(Copy, Clone)] pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
 
-                #[derive(Copy)] pub enum timezone {}
+                pub enum timezone {}
             }
 
             pub mod bsd44 {
@@ -1622,7 +1646,7 @@ pub mod bsd44 {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr {
+                #[derive(Copy, Clone)] pub struct sockaddr {
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
                 }
@@ -1633,19 +1657,22 @@ pub mod bsd44 {
                     pub __ss_align: i64,
                     pub __ss_pad2: [u8; 112],
                 }
+                impl ::core::clone::Clone for sockaddr_storage {
+                    fn clone(&self) -> sockaddr_storage { *self }
+                }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)] pub struct sockaddr_in {
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
                     pub sin_addr: in_addr,
                     pub sin_zero: [u8; 8],
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in_addr {
+                #[derive(Copy, Clone)] pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
                     pub sin6_flowinfo: u32,
@@ -1653,21 +1680,21 @@ pub mod bsd44 {
                     pub sin6_scope_id: u32,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct in6_addr {
+                #[derive(Copy, Clone)] pub struct in6_addr {
                     pub s6_addr: [u16; 8]
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip_mreq {
+                #[derive(Copy, Clone)] pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)] pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
                 #[repr(C)]
-                #[derive(Copy)] pub struct addrinfo {
+                #[derive(Copy, Clone)] pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -1682,6 +1709,9 @@ pub mod bsd44 {
                     pub sun_family: sa_family_t,
                     pub sun_path: [c_char; 108]
                 }
+                impl ::core::clone::Clone for sockaddr_un {
+                    fn clone(&self) -> sockaddr_un { *self }
+                }
             }
         }
 
@@ -1807,7 +1837,7 @@ pub mod extra {
                 pub type LPCH = *mut CHAR;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct SECURITY_ATTRIBUTES {
+                #[derive(Copy, Clone)] pub struct SECURITY_ATTRIBUTES {
                     pub nLength: DWORD,
                     pub lpSecurityDescriptor: LPVOID,
                     pub bInheritHandle: BOOL,
@@ -1831,7 +1861,7 @@ pub mod extra {
                 pub type int64 = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct STARTUPINFO {
+                #[derive(Copy, Clone)] pub struct STARTUPINFO {
                     pub cb: DWORD,
                     pub lpReserved: LPWSTR,
                     pub lpDesktop: LPWSTR,
@@ -1854,7 +1884,7 @@ pub mod extra {
                 pub type LPSTARTUPINFO = *mut STARTUPINFO;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct PROCESS_INFORMATION {
+                #[derive(Copy, Clone)] pub struct PROCESS_INFORMATION {
                     pub hProcess: HANDLE,
                     pub hThread: HANDLE,
                     pub dwProcessId: DWORD,
@@ -1863,7 +1893,7 @@ pub mod extra {
                 pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct SYSTEM_INFO {
+                #[derive(Copy, Clone)] pub struct SYSTEM_INFO {
                     pub wProcessorArchitecture: WORD,
                     pub wReserved: WORD,
                     pub dwPageSize: DWORD,
@@ -1879,7 +1909,7 @@ pub mod extra {
                 pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct MEMORY_BASIC_INFORMATION {
+                #[derive(Copy, Clone)] pub struct MEMORY_BASIC_INFORMATION {
                     pub BaseAddress: LPVOID,
                     pub AllocationBase: LPVOID,
                     pub AllocationProtect: DWORD,
@@ -1891,7 +1921,7 @@ pub mod extra {
                 pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct OVERLAPPED {
+                #[derive(Copy, Clone)] pub struct OVERLAPPED {
                     pub Internal: *mut c_ulong,
                     pub InternalHigh: *mut c_ulong,
                     pub Offset: DWORD,
@@ -1902,7 +1932,7 @@ pub mod extra {
                 pub type LPOVERLAPPED = *mut OVERLAPPED;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct FILETIME {
+                #[derive(Copy, Clone)] pub struct FILETIME {
                     pub dwLowDateTime: DWORD,
                     pub dwHighDateTime: DWORD,
                 }
@@ -1910,7 +1940,7 @@ pub mod extra {
                 pub type LPFILETIME = *mut FILETIME;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct GUID {
+                #[derive(Copy, Clone)] pub struct GUID {
                     pub Data1: DWORD,
                     pub Data2: WORD,
                     pub Data3: WORD,
@@ -1918,7 +1948,7 @@ pub mod extra {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct WSAPROTOCOLCHAIN {
+                #[derive(Copy, Clone)] pub struct WSAPROTOCOLCHAIN {
                     pub ChainLen: c_int,
                     pub ChainEntries: [DWORD; MAX_PROTOCOL_CHAIN as usize],
                 }
@@ -1948,6 +1978,9 @@ pub mod extra {
                     pub dwProviderReserved: DWORD,
                     pub szProtocol: [u8; WSAPROTOCOL_LEN as usize + 1],
                 }
+                impl ::core::clone::Clone for WSAPROTOCOL_INFO {
+                    fn clone(&self) -> WSAPROTOCOL_INFO { *self }
+                }
 
                 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
 
@@ -1966,6 +1999,9 @@ pub mod extra {
                     pub cFileName: [wchar_t; 260], // #define MAX_PATH 260
                     pub cAlternateFileName: [wchar_t; 14],
                 }
+                impl ::core::clone::Clone for WIN32_FIND_DATAW {
+                    fn clone(&self) -> WIN32_FIND_DATAW { *self }
+                }
 
                 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
             }
@@ -1985,7 +2021,7 @@ pub mod posix01 {
                 pub type rlim_t = u64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct glob_t {
+                #[derive(Copy, Clone)] pub struct glob_t {
                     pub gl_pathc:  size_t,
                     pub __unused1: c_int,
                     pub gl_offs:   size_t,
@@ -2002,23 +2038,23 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timeval {
+                #[derive(Copy, Clone)] pub struct timeval {
                     pub tv_sec: time_t,
                     pub tv_usec: suseconds_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct timespec {
+                #[derive(Copy, Clone)] pub struct timespec {
                     pub tv_sec: time_t,
                     pub tv_nsec: c_long,
                 }
 
-                #[derive(Copy)] pub enum timezone {}
+                pub enum timezone {}
 
                 pub type sighandler_t = size_t;
 
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rlimit {
                     pub rlim_cur: rlim_t,
                     pub rlim_max: rlim_t,
@@ -2029,7 +2065,7 @@ pub mod bsd43 {
                 use types::os::common::posix01::timeval;
                 use types::os::arch::c95::c_long;
                 #[repr(C)]
-                #[derive(Copy)]
+                #[derive(Copy, Clone)]
                 pub struct rusage {
                     pub ru_utime: timeval,
                     pub ru_stime: timeval,
@@ -2059,7 +2095,7 @@ pub mod bsd44 {
                 pub type in_port_t = u16;
                 pub type in_addr_t = u32;
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr {
+                #[derive(Copy, Clone)] pub struct sockaddr {
                     pub sa_len: u8,
                     pub sa_family: sa_family_t,
                     pub sa_data: [u8; 14],
@@ -2073,9 +2109,12 @@ pub mod bsd44 {
                     pub __ss_align: i64,
                     pub __ss_pad2: [u8; 112],
                 }
+                impl ::core::clone::Clone for sockaddr_storage {
+                    fn clone(&self) -> sockaddr_storage { *self }
+                }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in {
+                #[derive(Copy, Clone)] pub struct sockaddr_in {
                     pub sin_len: u8,
                     pub sin_family: sa_family_t,
                     pub sin_port: in_port_t,
@@ -2084,12 +2123,12 @@ pub mod bsd44 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct in_addr {
+                #[derive(Copy, Clone)] pub struct in_addr {
                     pub s_addr: in_addr_t,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct sockaddr_in6 {
+                #[derive(Copy, Clone)] pub struct sockaddr_in6 {
                     pub sin6_len: u8,
                     pub sin6_family: sa_family_t,
                     pub sin6_port: in_port_t,
@@ -2099,24 +2138,24 @@ pub mod bsd44 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct in6_addr {
+                #[derive(Copy, Clone)] pub struct in6_addr {
                     pub s6_addr: [u16; 8]
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip_mreq {
+                #[derive(Copy, Clone)] pub struct ip_mreq {
                     pub imr_multiaddr: in_addr,
                     pub imr_interface: in_addr,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct ip6_mreq {
+                #[derive(Copy, Clone)] pub struct ip6_mreq {
                     pub ipv6mr_multiaddr: in6_addr,
                     pub ipv6mr_interface: c_uint,
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct addrinfo {
+                #[derive(Copy, Clone)] pub struct addrinfo {
                     pub ai_flags: c_int,
                     pub ai_family: c_int,
                     pub ai_socktype: c_int,
@@ -2133,9 +2172,12 @@ pub mod bsd44 {
                     pub sun_family: sa_family_t,
                     pub sun_path: [c_char; 104]
                 }
+                impl ::core::clone::Clone for sockaddr_un {
+                    fn clone(&self) -> sockaddr_un { *self }
+                }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct ifaddrs {
+                #[derive(Copy, Clone)] pub struct ifaddrs {
                     pub ifa_next: *mut ifaddrs,
                     pub ifa_name: *mut c_char,
                     pub ifa_flags: c_uint,
@@ -2200,7 +2242,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub st_mode: mode_t,
                     pub st_nlink: nlink_t,
@@ -2226,7 +2268,7 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -2236,6 +2278,9 @@ pub mod posix01 {
                     pub __sig: c_long,
                     pub __opaque: [c_char; 36]
                 }
+                impl ::core::clone::Clone for pthread_attr_t {
+                    fn clone(&self) -> pthread_attr_t { *self }
+                }
             }
             pub mod posix08 {
             }
@@ -2243,7 +2288,7 @@ pub mod bsd44 {
             }
             pub mod extra {
                 #[repr(C)]
-                #[derive(Copy)] pub struct mach_timebase_info {
+                #[derive(Copy, Clone)] pub struct mach_timebase_info {
                     pub numer: u32,
                     pub denom: u32,
                 }
@@ -2306,7 +2351,7 @@ pub mod posix01 {
                 pub type blkcnt_t = i64;
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct stat {
+                #[derive(Copy, Clone)] pub struct stat {
                     pub st_dev: dev_t,
                     pub st_mode: mode_t,
                     pub st_nlink: nlink_t,
@@ -2332,7 +2377,7 @@ pub mod posix01 {
                 }
 
                 #[repr(C)]
-                #[derive(Copy)] pub struct utimbuf {
+                #[derive(Copy, Clone)] pub struct utimbuf {
                     pub actime: time_t,
                     pub modtime: time_t,
                 }
@@ -2342,6 +2387,9 @@ pub mod posix01 {
                     pub __sig: c_long,
                     pub __opaque: [c_char; 56]
                 }
+                impl ::core::clone::Clone for pthread_attr_t {
+                    fn clone(&self) -> pthread_attr_t { *self }
+                }
             }
             pub mod posix08 {
             }
@@ -2349,7 +2397,7 @@ pub mod bsd44 {
             }
             pub mod extra {
                 #[repr(C)]
-                #[derive(Copy)] pub struct mach_timebase_info {
+                #[derive(Copy, Clone)] pub struct mach_timebase_info {
                     pub numer: u32,
                     pub denom: u32,
                 }
@@ -2564,7 +2612,7 @@ pub mod extra {
             pub const ERROR_IO_PENDING: c_int = 997;
             pub const ERROR_FILE_INVALID : c_int = 1006;
             pub const ERROR_NOT_FOUND: c_int = 1168;
-            pub const INVALID_HANDLE_VALUE: HANDLE = -1 as HANDLE;
+            pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
 
             pub const DELETE : DWORD = 0x00010000;
             pub const READ_CONTROL : DWORD = 0x00020000;
@@ -2602,12 +2650,12 @@ pub mod extra {
             pub const WAIT_ABANDONED : DWORD = 0x00000080;
             pub const WAIT_OBJECT_0 : DWORD = 0x00000000;
             pub const WAIT_TIMEOUT : DWORD = 0x00000102;
-            pub const WAIT_FAILED : DWORD = -1;
+            pub const WAIT_FAILED : DWORD = !0;
 
             pub const DUPLICATE_CLOSE_SOURCE : DWORD = 0x00000001;
             pub const DUPLICATE_SAME_ACCESS : DWORD = 0x00000002;
 
-            pub const INFINITE : DWORD = -1;
+            pub const INFINITE : DWORD = !0;
             pub const STILL_ACTIVE : DWORD = 259;
 
             pub const MEM_COMMIT : DWORD = 0x00001000;
@@ -2865,7 +2913,7 @@ pub mod posix88 {
             pub const MAP_FIXED : c_int = 0x0010;
             pub const MAP_ANON : c_int = 0x0020;
 
-            pub const MAP_FAILED : *mut c_void = -1 as *mut c_void;
+            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
 
             pub const MCL_CURRENT : c_int = 0x0001;
             pub const MCL_FUTURE : c_int = 0x0002;
@@ -3086,7 +3134,7 @@ pub mod posix88 {
             pub const MAP_FIXED : c_int = 0x0010;
             pub const MAP_ANON : c_int = 0x0800;
 
-            pub const MAP_FAILED : *mut c_void = -1 as *mut c_void;
+            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
 
             pub const MCL_CURRENT : c_int = 0x0001;
             pub const MCL_FUTURE : c_int = 0x0002;
@@ -3822,7 +3870,7 @@ pub mod posix88 {
             pub const MAP_FIXED : c_int = 0x0010;
             pub const MAP_ANON : c_int = 0x1000;
 
-            pub const MAP_FAILED : *mut c_void = -1 as *mut c_void;
+            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
 
             pub const MCL_CURRENT : c_int = 0x0001;
             pub const MCL_FUTURE : c_int = 0x0002;
@@ -4276,7 +4324,7 @@ pub mod posix88 {
             pub const MAP_FIXED : c_int = 0x0010;
             pub const MAP_ANON : c_int = 0x1000;
 
-            pub const MAP_FAILED : *mut c_void = -1 as *mut c_void;
+            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
 
             pub const MCL_CURRENT : c_int = 0x0001;
             pub const MCL_FUTURE : c_int = 0x0002;
@@ -4696,7 +4744,7 @@ pub mod posix88 {
             pub const MAP_FIXED : c_int = 0x0010;
             pub const MAP_ANON : c_int = 0x1000;
 
-            pub const MAP_FAILED : *mut c_void = -1 as *mut c_void;
+            pub const MAP_FAILED : *mut c_void = !0 as *mut c_void;
 
             pub const MCL_CURRENT : c_int = 0x0001;
             pub const MCL_FUTURE : c_int = 0x0002;
index 1cfac4d86680dc12f59e941aff3c5296f5d03f14..453d087196b1318c57b95e19c202c2f3e2dc7b56 100644 (file)
@@ -239,7 +239,7 @@ pub trait Logger {
 struct DefaultLogger { handle: Stderr }
 
 /// Wraps the log level with fmt implementations.
-#[derive(Copy, PartialEq, PartialOrd, Debug)]
+#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
 pub struct LogLevel(pub u32);
 
 impl fmt::Display for LogLevel {
@@ -355,7 +355,7 @@ pub struct LogRecord<'a> {
 }
 
 #[doc(hidden)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct LogLocation {
     pub module_path: &'static str,
     pub file: &'static str,
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 0c5f5cb0d444ee44962375c1b6a8818dde76b294..2ba3164e1b0617125244ad53d3d60baacda3b697 100644 (file)
@@ -29,7 +29,7 @@
 /// Generate Normal Random
 /// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
 /// College, Oxford
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Exp1(pub f64);
 
 // This could be done via `-rng.gen::<f64>().ln()` but that is slower.
@@ -68,7 +68,7 @@ fn zero_case<R:Rng>(rng: &mut R, _u: f64) -> f64 {
 /// let v = exp.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a Exp(2) distribution", v);
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Exp {
     /// `lambda` stored as `1/lambda`, since this is what we scale by.
     lambda_inverse: f64
index 62189e721e59d70f554bf6e0934a64858ad3c3d7..432081063c50f7c6e8eba15f781e63c2cc7002e7 100644 (file)
@@ -361,7 +361,7 @@ fn test_weighted_choice_zero_weight() {
     }
     #[test] #[should_panic]
     fn test_weighted_choice_weight_overflows() {
-        let x = (-1) as usize / 2; // x + x + 2 is the overflow
+        let x = (!0) as usize / 2; // x + x + 2 is the overflow
         WeightedChoice::new(&mut [Weighted { weight: x, item: 0 },
                                   Weighted { weight: 1, item: 1 },
                                   Weighted { weight: x, item: 2 },
index 7cecc6ac611e2af1e6b587b03b2adaa228974f0b..fa41c3edfe5ac4e49655f7119ad985c375950ac6 100644 (file)
@@ -28,7 +28,7 @@
 /// Generate Normal Random
 /// Samples*](http://www.doornik.com/research/ziggurat.pdf). Nuffield
 /// College, Oxford
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct StandardNormal(pub f64);
 
 impl Rand for StandardNormal {
@@ -85,7 +85,7 @@ fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 {
 /// let v = normal.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from a N(2, 9) distribution", v)
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Normal {
     mean: f64,
     std_dev: f64,
@@ -134,7 +134,7 @@ fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
 /// let v = log_normal.ind_sample(&mut rand::thread_rng());
 /// println!("{} is from an ln N(2, 9) distribution", v)
 /// ```
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct LogNormal {
     norm: Normal
 }
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 ab4939f57d41a62ff357bd543db5d4fa3d2b9097..98d1bbf5af9da0b54ccdceac90c230fc30722e07 100644 (file)
@@ -134,7 +134,7 @@ pub trait Reseeder<R> {
 
 /// Reseed an RNG using a `Default` instance. This reseeds by
 /// replacing the RNG with the result of a `Default::default` call.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct ReseedWithDefault;
 
 impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
index 092cd780ec7c7cfb02efc8e16e996c3f8d5ae1d7..e2875ac8ca529479ab904f06a0c843375c880b6e 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)]
@@ -176,7 +175,7 @@ pub struct TaggedDoc<'a> {
     pub doc: Doc<'a>,
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum EbmlEncoderTag {
     // tags 00..1f are reserved for auto-serialization.
     // first NUM_IMPLICIT_TAGS tags are implicitly sized and lengths are not encoded.
@@ -266,7 +265,7 @@ macro_rules! try_or {
         )
     }
 
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub struct Res {
         pub val: usize,
         pub next: usize
@@ -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 9093cd00ca0014d4b729239ca382c95f055bd282..495044f9459494f738fa501c229b69de93f22da3 100644 (file)
 }
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct HardwiredLints;
 
 impl LintPass for HardwiredLints {
index 23f9cbc3a4b9cd37391b80598ee2c52a97840bd5..498b2ce518c16dc6055166053e19ed7ac5cb8b20 100644 (file)
@@ -41,7 +41,7 @@
                         GatherNodeLevels};
 
 /// Specification of a single lint.
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct Lint {
     /// A string identifier for the lint.
     ///
index e4c0eda0448bdae443eeaeed4503b5dee84ff8d8..cda0084768644a599a98b438b52539d184758109 100644 (file)
@@ -116,7 +116,7 @@ impl items contain tag_item_impl_item elements, and classes
 pub const tag_items_data_item_reexport_name: usize = 0x48;
 
 // used to encode crate_ctxt side tables
-#[derive(Copy, PartialEq, FromPrimitive)]
+#[derive(Copy, Clone, PartialEq, FromPrimitive)]
 #[repr(usize)]
 pub enum astencode_tag { // Reserves 0x50 -- 0x6f
     tag_ast = 0x50,
index ebc3a6fd52c939b0afaf4b9004970f9450314bd5..d528e38d341cfe099a80acf0f37d039e9bc3c107 100644 (file)
@@ -29,7 +29,7 @@
 
 use std::collections::hash_map::HashMap;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct MethodInfo {
     pub name: ast::Name,
     pub def_id: ast::DefId,
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 284e76b328a6912323692c82f0f6180e8f29f97e..1567f4b99475cb1fe345e0f1983f487cb695e12b 100644 (file)
@@ -21,7 +21,7 @@
 use util::fs as myfs;
 use session::search_paths::{SearchPaths, PathKind};
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum FileMatch {
     FileMatches,
     FileDoesntMatch,
index e2eebbfdc724d255056aad3cb6ba03d08a39e7c9..3fb128b1881f5b949bed0c91cc9c73b7ba1ba365 100644 (file)
@@ -43,7 +43,7 @@
 // def-id will depend on where it originated from.  Therefore, the conversion
 // function is given an indicator of the source of the def-id.  See
 // astencode.rs for more information.
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum DefIdSource {
     // Identifies a struct, trait, enum, etc.
     NominalType,
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 24c54b53590c04f57a4ff6eafe82f3179b9d3cfa..cbc2ef1535ea6794b5705bfe15c0d27fbb16dce1 100644 (file)
@@ -25,7 +25,7 @@ struct CFGBuilder<'a, 'tcx: 'a> {
     loop_scopes: Vec<LoopScope>,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct LoopScope {
     loop_id: ast::NodeId,     // id of loop/while node
     continue_index: CFGIndex, // where to go on a `loop`
index e8a99f59b1e95b365c9c0e4184757608978b8638..ad4fdcd7b834ef2e5b0bc427820d2ce5f522d9eb 100644 (file)
@@ -24,7 +24,7 @@ pub struct CFG {
     pub exit: CFGIndex,
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum CFGNodeData {
     AST(ast::NodeId),
     Entry,
index 497022ac6ac49b3eb87ebfccf0a499db4722f8ba..ce011f2561b79f661744aa78f613fff58e023a23 100644 (file)
@@ -76,7 +76,7 @@
     }
 }
 
-#[derive(Copy, Eq, PartialEq)]
+#[derive(Copy, Clone, Eq, PartialEq)]
 enum Mode {
     Const,
     Static,
index ea584407944abeaa89d657e1cf47953fa62700ef..bf6829d96765058feea270ec09378d460ecfad1a 100644 (file)
@@ -21,7 +21,7 @@ enum Context {
     Normal, Loop, Closure
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct CheckLoopVisitor<'a> {
     sess: &'a Session,
     cx: Context
index 01692158c17f43355296dcf9e7c022d379ec5e3b..79f4d62b45e75fb41740fada747d1a5274163cc4 100644 (file)
@@ -128,7 +128,7 @@ enum Usefulness {
     NotUseful
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum WitnessPreference {
     ConstructWitness,
     LeaveOutWitness
index 0d9e0d14def645ced90898ae7b5c300def44859e..367bcbbe1d8a972add77a29907999a4cbfaed013 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;
 
 use syntax::ast::{self, Expr};
 use syntax::codemap::Span;
+use syntax::feature_gate;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
 use syntax::{ast_map, ast_util, codemap};
 
 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 +238,7 @@ pub enum ErrKind {
     NotOnStruct,
     NotOnTuple,
 
+    NegateWithOverflow(i64),
     AddiWithOverflow(i64, i64),
     SubiWithOverflow(i64, i64),
     MuliWithOverflow(i64, i64),
@@ -244,6 +249,8 @@ pub enum ErrKind {
     DivideWithOverflow,
     ModuloByZero,
     ModuloWithOverflow,
+    ShiftLeftWithOverflow,
+    ShiftRightWithOverflow,
     MissingStructField,
     NonConstPath,
     ExpectedConstTuple,
@@ -257,6 +264,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 +283,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 +294,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 +308,303 @@ 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).wrapping_add(1)))
+}
+
+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(i) => {
+              if !tcx.sess.features.borrow().negate_unsigned {
+                  feature_gate::emit_feature_err(
+                      &tcx.sess.parse_sess.span_diagnostic,
+                      "negate_unsigned",
+                      e.span,
+                      "unary negation of unsigned integers may be removed in the future");
+              }
+              try!(const_uint_checked_neg(i, e, expr_uint_type))
+          }
           const_str(_) => signal!(e, NegateOnString),
           const_bool(_) => signal!(e, NegateOnBoolean),
           const_binary(_) => signal!(e, NegateOnBinary),
@@ -391,51 +648,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 +669,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 +690,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 +727,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 +833,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..b20e4c3f563ca8a7d20f6b8e5464b430a2d98426 100644 (file)
@@ -28,7 +28,7 @@
 use syntax::print::{pp, pprust};
 use util::nodemap::NodeMap;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum EntryOrExit {
     Entry,
     Exit,
@@ -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
         };
 
@@ -195,7 +195,7 @@ pub fn new(tcx: &'a ty::ctxt<'tcx>,
                oper: O,
                id_range: IdRange,
                bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> {
-        let words_per_id = (bits_per_id + usize::BITS as usize - 1) / usize::BITS as usize;
+        let words_per_id = (bits_per_id + usize::BITS - 1) / usize::BITS;
         let num_nodes = cfg.graph.all_nodes().len();
 
         debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \
@@ -367,7 +367,7 @@ fn each_bit<F>(&self, words: &[usize], mut f: F) -> bool where
 
         for (word_index, &word) in words.iter().enumerate() {
             if word != 0 {
-                let base_index = word_index * usize::BITS as usize;
+                let base_index = word_index * usize::BITS;
                 for offset in 0..usize::BITS {
                     let bit = 1 << offset;
                     if (word & bit) != 0 {
@@ -601,8 +601,8 @@ fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
 fn set_bit(words: &mut [usize], bit: usize) -> bool {
     debug!("set_bit: words={} bit={}",
            mut_bits_to_string(words), bit_str(bit));
-    let word = bit / usize::BITS as usize;
-    let bit_in_word = bit % usize::BITS as usize;
+    let word = bit / usize::BITS;
+    let bit_in_word = bit % usize::BITS;
     let bit_mask = 1 << bit_in_word;
     debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, word);
     let oldv = words[word];
index 1a054c0f464aac9afb5a91adb6f007490a8969da..6707a4d3fd775454ca0d9a109469a08c6cf3c9a9 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
@@ -93,7 +104,7 @@ pub fn def_id(&self) -> ast::DefId {
 // within.
 pub type ExportMap = NodeMap<Vec<Export>>;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Export {
     pub name: ast::Name,    // The name of the target.
     pub def_id: ast::DefId, // The definition of the target.
index 5d970c59f639bd5e3b4a289a7419ce7ddb52dfd0..814492cbef1dd3fca1dd8d3d92d3f7c46fcd2303 100644 (file)
@@ -22,7 +22,7 @@
 use syntax::visit;
 use syntax::visit::Visitor;
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum UnsafeContext {
     SafeContext,
     UnsafeFn,
index e98b438d370c70055c9cbda771733033b8464814..2fa9c7c8fbebb0a7e8ceb794b5926ace6f818259 100644 (file)
@@ -94,7 +94,7 @@ fn mutate(&mut self,
               mode: MutateMode);
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum LoanCause {
     ClosureCapture(Span),
     AddrOf,
@@ -106,20 +106,20 @@ pub enum LoanCause {
     MatchDiscriminant
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum ConsumeMode {
     Copy,                // reference to x where x has a type that copies
     Move(MoveReason),    // reference to x where x has a type that moves
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum MoveReason {
     DirectRefMove,
     PatBindingMove,
     CaptureMove,
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum MatchMode {
     NonBindingMatch,
     BorrowingMatch,
@@ -127,7 +127,7 @@ pub enum MatchMode {
     MovingMatch,
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 enum TrackMatchMode {
     Unknown,
     Definite(MatchMode),
@@ -194,14 +194,14 @@ fn match_mode(&self) -> MatchMode {
     }
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum MutateMode {
     Init,
     JustWrite,    // x = y
     WriteAndRead, // x += y
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum OverloadedCallType {
     FnOverloadedCall,
     FnMutOverloadedCall,
index 8673273f9b3c9c3c4fdd947ea14c462110fbc5b3..a9ac61b49eca8bd247ffd8a7ce06e0275db5521b 100644 (file)
@@ -66,13 +66,13 @@ fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
 #[allow(non_upper_case_globals)]
 pub const InvalidNodeIndex: NodeIndex = NodeIndex(usize::MAX);
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub struct EdgeIndex(pub usize);
 #[allow(non_upper_case_globals)]
 pub const InvalidEdgeIndex: EdgeIndex = EdgeIndex(usize::MAX);
 
 // Use a private field here to guarantee no more instances are created:
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct Direction { repr: usize }
 #[allow(non_upper_case_globals)]
 pub const Outgoing: Direction = Direction { repr: 0 };
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..b11e25c059d08ffafc1af1184063aeef34f9982e 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),
@@ -294,7 +290,7 @@ pub enum RegionVariableOrigin<'tcx> {
     BoundRegionInCoherence(ast::Name),
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum fixup_err {
     unresolved_int_ty(IntVid),
     unresolved_float_ty(FloatVid),
@@ -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..d41fdc5f09acd4a03a8959ef94524f84a8dda44c 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;
@@ -74,13 +74,13 @@ pub enum GenericKind<'tcx> {
     Projection(ty::ProjectionTy<'tcx>),
 }
 
-#[derive(Copy, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct TwoRegions {
     a: Region,
     b: Region,
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum UndoLogEntry {
     OpenSnapshot,
     CommitedSnapshot,
@@ -91,7 +91,7 @@ pub enum UndoLogEntry {
     AddCombination(CombineMapType, TwoRegions)
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum CombineMapType {
     Lub, Glb
 }
@@ -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,20 +938,23 @@ 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))
         }
     }
 }
 
 // ______________________________________________________________________
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 enum Classification { Expanding, Contracting }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum VarValue { NoValue, Value(Region), ErrorValue }
 
 struct VarData {
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 553ef9afc28165da821f6dad614e8d2d30d6a78d..03612a6c1ae5bc2401e5ddc3ca4b82e1ed0a48f3 100644 (file)
@@ -47,7 +47,7 @@ enum UndoEntry {
 
 type Relation = (RelationDir, ty::TyVid);
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum RelationDir {
     SubtypeOf, SupertypeOf, EqTo, BiTo
 }
index 8a736d47b5d8944a338c1ad9a9dcdc3ee2bea29f..4bbced1d75caf970924f990f25bd9ee2ae7fc336 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;
 }
@@ -92,7 +84,7 @@ pub struct Node<K:UnifyKey> {
     pub rank: usize,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Delegate<K>(PhantomData<K>);
 
 // We can't use V:LatticeValue, much as I would like to,
@@ -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 b9a82669f65d3910f0606e884f88aafc7d64f141..a08de58f909d3a5f177161d4a074be53b10700e0 100644 (file)
@@ -46,7 +46,7 @@ macro_rules! lets_do_this {
         $( $variant:ident, $name:expr, $method:ident; )*
     ) => {
 
-#[derive(Copy, FromPrimitive, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, FromPrimitive, PartialEq, Eq, Hash)]
 pub enum LangItem {
     $($variant),*
 }
index 705f20559afde27711c2c0934f7aba5c68aa5df0..d7161607b61eb9c3e9a1ea032db5e76b42894166 100644 (file)
@@ -139,7 +139,7 @@ enum LoopKind<'a> {
     WhileLoop(&'a Expr),
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 struct Variable(usize);
 
 #[derive(Copy, PartialEq)]
@@ -159,7 +159,7 @@ fn clone(&self) -> LiveNode {
     }
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 enum LiveNodeKind {
     FreeVarNode(Span),
     ExprNode(Span),
@@ -245,13 +245,13 @@ struct CaptureInfo {
     var_nid: NodeId
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 struct LocalInfo {
     id: NodeId,
     ident: ast::Ident
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum VarKind {
     Arg(NodeId, ast::Ident),
     Local(LocalInfo),
@@ -534,7 +534,7 @@ fn invalid_users() -> Users {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Specials {
     exit_ln: LiveNode,
     fallthrough_ln: LiveNode,
index 3738e38f68704988e75dfc6c1231570f1e6c2fa2..85255d04df4329adc0033d8451fa3940f62379cb 100644 (file)
@@ -199,7 +199,7 @@ pub struct cmt_<'tcx> {
 
 // We pun on *T to mean both actual deref of a ptr as well
 // as accessing of components:
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum deref_kind {
     deref_ptr(PointerKind),
     deref_interior(InteriorKind),
@@ -263,6 +263,9 @@ pub struct MemCategorizationContext<'t,TYPER:'t> {
 }
 
 impl<'t,TYPER:'t> Copy for MemCategorizationContext<'t,TYPER> {}
+impl<'t,TYPER:'t> Clone for MemCategorizationContext<'t,TYPER> {
+    fn clone(&self) -> MemCategorizationContext<'t,TYPER> { *self }
+}
 
 pub type McResult<T> = Result<T, ()>;
 
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..652f661325206fdf89ba15fc839c8e3780fc21c7 100644 (file)
@@ -206,56 +206,72 @@ 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,
 /// for building up the `var_map` which maps ids to the blocks in
 /// which they were declared.
-#[derive(PartialEq, Eq, Debug, Copy)]
+#[derive(PartialEq, Eq, Debug, Copy, Clone)]
 enum InnermostDeclaringBlock {
     None,
     Block(ast::NodeId),
@@ -280,7 +296,7 @@ fn to_code_extent(&self) -> Option<CodeExtent> {
 /// Contextual information for declarations introduced by a statement
 /// (i.e. `let`). It carries node-id's for statement and enclosing
 /// block both, as well as the statement's index within the block.
-#[derive(PartialEq, Eq, Debug, Copy)]
+#[derive(PartialEq, Eq, Debug, Copy, Clone)]
 struct DeclaringStatementContext {
     stmt_id: ast::NodeId,
     block_id: ast::NodeId,
@@ -296,7 +312,7 @@ fn to_code_extent(&self) -> CodeExtent {
     }
 }
 
-#[derive(PartialEq, Eq, Debug, Copy)]
+#[derive(PartialEq, Eq, Debug, Copy, Clone)]
 enum InnermostEnclosingExpr {
     None,
     Some(ast::NodeId),
@@ -318,8 +334,16 @@ fn to_code_extent(&self) -> Option<CodeExtent> {
     }
 }
 
-#[derive(Debug, Copy)]
+#[derive(Debug, Copy, Clone)]
 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..2f2db8f38bd87e00ee12b8373c8edb5b302943e7 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, Clone)]
+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..f7e7d071f8ca4b7c81d5373e5aa576c26e70cece 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 {
@@ -96,7 +99,7 @@ pub enum MethodMatchResult {
     MethodDidNotMatch,
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum MethodMatchedData {
     // In the case of a precise match, we don't really need to store
     // how the match was found. So don't.
@@ -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..1123c9236312a70a9bd069445a5ef25d6b5ca0fe 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;
 
@@ -258,7 +262,7 @@ pub struct field_ty {
 
 // Contains information needed to resolve types and (in the future) look up
 // the types of AST nodes.
-#[derive(Copy, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct creader_cache_key {
     pub cnum: CrateNum,
     pub pos: usize,
@@ -592,7 +596,7 @@ fn foo<T:quux,baz,bar>(a: T) -- a's vtable would have a
 /// will push one or more such restriction into the
 /// `transmute_restrictions` vector during `intrinsicck`. They are
 /// then checked during `trans` by the fn `check_intrinsics`.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct TransmuteRestriction<'tcx> {
     /// The span whence the restriction comes.
     pub span: Span,
@@ -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
@@ -875,7 +886,7 @@ macro_rules! sty_debug_print {
         // variable names.
         mod inner {
             use middle::ty;
-            #[derive(Copy)]
+            #[derive(Copy, Clone)]
             struct DebugStat {
                 total: usize,
                 region_infer: usize,
@@ -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> {
@@ -4002,7 +4003,7 @@ fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
 ///
 /// The ordering of the cases is significant. They are sorted so that cmp::max
 /// will keep the "more erroneous" of two values.
-#[derive(Copy, PartialOrd, Ord, Eq, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)]
 pub enum Representability {
     Representable,
     ContainsRecursive,
@@ -4733,7 +4734,7 @@ pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
 /// two kinds of rvalues is an artifact of trans which reflects how we will
 /// generate code for that kind of expression.  See trans/expr.rs for more
 /// information.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum ExprKind {
     LvalueExpr,
     RvalueDpsExpr,
@@ -5429,7 +5430,7 @@ pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
     with_path(cx, id, |path| ast_map::path_to_string(path)).to_string()
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum DtorKind {
     NoDtor,
     TraitDtor(DefId, bool)
@@ -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);
         }
     }
@@ -6947,7 +7154,7 @@ pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>,
     trait_ref.substs.clone().with_method(meth_tps, meth_regions)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum CopyImplementationError {
     FieldDoesNotImplementCopy(ast::Name),
     VariantDoesNotImplementCopy(ast::Name),
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 c67819ab7e3c42751c327342ed53ab86f73f8bf1..a7d608d2c879c960df0158c2e09fe6a20f9d7d48 100644 (file)
@@ -247,7 +247,7 @@ pub fn basic_options() -> Options {
 // users can have their own entry
 // functions that don't start a
 // scheduler
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum EntryFnType {
     EntryMain,
     EntryStart,
@@ -304,7 +304,7 @@ pub fn $buildfn(matches: &getopts::Matches) -> $struct_name
     {
         let mut op = $defaultfn();
         for option in matches.opt_strs($prefix) {
-            let mut iter = option.splitn(1, '=');
+            let mut iter = option.splitn(2, '=');
             let key = iter.next().unwrap();
             let value = iter.next();
             let option_to_lookup = key.replace("-", "_");
@@ -958,7 +958,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     }
 
     let libs = matches.opt_strs("l").into_iter().map(|s| {
-        let mut parts = s.splitn(1, '=');
+        let mut parts = s.splitn(2, '=');
         let kind = parts.next().unwrap();
         let (name, kind) = match (parts.next(), kind) {
             (None, name) |
@@ -1010,7 +1010,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let mut externs = HashMap::new();
     for arg in &matches.opt_strs("extern") {
-        let mut parts = arg.splitn(1, '=');
+        let mut parts = arg.splitn(2, '=');
         let name = match parts.next() {
             Some(s) => s,
             None => early_error("--extern value must not be empty"),
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..7dcd6ba6cd11f9fae652f40f996aa23d88ba43c8 100644 (file)
@@ -15,7 +15,7 @@
 use self::Arch::*;
 
 #[allow(non_camel_case_types)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Arch {
     Armv7,
     Armv7s,
@@ -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 268e469b7f91580b0e5a0773baea799e5e27f19e..f8da075e4bdc239929212106049be19c7bf0beca 100644 (file)
@@ -334,7 +334,7 @@ fn cleaned(self) -> InteriorKind {
     }
 }
 
-#[derive(Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum LoanPathElem {
     LpDeref(mc::PointerKind),    // `*LV` in README.md
     LpInterior(InteriorKind),    // `LV.f` in README.md
@@ -500,13 +500,13 @@ pub struct BckError<'tcx> {
     code: bckerr_code
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AliasableViolationKind {
     MutabilityViolation,
     BorrowViolation(euv::LoanCause)
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum MovedValueUseKind {
     MovedInUse,
     MovedInCapture,
index a4470acbe4d20dc8f043943759a32982c7a4ba6b..2d1b57243d1cccd192b7037d2a79134835b39d32 100644 (file)
@@ -94,7 +94,7 @@ fn clone(&self) -> MovePathIndex {
 const InvalidMovePathIndex: MovePathIndex = MovePathIndex(usize::MAX);
 
 /// Index into `MoveData.moves`, used like a pointer
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub struct MoveIndex(usize);
 
 impl MoveIndex {
@@ -125,7 +125,7 @@ pub struct MovePath<'tcx> {
     pub next_sibling: MovePathIndex,
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum MoveKind {
     Declared,   // When declared, variables start out "moved".
     MoveExpr,   // Expression or binding that moves a variable
@@ -133,7 +133,7 @@ pub enum MoveKind {
     Captured    // Closure creation that moves a value
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Move {
     /// Path being moved.
     pub path: MovePathIndex,
@@ -148,7 +148,7 @@ pub struct Move {
     pub next_move: MoveIndex
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Assignment {
     /// Path being assigned.
     pub path: MovePathIndex,
@@ -160,7 +160,7 @@ pub struct Assignment {
     pub span: Span,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct VariantMatch {
     /// downcast to the variant.
     pub path: MovePathIndex,
index fb8afa83d864d5dfc9f10a449945019284d06c81..ade52bfde35e6cac3cb3425429849f8a0756e7ad 100644 (file)
@@ -26,7 +26,7 @@
 use std::rc::Rc;
 use std::borrow::IntoCow;
 
-#[derive(Debug, Copy)]
+#[derive(Debug, Copy, Clone)]
 pub enum Variant {
     Loans,
     Moves,
index 456d5f7a60ab7bec88aa167507125b6da085e801..b32c6829a221ba481d87a8e5f865fc50e1ba69e1 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;
@@ -185,7 +182,7 @@ fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> {
 }
 
 // Whether to stop or continue compilation.
-#[derive(Copy, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum Compilation {
     Stop,
     Continue,
@@ -268,7 +265,7 @@ fn parse_pretty(&mut self,
 }
 
 // CompilerCalls instance for a regular rustc build.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct RustcDefaultCalls;
 
 impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
index 9e693a64ef0a2bf5710e77d22c5b513da98a806d..410f31e0900c4cabd7776454291e4f95b7d28785 100644 (file)
@@ -44,7 +44,7 @@
 use std::path::PathBuf;
 use std::str::FromStr;
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpSourceMode {
     PpmNormal,
     PpmEveryBodyLoops,
@@ -56,7 +56,7 @@ pub enum PpSourceMode {
 }
 
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpFlowGraphMode {
     Default,
     /// Drops the labels from the edges in the flowgraph output. This
@@ -65,7 +65,7 @@ pub enum PpFlowGraphMode {
     /// have become a pain to maintain.
     UnlabelledEdges,
 }
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpMode {
     PpmSource(PpSourceMode),
     PpmFlowGraph(PpFlowGraphMode),
@@ -74,7 +74,7 @@ pub enum PpMode {
 pub fn parse_pretty(sess: &Session,
                     name: &str,
                     extended: bool) -> (PpMode, Option<UserIdentifiedItem>) {
-    let mut split = name.splitn(1, '=');
+    let mut split = name.splitn(2, '=');
     let first = split.next().unwrap();
     let opt_second = split.next();
     let first = match (first, extended) {
@@ -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 e7443af3013aeff4519b5eae2585187b7257782f..3bb737ddc1279787b7c3de8fbf82a0eeb4db0259 100644 (file)
@@ -63,7 +63,7 @@
     "suggest using `loop { }` instead of `while true { }`"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct WhileTrue;
 
 impl LintPass for WhileTrue {
@@ -107,7 +107,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
     "shift exceeds the type's number of bits"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct TypeLimits {
     /// Id of the last visited negated expression
     negated_expr_id: ast::NodeId,
@@ -116,7 +116,7 @@ pub struct TypeLimits {
 impl TypeLimits {
     pub fn new() -> TypeLimits {
         TypeLimits {
-            negated_expr_id: -1,
+            negated_expr_id: !0,
         }
     }
 }
@@ -431,7 +431,7 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct ImproperCTypes;
 
 impl LintPass for ImproperCTypes {
@@ -474,7 +474,7 @@ fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
     "use of owned (Box type) heap memory"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct BoxPointers;
 
 impl BoxPointers {
@@ -621,7 +621,7 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
     "detects attributes that were not used by the compiler"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedAttributes;
 
 impl LintPass for UnusedAttributes {
@@ -662,7 +662,7 @@ fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
     "path statements with no effect"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct PathStatements;
 
 impl LintPass for PathStatements {
@@ -696,7 +696,7 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
     "unused result of an expression in a statement"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedResults;
 
 impl LintPass for UnusedResults {
@@ -764,7 +764,7 @@ fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool {
     "types, variants, traits and type parameters should have camel case names"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct NonCamelCaseTypes;
 
 impl NonCamelCaseTypes {
@@ -874,7 +874,7 @@ fn method_context(cx: &Context, id: ast::NodeId, span: Span) -> MethodContext {
     "methods, functions, lifetime parameters and modules should have snake case names"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct NonSnakeCase;
 
 impl NonSnakeCase {
@@ -1014,7 +1014,7 @@ fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
     "static constants should have uppercase identifiers"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct NonUpperCaseGlobals;
 
 impl NonUpperCaseGlobals {
@@ -1072,7 +1072,7 @@ fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
     "`if`, `match`, `while` and `return` do not need parentheses"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedParens;
 
 impl UnusedParens {
@@ -1166,7 +1166,7 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
     "unnecessary braces around an imported item"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedImportBraces;
 
 impl LintPass for UnusedImportBraces {
@@ -1196,7 +1196,7 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
     "using `Struct { x: x }` instead of `Struct { x }`"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct NonShorthandFieldPatterns;
 
 impl LintPass for NonShorthandFieldPatterns {
@@ -1233,7 +1233,7 @@ fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
     "unnecessary use of an `unsafe` block"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedUnsafe;
 
 impl LintPass for UnusedUnsafe {
@@ -1258,7 +1258,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
     "usage of `unsafe` code"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnsafeCode;
 
 impl LintPass for UnsafeCode {
@@ -1319,7 +1319,7 @@ fn check_trait_item(&mut self, cx: &Context, trait_item: &ast::TraitItem) {
     "detect mut variables which don't need to be mutable"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedMut;
 
 impl UnusedMut {
@@ -1388,7 +1388,7 @@ fn check_fn(&mut self, cx: &Context,
     "detects unnecessary allocations that can be eliminated"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnusedAllocation;
 
 impl LintPass for UnusedAllocation {
@@ -1625,7 +1625,7 @@ fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generic
     "detects potentially-forgotten implementations of `Copy`"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct MissingCopyImplementations;
 
 impl LintPass for MissingCopyImplementations {
@@ -1740,7 +1740,7 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) {
 }
 
 /// Checks for use of items with `#[deprecated]` attributes
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Stability;
 
 impl Stability {
@@ -1800,7 +1800,7 @@ fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
     "functions that cannot return without calling themselves"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnconditionalRecursion;
 
 
@@ -1991,7 +1991,7 @@ fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     "compiler plugin used as ordinary library in non-plugin crate"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct PluginAsLibrary;
 
 impl LintPass for PluginAsLibrary {
@@ -2045,7 +2045,7 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
     "const items will not have their symbols exported"
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct InvalidNoMangleItems;
 
 impl LintPass for InvalidNoMangleItems {
@@ -2088,7 +2088,7 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
 }
 
 /// Forbids using the `#[feature(...)]` attribute
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnstableFeatures;
 
 declare_lint! {
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 aca4d265bc963d12ec40d18a2c072c9fd9efac9f..e6350ae44d43f924d7ff2b12ea46435b6d551230 100644 (file)
@@ -18,7 +18,7 @@
 
 use {ValueRef, TwineRef, DebugLocRef, DiagnosticInfoRef};
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum OptimizationDiagnosticKind {
     OptimizationRemark,
     OptimizationMissed,
@@ -38,7 +38,7 @@ pub fn describe(self) -> &'static str {
 }
 
 #[allow(raw_pointer_derive)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct OptimizationDiagnostic {
     pub kind: OptimizationDiagnosticKind,
     pub pass_name: *const c_char,
@@ -69,14 +69,13 @@ unsafe fn unpack(kind: OptimizationDiagnosticKind, di: DiagnosticInfoRef)
     }
 }
 
+#[derive(Copy, Clone)]
 pub struct InlineAsmDiagnostic {
     pub cookie: c_uint,
     pub message: TwineRef,
     pub instruction: ValueRef,
 }
 
-impl Copy for InlineAsmDiagnostic {}
-
 impl InlineAsmDiagnostic {
     unsafe fn unpack(di: DiagnosticInfoRef)
             -> InlineAsmDiagnostic {
@@ -96,7 +95,7 @@ unsafe fn unpack(di: DiagnosticInfoRef)
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Diagnostic {
     Optimization(OptimizationDiagnostic),
     InlineAsm(InlineAsmDiagnostic),
index c7b5b2e75346f9d2f77b31d24fe276eae5332e4c..9b0ae2e9ef858e852aa2c17788cb1f68636bcda4 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;
@@ -77,7 +76,7 @@
 
 // Consts for the LLVM CallConv type, pre-cast to usize.
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum CallConv {
     CCallConv = 0,
     FastCallConv = 8,
@@ -87,7 +86,7 @@ pub enum CallConv {
     X86_64_Win64 = 79,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Visibility {
     LLVMDefaultVisibility = 0,
     HiddenVisibility = 1,
@@ -98,7 +97,7 @@ pub enum Visibility {
 // DLLExportLinkage, GhostLinkage and LinkOnceODRAutoHideLinkage.
 // LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
 // they've been removed in upstream LLVM commit r203866.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Linkage {
     ExternalLinkage = 0,
     AvailableExternallyLinkage = 1,
@@ -114,7 +113,7 @@ pub enum Linkage {
 }
 
 #[repr(C)]
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum DiagnosticSeverity {
     Error,
     Warning,
@@ -155,7 +154,7 @@ pub enum DiagnosticSeverity {
 
 
 #[repr(u64)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum OtherAttribute {
     // The following are not really exposed in
     // the LLVM c api so instead to add these
@@ -176,13 +175,13 @@ pub enum OtherAttribute {
     NonNullAttribute = 1 << 44,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum SpecialAttribute {
     DereferenceableAttribute(u64)
 }
 
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AttributeSet {
     ReturnIndex = 0,
     FunctionIndex = !0
@@ -274,7 +273,7 @@ pub fn apply_callsite(&self, callsite: ValueRef) {
 }
 
 // enum for the LLVM IntPredicate type
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum IntPredicate {
     IntEQ = 32,
     IntNE = 33,
@@ -289,7 +288,7 @@ pub enum IntPredicate {
 }
 
 // enum for the LLVM RealPredicate type
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum RealPredicate {
     RealPredicateFalse = 0,
     RealOEQ = 1,
@@ -311,7 +310,7 @@ pub enum RealPredicate {
 
 // The LLVM TypeKind type - must stay in sync with the def of
 // LLVMTypeKind in llvm/include/llvm-c/Core.h
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 #[repr(C)]
 pub enum TypeKind {
     Void      = 0,
@@ -333,7 +332,7 @@ pub enum TypeKind {
 }
 
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AtomicBinOp {
     AtomicXchg = 0,
     AtomicAdd  = 1,
@@ -349,7 +348,7 @@ pub enum AtomicBinOp {
 }
 
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AtomicOrdering {
     NotAtomic = 0,
     Unordered = 1,
@@ -363,13 +362,13 @@ pub enum AtomicOrdering {
 
 // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum FileType {
     AssemblyFileType = 0,
     ObjectFileType = 1
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum MetadataType {
     MD_dbg = 0,
     MD_tbaa = 1,
@@ -386,13 +385,13 @@ pub enum MetadataType {
 }
 
 // Inline Asm Dialect
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AsmDialect {
     AD_ATT   = 0,
     AD_Intel = 1
 }
 
-#[derive(Copy, PartialEq, Clone)]
+#[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
 pub enum CodeGenOptLevel {
     CodeGenLevelNone = 0,
@@ -401,7 +400,7 @@ pub enum CodeGenOptLevel {
     CodeGenLevelAggressive = 3,
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 #[repr(C)]
 pub enum RelocMode {
     RelocDefault = 0,
@@ -411,7 +410,7 @@ pub enum RelocMode {
 }
 
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum CodeGenModel {
     CodeModelDefault = 0,
     CodeModelJITDefault = 1,
@@ -422,7 +421,7 @@ pub enum CodeGenModel {
 }
 
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum DiagnosticKind {
     DK_InlineAsm = 0,
     DK_StackSize,
@@ -534,7 +533,7 @@ pub enum DIBuilder_opaque {}
     pub type DIEnumerator = DIDescriptor;
     pub type DITemplateTypeParameter = DIDescriptor;
 
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub enum DIDescriptorFlags {
       FlagPrivate            = 1 << 0,
       FlagProtected          = 1 << 1,
@@ -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 5bff5479e2ea3ac82a77872f8aa5e7b681a2e9f4..52db6013f4d5df0b54f01abe3c47a026fc486b5d 100644 (file)
@@ -61,7 +61,7 @@
 
 // Specifies how duplicates should be handled when adding a child item if
 // another item exists with the same name in some namespace.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum DuplicateCheckingMode {
     ForbidDuplicateModules,
     ForbidDuplicateTypesAndModules,
@@ -70,7 +70,7 @@ enum DuplicateCheckingMode {
     OverwriteDuplicates
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum NamespaceError {
     NoError,
     ModuleError,
index ff635a6c46b22a34c6d4e2f913bad68e46f7d793..045320e4fa42565e3782bd682d76757d03631911 100644 (file)
 mod build_reduced_graph;
 mod resolve_imports;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct BindingInfo {
     span: Span,
     binding_mode: BindingMode,
@@ -116,14 +116,14 @@ struct BindingInfo {
 // Map from the name in a pattern to its binding mode.
 type BindingMap = HashMap<Name, BindingInfo>;
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum PatternBindingMode {
     RefutableMode,
     LocalIrrefutableMode,
     ArgumentIrrefutableMode,
 }
 
-#[derive(Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 enum Namespace {
     TypeNS,
     ValueNS
@@ -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> {
@@ -277,7 +280,7 @@ enum FallbackSuggestion {
     TraitMethod(String),
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum TypeParameters<'a> {
     NoTypeParameters,
     HasTypeParameters(
@@ -294,7 +297,7 @@ enum TypeParameters<'a> {
 
 // The rib kind controls the translation of local
 // definitions (`DefLocal`) to upvars (`DefUpvar`).
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum RibKind {
     // No translation needs to be applied.
     NormalRibKind,
@@ -316,7 +319,7 @@ enum RibKind {
     ConstantItemRibKind
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum UseLexicalScopeFlag {
     DontUseLexicalScope,
     UseLexicalScope
@@ -327,7 +330,7 @@ enum ModulePrefixResult {
     PrefixFound(Rc<Module>, usize)
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum NameSearchType {
     /// We're doing a name search in order to resolve a `use` directive.
     ImportSearch,
@@ -337,7 +340,7 @@ enum NameSearchType {
     PathSearch,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum BareIdentifierPatternResolution {
     FoundStructOrEnumVariant(Def, LastPrivate),
     FoundConst(Def, LastPrivate),
@@ -369,7 +372,7 @@ enum ParentLink {
 }
 
 /// The type of module this is.
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 enum ModuleKind {
     NormalModuleKind,
     TraitModuleKind,
@@ -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 \
@@ -3539,7 +3527,7 @@ pub struct CrateMap {
     pub glob_map: Option<GlobMap>
 }
 
-#[derive(PartialEq,Copy)]
+#[derive(PartialEq,Copy, Clone)]
 pub enum MakeGlobMap {
     Yes,
     No
index 44c803c77656d68e3704f4549e30d7ee99dbb306..f1a8507b1781197cc6683163bbf2b466978a2687 100644 (file)
@@ -37,7 +37,7 @@
 
 
 /// Contains data for specific types of import directives.
-#[derive(Copy,Debug)]
+#[derive(Copy, Clone,Debug)]
 pub enum ImportDirectiveSubclass {
     SingleImport(Name /* target */, Name /* source */),
     GlobImport
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 f7c0d6a983fb77899f9f9aef1e284b02bd13fd28..db724b0ef6b650b5eac3238af14bfc607add3b11 100644 (file)
@@ -62,7 +62,7 @@ macro_rules! svec {
     })
 }
 
-#[derive(Copy, Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 pub enum Row {
     Variable,
     Enum,
index ea8197d0c407e57a841e85f32488e072b8c2cf67..ef599a01e7c40fc5b8697ced0b52811c936bea3c 100644 (file)
 use syntax::fold::Folder;
 use syntax::ptr::P;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 struct ConstantExpr<'a>(&'a ast::Expr);
 
 impl<'a> ConstantExpr<'a> {
@@ -311,7 +311,7 @@ fn debug_loc(&self) -> DebugLoc {
     }
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum BranchKind {
     NoBranch,
     Single,
index e32d8e2b9cfdf8a7924442365489a2fb75598cd5..fd1fff308dfe3a543252305d73c4a9e427c3b326 100644 (file)
@@ -830,7 +830,7 @@ fn load_discr(bcx: Block, ity: IntType, ptr: ValueRef, min: Disr, max: Disr)
     let bits = machine::llbitsize_of_real(bcx.ccx(), llty);
     assert!(bits <= 64);
     let  bits = bits as usize;
-    let mask = (-1u64 >> (64 - bits)) as Disr;
+    let mask = (!0u64 >> (64 - bits)) as Disr;
     // For a (max) discr of -1, max will be `-1 as usize`, which overflows.
     // However, that is fine here (it would still represent the full range),
     if (max.wrapping_add(1)) & mask == min & mask {
index 61e332f87ad1a2683aeb65b8676b7e4cfc570509..05c366a645e76daaec0816d2d4187d436d1ee565 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)));
@@ -859,7 +868,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
             _ => unreachable!(),
         };
         let minus_one = ICmp(bcx, llvm::IntEQ, rhs,
-                             C_integral(llty, -1, false), debug_loc);
+                             C_integral(llty, !0, false), debug_loc);
         with_cond(bcx, minus_one, |bcx| {
             let is_min = ICmp(bcx, llvm::IntEQ, lhs,
                               C_integral(llty, min, true), debug_loc);
@@ -1379,7 +1388,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
     common::validate_substs(param_substs);
 
     debug!("new_fn_ctxt(path={}, id={}, param_substs={})",
-           if id == -1 {
+           if id == !0 {
                "".to_string()
            } else {
                ccx.tcx().map.path_to_string(id).to_string()
@@ -2103,7 +2112,7 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
 
 
 /// Enum describing the origin of an LLVM `Value`, for linkage purposes.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum ValueOrigin {
     /// The LLVM `Value` is in this context because the corresponding item was
     /// assigned to the current compilation unit.
index a0aca17538fa9966269d8ed15ee10c6ccd65969b..d3d055cda120293d172413158976fef590039b96 100644 (file)
@@ -13,7 +13,7 @@
 use trans::value::{Users, Value};
 use std::iter::{Filter, Map};
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct BasicBlock(pub BasicBlockRef);
 
 pub type Preds = Map<Filter<Users, fn(&Value) -> bool>, fn(Value) -> BasicBlock>;
index e33ec29017cc8120b02f945f047a5c052e1ff3c1..9eb46d3ff549a80bd33a7ef06295fc67f8a676a8 100644 (file)
@@ -60,7 +60,7 @@
 use syntax::ast_map;
 use syntax::ptr::P;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct MethodData {
     pub llfn: ValueRef,
     pub llself: ValueRef,
@@ -1110,7 +1110,7 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     bcx
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AutorefArg {
     DontAutorefArg,
     DoAutorefArg(ast::NodeId)
index 4897ae286d3e96354b19cbeb5dbbf3bb40beddb9..19891e9307229fa52ee380c21b743b0f67fe9d5b 100644 (file)
@@ -153,7 +153,7 @@ pub struct CleanupScope<'blk, 'tcx: 'blk> {
     cached_landing_pad: Option<BasicBlockRef>,
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct CustomScopeIndex {
     index: usize
 }
@@ -184,14 +184,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum EarlyExitLabel {
     UnwindExit,
     ReturnExit,
     LoopExit(ast::NodeId, usize)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct CachedEarlyExit {
     label: EarlyExitLabel,
     cleanup_block: BasicBlockRef,
@@ -209,7 +209,7 @@ fn trans<'blk>(&self,
 
 pub type CleanupObj<'tcx> = Box<Cleanup<'tcx>+'tcx>;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum ScopeId {
     AstScope(ast::NodeId),
     CustomScope(CustomScopeIndex)
@@ -982,7 +982,7 @@ fn is_unwind(&self) -> bool {
 ///////////////////////////////////////////////////////////////////////////
 // Cleanup types
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct DropValue<'tcx> {
     is_immediate: bool,
     must_unwind: bool,
@@ -1021,12 +1021,12 @@ fn trans<'blk>(&self,
     }
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum Heap {
     HeapExchange
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct FreeValue<'tcx> {
     ptr: ValueRef,
     heap: Heap,
@@ -1061,7 +1061,7 @@ fn trans<'blk>(&self,
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct FreeSlice {
     ptr: ValueRef,
     size: ValueRef,
@@ -1098,7 +1098,7 @@ fn trans<'blk>(&self,
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct LifetimeEnd {
     ptr: ValueRef,
 }
index 745098d6e87d11f9b1b8cac372e313dadbb91e40..c5985e930e97b98b72fc9e3ffdb72a3c6e1af935 100644 (file)
@@ -343,7 +343,7 @@ pub fn gensym_name(name: &str) -> PathElem {
 *
 */
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct NodeIdAndSpan {
     pub id: ast::NodeId,
     pub span: Span,
@@ -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
@@ -1199,7 +1225,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &infer::InferCtxt<'a,'tcx>,
 }
 
 // Key used to lookup values supplied for type parameters in an expr.
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum ExprOrMethodCall {
     // Type parameters for a path like `None::<int>`
     ExprId(ast::NodeId),
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 3542bcd081f31c3e744988daac3d34750c3ff353..8919a386a45fb0ac1182174d8dbc65301f9f0318 100644 (file)
@@ -459,7 +459,7 @@ fn dummy_ccx<'a>(&'a self, shared: &'a SharedCrateContext<'tcx>)
         CrateContext {
             shared: shared,
             local: self,
-            index: -1 as usize,
+            index: !0 as usize,
         }
     }
 }
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 7b983ca4ac6ac9cfaa394724febd87674c79b84f..a736a9fe88a1408de7da76457766aa7ca8fa8f52 100644 (file)
@@ -172,7 +172,7 @@ impl Drop for Rvalue {
     fn drop(&mut self) { }
 }
 
-#[derive(Copy, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub enum RvalueMode {
     /// `val` is a pointer to the actual value (and thus has type *T)
     ByRef,
index f2c24501c66c8e6c97856919fa471b01f01b0fcb..2747288b60755c9245156bb496e4278d859e1aef 100644 (file)
@@ -2382,7 +2382,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum EnumDiscriminantInfo {
     RegularDiscriminant(DIType),
     OptimizedDiscriminant,
@@ -3106,7 +3106,7 @@ fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationRes
     }
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum InternalDebugLocation {
     KnownLocation { scope: DIScope, line: usize, col: usize },
     UnknownLocation
@@ -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 46cbd1936002aef12621e03f91d45205ea0eb74b..5a79aa35bfae175b1eee83da494f2a9ae2563a39 100644 (file)
@@ -94,7 +94,7 @@
 // These are passed around by the code generating functions to track the
 // destination of a computation's value.
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum Dest {
     SaveIn(ValueRef),
     Ignore,
@@ -2038,7 +2038,7 @@ fn float_cast(bcx: Block,
     } else { llsrc };
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum cast_kind {
     cast_pointer,
     cast_integral,
index f7433e6a774093de216abddf42379d9c492081ff..c7857d6a775f3f3163c81b191b5b5033f25b605e 100644 (file)
@@ -57,7 +57,7 @@
 mod llrepr;
 mod cleanup;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct ModuleTranslation {
     pub llcx: ContextRef,
     pub llmod: ModuleRef,
index 34dfb0eebcf9d47cfb7cacbce210dd8d35f175f1..791b58d88a93e97d84e934371ad2df617c49c3f2 100644 (file)
@@ -33,7 +33,7 @@
 use syntax::ast;
 use syntax::parse::token::InternedString;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct VecTypes<'tcx> {
     unit_ty: Ty<'tcx>,
     llunit_ty: Type
index c2d91e4e160248925d084b34c5e259515b0645f9..bc71278c157434988a59da92ab11681d4b141976 100644 (file)
@@ -14,7 +14,7 @@
 use trans::common::Block;
 use libc::c_uint;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Value(pub ValueRef);
 
 macro_rules! opt_val { ($e:expr) => (
@@ -125,7 +125,7 @@ pub fn is_a_terminator_inst(self) -> bool {
 }
 
 /// Wrapper for LLVM UseRef
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Use(UseRef);
 
 impl Use {
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 af33cdb39326371cbe42205ad6c3d92ef8ed5c96..677ab56852434802541e68a64f1014b2548085e8 100644 (file)
@@ -52,7 +52,7 @@ pub enum MethodError {
 
 // A pared down enum describing just the places from which a method
 // candidate can arise. Used for error reporting only.
-#[derive(Copy, PartialOrd, Ord, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
 pub enum CandidateSource {
     ImplSource(ast::DefId),
     TraitSource(/* trait id */ ast::DefId),
index 6349ea57f2ff15d96801592117cc9fc0ace1d2a5..41eae88158905f3ebc6e0180e351e71e6f9c97a2 100644 (file)
@@ -109,7 +109,7 @@ pub enum PickAdjustment {
     AutoRef(ast::Mutability, Box<PickAdjustment>),
 }
 
-#[derive(PartialEq, Eq, Copy)]
+#[derive(PartialEq, Eq, Copy, Clone)]
 pub enum Mode {
     // An expression of the form `receiver.method_name(...)`.
     // Autoderefs are performed on `receiver`, lookup is done based on the
@@ -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 9832fe1cb6eacd35ebf8ac3723829c28a68a129b..c5ff8a14bc1cf33be1a294297b2fc5cbddc8b800 100644 (file)
@@ -266,7 +266,7 @@ fn is_local(ty: Ty) -> bool {
     }).2.is_some()
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct TraitInfo {
     pub def_id: ast::DefId,
 }
index 16501ec280791d2886daffee7a0d39d9e71d4645..156fbfede9c98aebf51b120086f56b005bbdd28c 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;
 use syntax::ast::{self, DefId, Visibility};
 use syntax::ast_util::{self, local_def};
 use syntax::codemap::{self, Span};
+use syntax::feature_gate;
 use syntax::owned_slice::OwnedSlice;
 use syntax::parse::token;
 use syntax::print::pprust;
@@ -204,7 +205,7 @@ struct CastCheck<'tcx> {
 
 /// When type-checking an expression, we propagate downward
 /// whatever type hint we are able in the form of an `Expectation`.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Expectation<'tcx> {
     /// We know nothing about what type this expression should have.
     NoExpectation,
@@ -1951,14 +1952,14 @@ fn anon_regions(&self, span: Span, count: usize)
     }
 }
 
-#[derive(Copy, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum LvaluePreference {
     PreferMutLvalue,
     NoPreference
 }
 
 /// Whether `autoderef` requires types to resolve.
-#[derive(Copy, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub enum UnresolvedTypeAction {
     /// Produce an error and return `ty_err` whenever a type cannot
     /// be resolved (i.e. it is `ty_infer`).
@@ -3258,6 +3259,15 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                                       tcx.lang_items.neg_trait(),
                                                       expr, &**oprnd, oprnd_t, unop);
                     }
+                    if let ty::ty_uint(_) = oprnd_t.sty {
+                        if !tcx.sess.features.borrow().negate_unsigned {
+                            feature_gate::emit_feature_err(
+                                &tcx.sess.parse_sess.span_diagnostic,
+                                "negate_unsigned",
+                                expr.span,
+                                "unary negation of unsigned integers may be removed in the future");
+                        }
+                    }
                 }
             }
         }
@@ -3329,7 +3339,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 +3349,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 +4295,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;
 
+        let inh = static_inherited_fields(ccx);
+        let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
+
+        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);
+            }
+        }
 
-            // 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 def_id = local_def(id);
 
-            match v.node.disr_expr {
-                Some(ref e) => {
-                    debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
+        // ty::enum_variants guards against discriminant overflows, so
+        // we need not check for that.
+        let variants = ty::enum_variants(ccx.tcx, 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,
-
-                        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 +4346,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 +4362,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 23e31df5395268971b0c821f8ffd96a08da76d0d..a86e2b17c93b839775dc3f13457033c5a215d283 100644 (file)
@@ -249,11 +249,6 @@ fn check_impl(&mut self,
                                                         &fcx.inh.param_env.free_substs,
                                                         &trait_ref);
 
-            if fcx.tcx().lang_items.copy_trait() == Some(trait_ref.def_id) {
-                // This is checked in coherence.
-                return
-            }
-
             // We are stricter on the trait-ref in an impl than the
             // self-type.  In particular, we enforce region
             // relationships. The reason for this is that (at least
index 4d7a046fc607bd125df812c1d6fd86d5343b76af..37f43252483aae2fe2ffbad0d43f2f045613ade1 100644 (file)
@@ -350,7 +350,7 @@ fn resolve<T:TypeFoldable<'tcx>>(&self, t: &T, reason: ResolveReason) -> T {
 ///////////////////////////////////////////////////////////////////////////
 // Resolution reason.
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum ResolveReason {
     ResolvingExpr(Span),
     ResolvingLocal(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 dd306c4da862d79a3f21587f65addc567ef03f06..8f1b8bf109215d6caa2825ce2dc7eac907ef89ed 100644 (file)
@@ -135,7 +135,7 @@ struct ItemCtxt<'a,'tcx:'a> {
     param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
 }
 
-#[derive(Copy, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq)]
 enum AstConvRequest {
     GetItemTypeScheme(ast::DefId),
     GetTraitDef(ast::DefId),
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 f1050a936e276f480f5ff0f822432dafe4ba90de..c908e21626e56eaa33c616f1ed044210a3ebdc3d 100644 (file)
@@ -40,7 +40,7 @@ fn anon_regions(&self,
 
 // A scope in which all regions must be explicitly named. This is used
 // for types that appear in structs and so on.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct ExplicitRscope;
 
 impl RegionScope for ExplicitRscope {
index b014238b6f286d32fa50502c38188f21234a7d47..b83d8fc6af7fafe60871137dc864d67a66b91e7d 100644 (file)
@@ -295,10 +295,10 @@ pub fn infer_variance(tcx: &ty::ctxt) {
 
 type VarianceTermPtr<'a> = &'a VarianceTerm<'a>;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 struct InferredIndex(usize);
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum VarianceTerm<'a> {
     ConstantTerm(ty::Variance),
     TransformTerm(VarianceTermPtr<'a>, VarianceTermPtr<'a>),
@@ -336,7 +336,7 @@ struct TermsContext<'a, 'tcx: 'a> {
     inferred_infos: Vec<InferredInfo<'a>> ,
 }
 
-#[derive(Copy, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 enum ParamKind {
     TypeParam,
     RegionParam,
@@ -560,7 +560,7 @@ struct ConstraintContext<'a, 'tcx: 'a> {
 
 /// Declares that the variable `decl_id` appears in a location with
 /// variance `variance`.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Constraint<'a> {
     inferred: InferredIndex,
     variance: &'a VarianceTerm<'a>,
index e4d9fac5b9cb53e5d90bb790ef877d10879efecc..e0ed83f401945b11d07bfbaf5992fde6b75a3cff 100644 (file)
@@ -2392,7 +2392,7 @@ fn resolve_type(cx: &DocContext,
     };
 
     match def {
-        def::DefSelfTy(..) => {
+        def::DefSelfTy(..) if path.segments.len() == 1 => {
             return Generic(token::get_name(special_idents::type_self.name).to_string());
         }
         def::DefPrimTy(p) => match p {
@@ -2412,7 +2412,9 @@ fn resolve_type(cx: &DocContext,
             ast::TyFloat(ast::TyF32) => return Primitive(F32),
             ast::TyFloat(ast::TyF64) => return Primitive(F64),
         },
-        def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()),
+        def::DefTyParam(_, _, _, n) => {
+            return Generic(token::get_name(n).to_string())
+        }
         _ => {}
     };
     let did = register_def(&*cx, def);
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 df6beab0f5832ebc75bbfdf62fbd0b6a412bbeef..ed37b973f787ec16e4d9f9497f89732351789657 100644 (file)
 
 /// Helper to render an optional visibility with a space after it (if the
 /// visibility is preset)
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct VisSpace(pub Option<ast::Visibility>);
 /// Similarly to VisSpace, this structure is used to render a function style with a
 /// space after it.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct UnsafetySpace(pub ast::Unsafety);
 /// Wrapper struct for properly emitting a method declaration.
 pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl);
 /// Similar to VisSpace, but used for mutability
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct MutableSpace(pub clean::Mutability);
 /// Similar to VisSpace, but used for mutability
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct RawMutableSpace(pub clean::Mutability);
 /// Wrapper struct for properly emitting the stability level.
 pub struct Stability<'a>(pub &'a Option<clean::Stability>);
index 179418174d950ede4ade22a8c2c0af29d29773e1..ac097d051b28673aad0bf492abf01a75a4a05778 100644 (file)
@@ -225,7 +225,7 @@ struct SourceCollector<'a> {
 // Helper structs for rendering items/sidebars and carrying along contextual
 // information
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Item<'a> {
     cx: &'a Context,
     item: &'a clean::Item,
index 431cb4a28989e1902866b7d5674b38c3dd17839b..d1dcfc26008686624e92cdd22ce8085caf612980 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;
@@ -335,7 +333,7 @@ fn acquire_input(input: &str,
 fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
     let mut externs = HashMap::new();
     for arg in &matches.opt_strs("extern") {
-        let mut parts = arg.splitn(1, '=');
+        let mut parts = arg.splitn(2, '=');
         let name = match parts.next() {
             Some(s) => s,
             None => {
index f75fced3bc26d0e04faf4f95ed3d4df95bf81eca..3e4f6896ee68db2181121dd351b79ae33ee65ed2 100644 (file)
@@ -27,7 +27,7 @@
 
 #[derive(RustcEncodable, RustcDecodable, PartialEq, Eq)]
 /// The counts for each stability level.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Counts {
     pub deprecated: u64,
     pub unstable: u64,
index babbe15b17df51ad1beeaa06f6540f6c2c951e74..f5bee6240d46c80dc5ee321742b500cb958ec3c0 100644 (file)
@@ -19,7 +19,6 @@
 use std::process::Command;
 use std::str;
 use std::sync::{Arc, Mutex};
-use std::thunk::Thunk;
 
 use testing;
 use rustc_lint;
@@ -366,7 +365,7 @@ pub fn add_test(&mut self, test: String,
                 ignore: should_ignore,
                 should_panic: testing::ShouldPanic::No, // compiler failures are test failures
             },
-            testfn: testing::DynTestFn(Thunk::new(move|| {
+            testfn: testing::DynTestFn(Box::new(move|| {
                 runtest(&test,
                         &cratename,
                         libs,
index dc44536d60cea0403a619e3a27f814926111a6b3..0676edf81696f5647048681cccddb38ad175c81c 100644 (file)
@@ -62,7 +62,7 @@ pub trait FromHex {
 }
 
 /// Errors that can occur when decoding a hex encoded string
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum FromHexError {
     /// The input contained a character not part of the hex format
     InvalidHexCharacter(char, usize),
index 2d5d8cd501a46100e1fc493b03d382b6139ca784..5890bdec8c1bcdbcc66524c324095a7ceb91fd77 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();
 //! }
 //! ```
 //!
@@ -278,7 +278,7 @@ pub enum DecoderError {
     ApplicationError(string::String)
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum EncoderError {
     FmtError(fmt::Error),
     BadHashmapKey,
@@ -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..dec6d1e2209ad9b982f695ce6f06b2efb50ecd32 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;
@@ -87,6 +87,9 @@ struct RawBucket<K, V> {
 }
 
 impl<K,V> Copy for RawBucket<K,V> {}
+impl<K,V> Clone for RawBucket<K,V> {
+    fn clone(&self) -> RawBucket<K, V> { *self }
+}
 
 pub struct Bucket<K, V, M> {
     raw:   RawBucket<K, V>,
@@ -95,6 +98,9 @@ pub struct Bucket<K, V, M> {
 }
 
 impl<K,V,M:Copy> Copy for Bucket<K,V,M> {}
+impl<K,V,M:Copy> Clone for Bucket<K,V,M> {
+    fn clone(&self) -> Bucket<K,V,M> { *self }
+}
 
 pub struct EmptyBucket<K, V, M> {
     raw:   RawBucket<K, V>,
@@ -129,7 +135,7 @@ struct GapThenFull<K, V, M> {
 
 /// A hash that is not zero, since we use a hash of zero to represent empty
 /// buckets.
-#[derive(PartialEq, Copy)]
+#[derive(PartialEq, Copy, Clone)]
 pub struct SafeHash {
     hash: u64,
 }
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
     }
diff --git a/src/libstd/error.rs b/src/libstd/error.rs
new file mode 100644 (file)
index 0000000..150ffcd
--- /dev/null
@@ -0,0 +1,152 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Traits for working with Errors.
+//!
+//! # The `Error` trait
+//!
+//! `Error` is a trait representing the basic expectations for error values,
+//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
+//! a description, but they may optionally provide additional detail (via
+//! `Display`) and cause chain information:
+//!
+//! ```
+//! use std::fmt::Display;
+//!
+//! trait Error: Display {
+//!     fn description(&self) -> &str;
+//!
+//!     fn cause(&self) -> Option<&Error> { None }
+//! }
+//! ```
+//!
+//! The `cause` method is generally used when errors cross "abstraction
+//! boundaries", i.e.  when a one module must report an error that is "caused"
+//! by an error from a lower-level module. This setup makes it possible for the
+//! 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.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+// A note about crates and the facade:
+//
+// Originally, the `Error` trait was defined in libcore, and the impls
+// were scattered about. However, coherence objected to this
+// arrangement, because to create the blanket impls for `Box` required
+// knowing that `&str: !Error`, and we have no means to deal with that
+// sort of conflict just now. Therefore, for the time being, we have
+// moved the `Error` trait into libstd. As we evolve a sol'n to the
+// coherence challenge (e.g., specialization, neg impls, etc) we can
+// reconsider what crate these items belong in.
+
+use boxed::Box;
+use convert::From;
+use fmt::{self, Debug, Display};
+use marker::Send;
+use num;
+use option::Option;
+use option::Option::None;
+use str;
+use string::{self, String};
+
+/// Base functionality for all errors in Rust.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Error: Debug + Display {
+    /// A short description of the error.
+    ///
+    /// The description should not contain newlines or sentence-ending
+    /// punctuation, to facilitate embedding in larger user-facing
+    /// strings.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn description(&self) -> &str;
+
+    /// The lower-level cause of this error, if any.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn cause(&self) -> Option<&Error> { None }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+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(String);
+
+        impl Error for StringError {
+            fn description(&self) -> &str { &self.0 }
+        }
+
+        impl Display for StringError {
+            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+                Display::fmt(&self.0, f)
+            }
+        }
+
+        Box::new(StringError(String::from_str(err)))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for str::ParseBoolError {
+    fn description(&self) -> &str { "failed to parse bool" }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for str::Utf8Error {
+    fn description(&self) -> &str {
+        match *self {
+            str::Utf8Error::TooShort => "invalid utf-8: not enough bytes",
+            str::Utf8Error::InvalidByte(..) => "invalid utf-8: corrupt contents",
+        }
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for num::ParseIntError {
+    fn description(&self) -> &str {
+        self.description()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for num::ParseFloatError {
+    fn description(&self) -> &str {
+        self.description()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for string::FromUtf8Error {
+    fn description(&self) -> &str {
+        "invalid utf-8"
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for string::FromUtf16Error {
+    fn description(&self) -> &str {
+        "invalid utf-16"
+    }
+}
+
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..4e2dade
--- /dev/null
@@ -0,0 +1,1910 @@
+// 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.
+///
+/// Generally speaking, when using `OpenOptions`, you'll first call `new()`, then chain calls to
+/// methods to set each option, then call `open()`, passing the path of the file you're trying to
+/// open. This will give you a [`io::Result`][result] with a [`File`][file] inside that you can
+/// further operate on.
+///
+/// [result]: ../io/type.Result.html
+/// [file]: struct.File.html
+///
+/// # Examples
+///
+/// Opening a file to read:
+///
+/// ```no_run
+/// use std::fs;
+/// use std::fs::OpenOptions;
+///
+/// let file = OpenOptions::new().read(true).open("foo.txt");
+/// ```
+///
+/// Opening a file for both reading and writing, as well as creating it if it doesn't exist:
+///
+/// ```
+/// use std::fs;
+/// use std::fs::OpenOptions;
+///
+/// let file = OpenOptions::new()
+///             .read(true)
+///             .write(true)
+///             .create(true)
+///             .open("foo.txt");
+/// ```
+#[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`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().open("foo.txt");
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().read(true).open("foo.txt");
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().write(true).open("foo.txt");
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().append(true).open("foo.txt");
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().truncate(true).open("foo.txt");
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().create(true).open("foo.txt");
+    /// ```
+    #[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)
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::OpenOptions;
+    ///
+    /// let file = OpenOptions::new().open("foo.txt");
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// assert!(!metadata.is_dir());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// assert!(metadata.is_file());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// assert_eq!(0, metadata.len());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # fn foo() -> std::io::Result<()> {
+    /// use std::fs;
+    ///
+    /// let metadata = try!(fs::metadata("foo.txt"));
+    ///
+    /// assert!(!metadata.permissions().readonly());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    ///
+    /// assert_eq!(false, metadata.permissions().readonly());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let mut permissions = metadata.permissions();
+    ///
+    /// permissions.set_readonly(true);
+    ///
+    /// // filesystem doesn't change
+    /// assert_eq!(false, metadata.permissions().readonly());
+    ///
+    /// // just this particular `permissions`.
+    /// assert_eq!(true, permissions.readonly());
+    /// # Ok(())
+    /// # }
+    /// ```
+    #[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.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// # fn foo() -> std::io::Result<()> {
+    /// for entry in try!(fs::read_dir(".")) {
+    ///     let dir = try!(entry);
+    ///     println!("{:?}", dir.path());
+    /// }
+    /// # Ok(())
+    /// # }
+    /// ```
+    ///
+    /// This prints output like:
+    ///
+    /// ```text
+    /// "./whatever.txt"
+    /// "./foo.html"
+    /// "./hello_world.rs"
+    /// ```
+    ///
+    /// The exact text, of course, depends on what files you have in `.`.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn path(&self) -> PathBuf { self.0.path() }
+}
+
+/// Remove a file from the underlying filesystem.
+///
+/// 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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::remove_file("a.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[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
+/// # 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.
+///
+/// # 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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::rename("a.txt", "b.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[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.
+///
+/// # 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`
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::fs;
+///
+/// fs::copy("foo.txt", "bar.txt");
+/// ```
+#[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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::hard_link("a.txt", "b.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::soft_link("a.txt", "b.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let path = try!(fs::read_link("a.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[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
+///
+/// # 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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::create_dir("/some/dir"));
+/// # Ok(())
+/// # }
+/// ```
+#[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`.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::create_dir_all("/some/dir"));
+/// # Ok(())
+/// # }
+/// ```
+#[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
+///
+/// # 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.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::remove_dir("/some/dir"));
+/// # Ok(())
+/// # }
+/// ```
+#[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`.
+///
+/// # Examples
+///
+/// ```
+/// use std::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::remove_dir_all("/some/dir"));
+/// # Ok(())
+/// # }
+/// ```
+#[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)) {
+                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..5c9ff544fa3e8f3380b0876f87bf8e6495a4ef5e 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;
 pub use core::simd;
 pub use core::result;
 pub use core::option;
-pub use core::error;
+pub mod error;
 
 #[cfg(not(test))] pub use alloc::boxed;
 pub use alloc::rc;
 #[path = "num/f64.rs"]   pub mod f64;
 
 pub mod ascii;
+
 pub mod thunk;
 
 /* Common traits */
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..886f252fb192672b086bc347b87f8b0acae2d130 100644 (file)
@@ -435,13 +435,13 @@ macro_rules! try_opt {
                 match $e {
                     Some(r) => r,
                     None => return Err(io::Error::new(io::ErrorKind::InvalidInput,
-                                                      $msg, None)),
+                                                      $msg)),
                 }
             )
         }
 
         // split the string by ':' and convert the second part to u16
-        let mut parts_iter = self.rsplitn(1, ':');
+        let mut parts_iter = self.rsplitn(2, ':');
         let port_str = try_opt!(parts_iter.next(), "invalid socket address");
         let host = try_opt!(parts_iter.next(), "invalid socket address");
         let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
@@ -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 fe55f40390e1754a07a2b3da1bfffbc985527e28..ea869ebae100a9ca15294e1ed3da6d0d0b32f482 100644 (file)
@@ -25,7 +25,7 @@
 use vec::Vec;
 
 /// A flag that specifies whether to use exponential (scientific) notation.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum ExponentFormat {
     /// Do not use exponential notation.
     ExpNone,
@@ -40,7 +40,7 @@ pub enum ExponentFormat {
 
 /// The number of digits used for emitting the fractional part of a number, if
 /// any.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum SignificantDigits {
     /// All calculable digits will be printed.
     ///
@@ -57,7 +57,7 @@ pub enum SignificantDigits {
 }
 
 /// How to emit the sign of a number.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum SignFormat {
     /// No sign will be printed. The exponent sign will also be emitted.
     SignNone,
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..509daa46ef3be1b509d54da638c27590b8d2dff5 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)
     }
@@ -969,7 +970,7 @@ fn file_test_io_smoke_test() {
             let mut read_stream = File::open_mode(filename, Open, Read);
             let mut read_buf = [0; 1028];
             let read_str = match check!(read_stream.read(&mut read_buf)) {
-                -1|0 => panic!("shouldn't happen"),
+                0 => panic!("shouldn't happen"),
                 n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
             };
             assert_eq!(read_str, message);
@@ -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..5e93757668cbd45e3c4dc78bce1b4cdf826d8a1f 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};
@@ -391,7 +391,7 @@ fn description(&self) -> &str { self.desc }
 }
 
 /// A list specifying general categories of I/O error.
-#[derive(Copy, PartialEq, Eq, Clone, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum IoErrorKind {
     /// Any I/O error not part of this list.
     OtherIoError,
@@ -726,28 +726,28 @@ fn read_be_int_n(&mut self, nbytes: usize) -> IoResult<i64> {
     ///
     /// The number of bytes returned is system-dependent.
     fn read_le_uint(&mut self) -> IoResult<usize> {
-        self.read_le_uint_n(usize::BYTES as usize).map(|i| i as usize)
+        self.read_le_uint_n(usize::BYTES).map(|i| i as usize)
     }
 
     /// Reads a little-endian integer.
     ///
     /// The number of bytes returned is system-dependent.
     fn read_le_int(&mut self) -> IoResult<isize> {
-        self.read_le_int_n(isize::BYTES as usize).map(|i| i as isize)
+        self.read_le_int_n(isize::BYTES).map(|i| i as isize)
     }
 
     /// Reads a big-endian unsigned integer.
     ///
     /// The number of bytes returned is system-dependent.
     fn read_be_uint(&mut self) -> IoResult<usize> {
-        self.read_be_uint_n(usize::BYTES as usize).map(|i| i as usize)
+        self.read_be_uint_n(usize::BYTES).map(|i| i as usize)
     }
 
     /// Reads a big-endian integer.
     ///
     /// The number of bytes returned is system-dependent.
     fn read_be_int(&mut self) -> IoResult<isize> {
-        self.read_be_int_n(isize::BYTES as usize).map(|i| i as isize)
+        self.read_be_int_n(isize::BYTES).map(|i| i as isize)
     }
 
     /// Reads a big-endian `u64`.
@@ -1110,25 +1110,25 @@ fn write_uint(&mut self, n: usize) -> IoResult<()> {
     /// Write a little-endian usize (number of bytes depends on system).
     #[inline]
     fn write_le_uint(&mut self, n: usize) -> IoResult<()> {
-        extensions::u64_to_le_bytes(n as u64, usize::BYTES as usize, |v| self.write_all(v))
+        extensions::u64_to_le_bytes(n as u64, usize::BYTES, |v| self.write_all(v))
     }
 
     /// Write a little-endian isize (number of bytes depends on system).
     #[inline]
     fn write_le_int(&mut self, n: isize) -> IoResult<()> {
-        extensions::u64_to_le_bytes(n as u64, isize::BYTES as usize, |v| self.write_all(v))
+        extensions::u64_to_le_bytes(n as u64, isize::BYTES, |v| self.write_all(v))
     }
 
     /// Write a big-endian usize (number of bytes depends on system).
     #[inline]
     fn write_be_uint(&mut self, n: usize) -> IoResult<()> {
-        extensions::u64_to_be_bytes(n as u64, usize::BYTES as usize, |v| self.write_all(v))
+        extensions::u64_to_be_bytes(n as u64, usize::BYTES, |v| self.write_all(v))
     }
 
     /// Write a big-endian isize (number of bytes depends on system).
     #[inline]
     fn write_be_int(&mut self, n: isize) -> IoResult<()> {
-        extensions::u64_to_be_bytes(n as u64, isize::BYTES as usize, |v| self.write_all(v))
+        extensions::u64_to_be_bytes(n as u64, isize::BYTES, |v| self.write_all(v))
     }
 
     /// Write a big-endian u64 (8 bytes).
@@ -1553,7 +1553,7 @@ fn lines<'r>(&'r mut self) -> Lines<'r, T> {
 
 /// When seeking, the resulting cursor is offset from a base by the offset given
 /// to the `seek` function. The base used is specified by this enumeration.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum SeekStyle {
     /// Seek from the beginning of the stream
     SeekSet,
@@ -1744,7 +1744,7 @@ pub enum FileType {
 ///
 /// println!("byte size: {}", info.size);
 /// ```
-#[derive(Copy, Hash)]
+#[derive(Copy, Clone, Hash)]
 pub struct FileStat {
     /// The size of the file, in bytes
     pub size: u64,
@@ -1783,7 +1783,7 @@ pub struct FileStat {
 /// structure. This information is not necessarily platform independent, and may
 /// have different meanings or no meaning at all on some platforms.
 #[unstable(feature = "io")]
-#[derive(Copy, Hash)]
+#[derive(Copy, Clone, Hash)]
 pub struct UnstableFileStat {
     /// The ID of the device containing the file.
     pub device: u64,
index 739439ebd151ba50b5ff401a75c1fe183829022b..dd30363e316afee68a12ed105ac1293daeec084f 100644 (file)
@@ -29,7 +29,7 @@
 use vec::Vec;
 
 /// Hints to the types of sockets that are desired when looking up hosts
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum SocketType {
     Stream, Datagram, Raw
 }
@@ -38,7 +38,7 @@ pub enum SocketType {
 /// to manipulate how a query is performed.
 ///
 /// The meaning of each of these flags can be found with `man -s 3 getaddrinfo`
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum Flag {
     AddrConfig,
     All,
@@ -51,7 +51,7 @@ pub enum Flag {
 
 /// A transport protocol associated with either a hint or a return value of
 /// `lookup`
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum Protocol {
     TCP, UDP
 }
@@ -61,7 +61,7 @@ pub enum Protocol {
 ///
 /// For details on these fields, see their corresponding definitions via
 /// `man -s 3 getaddrinfo`
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct Hint {
     pub family: usize,
     pub socktype: Option<SocketType>,
@@ -69,7 +69,7 @@ pub struct Hint {
     pub flags: usize,
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub struct Info {
     pub address: SocketAddr,
     pub family: usize,
@@ -127,11 +127,10 @@ fn dns_smoke_test() {
         assert!(found_local);
     }
 
-    #[ignore]
     #[test]
     fn issue_10663() {
         // Something should happen here, but this certainly shouldn't cause
         // everything to die. The actual outcome we don't care too much about.
-        get_host_addresses("example.com").unwrap();
+        let _ = get_host_addresses("example.com");
     }
 }
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..818c8e76d6087aff50dbe3ae3e3675159bc5b0dd 100644 (file)
@@ -90,7 +90,7 @@ fn consume(&mut self, amt: usize) {
 }
 
 /// A `Writer` which ignores bytes written to it, like /dev/null.
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[deprecated(since = "1.0.0", reason = "use std::io::sink() instead")]
 #[unstable(feature = "old_io")]
 pub struct NullWriter;
@@ -103,7 +103,7 @@ fn write_all(&mut self, _buf: &[u8]) -> old_io::IoResult<()> { Ok(()) }
 }
 
 /// A `Reader` which returns an infinite stream of 0 bytes, like /dev/zero.
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[deprecated(since = "1.0.0", reason = "use std::io::repeat(0) instead")]
 #[unstable(feature = "old_io")]
 pub struct ZeroReader;
@@ -130,7 +130,7 @@ fn consume(&mut self, _amt: usize) {}
 }
 
 /// A `Reader` which is always at EOF, like /dev/null.
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 #[deprecated(since = "1.0.0", reason = "use std::io::empty() instead")]
 #[unstable(feature = "old_io")]
 pub struct NullReader;
@@ -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 58d3ae9f7cfabcff1c975fa162ac2cb6303e88da..4471b5afa84c888b600cd0def724eca4013466c8 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:\\");
@@ -344,6 +343,15 @@ fn has_implicit_root(&self) -> bool {
 
 /// Determine whether the character is one of the permitted path
 /// separators for the current platform.
+///
+/// # Examples
+///
+/// ```
+/// use std::path;
+///
+/// assert!(path::is_separator('/'));
+/// assert!(!path::is_separator('❤'));
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn is_separator(c: char) -> bool {
     use ascii::*;
@@ -407,7 +415,7 @@ fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
         // contents of the encoding and (2) new &OsStr values are produced
         // only from ASCII-bounded slices of existing &OsStr values.
 
-        let mut iter = os_str_as_u8_slice(file).rsplitn(1, |b| *b == b'.');
+        let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
         let after = iter.next();
         let before = iter.next();
         if before == Some(b"") {
@@ -521,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,
         }
     }
@@ -540,6 +548,18 @@ fn as_ref(&self) -> &OsStr {
 ///
 /// See the module documentation for an in-depth explanation of components and
 /// their role in the API.
+///
+/// # Examples
+///
+/// ```
+/// use std::path::Path;
+///
+/// let path = Path::new("/tmp/foo/bar.txt");
+///
+/// for component in path.components() {
+///     println!("{:?}", component);
+/// }
+/// ```
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Components<'a> {
@@ -610,6 +630,16 @@ fn is_sep_byte(&self, b: u8) -> bool {
     }
 
     /// Extract a slice corresponding to the portion of the path remaining for iteration.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp/foo/bar.txt");
+    ///
+    /// println!("{:?}", path.components().as_path());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_path(&self) -> &'a Path {
         let mut comps = self.clone();
@@ -893,7 +923,6 @@ fn cmp(&self, other: &Components<'a>) -> cmp::Ordering {
 /// # Examples
 ///
 /// ```
-/// # #![feature(convert)]
 /// use std::path::PathBuf;
 ///
 /// let mut path = PathBuf::from("c:\\");
@@ -918,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.
@@ -985,7 +1020,6 @@ pub fn pop(&mut self) -> bool {
     /// # Examples
     ///
     /// ```
-    /// # #![feature(convert)]
     /// use std::path::PathBuf;
     ///
     /// let mut buf = PathBuf::from("/");
@@ -1207,12 +1241,28 @@ fn as_u8_slice(&self) -> &[u8] {
     /// Directly wrap a string slice as a `Path` slice.
     ///
     /// This is a cost-free conversion.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// Path::new("foo.txt");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
         unsafe { mem::transmute(s.as_ref()) }
     }
 
     /// Yield the underlying `OsStr` slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let os_str = Path::new("foo.txt").as_os_str();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_os_str(&self) -> &OsStr {
         &self.inner
@@ -1221,6 +1271,14 @@ pub fn as_os_str(&self) -> &OsStr {
     /// Yield a `&str` slice if the `Path` is valid unicode.
     ///
     /// This conversion may entail doing a check for UTF-8 validity.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path_str = Path::new("foo.txt").to_str();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_str(&self) -> Option<&str> {
         self.inner.to_str()
@@ -1229,12 +1287,28 @@ pub fn to_str(&self) -> Option<&str> {
     /// Convert a `Path` to a `Cow<str>`.
     ///
     /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path_str = Path::new("foo.txt").to_string_lossy();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_string_lossy(&self) -> Cow<str> {
         self.inner.to_string_lossy()
     }
 
     /// Convert a `Path` to an owned `PathBuf`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path_str = Path::new("foo.txt").to_path_buf();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn to_path_buf(&self) -> PathBuf {
         PathBuf::from(self.inner.to_os_string())
@@ -1248,6 +1322,14 @@ pub fn to_path_buf(&self) -> PathBuf {
     /// * On Windows, a path is absolute if it has a prefix and starts with the
     /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not. In
     /// other words, `path.is_absolute() == path.prefix().is_some() && path.has_root()`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// assert_eq!(false, Path::new("foo.txt").is_absolute());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_absolute(&self) -> bool {
         self.has_root() &&
@@ -1255,6 +1337,14 @@ pub fn is_absolute(&self) -> bool {
     }
 
     /// A path is *relative* if it is not absolute.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// assert!(Path::new("foo.txt").is_relative());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn is_relative(&self) -> bool {
         !self.is_absolute()
@@ -1278,6 +1368,14 @@ pub fn prefix(&self) -> Option<Prefix> {
     ///     * has no prefix and begins with a separator, e.g. `\\windows`
     ///     * has a prefix followed by a separator, e.g. `c:\windows` but not `c:windows`
     ///     * has any non-disk prefix, e.g. `\\server\share`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// assert!(Path::new("/etc/passwd").has_root());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn has_root(&self) -> bool {
          self.components().has_root()
@@ -1294,8 +1392,11 @@ pub fn has_root(&self) -> bool {
     ///
     /// let path = Path::new("/foo/bar");
     /// let foo = path.parent().unwrap();
+    ///
     /// assert!(foo == Path::new("/foo"));
+    ///
     /// let root = foo.parent().unwrap();
+    ///
     /// assert!(root == Path::new("/"));
     /// assert!(root.parent() == None);
     /// ```
@@ -1315,10 +1416,21 @@ pub fn parent(&self) -> Option<&Path> {
     ///
     /// If the path terminates in `.`, `..`, or consists solely or a root of
     /// prefix, `file_name` will return `None`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("hello_world.rs");
+    /// let filename = "hello_world.rs";
+    ///
+    /// assert_eq!(filename, path.file_name().unwrap());
+    /// ```
     #[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
         })
     }
@@ -1334,12 +1446,32 @@ pub fn relative_from<'a, P: ?Sized + AsRef<Path>>(&'a self, base: &'a P) -> Opti
     }
 
     /// Determines whether `base` is a prefix of `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/etc/passwd");
+    ///
+    /// assert!(path.starts_with("/etc"));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn starts_with<P: AsRef<Path>>(&self, base: P) -> bool {
         iter_after(self.components(), base.as_ref().components()).is_some()
     }
 
     /// Determines whether `child` is a suffix of `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/etc/passwd");
+    ///
+    /// assert!(path.ends_with("passwd"));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
         iter_after(self.components().rev(), child.as_ref().components().rev()).is_some()
@@ -1353,6 +1485,16 @@ pub fn ends_with<P: AsRef<Path>>(&self, child: P) -> bool {
     /// * The entire file name if there is no embedded `.`;
     /// * The entire file name if the file name begins with `.` and has no other `.`s within;
     /// * Otherwise, the portion of the file name before the final `.`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("foo.rs");
+    ///
+    /// assert_eq!("foo", path.file_stem().unwrap());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn file_stem(&self) -> Option<&OsStr> {
         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.or(after))
@@ -1366,6 +1508,16 @@ pub fn file_stem(&self) -> Option<&OsStr> {
     /// * None, if there is no embedded `.`;
     /// * None, if the file name begins with `.` and has no other `.`s within;
     /// * Otherwise, the portion of the file name after the final `.`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("foo.rs");
+    ///
+    /// assert_eq!("rs", path.extension().unwrap());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn extension(&self) -> Option<&OsStr> {
         self.file_name().map(split_file_at_dot).and_then(|(before, after)| before.and(after))
@@ -1374,6 +1526,16 @@ pub fn extension(&self) -> Option<&OsStr> {
     /// Creates an owned `PathBuf` with `path` adjoined to `self`.
     ///
     /// See `PathBuf::push` for more details on what it means to adjoin a path.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp");
+    ///
+    /// let new_path = path.join("foo");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
         let mut buf = self.to_path_buf();
@@ -1384,6 +1546,16 @@ pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
     /// Creates an owned `PathBuf` like `self` but with the given file name.
     ///
     /// See `PathBuf::set_file_name` for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp/foo.rs");
+    ///
+    /// let new_path = path.with_file_name("bar.rs");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
         let mut buf = self.to_path_buf();
@@ -1394,6 +1566,16 @@ pub fn with_file_name<S: AsRef<OsStr>>(&self, file_name: S) -> PathBuf {
     /// Creates an owned `PathBuf` like `self` but with the given extension.
     ///
     /// See `PathBuf::set_extension` for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp/foo.rs");
+    ///
+    /// let new_path = path.with_extension("foo.txt");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
         let mut buf = self.to_path_buf();
@@ -1402,6 +1584,18 @@ pub fn with_extension<S: AsRef<OsStr>>(&self, extension: S) -> PathBuf {
     }
 
     /// Produce an iterator over the components of the path.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp/foo.rs");
+    ///
+    /// for component in path.components() {
+    ///     println!("{:?}", component);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn components(&self) -> Components {
         let prefix = parse_prefix(self.as_os_str());
@@ -1415,6 +1609,18 @@ pub fn components(&self) -> Components {
     }
 
     /// Produce an iterator over the path's components viewed as `OsStr` slices.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp/foo.rs");
+    ///
+    /// for component in path.iter() {
+    ///     println!("{:?}", component);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter {
         Iter { inner: self.components() }
@@ -1422,6 +1628,16 @@ pub fn iter(&self) -> Iter {
 
     /// Returns an object that implements `Display` for safely printing paths
     /// that may contain non-Unicode data.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::path::Path;
+    ///
+    /// let path = Path::new("/tmp/foo.rs");
+    ///
+    /// println!("{}", path.display());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn display(&self) -> Display {
         Display { path: self }
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..38c57eec684dbda7ff4f4d8eea948249ed532451 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 io;
+    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:
@@ -243,7 +241,7 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
                 SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
             };
             if ret == -1 {
-                panic!("couldn't generate random bytes: {}", os::last_os_error());
+                panic!("couldn't generate random bytes: {}", io::Error::last_os_error());
             }
         }
     }
@@ -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 9079c0aaffb7d3669e6bd57ecce4dde8d7b8c6c2..beb2870807a7e1aab75edf77b704879eb78e50ca 100644 (file)
@@ -64,7 +64,7 @@ pub fn cleanup() {
             if queue as usize != 0 {
                 let queue: Box<Queue> = Box::from_raw(queue);
                 for to_run in *queue {
-                    to_run.invoke(());
+                    to_run();
                 }
             }
         }
index b77699105646d3c009c451122f0fa4d87f5b7224..4b754bd5f589f22ac3d957986a6fcc536769d9bf 100644 (file)
@@ -25,7 +25,7 @@
 
 #[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum _Unwind_Action {
     _UA_SEARCH_PHASE = 1,
     _UA_CLEANUP_PHASE = 2,
index 696c7960c3e6f4e11b71aa268c932c47ceabf6c2..0d26206f26bcfc67630547b035b5ff7c66189f2c 100644 (file)
@@ -21,7 +21,6 @@
 
 use prelude::v1::*;
 use sys;
-use thunk::Thunk;
 use usize;
 
 // Reexport some of our utilities which are expected by other crates.
@@ -117,7 +116,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
             use libc;
             use libc::funcs::posix01::signal::signal;
             unsafe {
-                assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != -1);
+                assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
             }
         }
         ignore_sigpipe();
@@ -153,7 +152,7 @@ fn lang_start(main: *const u8, argc: isize, argv: *const *const u8) -> isize {
 /// that the closure could not be registered, meaning that it is not scheduled
 /// to be rune.
 pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
-    if at_exit_imp::push(Thunk::new(f)) {Ok(())} else {Err(())}
+    if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
 }
 
 /// One-time runtime cleanup.
index e4927bbd3d274c5436b4bbeee00457e092f94a3e..f71811b1eadf6f0c90567f684a872e9bb749d191 100644 (file)
@@ -398,7 +398,7 @@ pub mod eabi {
     pub struct DISPATCHER_CONTEXT;
 
     #[repr(C)]
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub enum EXCEPTION_DISPOSITION {
         ExceptionContinueExecution,
         ExceptionContinueSearch,
index 69c5267ab69fccdbddf013277216c831b26d6170..a7d8b287a64c031567a8605f50c69fb8ef6dc9a8 100644 (file)
@@ -140,33 +140,43 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
     /// Wait on this condition variable for a notification, timing out after a
     /// specified duration.
     ///
-    /// The semantics of this function are equivalent to `wait()` except that
-    /// the thread will be blocked for roughly no longer than `dur`. This method
-    /// should not be used for precise timing due to anomalies such as
-    /// preemption or platform differences that may not cause the maximum amount
-    /// of time waited to be precisely `dur`.
+    /// The semantics of this function are equivalent to `wait()`
+    /// except that the thread will be blocked for roughly no longer
+    /// than `ms` milliseconds. This method should not be used for
+    /// precise timing due to anomalies such as preemption or platform
+    /// differences that may not cause the maximum amount of time
+    /// waited to be precisely `ms`.
     ///
-    /// If the wait timed out, then `false` will be returned. Otherwise if a
-    /// notification was received then `true` will be returned.
+    /// The returned boolean is `false` only if the timeout is known
+    /// to have elapsed.
     ///
     /// Like `wait`, the lock specified will be re-acquired when this function
     /// returns, regardless of whether the timeout elapsed or not.
-    #[unstable(feature = "std_misc")]
-    pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
-                           -> LockResult<(MutexGuard<'a, T>, bool)> {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
+                                  -> LockResult<(MutexGuard<'a, T>, bool)> {
         unsafe {
             let me: &'static Condvar = &*(self as *const _);
-            me.inner.wait_timeout(guard, dur)
+            me.inner.wait_timeout_ms(guard, ms)
         }
     }
 
+    /// Deprecated: use `wait_timeout_ms` instead.
+    #[unstable(feature = "std_misc")]
+    #[deprecated(since = "1.0.0", reason = "use wait_timeout_ms instead")]
+    pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>, dur: Duration)
+                               -> LockResult<(MutexGuard<'a, T>, bool)> {
+        self.wait_timeout_ms(guard, dur.num_milliseconds() as u32)
+    }
+
     /// Wait on this condition variable for a notification, timing out after a
     /// specified duration.
     ///
     /// The semantics of this function are equivalent to `wait_timeout` except
     /// that the implementation will repeatedly wait while the duration has not
     /// passed and the provided function returns `false`.
-    #[unstable(feature = "std_misc")]
+    #[unstable(feature = "wait_timeout_with",
+               reason = "unsure if this API is broadly needed or what form it should take")]
     pub fn wait_timeout_with<'a, T, F>(&self,
                                        guard: MutexGuard<'a, T>,
                                        dur: Duration,
@@ -235,12 +245,12 @@ pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
     /// See `Condvar::wait_timeout`.
     #[unstable(feature = "std_misc",
                reason = "may be merged with Condvar in the future")]
-    pub fn wait_timeout<'a, T>(&'static self, guard: MutexGuard<'a, T>, dur: Duration)
-                               -> LockResult<(MutexGuard<'a, T>, bool)> {
+    pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32)
+                                  -> LockResult<(MutexGuard<'a, T>, bool)> {
         let (poisoned, success) = unsafe {
             let lock = mutex::guard_lock(&guard);
             self.verify(lock);
-            let success = self.inner.wait_timeout(lock, dur);
+            let success = self.inner.wait_timeout(lock, Duration::milliseconds(ms as i64));
             (mutex::guard_poison(&guard).get(), success)
         };
         if poisoned {
@@ -275,7 +285,8 @@ pub fn wait_timeout_with<'a, T, F>(&'static self,
             let now = SteadyTime::now();
             let consumed = &now - &start;
             let guard = guard_result.unwrap_or_else(|e| e.into_inner());
-            let (new_guard_result, no_timeout) = match self.wait_timeout(guard, dur - consumed) {
+            let res = self.wait_timeout_ms(guard, (dur - consumed).num_milliseconds() as u32);
+            let (new_guard_result, no_timeout) = match res {
                 Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout),
                 Err(err) => {
                     let (new_guard, no_timeout) = err.into_inner();
@@ -350,6 +361,7 @@ mod tests {
     use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
     use thread;
     use time::Duration;
+    use u32;
 
     #[test]
     fn smoke() {
@@ -418,19 +430,19 @@ fn notify_all() {
     }
 
     #[test]
-    fn wait_timeout() {
+    fn wait_timeout_ms() {
         static C: StaticCondvar = CONDVAR_INIT;
         static M: StaticMutex = MUTEX_INIT;
 
         let g = M.lock().unwrap();
-        let (g, _no_timeout) = C.wait_timeout(g, Duration::nanoseconds(1000)).unwrap();
+        let (g, _no_timeout) = C.wait_timeout_ms(g, 1).unwrap();
         // spurious wakeups mean this isn't necessarily true
         // assert!(!no_timeout);
         let _t = thread::spawn(move || {
             let _g = M.lock().unwrap();
             C.notify_one();
         });
-        let (g, no_timeout) = C.wait_timeout(g, Duration::days(1)).unwrap();
+        let (g, no_timeout) = C.wait_timeout_ms(g, u32::MAX).unwrap();
         assert!(no_timeout);
         drop(g);
         unsafe { C.destroy(); M.destroy(); }
index b2afe28fed46d5d30352caedbf7a00611490d365..2cdde1aca9e682c7696d67ffad62c8f45adaa043 100644 (file)
@@ -36,6 +36,7 @@
 use core::prelude::*;
 use core::mem::replace;
 
+use boxed::Box;
 use self::FutureState::*;
 use sync::mpsc::{Receiver, channel};
 use thunk::Thunk;
@@ -84,7 +85,7 @@ pub fn get_ref<'a>(&'a mut self) -> &'a A {
                 match replace(&mut self.state, Evaluating) {
                     Forced(_) | Evaluating => panic!("Logic error."),
                     Pending(f) => {
-                        self.state = Forced(f.invoke(()));
+                        self.state = Forced(f());
                         self.get_ref()
                     }
                 }
@@ -114,7 +115,7 @@ pub fn from_fn<F>(f: F) -> Future<A>
          * function. It is not spawned into another task.
          */
 
-        Future {state: Pending(Thunk::new(f))}
+        Future {state: Pending(Box::new(f))}
     }
 }
 
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..c80182ec07d3223df0b61929e50acf163a9b06a6 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:
 //!
 /// The receiving-half of Rust's channel type. This half can only be owned by
 /// one task
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Receiver<T:Send> {
+pub struct Receiver<T> {
     inner: UnsafeCell<Flavor<T>>,
 }
 
@@ -354,14 +354,14 @@ unsafe impl<T: Send> Send for Receiver<T> { }
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:Send+'a> {
+pub struct Iter<'a, T: 'a> {
     rx: &'a Receiver<T>
 }
 
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Sender<T:Send> {
+pub struct Sender<T> {
     inner: UnsafeCell<Flavor<T>>,
 }
 
@@ -372,7 +372,7 @@ unsafe impl<T: Send> Send for Sender<T> { }
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SyncSender<T: Send> {
+pub struct SyncSender<T> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
 }
 
@@ -433,7 +433,7 @@ pub enum TrySendError<T> {
     Disconnected(T),
 }
 
-enum Flavor<T:Send> {
+enum Flavor<T> {
     Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
     Stream(Arc<UnsafeCell<stream::Packet<T>>>),
     Shared(Arc<UnsafeCell<shared::Packet<T>>>),
@@ -441,7 +441,7 @@ enum Flavor<T:Send> {
 }
 
 #[doc(hidden)]
-trait UnsafeFlavor<T:Send> {
+trait UnsafeFlavor<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
     unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
         &mut *self.inner_unsafe().get()
@@ -450,12 +450,12 @@ unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
         &*self.inner_unsafe().get()
     }
 }
-impl<T:Send> UnsafeFlavor<T> for Sender<T> {
+impl<T> UnsafeFlavor<T> for Sender<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
         &self.inner
     }
 }
-impl<T:Send> UnsafeFlavor<T> for Receiver<T> {
+impl<T> UnsafeFlavor<T> for Receiver<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
         &self.inner
     }
@@ -488,7 +488,7 @@ fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
 /// println!("{:?}", rx.recv().unwrap());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
+pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
     (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
 }
@@ -528,7 +528,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
 /// assert_eq!(rx.recv().unwrap(), 2);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn sync_channel<T: Send>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
+pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
     (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
 }
@@ -537,7 +537,7 @@ pub fn sync_channel<T: Send>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
 // Sender
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send> Sender<T> {
+impl<T> Sender<T> {
     fn new(inner: Flavor<T>) -> Sender<T> {
         Sender {
             inner: UnsafeCell::new(inner),
@@ -619,7 +619,7 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Clone for Sender<T> {
+impl<T> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
         let (packet, sleeper, guard) = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
@@ -665,7 +665,7 @@ fn clone(&self) -> Sender<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Sender<T> {
+impl<T> Drop for Sender<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
             Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
@@ -680,7 +680,7 @@ fn drop(&mut self) {
 // SyncSender
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send> SyncSender<T> {
+impl<T> SyncSender<T> {
     fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
         SyncSender { inner: inner }
     }
@@ -720,7 +720,7 @@ pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Clone for SyncSender<T> {
+impl<T> Clone for SyncSender<T> {
     fn clone(&self) -> SyncSender<T> {
         unsafe { (*self.inner.get()).clone_chan(); }
         return SyncSender::new(self.inner.clone());
@@ -729,7 +729,7 @@ fn clone(&self) -> SyncSender<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for SyncSender<T> {
+impl<T> Drop for SyncSender<T> {
     fn drop(&mut self) {
         unsafe { (*self.inner.get()).drop_chan(); }
     }
@@ -739,7 +739,7 @@ fn drop(&mut self) {
 // Receiver
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send> Receiver<T> {
+impl<T> Receiver<T> {
     fn new(inner: Flavor<T>) -> Receiver<T> {
         Receiver { inner: UnsafeCell::new(inner) }
     }
@@ -858,7 +858,7 @@ pub fn iter(&self) -> Iter<T> {
     }
 }
 
-impl<T: Send> select::Packet for Receiver<T> {
+impl<T> select::Packet for Receiver<T> {
     fn can_recv(&self) -> bool {
         loop {
             let new_port = match *unsafe { self.inner() } {
@@ -945,7 +945,7 @@ fn abort_selection(&self) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: Send> Iterator for Iter<'a, T> {
+impl<'a, T> Iterator for Iter<'a, T> {
     type Item = T;
 
     fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
@@ -953,7 +953,7 @@ fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Receiver<T> {
+impl<T> Drop for Receiver<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
             Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
index 1be8b0dd8628a217e57fdcaaaeb48c0c65cdc9e9..9b6c8f4dd9775bbabc18c00a3c68a85815fa8235 100644 (file)
@@ -72,12 +72,12 @@ struct Node<T> {
 /// The multi-producer single-consumer structure. This is not cloneable, but it
 /// may be safely shared so long as it is guaranteed that there is only one
 /// popper at a time (many pushers are allowed).
-pub struct Queue<T: Send> {
+pub struct Queue<T> {
     head: AtomicPtr<Node<T>>,
     tail: UnsafeCell<*mut Node<T>>,
 }
 
-unsafe impl<T:Send> Send for Queue<T> { }
+unsafe impl<T: Send> Send for Queue<T> { }
 unsafe impl<T: Send> Sync for Queue<T> { }
 
 impl<T> Node<T> {
@@ -89,7 +89,7 @@ unsafe fn new(v: Option<T>) -> *mut Node<T> {
     }
 }
 
-impl<T: Send> Queue<T> {
+impl<T> Queue<T> {
     /// Creates a new queue that is safe to share among multiple producers and
     /// one consumer.
     pub fn new() -> Queue<T> {
@@ -140,7 +140,7 @@ pub fn pop(&self) -> PopResult<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Queue<T> {
+impl<T> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
             let mut cur = *self.tail.get();
index 13578ce0517911393e106c941ea30e73ce6845a8..c6e8d87a22e71412c234f05de9694b2283779f73 100644 (file)
@@ -54,7 +54,7 @@
 // moves *from* a pointer, ownership of the token is transferred to
 // whoever changed the state.
 
-pub struct Packet<T:Send> {
+pub struct Packet<T> {
     // Internal state of the chan/port pair (stores the blocked task as well)
     state: AtomicUsize,
     // One-shot data slot location
@@ -64,7 +64,7 @@ pub struct Packet<T:Send> {
     upgrade: MyUpgrade<T>,
 }
 
-pub enum Failure<T:Send> {
+pub enum Failure<T> {
     Empty,
     Disconnected,
     Upgraded(Receiver<T>),
@@ -76,19 +76,19 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T:Send> {
+pub enum SelectionResult<T> {
     SelCanceled,
     SelUpgraded(SignalToken, Receiver<T>),
     SelSuccess,
 }
 
-enum MyUpgrade<T:Send> {
+enum MyUpgrade<T> {
     NothingSent,
     SendUsed,
     GoUp(Receiver<T>),
 }
 
-impl<T: Send> Packet<T> {
+impl<T> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
             data: None,
@@ -368,7 +368,7 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
 }
 
 #[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
     }
index 80cbd0761638ff398bc2f4c79a69e7822161b7f7..5c1610bdc317566fe49ae6fd0533f21756b2309e 100644 (file)
@@ -40,7 +40,7 @@
 #[cfg(not(test))]
 const MAX_STEALS: isize = 1 << 20;
 
-pub struct Packet<T: Send> {
+pub struct Packet<T> {
     queue: mpsc::Queue<T>,
     cnt: AtomicIsize, // How many items are on this channel
     steals: isize, // How many times has a port received without blocking?
@@ -64,7 +64,7 @@ pub enum Failure {
     Disconnected,
 }
 
-impl<T: Send> Packet<T> {
+impl<T> Packet<T> {
     // Creation of a packet *must* be followed by a call to postinit_lock
     // and later by inherit_blocker
     pub fn new() -> Packet<T> {
@@ -474,7 +474,7 @@ pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
 }
 
 #[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         // Note that this load is not only an assert for correctness about
         // disconnection, but also a proper fence before the read of
index cd6d1ee05c788bb453b6ceba4f5112c03f9aef42..c75ac13080866ce2a0f3376a91cf830af7691ac0 100644 (file)
@@ -57,7 +57,7 @@ struct Node<T> {
 /// but it can be safely shared in an Arc if it is guaranteed that there
 /// is only one popper and one pusher touching the queue at any one point in
 /// time.
-pub struct Queue<T: Send> {
+pub struct Queue<T> {
     // consumer fields
     tail: UnsafeCell<*mut Node<T>>, // where to pop from
     tail_prev: AtomicPtr<Node<T>>, // where to pop from
@@ -78,7 +78,7 @@ unsafe impl<T: Send> Send for Queue<T> { }
 
 unsafe impl<T: Send> Sync for Queue<T> { }
 
-impl<T: Send> Node<T> {
+impl<T> Node<T> {
     fn new() -> *mut Node<T> {
         unsafe {
             boxed::into_raw(box Node {
@@ -89,7 +89,7 @@ fn new() -> *mut Node<T> {
     }
 }
 
-impl<T: Send> Queue<T> {
+impl<T> Queue<T> {
     /// Creates a new queue.
     ///
     /// This is unsafe as the type system doesn't enforce a single
@@ -227,7 +227,7 @@ pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
 }
 
 #[unsafe_destructor]
-impl<T: Send> Drop for Queue<T> {
+impl<T> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
             let mut cur = *self.first.get();
index a5a73314a6db3d36e29cd08540744954ee986c1e..f0363fae84f73f16ecdbf78f13e8006677eab7f3 100644 (file)
@@ -39,7 +39,7 @@
 #[cfg(not(test))]
 const MAX_STEALS: isize = 1 << 20;
 
-pub struct Packet<T:Send> {
+pub struct Packet<T> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
     cnt: AtomicIsize, // How many items are on this channel
@@ -49,7 +49,7 @@ pub struct Packet<T:Send> {
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
 }
 
-pub enum Failure<T:Send> {
+pub enum Failure<T> {
     Empty,
     Disconnected,
     Upgraded(Receiver<T>),
@@ -61,7 +61,7 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T:Send> {
+pub enum SelectionResult<T> {
     SelSuccess,
     SelCanceled,
     SelUpgraded(SignalToken, Receiver<T>),
@@ -69,12 +69,12 @@ pub enum SelectionResult<T:Send> {
 
 // Any message could contain an "upgrade request" to a new shared port, so the
 // internal queue it's a queue of T, but rather Message<T>
-enum Message<T:Send> {
+enum Message<T> {
     Data(T),
     GoUp(Receiver<T>),
 }
 
-impl<T: Send> Packet<T> {
+impl<T> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
             queue: unsafe { spsc::Queue::new(128) },
@@ -472,7 +472,7 @@ pub fn abort_selection(&mut self,
 }
 
 #[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         // Note that this load is not only an assert for correctness about
         // disconnection, but also a proper fence before the read of
index 71236269487ef8c803ce2fc1af7d01572cb025a9..6221ca59b54f7094e0d47b102bd8ece1e57e30af 100644 (file)
@@ -47,7 +47,7 @@
 use sync::mpsc::select::StartResult::{self, Installed, Abort};
 use sync::{Mutex, MutexGuard};
 
-pub struct Packet<T: Send> {
+pub struct Packet<T> {
     /// Only field outside of the mutex. Just done for kicks, but mainly because
     /// the other shared channel already had the code implemented
     channels: AtomicUsize,
@@ -113,10 +113,10 @@ pub enum Failure {
 
 /// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
 /// in the meantime. This re-locks the mutex upon returning.
-fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
-                         mut guard: MutexGuard<'b, State<T>>,
-                         f: fn(SignalToken) -> Blocker)
-                         -> MutexGuard<'a, State<T>>
+fn wait<'a, 'b, T>(lock: &'a Mutex<State<T>>,
+                   mut guard: MutexGuard<'b, State<T>>,
+                   f: fn(SignalToken) -> Blocker)
+                   -> MutexGuard<'a, State<T>>
 {
     let (wait_token, signal_token) = blocking::tokens();
     match mem::replace(&mut guard.blocker, f(signal_token)) {
@@ -136,7 +136,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
     token.signal();
 }
 
-impl<T: Send> Packet<T> {
+impl<T> Packet<T> {
     pub fn new(cap: usize) -> Packet<T> {
         Packet {
             channels: AtomicUsize::new(1),
@@ -412,7 +412,7 @@ pub fn abort_selection(&self) -> bool {
 }
 
 #[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
+impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.channels.load(Ordering::SeqCst), 0);
         let mut guard = self.lock.lock().unwrap();
index b24cfbb6899a9c655d794958259477a7f8217e11..16e7f265412f3211a40e0118c6b40ff4d26b8757 100644 (file)
 /// *guard += 1;
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Mutex<T: Send> {
+pub struct Mutex<T> {
     // Note that this static mutex is in a *box*, not inlined into the struct
     // itself. Once a native mutex has been used once, its address can never
     // change (it can't be moved). This mutex type can be safely moved at any
@@ -122,6 +122,8 @@ pub struct Mutex<T: Send> {
     data: UnsafeCell<T>,
 }
 
+// these are the only places where `T: Send` matters; all other
+// functionality works fine on a single thread.
 unsafe impl<T: Send> Send for Mutex<T> { }
 
 unsafe impl<T: Send> Sync for Mutex<T> { }
@@ -181,7 +183,7 @@ impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
     poison: poison::FLAG_INIT,
 };
 
-impl<T: Send> Mutex<T> {
+impl<T> Mutex<T> {
     /// Creates a new mutex in an unlocked state ready for use.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(t: T) -> Mutex<T> {
@@ -244,7 +246,7 @@ pub fn is_poisoned(&self) -> bool {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send> Drop for Mutex<T> {
+impl<T> Drop for Mutex<T> {
     fn drop(&mut self) {
         // This is actually safe b/c we know that there is no further usage of
         // this mutex (it's up to the user to arrange for a mutex to get
@@ -254,7 +256,7 @@ fn drop(&mut self) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug + Send + 'static> fmt::Debug for Mutex<T> {
+impl<T: fmt::Debug + 'static> fmt::Debug for Mutex<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_lock() {
             Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard),
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)
     }
 }
index a79ffaa0860e3673f349396ff880394358d8740b..d70350bc7d6512d40a975dd8dd1da2637c6afa4c 100644 (file)
@@ -130,7 +130,7 @@ pub struct RwLockWriteGuard<'a, T: 'a> {
 
 impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {}
 
-impl<T: Send + Sync> RwLock<T> {
+impl<T> RwLock<T> {
     /// Creates a new instance of an `RwLock<T>` which is unlocked.
     ///
     /// # Examples
@@ -258,7 +258,7 @@ fn drop(&mut self) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug + Send + Sync> fmt::Debug for RwLock<T> {
+impl<T: fmt::Debug> fmt::Debug for RwLock<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.try_read() {
             Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", *guard),
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 1a0ee17904a243afa274b3b6347b2e43145feb22..fc21effb45a8da06cf01b0c57534325bbd2c1d06 100644 (file)
@@ -115,9 +115,9 @@ pub fn socket(addr: SocketAddr, ty: libc::c_int) -> IoResult<sock_t> {
             Ipv4Addr(..) => libc::AF_INET,
             Ipv6Addr(..) => libc::AF_INET6,
         };
-        match libc::socket(fam, ty, 0) {
+        match libc::socket(fam, ty, 0) as i32 {
             -1 => Err(last_net_error()),
-            fd => Ok(fd),
+            fd => Ok(fd as sock_t),
         }
     }
 }
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 f45daea18a21f3f2bc65e763f6cb6fdf648c54d2..1845b6266ed8d1aa405ad7581278205ef5a30546 100644 (file)
@@ -25,6 +25,7 @@ pub fn start_thread(main: *mut libc::c_void) {
     unsafe {
         stack::record_os_managed_stack_bounds(0, usize::MAX);
         let _handler = stack_overflow::Handler::new();
-        Box::from_raw(main as *mut Thunk).invoke(());
+        let main: Box<Thunk> = Box::from_raw(main as *mut Thunk);
+        main();
     }
 }
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 2514d4bf4a39605b0c7b76a4ae30d51be503ae87..5ae508e46106a7f35fcbc431d90db5aba18a1e4b 100644 (file)
@@ -194,12 +194,12 @@ mod select {
     #[repr(C)]
     pub struct fd_set {
         // FIXME: shouldn't this be a c_ulong?
-        fds_bits: [libc::uintptr_t; (FD_SETSIZE / usize::BITS as usize)]
+        fds_bits: [libc::uintptr_t; (FD_SETSIZE / usize::BITS)]
     }
 
     pub fn fd_set(set: &mut fd_set, fd: i32) {
         let fd = fd as usize;
-        set.fds_bits[fd / usize::BITS as usize] |= 1 << (fd % usize::BITS as usize);
+        set.fds_bits[fd / usize::BITS] |= 1 << (fd % usize::BITS);
     }
 }
 
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..d2220bdec32b78fa1f054a720742c900ac7a6e63 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)
@@ -408,7 +409,7 @@ pub fn env() -> Env {
     };
 
     fn parse(input: &[u8]) -> (OsString, OsString) {
-        let mut it = input.splitn(1, |b| *b == b'=');
+        let mut it = input.splitn(2, |b| *b == b'=');
         let key = it.next().unwrap().to_vec();
         let default: &[u8] = &[];
         let val = it.next().unwrap_or(default).to_vec();
@@ -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..4804f6504419c599992c3549c12f9fcb652f7c65 100644 (file)
@@ -49,9 +49,9 @@
 pub const TOKEN_READ: libc::DWORD = 0x20008;
 
 // Note that these are not actually HANDLEs, just values to pass to GetStdHandle
-pub const STD_INPUT_HANDLE: libc::DWORD = -10;
-pub const STD_OUTPUT_HANDLE: libc::DWORD = -11;
-pub const STD_ERROR_HANDLE: libc::DWORD = -12;
+pub const STD_INPUT_HANDLE: libc::DWORD = -10i32 as libc::DWORD;
+pub const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
+pub const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD;
 
 #[repr(C)]
 #[cfg(target_arch = "x86")]
@@ -89,7 +89,6 @@ pub struct WSANETWORKEVENTS {
 pub type WSAEVENT = libc::HANDLE;
 
 #[repr(C)]
-#[derive(Copy)]
 pub struct WSAPROTOCOL_INFO {
     pub dwServiceFlags1: libc::DWORD,
     pub dwServiceFlags2: libc::DWORD,
@@ -433,6 +432,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 2ac8ac10aa9ae7a3b09f58ae03524aae581978eb..41e97dc8475027741473f7f5458ff89661bdfea2 100644 (file)
@@ -15,6 +15,7 @@
 use old_io::net::ip;
 use old_io::IoResult;
 use libc;
+use libc::consts::os::extra::INVALID_SOCKET;
 use mem;
 use ptr;
 use super::{last_error, last_net_error, sock_t};
@@ -183,8 +184,8 @@ pub fn accept(&mut self) -> IoResult<TcpStream> {
             match unsafe {
                 libc::accept(self.socket(), ptr::null_mut(), ptr::null_mut())
             } {
-                -1 if wouldblock() => {}
-                -1 => return Err(last_net_error()),
+                INVALID_SOCKET if wouldblock() => {}
+                INVALID_SOCKET => return Err(last_net_error()),
 
                 // Accepted sockets inherit the same properties as the caller,
                 // so we need to deregister our event and switch the socket back
index a2b824bb016ffa401255a488249e480e0d56eaf8..acd6970f113731a95dd79b8c7d662bee55e50010 100644 (file)
@@ -197,7 +197,7 @@ macro_rules! __thread_local_inner {
 /// Indicator of the state of a thread local storage key.
 #[unstable(feature = "std_misc",
            reason = "state querying was recently added")]
-#[derive(Eq, PartialEq, Copy)]
+#[derive(Eq, PartialEq, Copy, Clone)]
 pub enum LocalKeyState {
     /// All keys are in this state whenever a thread starts. Keys will
     /// transition to the `Valid` state once the first call to `with` happens
@@ -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..5fe6e80d6e93a0c851b2c857e9d220b6f6c14051 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
@@ -281,7 +257,7 @@ pub fn stderr(self, _stderr: Box<Writer + Send + 'static>) -> Builder {
     pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
         F: FnOnce(), F: Send + 'static
     {
-        self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i))
+        self.spawn_inner(Box::new(f)).map(|i| JoinHandle(i))
     }
 
     /// Spawn a new child thread that must be joined within a given
@@ -303,7 +279,7 @@ pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
     pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
         T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
     {
-        self.spawn_inner(Thunk::new(f)).map(|inner| {
+        self.spawn_inner(Box::new(f)).map(|inner| {
             JoinGuard { inner: inner, _marker: PhantomData }
         })
     }
@@ -339,7 +315,7 @@ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
                 thread_info::set(imp::guard::current(), their_thread);
             }
 
-            let mut output = None;
+            let mut output: Option<T> = None;
             let try_result = {
                 let ptr = &mut output;
 
@@ -351,7 +327,11 @@ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
                 // 'unwinding' flag in the thread itself. For these reasons,
                 // this unsafety should be ok.
                 unsafe {
-                    unwind::try(move || *ptr = Some(f.invoke(())))
+                    unwind::try(move || {
+                        let f: Thunk<(), T> = f;
+                        let v: T = f();
+                        *ptr = Some(v)
+                    })
                 }
             };
             unsafe {
@@ -364,7 +344,7 @@ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
         };
 
         Ok(JoinInner {
-            native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }),
+            native: try!(unsafe { imp::create(stack_size, Box::new(main)) }),
             thread: my_thread,
             packet: my_packet,
             joined: false,
@@ -489,9 +469,16 @@ pub fn catch_panic<F, R>(f: F) -> Result<R>
 /// specifics or platform-dependent functionality. Note that on unix platforms
 /// this function will not return early due to a signal being received or a
 /// spurious wakeup.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn sleep_ms(ms: u32) {
+    imp::sleep(Duration::milliseconds(ms as i64))
+}
+
+/// Deprecated: use `sleep_ms` instead.
 #[unstable(feature = "thread_sleep",
            reason = "recently added, needs an RFC, and `Duration` itself is \
                      unstable")]
+#[deprecated(since = "1.0.0", reason = "use sleep_ms instead")]
 pub fn sleep(dur: Duration) {
     imp::sleep(dur)
 }
@@ -525,17 +512,24 @@ pub fn park() {
 /// amount of time waited to be precisely *duration* long.
 ///
 /// See the module doc for more detail.
-#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
-pub fn park_timeout(duration: Duration) {
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn park_timeout_ms(ms: u32) {
     let thread = current();
     let mut guard = thread.inner.lock.lock().unwrap();
     if !*guard {
-        let (g, _) = thread.inner.cvar.wait_timeout(guard, duration).unwrap();
+        let (g, _) = thread.inner.cvar.wait_timeout_ms(guard, ms).unwrap();
         guard = g;
     }
     *guard = false;
 }
 
+/// Deprecated: use `park_timeout_ms`
+#[unstable(feature = "std_misc", reason = "recently introduced, depends on Duration")]
+#[deprecated(since = "1.0.0", reason = "use park_timeout_ms instead")]
+pub fn park_timeout(duration: Duration) {
+    park_timeout_ms(duration.num_milliseconds() as u32)
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Thread
 ////////////////////////////////////////////////////////////////////////////////
@@ -568,71 +562,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 +691,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 +706,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,13 +728,13 @@ mod test {
 
     use any::Any;
     use sync::mpsc::{channel, Sender};
-    use boxed::BoxAny;
     use result;
     use std::old_io::{ChanReader, ChanWriter};
     use super::{Builder};
     use thread;
     use thunk::Thunk;
     use time::Duration;
+    use u32;
 
     // !!! These tests are dangerous. If something is buggy, they will hang, !!!
     // !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
@@ -921,7 +839,7 @@ fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk<'static>) {
         let x: Box<_> = box 1;
         let x_in_parent = (&*x) as *const i32 as usize;
 
-        spawnfn(Thunk::new(move|| {
+        spawnfn(Box::new(move|| {
             let x_in_child = (&*x) as *const i32 as usize;
             tx.send(x_in_child).unwrap();
         }));
@@ -933,7 +851,7 @@ fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk<'static>) {
     #[test]
     fn test_avoid_copying_the_body_spawn() {
         avoid_copying_the_body(|v| {
-            thread::spawn(move || v.invoke(()));
+            thread::spawn(move || v());
         });
     }
 
@@ -941,7 +859,7 @@ fn test_avoid_copying_the_body_spawn() {
     fn test_avoid_copying_the_body_thread_spawn() {
         avoid_copying_the_body(|f| {
             thread::spawn(move|| {
-                f.invoke(());
+                f();
             });
         })
     }
@@ -950,7 +868,7 @@ fn test_avoid_copying_the_body_thread_spawn() {
     fn test_avoid_copying_the_body_join() {
         avoid_copying_the_body(|f| {
             let _ = thread::spawn(move|| {
-                f.invoke(())
+                f()
             }).join();
         })
     }
@@ -963,13 +881,13 @@ fn test_child_doesnt_ref_parent() {
         // valgrind-friendly. try this at home, instead..!)
         const GENERATIONS: u32 = 16;
         fn child_no(x: u32) -> Thunk<'static> {
-            return Thunk::new(move|| {
+            return Box::new(move|| {
                 if x < GENERATIONS {
-                    thread::spawn(move|| child_no(x+1).invoke(()));
+                    thread::spawn(move|| child_no(x+1)());
                 }
             });
         }
-        thread::spawn(|| child_no(0).invoke(()));
+        thread::spawn(|| child_no(0)());
     }
 
     #[test]
@@ -1037,14 +955,14 @@ fn test_try_panic_message_unit_struct() {
     fn test_park_timeout_unpark_before() {
         for _ in 0..10 {
             thread::current().unpark();
-            thread::park_timeout(Duration::seconds(10_000_000));
+            thread::park_timeout_ms(u32::MAX);
         }
     }
 
     #[test]
     fn test_park_timeout_unpark_not_called() {
         for _ in 0..10 {
-            thread::park_timeout(Duration::milliseconds(10));
+            thread::park_timeout_ms(10);
         }
     }
 
@@ -1060,14 +978,13 @@ fn test_park_timeout_unpark_called_other_thread() {
                 th.unpark();
             });
 
-            thread::park_timeout(Duration::seconds(10_000_000));
+            thread::park_timeout_ms(u32::MAX);
         }
     }
 
     #[test]
-    fn sleep_smoke() {
-        thread::sleep(Duration::milliseconds(2));
-        thread::sleep(Duration::milliseconds(-2));
+    fn sleep_ms_smoke() {
+        thread::sleep_ms(2);
     }
 
     // NOTE: the corresponding test for stderr is in run-pass/task-stderr, due
index a9cb05b368f02a200acd64526b82dee685153639..6091794ed428660162d848512845e186a1b075a9 100644 (file)
 #![allow(missing_docs)]
 #![unstable(feature = "std_misc")]
 
-use alloc::boxed::Box;
+use alloc::boxed::{Box, FnBox};
 use core::marker::Send;
-use core::ops::FnOnce;
 
-pub struct Thunk<'a, A=(),R=()> {
-    invoke: Box<Invoke<A,R>+Send + 'a>,
-}
+pub type Thunk<'a, A=(), R=()> =
+    Box<FnBox<A,Output=R> + Send + 'a>;
 
-impl<'a, R> Thunk<'a,(),R> {
-    pub fn new<F>(func: F) -> Thunk<'a,(),R>
-        where F : FnOnce() -> R, F : Send + 'a
-    {
-        Thunk::with_arg(move|()| func())
-    }
-}
-
-impl<'a,A,R> Thunk<'a,A,R> {
-    pub fn with_arg<F>(func: F) -> Thunk<'a,A,R>
-        where F : FnOnce(A) -> R, F : Send + 'a
-    {
-        Thunk {
-            invoke: Box::<F>::new(func)
-        }
-    }
-
-    pub fn invoke(self, arg: A) -> R {
-        self.invoke.invoke(arg)
-    }
-}
-
-pub trait Invoke<A=(),R=()> {
-    fn invoke(self: Box<Self>, arg: A) -> R;
-}
-
-impl<A,R,F> Invoke<A,R> for F
-    where F : FnOnce(A) -> R
-{
-    fn invoke(self: Box<F>, arg: A) -> R {
-        let f = *self;
-        f(arg)
-    }
-}
index 896e638deb46540ccb910309fd3f8d345aaf94a1..27e331893e5d7fcd642113988baf2123092ef15a 100644 (file)
@@ -15,7 +15,7 @@
 
 use std::fmt;
 
-#[derive(Copy, PartialEq, Eq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum Os {
     OsWindows,
     OsMacos,
@@ -49,7 +49,7 @@ pub enum Abi {
 }
 
 #[allow(non_camel_case_types)]
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub enum Architecture {
     X86,
     X86_64,
@@ -58,7 +58,7 @@ pub enum Architecture {
     Mipsel
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct AbiData {
     abi: Abi,
 
@@ -66,7 +66,7 @@ pub struct AbiData {
     name: &'static str,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum AbiArchitecture {
     /// Not a real ABI (e.g., intrinsic)
     RustArch,
index ce1539c62f80bc673edba482ca1fa2c35ee3f435..40390765dde84b54b5addb290961af2fce61cb32 100644 (file)
@@ -388,7 +388,7 @@ pub fn local_id(&self) -> NodeId {
 /// When parsing and doing expansions, we initially give all AST nodes this AST
 /// node value. Then later, in the renumber pass, we renumber them to have
 /// small, positive ids.
-pub const DUMMY_NODE_ID: NodeId = -1;
+pub const DUMMY_NODE_ID: NodeId = !0;
 
 /// The AST represents all type param bounds as types.
 /// typeck::collect::compute_bounds matches these against
index 1994ca70bbbb4096783fb513c4300930b5454ce6..475970ac30a75c972aaaa029adf92edcd1166dd5 100644 (file)
@@ -40,7 +40,7 @@
 ///   - The default implementation for a trait method.
 ///
 /// To construct one, use the `Code::from_node` function.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct FnLikeNode<'a> { node: ast_map::Node<'a> }
 
 /// MaybeFnLike wraps a method that indicates if an object
@@ -80,7 +80,7 @@ fn is_fn_like(&self) -> bool {
 /// Carries either an FnLikeNode or a Block, as these are the two
 /// constructs that correspond to "code" (as in, something from which
 /// we can construct a control-flow graph).
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Code<'a> {
     FnLikeCode(FnLikeNode<'a>),
     BlockCode(&'a Block),
index 48bb044cb1854cafba113fd3a9b56ff1c3aa3ec9..2a9a609ecd1e9dcbc89278eb04806f1c88dd77c0 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)
@@ -90,7 +101,7 @@ pub fn path_to_string<PI: Iterator<Item=PathElem>>(path: PI) -> String {
     })
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 pub enum Node<'ast> {
     NodeItem(&'ast Item),
     NodeForeignItem(&'ast ForeignItem),
@@ -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 b83b42c73e70899895dcd2e8f7ed367ef1859176..c4c2249d029596b2af15a845bb8823d18bdd4d29 100644 (file)
@@ -291,7 +291,7 @@ pub fn empty_generics() -> Generics {
 // ______________________________________________________________________
 // Enumerating the IDs which appear in an AST
 
-#[derive(RustcEncodable, RustcDecodable, Debug, Copy)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct IdRange {
     pub min: NodeId,
     pub max: NodeId,
index 2d8484e95bbc93bbae1c9763843e3bd6986385d1..06e447bb12af4b076c8dad9c8c9cb0d0031478d0 100644 (file)
@@ -282,7 +282,7 @@ pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
     first_attr_value_str_by_name(attrs, "crate_name")
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum InlineAttr {
     None,
     Hint,
@@ -571,7 +571,7 @@ fn int_type_of_word(s: &str) -> Option<IntType> {
     }
 }
 
-#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy)]
+#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
 pub enum ReprAttr {
     ReprAny,
     ReprInt(Span, IntType),
@@ -590,7 +590,7 @@ pub fn is_ffi_safe(&self) -> bool {
     }
 }
 
-#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy)]
+#[derive(Eq, Hash, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
 pub enum IntType {
     SignedInt(ast::IntTy),
     UnsignedInt(ast::UintTy)
index 6a00fff186002f4383ec2b0e24da9556d3b25dcd..b563a5e7d6e841f017c94eb0cc9e134985fd77d4 100644 (file)
@@ -47,7 +47,7 @@ pub trait Pos {
 /// A character offset. Because of multibyte utf8 characters, a byte offset
 /// is not equivalent to a character offset. The CodeMap will convert BytePos
 /// values to CharPos values as necessary.
-#[derive(Copy, PartialEq, Hash, PartialOrd, Debug)]
+#[derive(Copy, Clone, PartialEq, Hash, PartialOrd, Debug)]
 pub struct CharPos(pub usize);
 
 // FIXME: Lots of boilerplate in these impls, but so far my attempts to fix
@@ -278,9 +278,9 @@ pub struct ExpnInfo {
 #[derive(PartialEq, Eq, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Copy)]
 pub struct ExpnId(u32);
 
-pub const NO_EXPANSION: ExpnId = ExpnId(-1);
+pub const NO_EXPANSION: ExpnId = ExpnId(!0);
 // For code appearing from the command line
-pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(-2);
+pub const COMMAND_LINE_EXPN: ExpnId = ExpnId(!1);
 
 impl ExpnId {
     pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
@@ -305,7 +305,7 @@ pub struct FileLines {
 }
 
 /// Identifies an offset of a multi-byte character in a FileMap
-#[derive(Copy, RustcEncodable, RustcDecodable, Eq, PartialEq)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Eq, PartialEq)]
 pub struct MultiByteChar {
     /// The absolute offset of the character in the CodeMap
     pub pos: BytePos,
index 32857769acf4a34ab2a08989981bba8167fd9ed1..f35cc8c8d2399f9d695364c5cb4b121d3ace8399 100644 (file)
@@ -71,12 +71,12 @@ fn custom_emit(&mut self, cm: &codemap::CodeMap,
 /// This structure is used to signify that a task has panicked with a fatal error
 /// from the diagnostics. You can use this with the `Any` trait to figure out
 /// how a rustc task died (if so desired).
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct FatalError;
 
 /// Signifies that the compiler died with an explicit call to `.bug`
 /// or `.span_bug` rather than a failed assertion, etc.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct ExplicitBug;
 
 /// A span-handler is like a handler but also
@@ -371,7 +371,7 @@ fn stderr_isatty() -> bool {
 }
 #[cfg(windows)]
 fn stderr_isatty() -> bool {
-    const STD_ERROR_HANDLE: libc::DWORD = -12;
+    const STD_ERROR_HANDLE: libc::DWORD = -12i32 as libc::DWORD;
     extern "system" {
         fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
         fn GetConsoleMode(hConsoleHandle: libc::HANDLE,
index b679456b3537ba00ea448ec2ca0706e7da07bbd3..71fba789ff83509fcdaa2d82d95b128ce05b7793 100644 (file)
@@ -318,7 +318,7 @@ fn make_pat(self: Box<Self>) -> Option<P<ast::Pat>> {
 
 /// Fill-in macro expansion result, to allow compilation to continue
 /// after hitting errors.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct DummyResult {
     expr_only: bool,
     span: Span
index b2b2654801863daa9512e5f9d029332282f3ffbc..8ecd172b2f0d836899bcd067d1047283a9bd1d30 100644 (file)
@@ -84,7 +84,7 @@ macro_rules! md {
     trait_def.expand(cx, mitem, item, push)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum OrderingOp {
     PartialCmpOp, LtOp, LeOp, GtOp, GeOp,
 }
index ee2cf9017bbf34e38e47d917ef30a03c709e0db3..94abc0b34bc62d781a5a1c252027be86d6166680 100644 (file)
@@ -1770,7 +1770,8 @@ fn main() -> i32 {user!(z)}",
     // suggests that this can only occur in the presence of local-expand, which
     // we have no plans to support. ... unless it's needed for item hygiene....
     #[ignore]
-    #[test] fn issue_8062(){
+    #[test]
+    fn issue_8062(){
         run_renaming_test(
             &("fn main() {let hrcoo = 19; macro_rules! getx(()=>(hrcoo)); getx!();}",
               vec!(vec!(0)), true), 0)
@@ -1781,7 +1782,8 @@ fn main() -> i32 {user!(z)}",
     // (just g) along the other, so the result of the whole thing should
     // be "let z_123 = 3; z_123"
     #[ignore]
-    #[test] fn issue_6994(){
+    #[test]
+    fn issue_6994(){
         run_renaming_test(
             &("macro_rules! g (($x:ident) =>
               ({macro_rules! f(($y:ident)=>({let $y=3;$x}));f!($x)}));
@@ -1792,7 +1794,8 @@ fn a(){g!(z)}",
 
     // match variable hygiene. Should expand into
     // fn z() {match 8 {x_1 => {match 9 {x_2 | x_2 if x_2 == x_1 => x_2 + x_1}}}}
-    #[test] fn issue_9384(){
+    #[test]
+    fn issue_9384(){
         run_renaming_test(
             &("macro_rules! bad_macro (($ex:expr) => ({match 9 {x | x if x == $ex => x + $ex}}));
               fn z() {match 8 {x => bad_macro!(x)}}",
@@ -1805,7 +1808,8 @@ fn z() {match 8 {x => bad_macro!(x)}}",
     // interpolated nodes weren't getting labeled.
     // should expand into
     // fn main(){let g1_1 = 13; g1_1}}
-    #[test] fn pat_expand_issue_15221(){
+    #[test]
+    fn pat_expand_issue_15221(){
         run_renaming_test(
             &("macro_rules! inner ( ($e:pat ) => ($e));
               macro_rules! outer ( ($e:pat ) => (inner!($e)));
@@ -1821,7 +1825,8 @@ fn z() {match 8 {x => bad_macro!(x)}}",
 
     // method arg hygiene
     // method expands to fn get_x(&self_0, x_1: i32) {self_0 + self_2 + x_3 + x_1}
-    #[test] fn method_arg_hygiene(){
+    #[test]
+    fn method_arg_hygiene(){
         run_renaming_test(
             &("macro_rules! inject_x (()=>(x));
               macro_rules! inject_self (()=>(self));
@@ -1834,7 +1839,8 @@ fn z() {match 8 {x => bad_macro!(x)}}",
 
     // ooh, got another bite?
     // expands to struct A; impl A {fn thingy(&self_1) {self_1;}}
-    #[test] fn method_arg_hygiene_2(){
+    #[test]
+    fn method_arg_hygiene_2(){
         run_renaming_test(
             &("struct A;
               macro_rules! add_method (($T:ty) =>
@@ -1847,7 +1853,8 @@ macro_rules! add_method (($T:ty) =>
 
     // item fn hygiene
     // expands to fn q(x_1: i32){fn g(x_2: i32){x_2 + x_1};}
-    #[test] fn issue_9383(){
+    #[test]
+    fn issue_9383(){
         run_renaming_test(
             &("macro_rules! bad_macro (($ex:expr) => (fn g(x: i32){ x + $ex }));
               fn q(x: i32) { bad_macro!(x); }",
@@ -1857,7 +1864,8 @@ macro_rules! add_method (($T:ty) =>
 
     // closure arg hygiene (ExprClosure)
     // expands to fn f(){(|x_1 : i32| {(x_2 + x_1)})(3);}
-    #[test] fn closure_arg_hygiene(){
+    #[test]
+    fn closure_arg_hygiene(){
         run_renaming_test(
             &("macro_rules! inject_x (()=>(x));
             fn f(){(|x : i32| {(inject_x!() + x)})(3);}",
@@ -1867,7 +1875,8 @@ macro_rules! add_method (($T:ty) =>
     }
 
     // macro_rules in method position. Sadly, unimplemented.
-    #[test] fn macro_in_method_posn(){
+    #[test]
+    fn macro_in_method_posn(){
         expand_crate_str(
             "macro_rules! my_method (() => (fn thirteen(&self) -> i32 {13}));
             struct A;
@@ -1877,7 +1886,8 @@ macro_rules! add_method (($T:ty) =>
 
     // another nested macro
     // expands to impl Entries {fn size_hint(&self_1) {self_1;}
-    #[test] fn item_macro_workaround(){
+    #[test]
+    fn item_macro_workaround(){
         run_renaming_test(
             &("macro_rules! item { ($i:item) => {$i}}
               struct Entries;
@@ -1961,7 +1971,8 @@ fn run_renaming_test(t: &RenamingTest, test_idx: usize) {
         }
     }
 
-    #[test] fn fmt_in_macro_used_inside_module_macro() {
+    #[test]
+    fn fmt_in_macro_used_inside_module_macro() {
         let crate_str = "macro_rules! fmt_wrap(($b:expr)=>($b.to_string()));
 macro_rules! foo_module (() => (mod generated { fn a() { let xx = 147; fmt_wrap!(xx);}}));
 foo_module!();
index a2023d6832efbce2fe48cf33ed7e85962fc9c431..f514f72d565487d26df304dd52a8144a9a01f3a8 100644 (file)
@@ -38,7 +38,7 @@ pub struct SCTable {
     rename_memo: RefCell<HashMap<(SyntaxContext,Ident,Name),SyntaxContext>>,
 }
 
-#[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy, Clone)]
 pub enum SyntaxContext_ {
     EmptyCtxt,
     Mark (Mrk,SyntaxContext),
index 1b03a18072011a2c1f5acf0bbcf306369af6fe28..689b4595d39a695c265aa161a8a5759a1f7788ac 100644 (file)
@@ -25,7 +25,7 @@
 use self::Status::*;
 use self::AttributeType::*;
 
-use abi::RustIntrinsic;
+use abi::Abi;
 use ast::NodeId;
 use ast;
 use attr;
     ("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),
 
 
     // #23121. Array patterns have some hazards yet.
     ("slice_patterns", "1.0.0", Active),
+
+    // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
+    ("negate_unsigned", "1.0.0", Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -161,10 +163,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 +242,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 +279,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",
@@ -296,7 +295,7 @@ enum Status {
     ("recursion_limit", CrateLevel),
 ];
 
-#[derive(PartialEq, Copy, Debug)]
+#[derive(PartialEq, Copy, Clone, Debug)]
 pub enum AttributeType {
     /// Normal, builtin attribute that is consumed
     /// by the compiler before the unused_attribute check
@@ -327,9 +326,9 @@ 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,
+    pub negate_unsigned: bool,
     /// spans of #![feature] attrs for stable language features. for error reporting
     pub declared_stable_lang_features: Vec<Span>,
     /// #![feature] attrs for non-language (library) features
@@ -349,9 +348,9 @@ 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,
+            negate_unsigned: false,
             declared_stable_lang_features: Vec::new(),
             declared_lib_features: Vec::new()
         }
@@ -410,6 +409,9 @@ fn check_attribute(&self, attr: &ast::Attribute) {
 
 pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
     diag.span_err(span, explain);
+
+    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
+    if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
     diag.fileline_help(span, &format!("add #![feature({})] to the \
                                    crate attributes to enable",
                                   feature));
@@ -417,6 +419,9 @@ pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain:
 
 pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
     diag.span_warn(span, explain);
+
+    // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
+    if option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some() { return; }
     if diag.handler.can_emit_warnings {
         diag.fileline_help(span, &format!("add #![feature({})] to the \
                                        crate attributes to silence this warning",
@@ -523,7 +528,7 @@ fn visit_item(&mut self, i: &ast::Item) {
                                        across platforms, it is recommended to \
                                        use `#[link(name = \"foo\")]` instead")
                 }
-                if foreign_module.abi == RustIntrinsic {
+                if foreign_module.abi == Abi::RustIntrinsic {
                     self.gate_feature("intrinsics",
                                       i.span,
                                       "intrinsics are subject to change")
@@ -573,14 +578,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");
-                }
             }
 
             _ => {}
@@ -647,11 +644,17 @@ fn visit_fn(&mut self,
                 span: Span,
                 _node_id: NodeId) {
         match fn_kind {
-            visit::FkItemFn(_, _, _, abi) if abi == RustIntrinsic => {
+            visit::FkItemFn(_, _, _, abi) if abi == Abi::RustIntrinsic => {
                 self.gate_feature("intrinsics",
                                   span,
                                   "intrinsics are subject to change")
             }
+            visit::FkItemFn(_, _, _, abi) |
+            visit::FkMethod(_, &ast::MethodSig { abi, .. }) if abi == Abi::RustCall => {
+                self.gate_feature("unboxed_closures",
+                                  span,
+                                  "rust-call ABI is subject to change")
+            }
             _ => {}
         }
         visit::walk_fn(self, fn_kind, fn_decl, block, span);
@@ -699,13 +702,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,9 +733,9 @@ 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"),
+        negate_unsigned: cx.has_feature("negate_unsigned"),
         declared_stable_lang_features: accepted_features,
         declared_lib_features: unknown_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 bb9b586bb3f3d1914320b1d452ba0678905cfc77..f120dde8e1cb6fc12225f1887fc4a290d58772b1 100644 (file)
@@ -20,7 +20,7 @@
 use ptr::P;
 
 /// The specific types of unsupported syntax
-#[derive(Copy, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub enum ObsoleteSyntax {
     ClosureKind,
     ExternCrateString,
index 6f1f73aa2a9c5d6027e844f2d30c31a618b36491..c721624323923e18a999552bcb6b825af5af48d9 100644 (file)
@@ -96,7 +96,7 @@
 
 /// How to parse a path. There are four different kinds of paths, all of which
 /// are parsed somewhat differently.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum PathParsingMode {
     /// A path with no type parameters; e.g. `foo::bar::Baz`
     NoTypesAllowed,
@@ -109,7 +109,7 @@ pub enum PathParsingMode {
 }
 
 /// How to parse a bound, whether to allow bound modifiers such as `?`.
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 pub enum BoundParsingMode {
     Bare,
     Modified,
index 640b7d1c91d503db577ccd3b1bed78392452f759..ebfd970f3dbfc3c3e3d0634924bc90352ff11908 100644 (file)
@@ -147,13 +147,13 @@ pub fn buf_str(toks: &[Token],
     s
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum PrintStackBreak {
     Fits,
     Broken(Breaks),
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct PrintStackElem {
     offset: isize,
     pbreak: PrintStackBreak
index da1b7a7bdde50e93ec50a11aac7702b4db45b759..46d196d13fa72f4c9191c872835e0f89ba681dfa 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),
 }
@@ -46,12 +47,12 @@ fn pre(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
     fn post(&self, _state: &mut State, _node: AnnNode) -> io::Result<()> { Ok(()) }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct NoAnn;
 
 impl PpAnn for NoAnn {}
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct CurrentCommentAndLiteral {
     cur_cmnt: usize,
     cur_lit: usize,
@@ -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,
@@ -3048,7 +3053,7 @@ fn test_variant_to_string() {
     #[test]
     fn test_signed_int_to_string() {
         let pos_int = ast::LitInt(42, ast::SignedIntLit(ast::TyI32, ast::Plus));
-        let neg_int = ast::LitInt((-42) as u64, ast::SignedIntLit(ast::TyI32, ast::Minus));
+        let neg_int = ast::LitInt((!42 + 1) as u64, ast::SignedIntLit(ast::TyI32, ast::Minus));
         assert_eq!(format!("-{}", lit_to_string(&codemap::dummy_spanned(pos_int))),
                    lit_to_string(&codemap::dummy_spanned(neg_int)));
     }
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 638ddd3ea2e5b5523d7160c9e29dc60f4dd46ce6..5c345c75642b8eb39ff81a692f052c694b5e07e1 100644 (file)
@@ -32,7 +32,7 @@
 use ptr::P;
 use owned_slice::OwnedSlice;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum FnKind<'a> {
     /// fn foo() or extern "Abi" fn foo()
     FkItemFn(Ident, &'a Generics, Unsafety, Abi),
index ed2d00d6ad788ad00008e3a6fb868745f4a1df84..74ec3406f73bc3a735f640dfdb9375a9566acd25 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;
@@ -185,7 +184,7 @@ pub mod attr {
     /// Most attributes can only be turned on and must be turned off with term.reset().
     /// The ones that can be turned off explicitly take a boolean value.
     /// Color is also represented as an attribute for convenience.
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub enum Attr {
         /// Bold (or possibly bright) mode
         Bold,
index d6a4659c45a893275093250a7d1b14f8407452f5..01586b8f36ed0b35467b446c35fa01d19a1234d5 100644 (file)
@@ -18,7 +18,7 @@
 use std::mem::replace;
 use std::iter::repeat;
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum States {
     Nothing,
     Percent,
@@ -35,7 +35,7 @@ enum States {
     SeekIfEndPercent(isize)
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 enum FormatState {
     FormatStateFlags,
     FormatStateWidth,
@@ -444,7 +444,7 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)
     Ok(output)
 }
 
-#[derive(Copy, PartialEq)]
+#[derive(Copy, Clone, PartialEq)]
 struct Flags {
     width: usize,
     precision: usize,
@@ -461,7 +461,7 @@ fn new() -> Flags {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum FormatOp {
     FormatDigit,
     FormatOctal,
index 001313db6769f133b8f8166b16c61428ead730a4..66ef5e8661797f241f9737f5988282886191062b 100644 (file)
@@ -104,7 +104,7 @@ fn apply(&mut self) {
             // terminal! Admittedly, this is fragile, since stderr could be
             // redirected to a different console. This is good enough for
             // rustc though. See #13400.
-            let out = GetStdHandle(-11);
+            let out = GetStdHandle(-11i32 as libc::DWORD);
             SetConsoleTextAttribute(out, accum);
         }
     }
@@ -116,7 +116,8 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
         let bg;
         unsafe {
             let mut buffer_info = ::std::mem::uninitialized();
-            if GetConsoleScreenBufferInfo(GetStdHandle(-11), &mut buffer_info) != 0 {
+            if GetConsoleScreenBufferInfo(GetStdHandle(-11i32 as libc::DWORD),
+                                          &mut buffer_info) != 0 {
                 fg = bits_to_color(buffer_info.wAttributes);
                 bg = bits_to_color(buffer_info.wAttributes >> 4);
             } else {
index ee0d190d729eb30f9ab1445368a64ea596733a48..c84703b93ed263283d619ca7dbc81d75854b602a 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;
@@ -64,6 +62,7 @@
 use stats::Stats;
 use getopts::{OptGroup, optflag, optopt};
 use serialize::Encodable;
+use std::boxed::FnBox;
 use term::Terminal;
 use term::color::{Color, RED, YELLOW, GREEN, CYAN};
 
@@ -81,7 +80,7 @@
 use std::sync::mpsc::{channel, Sender};
 use std::sync::{Arc, Mutex};
 use std::thread;
-use std::thunk::{Thunk, Invoke};
+use std::thunk::Thunk;
 use std::time::Duration;
 
 // to be used by rustc to compile tests in libtest
@@ -160,7 +159,7 @@ pub enum TestFn {
     StaticBenchFn(fn(&mut Bencher)),
     StaticMetricFn(fn(&mut MetricMap)),
     DynTestFn(Thunk<'static>),
-    DynMetricFn(Box<for<'a> Invoke<&'a mut MetricMap>+'static>),
+    DynMetricFn(Box<FnBox(&mut MetricMap)+Send>),
     DynBenchFn(Box<TDynBenchFn+'static>)
 }
 
@@ -195,7 +194,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 /// This is fed into functions marked with `#[bench]` to allow for
 /// set-up & tear-down before running a piece of code repeatedly via a
 /// call to `iter`.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Bencher {
     iterations: u64,
     dur: Duration,
@@ -282,7 +281,7 @@ pub fn test_main_static(args: env::Args, tests: &[TestDescAndFn]) {
     test_main(&args, owned_tests)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum ColorConfig {
     AutoColor,
     AlwaysColor,
@@ -758,7 +757,7 @@ fn stdout_isatty() -> bool {
 }
 #[cfg(windows)]
 fn stdout_isatty() -> bool {
-    const STD_OUTPUT_HANDLE: libc::DWORD = -11;
+    const STD_OUTPUT_HANDLE: libc::DWORD = -11i32 as libc::DWORD;
     extern "system" {
         fn GetStdHandle(which: libc::DWORD) -> libc::HANDLE;
         fn GetConsoleMode(hConsoleHandle: libc::HANDLE,
@@ -857,7 +856,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 }
             }
         }
     }
@@ -937,7 +937,7 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
                     io::set_print(box Sink(data2.clone()));
                     io::set_panic(box Sink(data2));
                 }
-                testfn.invoke(())
+                testfn()
             }).unwrap();
             let test_result = calc_result(&desc, result_guard.join());
             let stdout = data.lock().unwrap().to_vec();
@@ -958,7 +958,7 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
         }
         DynMetricFn(f) => {
             let mut mm = MetricMap::new();
-            f.invoke(&mut mm);
+            f.call_box((&mut mm,));
             monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
             return;
         }
@@ -970,7 +970,7 @@ fn flush(&mut self) -> io::Result<()> { Ok(()) }
         }
         DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
         StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
-                                          Thunk::new(move|| f()))
+                                          Box::new(move|| f()))
     }
 }
 
@@ -1186,7 +1186,7 @@ pub fn do_not_run_ignored_tests() {
                 ignore: true,
                 should_panic: ShouldPanic::No,
             },
-            testfn: DynTestFn(Thunk::new(move|| f())),
+            testfn: DynTestFn(Box::new(move|| f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1203,7 +1203,7 @@ fn f() { }
                 ignore: true,
                 should_panic: ShouldPanic::No,
             },
-            testfn: DynTestFn(Thunk::new(move|| f())),
+            testfn: DynTestFn(Box::new(move|| f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1220,7 +1220,7 @@ fn test_should_panic() {
                 ignore: false,
                 should_panic: ShouldPanic::Yes(None)
             },
-            testfn: DynTestFn(Thunk::new(move|| f())),
+            testfn: DynTestFn(Box::new(move|| f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1237,7 +1237,7 @@ fn test_should_panic_good_message() {
                 ignore: false,
                 should_panic: ShouldPanic::Yes(Some("error message"))
             },
-            testfn: DynTestFn(Thunk::new(move|| f())),
+            testfn: DynTestFn(Box::new(move|| f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1254,7 +1254,7 @@ fn test_should_panic_bad_message() {
                 ignore: false,
                 should_panic: ShouldPanic::Yes(Some("foobar"))
             },
-            testfn: DynTestFn(Thunk::new(move|| f())),
+            testfn: DynTestFn(Box::new(move|| f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1271,7 +1271,7 @@ fn f() { }
                 ignore: false,
                 should_panic: ShouldPanic::Yes(None)
             },
-            testfn: DynTestFn(Thunk::new(move|| f())),
+            testfn: DynTestFn(Box::new(move|| f())),
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
@@ -1307,7 +1307,7 @@ pub fn filter_for_ignored_option() {
                     ignore: true,
                     should_panic: ShouldPanic::No,
                 },
-                testfn: DynTestFn(Thunk::new(move|| {})),
+                testfn: DynTestFn(Box::new(move|| {})),
             },
             TestDescAndFn {
                 desc: TestDesc {
@@ -1315,7 +1315,7 @@ pub fn filter_for_ignored_option() {
                     ignore: false,
                     should_panic: ShouldPanic::No,
                 },
-                testfn: DynTestFn(Thunk::new(move|| {})),
+                testfn: DynTestFn(Box::new(move|| {})),
             });
         let filtered = filter_tests(&opts, tests);
 
@@ -1351,7 +1351,7 @@ fn testfn() { }
                         ignore: false,
                         should_panic: ShouldPanic::No,
                     },
-                    testfn: DynTestFn(Thunk::new(testfn)),
+                    testfn: DynTestFn(Box::new(testfn)),
                 };
                 tests.push(test);
             }
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..5d265478b64da2575ea1e08427f19a8f3ee56f3f 100644 (file)
@@ -1,5 +1,15 @@
+S 2015-03-27 5520801
+  bitrig-x86_64 55a69b0ae5481ccda54c2fcfc54025a0945c4f57
+  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
+  bitrig-x86_64 e56c400a04bca7b52ab54e0780484bb68fa449c2
   freebsd-x86_64 cd02c86a9218da73b2a45aff293787010d33bf3e
   linux-i386 da50141558eed6dabab97b79b2c6a7de4f2d2c5e
   linux-x86_64 bca03458d28d07506bad4b80e5770b2117286244
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 3e23698397b4f5da4dd31ceac6ce53141537cc01..32af6d9255e5bd959ff36375cee78111ee38a514 100644 (file)
@@ -23,7 +23,7 @@ pub mod aliases {
     pub mod hidden_core {
         use super::aliases::B;
 
-        #[derive(Copy)]
+        #[derive(Copy, Clone)]
         pub struct A;
 
         pub fn make() -> B { A }
index c2acc514346150c8208fcb316731e009316ea146..d0566a1e0914bff0230151abd5be41fdf5953419 100644 (file)
 
 pub use private::P;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct S {
     p: P,
 }
 
 mod private {
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub struct P {
         p: i32,
     }
index 643442363a4463e6ac8e2c5701dedc77bbdf4c94..348b71faf0cdbd39632ff5ab9c98a677571b6d6c 100644 (file)
@@ -17,7 +17,7 @@
 
 pub fn get_count() -> u64 { unsafe { COUNT } }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Foo;
 
 impl Foo {
index fd99da87e6b0d1f1e00f67425ba66fe22a9805a5..b67ec1b9bfc655e8014e923abbacc7f28d0df50d 100644 (file)
@@ -17,7 +17,7 @@
 
 pub fn get_count() -> u64 { unsafe { COUNT } }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Foo;
 
 impl Foo {
index 8670cd96fc6de7f406f85439d8532b21a9464089..201f028b6b658acc981dbb5eca0f04ac44f75854 100644 (file)
@@ -11,7 +11,7 @@
 #![crate_name="struct_variant_xc_aux"]
 #![crate_type = "lib"]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Enum {
     Variant(u8),
     StructVariant { arg: u8 }
index 6799cbc6f335531f9a658eacd86698c6be172528..7a69be2b06c7cf2438a8f3c61fd2013871a76845 100644 (file)
 
 // used by the rpass test
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Struct;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Unit {
     UnitVariant,
     Argument(Struct)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct TupleStruct(pub usize, pub &'static str);
 
 // used by the cfail test
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct StructWithFields {
     foo: isize,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum EnumWithVariants {
     EnumVariant,
     EnumVariantArg(isize)
index d6577036b8ebed47d03ac9802dc8ddc03eea3022..83c39b3f3faf6c9e5b68d474b6b96464da7914c2 100644 (file)
@@ -18,7 +18,7 @@
 use std::num::Float;
 use std::rand::{Rng, StdRng};
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Vec2 {
     x: f32,
     y: f32,
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 891d8143dd8c0ba1fb3fd3701485685bce9b91b0..72f3464cdb72d165d101cc5460845ac6bfda880d 100644 (file)
@@ -54,7 +54,7 @@ fn print_complements() {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Color {
     Red,
     Yellow,
@@ -72,7 +72,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct CreatureInfo {
     name: usize,
     color: Color
index 3a1da4c32af4c1ce5d265a8ab98275a2ad0a83a1..4489a124abe0f3cb50e8d699acca7f981b308848 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]) {
@@ -63,12 +63,12 @@ fn next_permutation(perm: &mut [i32], count: &mut [i32]) {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct P {
     p: [i32; 16],
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Perm {
     cnt: [i32; 16],
     fact: [u32; 16],
@@ -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 7c4cc0eaab7ce403267064511da85cb858aedba3..effdd67027a44b8a32b230a494451fbc2d8738cc 100644 (file)
@@ -105,7 +105,7 @@ fn sum_and_scale(a: &'static [AminoAcid]) -> Vec<AminoAcid> {
     result
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct AminoAcid {
     c: u8,
     p: f32,
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 ba4f2c9b1c563abbfc9a00fc9d122bb22342521a..db131bcfdc354e55c7e14922d89a59db92151db8 100644 (file)
@@ -64,7 +64,7 @@
 
 // Code implementation
 
-#[derive(Copy, PartialEq, PartialOrd, Ord, Eq)]
+#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
 struct Code(u64);
 
 impl Code {
index 13154e025d2cde61cfbf43e04919e1c00f19e9ed..669a0e86f1e659406f8f9b232532f27ec1b32780 100644 (file)
@@ -96,7 +96,7 @@
     },
 ];
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Planet {
     x: f64, y: f64, z: f64,
     vx: f64, vy: f64, vz: f64,
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)
index a88445bafc049e8920b440627911a4b221b9ed5f..022a6b4f2f7deb95718dce6ab5a5ed1e86d6a916 100644 (file)
@@ -19,4 +19,3 @@
 #[macro_use] #[no_link]
 extern crate macro_reexport_1;
 //~^ ERROR macros reexports are experimental and possibly buggy
-//~| HELP add #![feature(macro_reexport)] to the crate attributes to enable
index 99618c6bf5626911d8629249df01a2a9c126e052..e5091a92581b45e613d792ee8057b16941309922 100644 (file)
@@ -9,13 +9,13 @@
 // except according to those terms.
 
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Foo {
   bar1: Bar,
   bar2: Bar
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Bar {
   int1: isize,
   int2: isize,
index 849c98e122e526b2b78f7adbf25fe7f0a3eb4c09..440be93dfdca18fea34311aa6aa08a007c22eeb8 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Foo {
   bar1: Bar,
   bar2: Bar
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Bar {
   int1: isize,
   int2: isize,
index b1eb06d16b19ae47b1d199caeb62b42fc79d8eb0..cce55b6c941b90e019add2efc7d328489a341a77 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::ops::Add;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Point {
     x: isize,
     y: isize,
index e14df7329eac4129b76636606fee3be7551ce709..c11e58651aa76a1f7979bafda0f0e12cd8100c1a 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(box_syntax)]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct A { a: isize, b: isize }
 
 struct B { a: isize, b: Box<isize> }
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..1be606c3546fd18168c58a3b5aee8882b7145dbc 100644 (file)
@@ -22,18 +22,32 @@ enum TestE {
 impl !Sync for NotSync {}
 
 impl Copy for TestE {}
+impl Clone for TestE { fn clone(&self) -> Self { *self } }
+
 impl Copy for MyType {}
+
+impl Copy for &'static mut MyType {}
+//~^ ERROR E0206
+//~| ERROR E0277
+//~| ERROR E0277
+impl Clone for MyType { fn clone(&self) -> Self { *self } }
+
 impl Copy for (MyType, MyType) {}
 //~^ ERROR E0206
+//~| ERROR E0117
 
 impl Copy for &'static NotSync {}
 //~^ ERROR E0206
 
 impl Copy for [MyType] {}
 //~^ ERROR E0206
+//~| ERROR E0117
+//~| ERROR E0277
+//~| ERROR E0277
 
 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..19b5f9b
--- /dev/null
@@ -0,0 +1,132 @@
+// 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(negate_unsigned)]
+
+#![allow(unused_imports)]
+#![feature(negate_unsigned)]
+
+// 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 021ef7343cbb4432f028f51e030967d23a98db43..c52458934bd1c90b378e9f15813201a8bc1e4378 100644 (file)
@@ -14,7 +14,7 @@
 use std::ops::Index;
 use std::fmt::Debug;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct S;
 
 impl Index<usize> for S {
@@ -25,7 +25,7 @@ fn index(&self, _: usize) -> &str {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct T;
 
 impl Index<usize> for T {
index 1d7794336a09671999d7f8f50ae9dff971bc9357..cdf7d026d5eebd4b26039d7b9508496c51b8aad4 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(negate_unsigned)]
+
 #[repr(u8)] //~ NOTE discriminant type specified here
 enum Eu8 {
     Au8 = 23,
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 f47f14d587992f83c2a95790130da77cf6651fdc..460c396750ff0b6fda97337e1d46c12824a46822 100644 (file)
 
 // issue #20126
 
-#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
+#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented
 struct Foo;
 
 impl Drop for Foo {
     fn drop(&mut self) {}
 }
 
-#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
+#[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented
 struct Bar<T>(::std::marker::PhantomData<T>);
 
 #[unsafe_destructor]
diff --git a/src/test/compile-fail/feature-gate-rust-call.rs b/src/test/compile-fail/feature-gate-rust-call.rs
new file mode 100644 (file)
index 0000000..029a9ca
--- /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.
+
+extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
+
+trait Foo {
+    extern "rust-call" fn foo();
+}
+
+impl Foo for i32 {
+    extern "rust-call" fn foo() { } //~ ERROR rust-call ABI is subject to change
+}
+
+fn main() { }
index 9ee3fcee0235557da422bec01305fb010d843112..dcd7a0ded812fcd7176d7143fe207ecfc34fb438 100644 (file)
@@ -13,7 +13,7 @@
 
 use std::simd::f32x4;
 
-#[simd] #[derive(Copy)] #[repr(C)] struct LocalSimd(u8, u8);
+#[simd] #[derive(Copy, Clone)] #[repr(C)] struct LocalSimd(u8, u8);
 
 extern {
     fn foo() -> f32x4; //~ ERROR use of SIMD type
index d86c5d211dc5fa2e339d1fa06582655ee0b44d3f..5df309321d3108a956131d8494dfc1d1a1ccd1f4 100644 (file)
 
 struct Foo;
 impl Fn<()> for Foo {
-    //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
     extern "rust-call" fn call(self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
 }
 struct Foo1;
 impl FnOnce() for Foo1 {
-    //~^ ERROR associated type bindings are not allowed here
     extern "rust-call" fn call_once(self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
 }
 struct Bar;
 impl FnMut<()> for Bar {
-    //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
 }
 struct Baz;
 impl FnOnce<()> for Baz {
-    //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
     extern "rust-call" fn call_once(&self, args: ()) -> () {}
+    //~^ ERROR rust-call ABI is subject to change
 }
 
 fn main() {}
index abaa256d52e7fa3e7e3cbccb8a714a64352efcfe..d82d0dec72bba4dd0e2e5d04cf4e8541acf85b37 100644 (file)
@@ -16,7 +16,6 @@ fn main() {
     match x {
         box 1 => (),
         //~^ box pattern syntax is experimental
-        //~| add #![feature(box_patterns)] to the crate attributes to enable
         _     => ()
     };
 }
index 3e08c1f7a71305ee1d64d977e4986023d5a5fdd3..a2643fe02b8f72bdc6fdd0594b73238386d01297 100644 (file)
@@ -13,5 +13,4 @@
 fn main() {
     let x = box 3;
     //~^ ERROR box expression syntax is experimental; you can call `Box::new` instead.
-    //~| HELP add #![feature(box_syntax)] to the crate attributes to enable
 }
index c8845ced2fc92cb9c99dd9156622eea020563ab0..7b1405c913f6b0236298d07d6521579cfa2938ea 100644 (file)
@@ -14,6 +14,5 @@
 #[link_args = "aFdEfSeVEEE"]
 extern {}
 //~^ ERROR the `link_args` attribute is not portable across platforms
-//~| HELP add #![feature(link_args)] to the crate attributes to enable
 
 fn main() { }
index 716ea9f8dba21ff678941d09bbd7ffe0e35ae60b..92a1b071437e60f9fb0867198ce5f1a46aaa3716 100644 (file)
@@ -12,7 +12,6 @@
     #[link_name = "llvm.sqrt.f32"]
     fn sqrt(x: f32) -> f32;
     //~^ ERROR linking to LLVM intrinsics is experimental
-    //~| HELP add #![feature(link_llvm_intrinsics)] to the crate attributes
 }
 
 fn main(){
index d716c53e1d18ce68c4db2f1a79f42b7c9802cae4..9cdebde7b7b9879946e83a4aaf2c274540cf6cda 100644 (file)
@@ -15,5 +15,4 @@
 #[plugin_registrar]
 pub fn registrar() {}
 //~^ ERROR compiler plugins are experimental
-//~| HELP add #![feature(plugin_registrar)] to the crate attributes to enable
 fn main() {}
index c0a251e77a3160c0f617d216cc9d702a7daf8c21..883e1be04b22893e4b3b9f93171365e973e8f7c3 100644 (file)
@@ -13,7 +13,7 @@
 #![feature(simd)]
 
 #[repr(C)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 #[simd]
 pub struct f32x4(f32, f32, f32, f32);
 
index 2aebbf3d54b9cd08d6151d071685887cde875098..9dd1e229e0af5a02b7fbe0e71d47941f27103498 100644 (file)
@@ -18,8 +18,6 @@
 
 #[unsafe_destructor]
 //~^ ERROR `#[unsafe_destructor]` does nothing anymore
-//~| HELP: add #![feature(unsafe_destructor)] to the crate attributes to enable
-// (but of couse there is no point in doing so)
 impl<'a> Drop for D<'a> {
     fn drop(&mut self) { }
 }
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 d5bfe3d16925c70b1b76a3ac8390c3a18fef64a4..1925caf6870eef80aab0daa80651683ffbbe46d8 100644 (file)
@@ -17,7 +17,7 @@ fn assert_copy<T:Copy>() { }
 
 trait Dummy : MarkerTrait { }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct MyStruct {
     x: isize,
     y: isize,
index 52ca24d0f547a7fe20a4177bdd25f5f19453c630..066590252a54ad769fcb599e94f616d25770b598 100644 (file)
@@ -25,13 +25,13 @@ fn take_param<T:Foo>(foo: &T) { }
 
 fn a() {
     let x: Box<_> = box 3;
-    take_param(&x); //~ ERROR `core::marker::Copy` is not implemented
+    take_param(&x); //~ ERROR E0277
 }
 
 fn b() {
     let x: Box<_> = box 3;
     let y = &x;
-    let z = &x as &Foo; //~ ERROR `core::marker::Copy` is not implemented
+    let z = &x as &Foo; //~ ERROR E0038
 }
 
 fn main() { }
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 171dedd5b2e5881ce5422307c2ee7188666d1e04..1f70828e411ef1cfc472b6ed1884690939457c71 100644 (file)
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(negate_unsigned)]
 #![deny(exceeding_bitshifts)]
 #![allow(unused_variables)]
 #![allow(dead_code)]
-#![feature(core)]
+#![feature(core, negate_unsigned)]
 
 fn main() {
       let n = 1u8 << 7;
index f36c726c875089104546f5594992014b9ce44b9a..798dc112b0af995b6b10a8b8d772b03e707e3190 100644 (file)
@@ -8,7 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(negate_unsigned)]
 #![allow(dead_code)]
+#![feature(negate_unsigned)]
 
 // compile-flags: -D unused-comparisons
 fn main() { }
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 bc18b52a0c1c9e3f8fdfd0f65994e4e2e0daf464..be321b6290354197c03dfcd2c5b0447e271b0cc2 100644 (file)
@@ -16,6 +16,7 @@ struct IWantToCopyThis {
 
 impl Copy for IWantToCopyThis {}
 //~^ ERROR the trait `Copy` may not be implemented for this type
+//~| ERROR E0277
 
 enum CantCopyThisEither {
     A,
@@ -28,5 +29,6 @@ enum IWantToCopyThisToo {
 
 impl Copy for IWantToCopyThisToo {}
 //~^ ERROR the trait `Copy` may not be implemented for this type
+//~| ERROR E0277
 
 fn main() {}
index aa890550f1c4868aa6ac3a4734bb98dc02fe19c6..198fa5b9aca0bf4009c238cc2ed2651278b86a15 100644 (file)
@@ -20,7 +20,7 @@ fn $n (&self) -> i32 {
         )
     }
 
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub struct S;
 
     impl S {
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/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs
deleted file mode 100644 (file)
index f51eee3..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::sync::mpsc::channel;
-
-// Test that a class with an unsendable field can't be
-// sent
-
-use std::rc::Rc;
-
-struct foo {
-  i: isize,
-  j: Rc<String>,
-}
-
-fn foo(i:isize, j: Rc<String>) -> foo {
-    foo {
-        i: i,
-        j: j
-    }
-}
-
-fn main() {
-  let cat = "kitty".to_string();
-  let (tx, _) = channel();
-  //~^ ERROR `core::marker::Send` is not implemented
-  tx.send(foo(42, Rc::new(cat)));
-}
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 7a285d90b9d6a1d053d79ec3885ba30c4d73e800..3024ca0fe69834142d101a102f98f220876f6228 100644 (file)
 use self::ManualDiscriminant::{OneHundred, OneThousand, OneMillion};
 use self::SingleVariant::TheOnlyVariant;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum AutoDiscriminant {
     One,
     Two,
     Three
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum ManualDiscriminant {
     OneHundred = 100,
     OneThousand = 1000,
     OneMillion = 1000000
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum SingleVariant {
     TheOnlyVariant
 }
index 06053965ca7571d7a28475b51be67aee8c0f1489..fc9ef8e3a98ed01ae87b7621a896a80a6662d7c3 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct<T> {
     x: T
 }
index 314ec472b69419a5671e201f2e66aad08baf42e9..6468a36f8c61c703c39fe5b0a421d6a5f4770355 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Enum {
     Variant1 { x: u16, y: u16 },
     Variant2 (u32)
index 564c2d26493d2dd8dd6e6df1c26b2765c85374e9..975668baa12852163c2008a7cf88e1f8f229f6f4 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct<T> {
     x: T
 }
index eba4370e698ed2ba4be685d79f169ff288e3b549..28885d0ad9b79828bd10b5638242babaef775081 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct {
     x: isize
 }
index 6df7cdfd47f1870901e46d750a550fdfa400312b..b69a3856736c4521d8677d5331fc1230462487a3 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct {
     x: isize
 }
index b638e210dd38aeb60a59d6dbfe081fa4b358c809..97d4496cce12b3d34a78aa520e50bd9434746fac 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct TupleStruct(isize, f64);
 
 impl TupleStruct {
index f61b78d5449e7e012c5a24f5ecaed02d1bb42fae..f16f236a0cb0612750600331e838bb786e0d03d1 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct {
     x: isize
 }
index 4ac436c9325bb0f3fa3d6f967076bfeaa6e73842..56de877016deebdb3d42b22de9abe7b872c199be 100644 (file)
 #![feature(box_syntax)]
 #![omit_gdb_pretty_printer_section]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct {
     x: isize
 }
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 6e75e0851384895b52ceed34f7e1457107eb3c41..3d5e6e78deaf15e4a601312396fd787217664a7e 100644 (file)
@@ -19,7 +19,7 @@
 
 fn test2() -> isize { let val = &0; { } *val }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct S { eax: isize }
 
 fn test3() {
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 19ce5d0a7ca40a60a787f82b8a6fd0fed6b1e783..a9e18f5a8f1e6b0dade592613e8579396a091dcd 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #[derive()]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Foo;
 
 pub fn main() { }
index 838ef338846a8dbb05ddf90cb1cf1bb43df039e7..c0f55893a3abe4370e0a779081591bd56a3cdc71 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #[repr(packed)]
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 struct Foo {
     a: i8,
     b: i16,
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 672090c13a23376ef59adf3665d903d6c8b13893..26a05f8490fd191d207d60a90d03fc0e7e3efd3d 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(unboxed_closures)]
+
 extern crate foo;
 
 // @has bar/trait.Foo.html //pre "pub trait Foo"
index fc5f03e8bd36a4abb029c6328fff6c61c64800c6..96a7a8378b792e04d01a0e5837043f455417af05 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![crate_type="lib"]
+#![feature(unboxed_closures)]
 
 pub trait Foo {
     extern "rust-call" fn foo(&self, _: ()) -> i32;
index 5310ed25d3b1bd8be509683cb5b171bb37d8c95b..9d1ab00359dd955e28a36f7eb93f73c255b5aebf 100644 (file)
@@ -179,7 +179,7 @@ enum SomeEnum<'a> {
     MyTypes(MyType, MyType)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum SomeOtherEnum {
     SomeConst1,
     SomeConst2,
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 82adac8cf861484e867cb47d0263ece060527b1c..3dffae99292c61b1c487c8c7d8e1f4d1e18dbffb 100644 (file)
@@ -20,10 +20,10 @@ pub trait Offset {
     fn dummy(&self) { }
 }
 
-#[derive(Copy)] pub struct X;
+#[derive(Copy, Clone)] pub struct X;
 impl Offset for X { type State = Y; }
 
-#[derive(Copy)] pub struct Y;
+#[derive(Copy, Clone)] pub struct Y;
 impl OffsetState for Y {}
 
 pub fn now() -> DateTime<X> { from_utc(Y) }
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..ab9d892ce2b60cd963140e1dd75a44bd689ae366 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!(0xffffffff, (!0 as u32));
+    assert_eq!(4294967295, (!0 as u32));
+    assert_eq!(0xffffffffffffffff, (!0 as u64));
+    assert_eq!(18446744073709551615, (!0 as u64));
 
-    assert_eq!(-2147483648 - 1, 2147483647);
+    assert_eq!((-2147483648i32).wrapping_sub(1), 2147483647);
 }
index 01c85023eda39a23d9ccba58c1e7955efe30d0cc..da7a3ae684c57aac9ca5c970d64cc2ad05d597f3 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::ops::Mul;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Foo {
     x: f64,
 }
index d6117a04e35df1633294de60210581dc96881d85..a9f19c12b0278e09b1d0f122028ae1f162671f7d 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(negate_unsigned)]
 
 #[cfg(any(target_arch = "x86", target_arch = "arm"))]
 fn target() {
index 84efe1903671f587285a84f790ebd1a425c378b8..a5c68c5ecf97671d4f8584a5daa810da87de61ef 100644 (file)
@@ -13,7 +13,7 @@
 
 use std::cell::Cell;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum newtype {
     newvar(isize)
 }
index 717348652ed617c3548b12f7d2968e3f42b95c64..c026ffc6d318d76e1bcbedef18c823fb4464c47a 100644 (file)
@@ -20,7 +20,7 @@
 use trait_superkinds_in_metadata::RequiresCopy;
 use std::marker;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct X<T>(T);
 
 impl<T:Sync> RequiresShare for X<T> { }
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 57c1fd80bd5420b2cb96a1e3436868627d4c42de..4c494293b517edbf83ca7de7439ebf42347a4844 100644 (file)
@@ -11,7 +11,7 @@
 
 use std::cmp;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum cat_type { tuxedo, tabby, tortoiseshell }
 
 impl cmp::PartialEq for cat_type {
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() { }
index 134549d747a0a580857acfe732ea3b4b3fdf4b6a..b0630b516407b60f3490ce6d3f2bb920c9bff545 100644 (file)
@@ -11,7 +11,7 @@
 // pretty-expanded FIXME #23616
 
 pub fn main() {
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     enum x { foo }
     impl ::std::cmp::PartialEq for x {
         fn eq(&self, other: &x) -> bool {
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 d0e9e5d610606631c363d5d978967362dfd15ad5..51926ececc2b1ff654334608cd8018bcace33459 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Foo {
     Bar = 0xDEADBEE
 }
index 6dfcc3b2a165acfe96065b63123facc89009091e..5c5765454d457adefd99ef00949d845a7302099d 100644 (file)
 
 // pretty-expanded FIXME #23616
 
+#[derive(Copy, Clone)]
 struct C { _x: u8 }
 
-impl Copy for C { }
-
 fn main() {
     fn d() -> C { C { _x: 0 } }
 
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 e0bbd0b2b041e447855bc4524f0c4ef072f4cdee..4204d9b5c3eaeb3006c3358e7b5ec6c6a31c2f89 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Test;
 
 pub fn main() {}
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 fd19d02e688e92ae99c47bef94ce99a2e28ab8ff..9bf286c434219ba504b4d51f1b37f46ec1401a53 100644 (file)
@@ -32,7 +32,7 @@ fn foo2<T:ToBar>(x: &Fat<[T]>) {
     assert!(x.ptr[1].to_bar() == bar);
 }
 
-#[derive(Copy, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq)]
 struct Bar;
 
 trait ToBar {
index 055b61b25fbf7ea5845f3942f1609b69622610fc..5198dd43d6db83380b0463ecd0c8bca4ce553d74 100644 (file)
@@ -51,7 +51,7 @@ fn foo3(x: &Fat<Fat<[isize]>>) {
 }
 
 
-#[derive(Copy, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq)]
 struct Bar;
 
 trait ToBar {
index ede4b8c442e17764a6a6fe9dbef27299ecb96100..370bc2882271f5681d5a035af2db7daac2ea931c 100644 (file)
@@ -19,10 +19,10 @@ struct Fat<T: ?Sized> {
     ptr: T
 }
 
-#[derive(Copy, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq)]
 struct Bar;
 
-#[derive(Copy, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq)]
 struct Bar1 {
     f: isize
 }
index ff2a70467ea889ca6ac86d11237b5f835202155c..e60cd02ce9994524f192f7392c8576c0452c7b7a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum chan { chan_t, }
 
 impl PartialEq for chan {
index 0242e53aa8c4ff761ec5d0cb0b8a23ad0bcc4f94..46238c4572080837d90148a0c0962e0729088869 100644 (file)
@@ -12,7 +12,7 @@ macro_rules! check {
     ($m:ident, $t:ty, $v:expr) => {{
         mod $m {
             use std::mem::size_of;
-            #[derive(Copy, Debug)]
+            #[derive(Copy, Clone, Debug)]
             enum E {
                 V = $v,
                 A = 0
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 25f09ee94b019db62ca375efd0dc8150f421642e..ee50d3bdf0ee8334278373fde4acf2d29ef30031 100644 (file)
@@ -13,7 +13,7 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct LM { resize_at: usize, size: usize }
 
 enum HashMap<K,V> {
index 80729fb2164745470106078153b0642337db7066..ca394f991f29b76f30b9259bf465a5cc779870a1 100644 (file)
@@ -15,7 +15,7 @@ fn f(arg: &mut A) {
     arg.a = 100;
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct A { a: isize }
 
 pub fn main() {
index ad39783063854a1c0f72d5c5e878440d23b7428e..e79daed4c33d7bd9ea9df42ed5e496e59052bf12 100644 (file)
@@ -14,7 +14,7 @@
 
 // Tests for if as expressions returning nominal types
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct I { i: isize }
 
 fn test_rec() {
@@ -22,7 +22,7 @@ fn test_rec() {
     assert_eq!(rs.i, 100);
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum mood { happy, sad, }
 
 impl PartialEq for mood {
index 91ad142c3863a7b6aac39c3ac724c17dd0feb180..2dcb0f833e4b327bf384c90654e59bc17be003b6 100644 (file)
@@ -13,7 +13,7 @@
 
 
 // Tests for match as expressions resulting in struct types
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct R { i: isize }
 
 fn test_rec() {
@@ -21,7 +21,7 @@ fn test_rec() {
     assert_eq!(rs.i, 100);
 }
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum mood { happy, sad, }
 
 impl PartialEq for mood {
index 25a990383e412eb19a5bb36970449bc445d6610b..9a039e8bc3539e40dfff5eeabf1abb853a401735 100644 (file)
@@ -13,7 +13,7 @@
 
 use std::cell::Cell;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Point {x: isize, y: isize, z: isize}
 
 fn f(p: &Cell<Point>) {
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 1f48dc3bcf1d7dbba1bf20a1ab25342dded4b0cd..9d304ea9e10b64c8b927a17d7e676a58b89b68d2 100644 (file)
@@ -11,7 +11,7 @@
 // Test a foreign function that accepts and returns a struct
 // by value.
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU16s {
     one: u16, two: u16
 }
index 171e2a647cc6386e9624b0f21908d0e9a04d17f9..8dae0473fd5ed64b203a585c701c297820a4031b 100644 (file)
@@ -11,7 +11,7 @@
 // Test a foreign function that accepts and returns a struct
 // by value.
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU32s {
     one: u32, two: u32
 }
index 83555f6bb1d51dd2a7ac5af64fd1fa60ad76ff42..14aeea34657985a3773149c9fb9f1a20876a0d8f 100644 (file)
@@ -11,7 +11,7 @@
 // Test a foreign function that accepts and returns a struct
 // by value.
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU64s {
     one: u64, two: u64
 }
index d2b13445e6a22d99d4b06dea9ca66992ec087080..75a109e442911c9b3d33893e74f03414b2f8828e 100644 (file)
@@ -11,7 +11,7 @@
 // Test a foreign function that accepts and returns a struct
 // by value.
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 pub struct TwoU8s {
     one: u8, two: u8
 }
index 4c0633d49c65fbcf36523f33b7d6ba344af8b73a..7883c22f909ddb40860c164be07fa3572b5615a3 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct S {
     x: u64,
     y: u64,
index 82b03abf0570b5325d3fe436a0ba554c39cc07b0..0ba0ed4bf7f979cae9cea0e8198c253757649d39 100644 (file)
@@ -12,7 +12,7 @@
 
 fn id<T>(x: T) -> T { return x; }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Triple {x: isize, y: isize, z: isize}
 
 pub fn main() {
index 59ec14e097e6728d34f7d9cd302687d278aa4aaa..f5f80914937d3cf51140c2aba67dceb1b64d6479 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Q { R(Option<usize>) }
 
 fn xyzzy(q: Q) -> usize {
index 598172ac18ead7816ace05bed580d10935db3c85..11c67b8af8107e11451e336d54f208052f4bb437 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Pair { x: isize, y: isize }
 
 pub fn main() {
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 8ececb3875acb045de742c8652c39517b11e6eae..b40f4d27a9c4d63a86e0b6d953fb37122682d2dc 100644 (file)
@@ -22,7 +22,7 @@
 
 use std::marker::PhantomData;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Foo<T> { x: T }
 
 type Ty<'tcx> = &'tcx TyS<'tcx>;
@@ -31,7 +31,7 @@ enum TyS<'tcx> {
     Boop(PhantomData<*mut &'tcx ()>)
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Bar<'tcx> {
     Baz(Foo<Ty<'tcx>>)
 }
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 a4661410ad6c0e14762248f746b9a2ccbb9cef8d..15dbe796ef589ebde03e193cc3bc819dd8685f90 100644 (file)
@@ -10,6 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
+#![feature(negate_unsigned)]
 #![feature(intrinsics)]
 
 mod rusti {
index da3efb4fea8cac85ca6c1d5557ba8810547586a5..3ad78f088f9c9f5fe26e92187f40e0cee21218d7 100644 (file)
@@ -25,7 +25,7 @@ fn test(slot: &mut Option<Thunk<(),Thunk>>) -> () {
   let a = slot.take();
   let _a = match a {
     // `{let .. a(); }` would break
-    Some(a) => { let _a = a.invoke(()); },
+    Some(a) => { let _a = a(); },
     None => (),
   };
 }
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 ed2009dab1bafe73dc01579b4420ed77a2245017..def85b4766783ff499e58efd9a8859a995968c03 100644 (file)
@@ -23,5 +23,5 @@
 
 pub fn main() {
     let mut x = 1;
-    let _thunk = Thunk::new(move|| { x = 2; });
+    let _thunk = Box::new(move|| { x = 2; });
 }
index ad03c7fddb49bb211100d6730bf8cdd8d932f7a8..dddfb9bacf9e211e016d5c31de5c1c9f0aa9a4c9 100644 (file)
@@ -16,7 +16,7 @@
 
 use std::collections::HashSet;
 
-#[derive(Copy, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 struct XYZ {
     x: isize,
     y: isize,
index e82a7602ef594f845cffa4bffed210609923e3ba..7acabf31c85a17587ed16823161e47b8545becf3 100644 (file)
@@ -24,7 +24,7 @@ fn deref<'a>(&'a self) -> &'a JSRef {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct JSRef {
     node: *const Node
 }
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 fb82cccc871e71032bb50dba67fd96cdbf28fade..e11270c94ca546dc980578b8c2eff4e987d92bc9 100644 (file)
@@ -14,7 +14,7 @@
 
 use std::u8;
 
-const NUM: usize = u8::BITS as usize;
+const NUM: usize = u8::BITS;
 
 struct MyStruct { nums: [usize; 8] }
 
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 31f6a4209de4dec5a9a6324189233d0247843156..08c313ab0a42b397404a8dcf547b4a8621f88516 100644 (file)
 
 // pretty-expanded FIXME #23616
 
-static X2: u64 = -1 as u16 as u64;
-static Y2: u64 = -1 as u32 as u64;
-const X: u64 = -1 as u16 as u64;
-const Y: u64 = -1 as u32 as u64;
+static X2: u64 = !0 as u16 as u64;
+static Y2: u64 = !0 as u32 as u64;
+const X: u64 = !0 as u16 as u64;
+const Y: u64 = !0 as u32 as u64;
 
 fn main() {
     assert_eq!(match 1 {
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 3fbdb92e906172564053987806902bcbcf860dca..cf8c54fdd808667afc3262f7791369e8746e8ec6 100644 (file)
 
 use std::thunk::Thunk;
 
-fn action(cb: Thunk<usize, usize>) -> usize {
-    cb.invoke(1)
+fn action(cb: Thunk<(usize,), usize>) -> usize {
+    cb(1)
 }
 
 pub fn main() {
-    println!("num: {}", action(Thunk::with_arg(move |u| u)));
+    println!("num: {}", action(Box::new(move |u| u)));
 }
index cd28d6425516dbe61fd2d95f32bb78a401884341..059d25173c2ad75e57f88fa3f2b979a13092eeb2 100644 (file)
 
 pub trait Promisable: Send + Sync {}
 impl<T: Send + Sync> Promisable for T {}
-pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a,Result<T, E>, Result<T, E>>
+pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a, (Result<T, E>,), Result<T, E>>
     where
         T: Promisable + Clone + 'a,
         E: Promisable + Clone + 'a,
         F: FnOnce(&T) -> Result<T, E> + Send + 'a,
         G: FnOnce(Result<T, E>) -> Result<T, E> + 'a {
-    Thunk::with_arg(move |result: Result<T, E>| {
+    Box::new(move |result: Result<T, E>| {
         match result {
             Ok(ref t) => action(t),
             Err(ref e) => Err(e.clone()),
index 26eacd682efddbdbe958a471dfa1ea3b37da8a1b..0fd4b4394dc271ab32e2df0e7b40deecbde298d7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Foo {
     Bar,
     Baz
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..8b5e6f837d852f070591e1591ba25f302c6cb866 100644 (file)
@@ -12,8 +12,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(convert)]
-
 use std::default::Default;
 use std::io;
 use std::fs;
@@ -36,7 +34,7 @@ pub trait Strategy {
 }
 
 /// The basic fully-recursive strategy. Nothing is pruned.
-#[derive(Copy, Default)]
+#[derive(Copy, Clone, Default)]
 pub struct Recursive;
 
 impl Strategy for Recursive {
index 2ce36b0dd44d7fb12417f3e6dbebeae5b36d4f2b..5e2ac61caa216e239291bd01c63eafd014cefd35 100644 (file)
@@ -14,4 +14,8 @@
 #[derive(Copy)]
 struct Test(*const i32);
 
+impl Clone for Test {
+    fn clone(&self) -> Test { *self }
+}
+
 fn main() {}
index b2c21a274cb83c07a6ea7a7bcae92b940dc4968e..5c84c30aa7fa3631a7fc277f4697f3cb8def9f1e 100644 (file)
 static generations: usize = 1024+256+128+49;
 
 fn spawn(f: Thunk<'static>) {
-    Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(()));
+    Builder::new().stack_size(32 * 1024).spawn(move|| f());
 }
 
 fn child_no(x: usize) -> Thunk<'static> {
-    Thunk::new(move|| {
+    Box::new(move|| {
         if x < generations {
             spawn(child_no(x+1));
         }
index 8b2e1c3e149f7eedb646defd0631451d145dbd2f..8a0f04a2cf0e413fd366ef3869a2da13d722cd17 100644 (file)
@@ -22,12 +22,14 @@ struct BufferHandle<R: Resources> {
     raw: <R as Resources>::Buffer,
 }
 impl<R: Resources> Copy for BufferHandle<R> {}
+impl<R: Resources> Clone for BufferHandle<R> {
+    fn clone(&self) -> BufferHandle<R> { *self }
+}
 
 enum Res {}
 impl Resources for Res {
     type Buffer = u32;
 }
-impl Copy for Res { }
 
 fn main() {
     let b: BufferHandle<Res> = BufferHandle { raw: 1 };
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 3364fae0d6f3418171ec1bb5ea707a11af3359e0..d16655a68554a2b654999f19ddda31c7e3efc848 100644 (file)
@@ -17,7 +17,7 @@ trait clam<A> {
   fn chowder(&self, y: A);
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct foo<A> {
   x: A,
 }
index 97357c1dba4674da12abf8aea1c12dc8721adb05..9b5ca23565e0d7710edf2d28806bae2809d750a3 100644 (file)
@@ -13,7 +13,7 @@
 
 use std::intrinsics;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Wrap(i64);
 
 // These volatile and atomic intrinsics used to cause an ICE
index de99141c80311381a47ca48841732d40c6e26142..5841a9ec176cdc6c13690250852145acdd7a2a86 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct cat {
     meow: extern "Rust" fn(),
 }
@@ -23,7 +23,7 @@ fn cat() -> cat {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct KittyInfo {kitty: cat}
 
 // Code compiles and runs successfully if we add a + before the first arg
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 5a1fedbdccc37c619f7b10d2ba19762b5e488ad9..777e5bf7a6dedfe37f1cbd02b7ddad32eb11a3dc 100644 (file)
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum side { mayo, catsup, vinegar }
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum order { hamburger, fries(side), shake }
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum meal { to_go(order), for_here(order) }
 
 fn foo(m: Box<meal>, cond: bool) {
index 078376251176134da55c46743748cbbdf3c17f13..cfdc54a362274e91c926e5b8b740909ecaba2558 100644 (file)
@@ -29,7 +29,7 @@
 use std::slice;
 
 // Represents a position on a canvas.
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Point {
     x: isize,
     y: isize,
@@ -37,13 +37,13 @@ struct Point {
 
 // Represents an offset on a canvas. (This has the same structure as a Point.
 // but different semantics).
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Size {
     width: isize,
     height: isize,
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Rect {
     top_left: Point,
     size: Size,
index 2bd56e8168787d279a6f9450cbfcdbb933677860..2167a3df9766ffd471abad9e07e154448ae16308 100644 (file)
@@ -11,9 +11,8 @@
 #![allow(unknown_features)]
 #![feature(std_misc)]
 
-use std::thread::Thread;
+use std::thread;
 use std::sync::mpsc::Sender;
-use std::thunk::Invoke;
 
 type RingBuffer = Vec<f64> ;
 type SamplesFn = Box<FnMut(&RingBuffer) + Send>;
@@ -24,7 +23,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..cd62c04a32581ea28e9bf35799d938a75df36d11 100644 (file)
 
 // If `Mul` used an associated type for its output, this test would
 // work more smoothly.
-#![feature(old_orphan_check)]
 
 use std::ops::Mul;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Vec2 {
     x: f64,
     y: f64
index bbfeb94cd9de1c5c52eac3046473135225c4a991..e81025d8464507b1cd5ffc55b89d781062a3ca4f 100644 (file)
 
 use std::f64;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Point {
     x: f64,
     y: f64
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub enum Shape {
     Circle(Point, f64),
     Rectangle(Point, Point)
index 3c25c6dc8edd743de11ceee267f6bf1e9ee08fcb..88ff103723c73265a9dcdc9fbe32f282e13146bc 100644 (file)
@@ -17,7 +17,7 @@
 failed to typecheck correctly.
 */
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct X { vec: &'static [isize] }
 
 static V: &'static [X] = &[X { vec: &[1, 2, 3] }];
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 e21f89aee43b4c1ca8119418e07a2f60ae5f3dfb..1b4dfb869d413dfb857aee0c1baa8412140f10d7 100644 (file)
@@ -38,7 +38,7 @@ enum EnumWithStructVariants {
     dir: Direction::North };
 
 pub mod glfw {
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub struct InputState(usize);
 
     pub const RELEASE  : InputState = InputState(0);
index 8687014bfbb53c41b52edc952e3b61d74ea3e74a..f0ca0a70acc96a4f828b835e99d4cb25b19d817f 100644 (file)
@@ -17,7 +17,7 @@
 
 static mut COUNT: u64 = 1;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Foo;
 
 trait Bar : Sized {
index 98ab67b05afda080a72915039aca16b33e197211..dfc121192228d4a21fa27bf8087d44c464c3d06d 100644 (file)
@@ -17,7 +17,7 @@
 
 static mut COUNT: usize = 1;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Foo;
 
 impl Foo {
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 726f205f5c4201f295a5d6a5517426ef09f571db..00e97ebc24e7ba5f5f1fa4b6a616a2cec0d6bc55 100644 (file)
@@ -18,7 +18,7 @@
  * and apply the wrong instance of the method `unwrap`.
  */
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct S<T> { i:u8, t:T }
 
 impl<T> S<T> {
@@ -27,10 +27,10 @@ fn unwrap(self) -> T {
     }
 }
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 struct A((u32, u32));
 
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 struct B(u64);
 
 pub fn main() {
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 0233a7ff48553552c5dcc54f3e1c7001c1ceba74..fdf9f95b274d44fd61c4716188a693c4559797c1 100644 (file)
@@ -16,7 +16,7 @@ trait MyTrait<T> {
     fn get(&self) -> T;
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct MyType {
     dummy: usize
 }
index 161913f6f5ddb2e81062e7264de84ad56e3509d4..75c6c5ac7d16543338cf0f3484f41000afb45584 100644 (file)
@@ -25,7 +25,7 @@ fn get(&self) -> T {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct MyType {
     dummy: usize
 }
index fb43f041e0465f19a572c4f934108c507816d7c9..818ea4c9f23262429aec69bc932fbad5d7cbce87 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct mytype(Mytype);
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Mytype {
     compute: fn(mytype) -> isize,
     val: isize,
index fc089839683ed5f2f856f141b8b8ede94a58af86..045af79189acd36cb74f4200a8011bfd76b055de 100644 (file)
@@ -13,7 +13,7 @@
 use std::cmp;
 use std::ops;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 struct Point {
     x: isize,
     y: isize
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());
index eb0a6c95134aea94d90a1b272ad970e49be66ee2..0a58411041e640df28eb16c58b2134e7e8124123 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Foo {
     f1: isize,
     _f2: isize,
index fdd7a5000b2ee3e64f9e864d1c438d4ec43840e3..6880032e69f66f5f2909a7ab25fd9c26ffedbeb4 100644 (file)
@@ -13,7 +13,7 @@
 use std::rc::Rc;
 use std::ops::Deref;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct DerefWrapper<X, Y> {
     x: X,
     y: Y
@@ -36,7 +36,7 @@ fn deref(&self) -> &Y {
 mod priv_test {
     use std::ops::Deref;
 
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     pub struct DerefWrapperHideX<X, Y> {
         x: X,
         pub y: Y
index 92f57f04b10ae5279fb9c3acce7a253ce86eb209..9a327eb567266bf0da01211ba00f160c4ebb0af1 100644 (file)
@@ -13,7 +13,7 @@
 use std::mem;
 
 #[repr(packed)]
-#[derive(Copy, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 struct Foo {
     bar: u8,
     baz: u64
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 c61c387c7812f7b51e10a033ea01ae53b44c5e2b..1644a1694269adb77b86a1b46ad4be717498a1fa 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Point {x: isize, y: isize}
 
 type rect = (Point, Point);
index 96b6b50237d73825ff6faadb72d596e0490ec2ac..a422aaba84b30677c7848ee57fa7930f40ecc290 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Rect {x: isize, y: isize, w: isize, h: isize}
 
 fn f(r: Rect, x: isize, y: isize, w: isize, h: isize) {
index 0cb70735dbac8c3a156b2ddd59ce39a2fbb81c5e..123806a4d9d175d21fa0a7f70e29d77d4a204cb5 100644 (file)
@@ -30,7 +30,7 @@ struct B {
     v6: Option<C>
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct C {
     f: isize
 }
index b1f9ff4de0f411c7410ac395d353132851c1dda8..6ad89951238893ea8fdbcf90ffbdd11e7b738d81 100644 (file)
@@ -17,7 +17,7 @@ trait GetRef<'a> {
     fn get(&self) -> &'a isize;
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Box<'a> {
     t: &'a isize
 }
index 9c2d2726a73502e8ea8f8d8d4c4e3ef8bc506392..6ab95d6e497bc9455f313b08c7c90170da423421 100644 (file)
@@ -17,12 +17,11 @@ trait GetRef<'a, T> {
     fn get(&self) -> &'a T;
 }
 
+#[derive(Copy, Clone)]
 struct Box<'a, T:'a> {
     t: &'a T
 }
 
-impl<'a,T:'a> Copy for Box<'a,T> {}
-
 impl<'a,T:Clone> GetRef<'a,T> for Box<'a,T> {
     fn get(&self) -> &'a T {
         self.t
index 830fb7127b9b4a59bb09568bd6410376eabe2720..dc991e9493fe46cf569b3c1f4b596c3229b84413 100644 (file)
@@ -17,7 +17,7 @@ trait Get<T> {
     fn get(&self) -> T;
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Box<T> {
     t: T
 }
index c6bacac63e068c34a7704de8b154578ac038b008..ed3cec465eff894ce54233eb78676666030b8150 100644 (file)
@@ -29,7 +29,7 @@
 
 type Type<'tcx> = &'tcx TypeStructure<'tcx>;
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum TypeStructure<'tcx> {
     TypeInt,
     TypeFunction(Type<'tcx>, Type<'tcx>),
@@ -94,20 +94,20 @@ fn ast(&mut self, a: AstKind<'ast>) -> Ast<'ast> {
     }
 }
 
-#[derive(Copy, PartialEq, Eq, Hash)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
 struct NodeId {
     id: usize
 }
 
 type Ast<'ast> = &'ast AstStructure<'ast>;
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct AstStructure<'ast> {
     id: NodeId,
     kind: AstKind<'ast>
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum AstKind<'ast> {
     ExprInt,
     ExprVar(usize),
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 fa7b21a26c542889fe13ba8b7501c1324b18bc49..fa9ad9f6517a609c6ddff771ad0141bf60a6ed43 100644 (file)
@@ -13,7 +13,7 @@
 
 // pretty-expanded FIXME #23616
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Value {
     n: isize
 }
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 201da8dbc948941c119f7f510faafe2ce6ce138f..867f028a3fb3c14aa977bca9dee19fbfa4f00025 100644 (file)
@@ -16,7 +16,7 @@
 use std::ops;
 
 #[simd]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct f32x4(f32, f32, f32, f32);
 
 fn add<T: ops::Add<Output=T>>(lhs: T, rhs: T) -> T {
index df204065d163e6a76769dc5993a4a9b599e58be5..9515da6fcbc8d2207add789f4c3172cec508a5b2 100644 (file)
 
 // 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.
  */
 
 #[repr(u8)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Eu { Lu = 0, Hu = 255 }
 
 static CLu: Eu = Eu::Lu;
 static CHu: Eu = Eu::Hu;
 
 #[repr(i8)]
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum Es { Ls = -128, Hs = 127 }
 
 static CLs: Es = Es::Ls;
 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 9e372913e0540ccb780142aba957fe9f2a9010da..1ff13d4eaeacb1c2129beb4835fb40ed722f0dbe 100644 (file)
 //
 // ignore-lexer-test FIXME #15883
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Quad { a: u64, b: u64, c: u64, d: u64 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 pub struct Floats { a: f64, b: u8, c: f64 }
 
 mod rustrt {
index 4df802849e2fdf88b1877f8e5ee4984c3c7b1a46..7974366c395fc922f0c4b2e728322a2e576f7d8d 100644 (file)
@@ -10,7 +10,7 @@
 
 
 
-#[derive(Copy, Debug)]
+#[derive(Copy, Clone, Debug)]
 enum foo { large, small, }
 
 impl PartialEq for foo {
index 7103fa7c33e3b8f9d05fcdbd2dcc7c1b74b8c545..447b4de450bf1097e046d90761b2c287bcd50d5b 100644 (file)
@@ -77,7 +77,7 @@ fn main() {
 
     all_sync_send!(LinkedList::<usize>::new(), iter, iter_mut, into_iter);
 
-    #[derive(Copy)]
+    #[derive(Copy, Clone)]
     #[repr(usize)]
     #[allow(dead_code)]
     enum Foo { A, B, C }
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 affabff916490d4616fc508a6ba01c53ba5b046e..a063801032e3decc613f8f016e4143780d6f6892 100644 (file)
@@ -11,7 +11,7 @@
 
 use color::{red, green, blue, black, white, imaginary, purple, orange};
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 enum color {
     red = 0xff0000,
     green = 0x00ff00,
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 2f33621e36c701a0542203bab422aa75a9f3fd90..f9a22d5ccec6d07a867ae5a24c27e5492f31a8e2 100644 (file)
@@ -12,7 +12,7 @@ trait Trait<T> {
     fn f(&self, x: T);
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct {
     x: isize,
     y: isize,
index de0a2e9e4d458ba83a8697d65909120df326642b..fa31d9891aaf7c9a1b14e9e2377ba69a6e94b3aa 100644 (file)
@@ -17,7 +17,7 @@ trait Trait {
     fn f(&self);
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Struct {
     x: isize,
     y: isize,
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 {
index 3a1394447f624d5c405f7ff16a1a8b1c4e9a7e61..bd09a311b70fb24d0fec3bc1669d0c3e87816311 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(unknown_features)]
 #![feature(box_syntax)]
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Foo {
     f: isize,
 }
@@ -28,7 +28,7 @@ fn baz(self: Box<Foo>, x: isize) -> isize {
     }
 }
 
-#[derive(Copy)]
+#[derive(Copy, Clone)]
 struct Bar<T> {
     f: 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() {
index 09ecdf45b939e3d4636a0f2eb6191f633c449381..eca7e62d67cbf4937f01045d56f6c05a097fb5af 100644 (file)
@@ -57,7 +57,7 @@ fn drop(&mut self) {
 }
 
 pub fn main() {
-    assert!(MAX_LEN <= std::usize::BITS as usize);
+    assert!(MAX_LEN <= std::usize::BITS);
     // len can't go above 64.
     for len in 2..MAX_LEN {
         for _ in 0..REPEATS {