]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #22573 - nwin:impl-debug-rwlock-weak, r=Manishearth
authorbors <bors@rust-lang.org>
Fri, 27 Feb 2015 10:35:51 +0000 (10:35 +0000)
committerbors <bors@rust-lang.org>
Fri, 27 Feb 2015 10:35:51 +0000 (10:35 +0000)
Implements `Debug`  for `RwLock` and `arc::Weak` in the same way it is implemented for `rc::Weak` (basically copy & paste).

The lack of this implementation prevents the automatic implementation of `Debug` for structs containing members of these types.

576 files changed:
CONTRIBUTING.md
README.md
RELEASES.md
configure
mk/cfg/x86_64-unknown-bitrig.mk [new file with mode: 0644]
mk/platform.mk
src/compiletest/compiletest.rs
src/compiletest/errors.rs
src/compiletest/header.rs
src/compiletest/runtest.rs
src/compiletest/util.rs
src/doc/index.md
src/doc/intro.md
src/doc/reference.md
src/doc/rust.css
src/doc/trpl/advanced-macros.md
src/doc/trpl/crates-and-modules.md
src/doc/trpl/error-handling.md
src/doc/trpl/guessing-game.md
src/doc/trpl/if.md
src/doc/trpl/iterators.md
src/doc/trpl/macros.md
src/doc/trpl/more-strings.md
src/doc/trpl/plugins.md
src/doc/trpl/pointers.md
src/doc/trpl/static-and-dynamic-dispatch.md
src/doc/trpl/strings.md
src/etc/htmldocck.py
src/etc/local_stage0.sh
src/etc/mklldeps.py
src/etc/snapshot.py
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/libbacktrace/configure
src/libbacktrace/ltmain.sh
src/libcollections/binary_heap.rs
src/libcollections/bit.rs
src/libcollections/borrow.rs
src/libcollections/borrow_stage0.rs [deleted file]
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/enum_set.rs
src/libcollections/fmt.rs
src/libcollections/lib.rs
src/libcollections/linked_list.rs
src/libcollections/macros.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollections/vec_map.rs
src/libcore/array.rs
src/libcore/atomic.rs
src/libcore/cell.rs
src/libcore/char.rs
src/libcore/cmp_macros.rs [new file with mode: 0644]
src/libcore/fmt/float.rs
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/mod.rs
src/libcore/ops.rs
src/libcore/option.rs
src/libcore/panicking.rs
src/libcore/ptr.rs
src/libcore/result.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcore/str/pattern.rs [new file with mode: 0644]
src/libcoretest/fmt/num.rs
src/libcoretest/iter.rs
src/libcoretest/lib.rs
src/libcoretest/mem.rs
src/libcoretest/nonzero.rs
src/libcoretest/num/mod.rs
src/libcoretest/ptr.rs
src/libcoretest/str.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/libgetopts/lib.rs
src/libgraphviz/lib.rs
src/liblibc/lib.rs
src/liblog/lib.rs
src/librand/lib.rs
src/librbml/io.rs
src/librbml/lib.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/macro_import.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astconv_util.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/cfg/graphviz.rs
src/librustc/middle/cfg/mod.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_match.rs
src/librustc/middle/check_static_recursion.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/dead.rs
src/librustc/middle/def.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/fast_reject.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/freshen.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/infer/region_inference/graphviz.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/infer/resolve.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/subst.rs
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/error_reporting.rs
src/librustc/middle/traits/fulfill.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/object_safety.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_walk.rs
src/librustc/plugin/load.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/util/common.rs
src/librustc/util/nodemap.rs
src/librustc/util/ppaux.rs
src/librustc_back/archive.rs
src/librustc_back/arm.rs
src/librustc_back/fs.rs
src/librustc_back/lib.rs
src/librustc_back/mips.rs
src/librustc_back/mipsel.rs
src/librustc_back/rpath.rs
src/librustc_back/svh.rs
src/librustc_back/target/bitrig_base.rs [new file with mode: 0644]
src/librustc_back/target/mod.rs
src/librustc_back/target/openbsd_base.rs
src/librustc_back/target/x86_64_unknown_bitrig.rs [new file with mode: 0644]
src/librustc_back/x86.rs
src/librustc_back/x86_64.rs
src/librustc_borrowck/borrowck/README.md
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/fragments.rs
src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/gather_loans/move_error.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/graphviz.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/save/recorder.rs
src/librustc_trans/save/span_utils.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/cabi.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/foreign.rs
src/librustc_trans/trans/glue.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/monomorphize.rs
src/librustc_trans/trans/tvec.rs
src/librustc_trans/trans/type_.rs
src/librustc_trans/trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/implicator.rs
src/librustc_typeck/check/method/confirm.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/vtable.rs
src/librustc_typeck/check/wf.rs
src/librustc_typeck/coherence/impls.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/flock.rs
src/librustdoc/html/format.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.css
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libserialize/collection_impls.rs
src/libserialize/json.rs
src/libstd/ascii.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/map_stage0.rs [deleted file]
src/libstd/collections/hash/mod.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/set_stage0.rs [deleted file]
src/libstd/collections/hash/state.rs
src/libstd/collections/hash/table.rs
src/libstd/collections/mod.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/ffi/c_str.rs
src/libstd/ffi/os_str.rs
src/libstd/fs.rs [deleted file]
src/libstd/fs/mod.rs [new file with mode: 0644]
src/libstd/fs/tempdir.rs [new file with mode: 0644]
src/libstd/io/buffered.rs
src/libstd/io/impls.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/net/tcp.rs
src/libstd/net/test.rs
src/libstd/num/int.rs [deleted file]
src/libstd/num/mod.rs
src/libstd/num/uint.rs [deleted file]
src/libstd/num/uint_macros.rs
src/libstd/old_io/extensions.rs
src/libstd/old_io/mem.rs
src/libstd/old_io/mod.rs
src/libstd/old_io/process.rs
src/libstd/old_io/result.rs
src/libstd/old_io/stdio.rs
src/libstd/old_io/tempfile.rs
src/libstd/old_io/test.rs
src/libstd/old_io/util.rs
src/libstd/old_path/mod.rs
src/libstd/old_path/posix.rs
src/libstd/old_path/windows.rs
src/libstd/os.rs
src/libstd/path.rs
src/libstd/prelude/v1.rs
src/libstd/process.rs
src/libstd/rand/os.rs
src/libstd/rt/args.rs
src/libstd/rt/at_exit_imp.rs
src/libstd/rt/libunwind.rs
src/libstd/rt/unwind.rs
src/libstd/rtdeps.rs
src/libstd/sync/barrier.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/blocking.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.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/once.rs
src/libstd/sync/poison.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/task_pool.rs
src/libstd/sys/common/helper_thread.rs
src/libstd/sys/common/net.rs
src/libstd/sys/common/stack.rs
src/libstd/sys/common/thread.rs
src/libstd/sys/common/wtf8.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/c.rs
src/libstd/sys/unix/condvar.rs
src/libstd/sys/unix/ext.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/fs2.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/mutex.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/pipe.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/process2.rs
src/libstd/sys/unix/rwlock.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/sync.rs
src/libstd/sys/unix/tcp.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/thread_local.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/unix/tty.rs
src/libstd/sys/windows/condvar.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/fs2.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/mutex.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/rwlock.rs
src/libstd/sys/windows/tcp.rs
src/libstd/sys/windows/thread.rs
src/libstd/sys/windows/thread_local.rs
src/libstd/sys/windows/tty.rs
src/libstd/thread.rs
src/libstd/thread_local/mod.rs
src/libstd/thread_local/scoped.rs
src/libstd/thunk.rs
src/libsyntax/abi.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/ast_util.rs
src/libsyntax/attr.rs
src/libsyntax/ext/asm.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/concat.rs
src/libsyntax/ext/concat_idents.rs
src/libsyntax/ext/deriving/clone.rs
src/libsyntax/ext/deriving/cmp/eq.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/libsyntax/ext/deriving/decodable.rs
src/libsyntax/ext/deriving/encodable.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/deriving/mod.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/env.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/format.rs
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/comments.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pp.rs
src/libsyntax/print/pprust.rs
src/libsyntax/ptr.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/util/interner.rs
src/libsyntax/util/small_vector.rs
src/libsyntax/visit.rs
src/libterm/lib.rs
src/libterm/terminfo/parm.rs
src/libterm/terminfo/searcher.rs
src/libtest/stats.rs
src/libunicode/u_str.rs
src/llvm
src/rt/arch/x86_64/morestack.S
src/rt/rust_builtin.c
src/rustbook/book.rs
src/rustbook/build.rs
src/rustbook/main.rs
src/rustbook/test.rs
src/rustllvm/llvm-auto-clean-trigger
src/snapshots.txt
src/test/auxiliary/cci_class_cast.rs
src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-in-ambiguous-context.rs
src/test/compile-fail/bad-mid-path-type-params.rs
src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
src/test/compile-fail/borrowck-fn-in-const-a.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-fn-in-const-b.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-fn-in-const-c.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-move-mut-base-ptr.rs
src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs
src/test/compile-fail/borrowck-swap-mut-base-ptr.rs
src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs
src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs
src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs
src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs
src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs
src/test/compile-fail/coherence-default-trait-impl.rs [new file with mode: 0644]
src/test/compile-fail/coherence-impls-builtin.rs
src/test/compile-fail/coherence-tuple-conflict.rs
src/test/compile-fail/cycle-projection-based-on-where-clause.rs [new file with mode: 0644]
src/test/compile-fail/cycle-trait-supertrait-direct.rs [new file with mode: 0644]
src/test/compile-fail/cycle-trait-supertrait-indirect.rs [new file with mode: 0644]
src/test/compile-fail/extern-with-type-bounds.rs
src/test/compile-fail/fn-trait-formatting.rs
src/test/compile-fail/generic-impl-less-params-with-defaults.rs
src/test/compile-fail/generic-impl-more-params-with-defaults.rs
src/test/compile-fail/glob-resolve1.rs
src/test/compile-fail/if-loop.rs [new file with mode: 0644]
src/test/compile-fail/impl-duplicate-methods.rs
src/test/compile-fail/impl-not-adjacent-to-type.rs [deleted file]
src/test/compile-fail/infinite-instantiation.rs
src/test/compile-fail/inner-static-type-parameter.rs
src/test/compile-fail/invalid-inline.rs [new file with mode: 0644]
src/test/compile-fail/issue-12729.rs [deleted file]
src/test/compile-fail/issue-13641.rs
src/test/compile-fail/issue-14254.rs
src/test/compile-fail/issue-17441.rs
src/test/compile-fail/issue-18959.rs
src/test/compile-fail/issue-19883.rs
src/test/compile-fail/issue-21202.rs
src/test/compile-fail/issue-22426-1.rs [new file with mode: 0644]
src/test/compile-fail/issue-22426-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-22426-3.rs [new file with mode: 0644]
src/test/compile-fail/issue-2356.rs
src/test/compile-fail/issue-3521-2.rs
src/test/compile-fail/issue-3521.rs
src/test/compile-fail/issue-3668-2.rs
src/test/compile-fail/issue-3668.rs
src/test/compile-fail/issue-3973.rs
src/test/compile-fail/issue-4265.rs
src/test/compile-fail/issue-7607-1.rs
src/test/compile-fail/issue-7607-2.rs [deleted file]
src/test/compile-fail/issue-8767.rs
src/test/compile-fail/lint-missing-doc.rs
src/test/compile-fail/lint-stability.rs
src/test/compile-fail/lint-unsafe-block.rs [deleted file]
src/test/compile-fail/lint-unsafe-code.rs [new file with mode: 0644]
src/test/compile-fail/method-macro-backtrace.rs
src/test/compile-fail/move-in-guard-1.rs [new file with mode: 0644]
src/test/compile-fail/move-in-guard-2.rs [new file with mode: 0644]
src/test/compile-fail/no-implicit-prelude-nested.rs
src/test/compile-fail/no-implicit-prelude.rs
src/test/compile-fail/object-safety-by-value-self-use.rs [new file with mode: 0644]
src/test/compile-fail/object-safety-by-value-self.rs
src/test/compile-fail/object-safety-generics.rs
src/test/compile-fail/object-safety-mentions-Self.rs
src/test/compile-fail/recursion.rs
src/test/compile-fail/recursion_limit.rs
src/test/compile-fail/resolve-unknown-trait.rs
src/test/compile-fail/retslot-cast.rs [new file with mode: 0644]
src/test/compile-fail/send-is-not-static-std-sync-2.rs [new file with mode: 0644]
src/test/compile-fail/send-is-not-static-std-sync.rs [new file with mode: 0644]
src/test/compile-fail/suggest-private-fields.rs [new file with mode: 0644]
src/test/compile-fail/syntaxt-default-trait-impls.rs [new file with mode: 0644]
src/test/compile-fail/trait-impl-2.rs [deleted file]
src/test/compile-fail/trait-impl-for-module.rs
src/test/compile-fail/trait-or-new-type-instead.rs
src/test/compile-fail/trait-test-2.rs
src/test/compile-fail/typeck-builtin-bound-type-parameters.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-negation-send.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-negation.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-precedence.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-send-param.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-superregion.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-supertrait.rs [new file with mode: 0644]
src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs [new file with mode: 0644]
src/test/compile-fail/typeck-negative-impls-builtin.rs
src/test/compile-fail/ufcs-qpath-missing-params.rs
src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
src/test/compile-fail/unsafe_no_drop_flag-gate.rs [new file with mode: 0644]
src/test/compile-fail/use-after-move-implicity-coerced-object.rs
src/test/compile-fail/use-from-trait.rs
src/test/parse-fail/empty-impl-semicolon.rs
src/test/parse-fail/issue-22647.rs [new file with mode: 0644]
src/test/parse-fail/issue-22712.rs [new file with mode: 0644]
src/test/parse-fail/multitrait.rs
src/test/parse-fail/trailing-plus-in-bounds.rs
src/test/parse-fail/trait-bounds-not-on-impl.rs
src/test/pretty/default-trait-impl.rs [new file with mode: 0644]
src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot
src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot
src/test/run-make/rustdoc-extern-default-method/Makefile [new file with mode: 0644]
src/test/run-make/rustdoc-extern-default-method/ext.rs [new file with mode: 0644]
src/test/run-make/rustdoc-extern-default-method/lib.rs [new file with mode: 0644]
src/test/run-make/weird-output-filenames/Makefile
src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs [new file with mode: 0644]
src/test/run-pass/auto-ref-sliceable.rs
src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs
src/test/run-pass/class-separate-impl.rs
src/test/run-pass/coerce-reborrow-mut-vec-arg.rs
src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs
src/test/run-pass/coherence-multidispatch-tuple.rs
src/test/run-pass/const-polymorphic-paths.rs [deleted file]
src/test/run-pass/cycle-generic-bound.rs [new file with mode: 0644]
src/test/run-pass/cycle-trait-type-trait.rs [new file with mode: 0644]
src/test/run-pass/dupe-first-attr.rc
src/test/run-pass/env-home-dir.rs
src/test/run-pass/extern-methods.rs [new file with mode: 0644]
src/test/run-pass/generic-static-methods.rs
src/test/run-pass/impl-inherent-non-conflict.rs [new file with mode: 0644]
src/test/run-pass/impl-inherent-prefer-over-trait.rs [new file with mode: 0644]
src/test/run-pass/impl-not-adjacent-to-type.rs [new file with mode: 0644]
src/test/run-pass/intrinsic-alignment.rs
src/test/run-pass/issue-12729.rs [new file with mode: 0644]
src/test/run-pass/issue-15149.rs
src/test/run-pass/issue-16272.rs
src/test/run-pass/issue-20091.rs
src/test/run-pass/issue-22356.rs [new file with mode: 0644]
src/test/run-pass/issue-22426.rs [new file with mode: 0644]
src/test/run-pass/issue-22577.rs [new file with mode: 0644]
src/test/run-pass/issue-3559.rs
src/test/run-pass/issue-3563-3.rs
src/test/run-pass/issue-7607-2.rs [new file with mode: 0644]
src/test/run-pass/lang-item-public.rs
src/test/run-pass/monad.rs
src/test/run-pass/move-guard-const.rs [new file with mode: 0644]
src/test/run-pass/object-safety-sized-self-by-value-self.rs [new file with mode: 0644]
src/test/run-pass/object-safety-sized-self-generic-method.rs [new file with mode: 0644]
src/test/run-pass/object-safety-sized-self-return-Self.rs [new file with mode: 0644]
src/test/run-pass/out-of-stack-new-thread-no-split.rs
src/test/run-pass/out-of-stack-no-split.rs
src/test/run-pass/rec-align-u64.rs
src/test/run-pass/sepcomp-lib-lto.rs
src/test/run-pass/std-sync-right-kind-impls.rs [new file with mode: 0644]
src/test/run-pass/sync-send-iterators-in-libcollections.rs [new file with mode: 0644]
src/test/run-pass/syntax-extension-source-utils-files/includeme.fragment
src/test/run-pass/syntax-extension-source-utils.rs
src/test/run-pass/trait-generic.rs
src/test/run-pass/trait-impl-2.rs [new file with mode: 0644]
src/test/run-pass/ufcs-polymorphic-paths.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-infer-upvar.rs
src/test/run-pass/unwind-resource.rs
src/test/run-pass/unwind-unique.rs
src/test/run-pass/x86stdcall.rs

index a4656dd415bbd3ec0972c1daad931a0945bba38c..71b20cb0946c482b519edbe74ba93b8ae12ff00c 100644 (file)
@@ -14,7 +14,7 @@ links to the major sections:
 If you have questions, please make a post on [internals.rust-lang.org][internals] or
 hop on [#rust-internals][pound-rust-internals].
 
-As a reminder, all contributors are expected to follow our [Code of Conduct](coc).
+As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
 [pound-rust-internals]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
 [internals]: http://internals.rust-lang.org
index b6a73730d351cc9f37c39a0fdc8d49bb59e75aca..c88c237cbee896985663697ed030b018393d8e89 100644 (file)
--- a/README.md
+++ b/README.md
@@ -15,28 +15,34 @@ Read ["Installing Rust"] from [The Book].
 ## Building from Source
 
 1. Make sure you have installed the dependencies:
-    * `g++` 4.7 or `clang++` 3.x
-    * `python` 2.6 or later (but not 3.x)
-    * GNU `make` 3.81 or later
-    * `curl`
-    * `git`
+
+   * `g++` 4.7 or `clang++` 3.x
+   * `python` 2.6 or later (but not 3.x)
+   * GNU `make` 3.81 or later
+   * `curl`
+   * `git`
 
 2. Clone the [source] with `git`:
 
-        $ git clone https://github.com/rust-lang/rust.git
-        $ cd rust
+   ```sh
+   $ git clone https://github.com/rust-lang/rust.git
+   $ cd rust
+   ```
 
 [source]: https://github.com/rust-lang/rust
 
 3. Build and install:
 
-        $ ./configure
-        $ make && make install
+    ```sh
+    $ ./configure
+    $ make && make install
+    ```
 
-    > ***Note:*** You may need to use `sudo make install` if you do not normally have
-    > permission to modify the destination directory. The install locations can
-    > be adjusted by passing a `--prefix` argument to `configure`. Various other
-    > options are also supported, pass `--help` for more information on them.
+    > ***Note:*** You may need to use `sudo make install` if you do not
+    > normally have permission to modify the destination directory. The
+    > install locations can be adjusted by passing a `--prefix` argument
+    > to `configure`. Various other options are also supported – pass
+    > `--help` for more information on them.
 
     When complete, `make install` will place several programs into
     `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
@@ -47,27 +53,30 @@ Read ["Installing Rust"] from [The Book].
 
 ### Building on Windows
 
-To easily build on windows we can use [MSYS2](http://msys2.github.io/):
+[MSYS2](http://msys2.github.io/) can be used to easily build Rust on Windows:
 
 1. Grab the latest MSYS2 installer and go through the installer.
-2. Now from the MSYS2 terminal we want to install the mingw64 toolchain and the other
-   tools we need.
 
-```bash
-# choose one based on platform
-$ pacman -S mingw-w64-i686-toolchain
-$ pacman -S mingw-w64-x86_64-toolchain
+2. From the MSYS2 terminal, install the `mingw64` toolchain and other required
+   tools.
+
+   ```sh
+   # Choose one based on platform:
+   $ pacman -S mingw-w64-i686-toolchain
+   $ pacman -S mingw-w64-x86_64-toolchain
+   
+   $ pacman -S base-devel
+   ```
 
-$ pacman -S base-devel
-```
+3. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed
+   MYSY2 (i.e. `C:\msys`), depending on whether you want 32-bit or 64-bit Rust.
 
-3. With that now start `mingw32_shell.bat` or `mingw64_shell.bat`
-   from where you installed MSYS2 (i.e. `C:\msys`). Which one you
-   choose depends on if you want 32 or 64 bit Rust.
-4. From there just navigate to where you have Rust's source code, configure and build it:
+4. Navigate to Rust's source code, configure and build it:
 
-        $ ./configure
-        $ make && make install
+   ```sh
+   $ ./configure
+   $ make && make install
+   ```
 
 ## Notes
 
@@ -92,15 +101,15 @@ There is more advice about hacking on Rust in [CONTRIBUTING.md].
 
 [CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md
 
-## Getting help
+## Getting Help
 
 The Rust community congregates in a few places:
 
-* [StackOverflow] - Direct questions about using the language here.
-* [users.rust-lang.org] - General discussion, broader questions.
+* [Stack Overflow] - Direct questions about using the language.
+* [users.rust-lang.org] - General discussion and broader questions.
 * [/r/rust] - News and general discussion.
 
-[StackOverflow]: http://stackoverflow.com/questions/tagged/rust
+[Stack Overflow]: http://stackoverflow.com/questions/tagged/rust
 [/r/rust]: http://reddit.com/r/rust
 [users.rust-lang.org]: http://users.rust-lang.org/
 
@@ -111,7 +120,7 @@ To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md).
 Rust has an [IRC] culture and most real-time collaboration happens in a
 variety of channels on Mozilla's IRC network, irc.mozilla.org. The
 most popular channel is [#rust], a venue for general discussion about
-Rust, and a good place to ask for help,
+Rust, and a good place to ask for help.
 
 [IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
 [#rust]: irc://irc.mozilla.org/rust
index 09929eee9230d3cefe236d3ecb66ee20770b6098..69b804cf24c40ab16e1d9fe431614a9ce6bb3c99 100644 (file)
@@ -51,7 +51,7 @@ Version 1.0.0-alpha.2 (February 2015)
     * Abstract [OS-specific string types][osstr], `std::ff::{OsString,
       OsStr}`, provide strings in platform-specific encodings for easier
       interop with system APIs. [RFC][osstr-rfc].
-    * The `boxed::into_raw` and `Box::frow_raw` functions [convert
+    * The `boxed::into_raw` and `Box::from_raw` functions [convert
       between `Box<T>` and `*mut T`][boxraw], a common pattern for
       creating raw pointers.
 
index d1b27a96f93b9caf7da8a4fbb9ac0b9e06a24a63..e722fe8772a394f21e90280aaf21c5bc727dd4a1 100755 (executable)
--- a/configure
+++ b/configure
@@ -374,8 +374,12 @@ case $CFG_OSTYPE in
         CFG_OSTYPE=unknown-dragonfly
         ;;
 
+    Bitrig)
+        CFG_OSTYPE=unknown-bitrig
+        ;;
+
     OpenBSD)
-       CFG_OSTYPE=unknown-openbsd
+        CFG_OSTYPE=unknown-openbsd
        ;;
 
     Darwin)
@@ -747,6 +751,13 @@ then
     CFG_ENABLE_CLANG=1
 fi
 
+# Force bitrig to build with clang; gcc doesn't like us there
+if [ $CFG_OSTYPE = unknown-bitrig ]
+then
+    step_msg "on Bitrig, forcing use of clang"
+    CFG_ENABLE_CLANG=1
+fi
+
 if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
 then
     err "either clang or gcc is required"
diff --git a/mk/cfg/x86_64-unknown-bitrig.mk b/mk/cfg/x86_64-unknown-bitrig.mk
new file mode 100644 (file)
index 0000000..ad34988
--- /dev/null
@@ -0,0 +1,26 @@
+# x86_64-unknown-bitrig-elf configuration
+CC_x86_64-unknown-bitrig=$(CC)
+CXX_x86_64-unknown-bitrig=$(CXX)
+CPP_x86_64-unknown-bitrig=$(CPP)
+AR_x86_64-unknown-bitrig=$(AR)
+CFG_LIB_NAME_x86_64-unknown-bitrig=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-bitrig=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM
+CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIC -m64 -I/usr/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS)
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-pic -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_x86_64-unknown-bitrig := .bsd.def
+CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
+CFG_INSTALL_NAME_x86_64-unknown-bitrig =
+CFG_EXE_SUFFIX_x86_64-unknown-bitrig :=
+CFG_WINDOWSY_x86_64-unknown-bitrig :=
+CFG_UNIXY_x86_64-unknown-bitrig := 1
+CFG_PATH_MUNGE_x86_64-unknown-bitrig :=
+CFG_LDPATH_x86_64-unknown-bitrig :=
+CFG_RUN_x86_64-unknown-bitrig=$(2)
+CFG_RUN_TARG_x86_64-unknown-bitrig=$(call CFG_RUN_x86_64-unknown-bitrig,,$(2))
+CFG_GNU_TRIPLE_x86_64-unknown-bitrig := x86_64-unknown-bitrig
index 78c1057c2fe524ca28a19e6d9164c0f1d08ab771..ed50585822ed432448079d431c9f28442f35896a 100644 (file)
@@ -144,14 +144,14 @@ FIND_COMPILER = $(word 1,$(1:ccache=))
 define CFG_MAKE_TOOLCHAIN
   # Prepend the tools with their prefix if cross compiling
   ifneq ($(CFG_BUILD),$(1))
-       CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1))
-       CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1))
-       CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1))
-       AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1))
-       RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \
-           -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1))
-
-       RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1))
+       CC_$(1)=$(CROSS_PREFIX_$(1))$(CC_$(1))
+       CXX_$(1)=$(CROSS_PREFIX_$(1))$(CXX_$(1))
+       CPP_$(1)=$(CROSS_PREFIX_$(1))$(CPP_$(1))
+       AR_$(1)=$(CROSS_PREFIX_$(1))$(AR_$(1))
+       RUSTC_CROSS_FLAGS_$(1)=-C linker=$$(call FIND_COMPILER,$$(CC_$(1))) \
+           -C ar=$$(call FIND_COMPILER,$$(AR_$(1))) $(RUSTC_CROSS_FLAGS_$(1))
+
+       RUSTC_FLAGS_$(1)=$$(RUSTC_CROSS_FLAGS_$(1)) $(RUSTC_FLAGS_$(1))
   endif
 
   CFG_COMPILE_C_$(1) = $$(CC_$(1)) \
@@ -179,11 +179,19 @@ define CFG_MAKE_TOOLCHAIN
 
   ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),)
 
+  # On Bitrig, we need the relocation model to be PIC for everthing
+  ifeq (,$(filter $(OSTYPE_$(1)),bitrig))
+    LLVM_MC_RELOCATION_MODEL="pic"
+  else
+    LLVM_MC_RELOCATION_MODEL="default"
+  endif
+
   # We're using llvm-mc as our assembler because it supports
   # .cfi pseudo-ops on mac
   CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(CFG_DEPEND_FLAGS) $$(2) | \
                     $$(LLVM_MC_$$(CFG_BUILD)) \
                     -assemble \
+                    -relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
                     -filetype=obj \
                     -triple=$(1) \
                     -o=$$(1)
@@ -192,7 +200,7 @@ define CFG_MAKE_TOOLCHAIN
   # For the ARM, AARCH64, MIPS and POWER crosses, use the toolchain assembler
   # FIXME: We should be able to use the LLVM assembler
   CFG_ASSEMBLE_$(1)=$$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
-                   $$(CFG_DEPEND_FLAGS) $$(2) -c -o $$(1)
+                   $$(CFG_DEPEND_FLAGS) $$(2) -c -o $$(1)
 
   endif
 
index 278ce5565d9fc38d8ce9bec899e5fcf3109d0ab1..417e050c8b8b35e6d9ff0cf98322aa247de46c50 100644 (file)
@@ -268,7 +268,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
         logfile: config.logfile.clone(),
         run_tests: true,
         run_benchmarks: true,
-        nocapture: false,
+        nocapture: env::var("RUST_TEST_NOCAPTURE").is_ok(),
         color: test::AutoColor,
     }
 }
index d8faa53a2de647bc8c82262505ec266572e00daa..7411a9b48d417e70936dcacfad51c6b10822a5ee 100644 (file)
@@ -58,7 +58,7 @@ pub fn load_errors(testfile: &Path) -> Vec<ExpectedError> {
 fn parse_expected(last_nonfollow_error: Option<uint>,
                   line_num: uint,
                   line: &str) -> Option<(WhichLine, ExpectedError)> {
-    let start = match line.find_str("//~") { Some(i) => i, None => return None };
+    let start = match line.find("//~") { Some(i) => i, None => return None };
     let (follow, adjusts) = if line.char_at(start + 3) == '|' {
         (true, 0)
     } else {
index c2539679643221332b31a32c6caba396dc6f3aee..e5570fe0b8fb0c84cd0dd0121e9f445f0c84f702 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::env;
+
 use common::Config;
 use common;
 use util;
@@ -125,6 +127,16 @@ pub fn load_props(testfile: &Path) -> TestProps {
         true
     });
 
+    for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_TASKS"] {
+        match env::var(key) {
+            Ok(val) =>
+                if exec_env.iter().find(|&&(ref x, _)| *x == key.to_string()).is_none() {
+                    exec_env.push((key.to_string(), val))
+                },
+            Err(..) => {}
+        }
+    }
+
     TestProps {
         error_patterns: error_patterns,
         compile_flags: compile_flags,
@@ -330,7 +342,7 @@ fn parse_name_directive(line: &str, directive: &str) -> bool {
 pub fn parse_name_value_directive(line: &str, directive: &str)
                                   -> Option<String> {
     let keycolon = format!("{}:", directive);
-    match line.find_str(&keycolon) {
+    match line.find(&keycolon) {
         Some(colon) => {
             let value = line[(colon + keycolon.len()) .. line.len()].to_string();
             debug!("{}: {}", directive, value);
index 1cbb8742bbc5ae511b89c812ecd115d869501c5b..85bbd2cb42e6983ce121cefe047f9ce431dae786 100644 (file)
@@ -89,7 +89,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
     let proc_res = compile_test(config, props, testfile);
 
     if proc_res.status.success() {
-        fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[],
+        fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[..],
                       &proc_res);
     }
 
@@ -398,7 +398,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
             for line in breakpoint_lines.iter() {
                 script_str.push_str(&format!("break {:?}:{}\n",
                                              testfile.filename_display(),
-                                             *line)[]);
+                                             *line)[..]);
             }
             script_str.push_str(&cmds);
             script_str.push_str("quit\n");
@@ -553,17 +553,17 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
             script_str.push_str("set print pretty off\n");
 
             // Add the pretty printer directory to GDB's source-file search path
-            script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path)[]);
+            script_str.push_str(&format!("directory {}\n", rust_pp_module_abs_path)[..]);
 
             // Load the target executable
             script_str.push_str(&format!("file {}\n",
-                                         exe_file.as_str().unwrap().replace("\\", "\\\\"))[]);
+                                         exe_file.as_str().unwrap().replace("\\", "\\\\"))[..]);
 
             // Add line breakpoints
             for line in &breakpoint_lines {
                 script_str.push_str(&format!("break '{}':{}\n",
                                              testfile.filename_display(),
-                                             *line)[]);
+                                             *line)[..]);
             }
 
             script_str.push_str(&cmds);
@@ -689,7 +689,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
                                                .unwrap()
                                                .to_string();
 
-    script_str.push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[]);
+    script_str.push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[..]);
     script_str.push_str("type summary add --no-value ");
     script_str.push_str("--python-function lldb_rust_formatters.print_val ");
     script_str.push_str("-x \".*\" --category Rust\n");
@@ -847,7 +847,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String])
             check_lines.iter().map(|s| {
                 s
                  .trim()
-                 .split_str("[...]")
+                 .split("[...]")
                  .map(|x| x.to_string())
                  .collect()
             }).collect();
@@ -866,7 +866,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String])
                         None
                     }
                 } else {
-                    rest.find_str(frag)
+                    rest.find(frag)
                 };
                 match found {
                     None => {
index c046a89cba55ff52c6681c1861c59f4f36fc9f44..778629dd2028f53ed838dd533198e2705045c358 100644 (file)
@@ -23,6 +23,7 @@
     ("linux", "linux"),
     ("freebsd", "freebsd"),
     ("dragonfly", "dragonfly"),
+    ("bitrig", "bitrig"),
     ("openbsd", "openbsd"),
 ];
 
index a4f79412220189436fb3ad850210a4a28dcf66d1..f6b0a18824a0253327356b9eeb169b2a1e7f3bf2 100644 (file)
@@ -68,7 +68,7 @@ There are questions that are asked quite often, and so we've made FAQs for them:
 * [Language Design FAQ](complement-design-faq.html)
 * [Language FAQ](complement-lang-faq.html)
 * [Project FAQ](complement-project-faq.html)
-* [How to submit a bug report](complement-bugreport.html)
+* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
 
 # The standard library
 
index d9bfe71e2e42827d3aaeaa43076a7ce34fab346b..c9d834ee123bb55f6bce8e16dff8ef94ef89d8ba 100644 (file)
@@ -426,39 +426,33 @@ use std::thread::Thread;
 fn main() {
     let mut numbers = vec![1, 2, 3];
 
-    for i in 0..3 {
-        Thread::spawn(move || {
+    let guards: Vec<_> = (0..3).map(|i| {
+        Thread::scoped(move || {
             for j in 0..3 { numbers[j] += 1 }
         });
-    }
+    }).collect();
 }
 ```
 
 It gives us this error:
 
 ```text
-6:71 error: capture of moved value: `numbers`
-    for j in 0..3 { numbers[j] += 1 }
-                    ^~~~~~~
-7:50 note: `numbers` moved into closure environment here
-    spawn(move || {
-        for j in 0..3 { numbers[j] += 1 }
-    });
-6:79 error: cannot assign to immutable dereference (dereference is implicit, due to indexing)
-        for j in 0..3 { numbers[j] += 1 }
-                        ^~~~~~~~~~~~~~~
+7:29: 9:10 error: cannot move out of captured outer variable in an `FnMut` closure
+7         Thread::scoped(move || {
+8             for j in 0..3 { numbers[j] += 1 }
+9         });
 ```
 
-It mentions that "numbers moved into closure environment". Because we
-declared the closure as a moving closure, and it referred to
-`numbers`, the closure will try to take ownership of the vector. But
-the closure itself is created in a loop, and hence we will actually
-create three closures, one for every iteration of the loop. This means
-that all three of those closures would try to own `numbers`, which is
-impossible -- `numbers` must have just one owner. Rust detects this
-and gives us the error: we claim that `numbers` has ownership, but our
-code tries to make three owners. This may cause a safety problem, so
-Rust disallows it.
+It mentions that "captured outer variable in an `FnMut` closure".
+Because we declared the closure as a moving closure, and it referred
+to `numbers`, the closure will try to take ownership of the
+vector. But the closure itself is created in a loop, and hence we will
+actually create three closures, one for every iteration of the
+loop. This means that all three of those closures would try to own
+`numbers`, which is impossible -- `numbers` must have just one
+owner. Rust detects this and gives us the error: we claim that
+`numbers` has ownership, but our code tries to make three owners. This
+may cause a safety problem, so Rust disallows it.
 
 What to do here? Rust has two types that helps us: `Arc<T>` and `Mutex<T>`.
 *Arc* stands for "atomically reference counted". In other words, an Arc will
@@ -480,14 +474,14 @@ use std::sync::{Arc,Mutex};
 fn main() {
     let numbers = Arc::new(Mutex::new(vec![1, 2, 3]));
 
-    for i in 0..3 {
+    let guards: Vec<_> = (0..3).map(|i| {
         let number = numbers.clone();
-        Thread::spawn(move || {
+        Thread::scoped(move || {
             let mut array = number.lock().unwrap();
             array[i] += 1;
             println!("numbers[{}] is {}", i, array[i]);
         });
-    }
+    }).collect();
 }
 ```
 
@@ -516,8 +510,10 @@ numbers[1] is 3
 numbers[0] is 2
 ```
 
-Each time, we get a slightly different output, because each thread works in a
-different order. You may not get the same output as this sample, even.
+Each time, we can get a slithtly different output because the threads
+are not quaranteed to run in any set order. If you get the same order
+every time it is because each of these threads are very small and
+complete too fast for their indeterminate behavior to surface.
 
 The important part here is that the Rust compiler was able to use ownership to
 give us assurance _at compile time_ that we weren't doing something incorrect
@@ -539,13 +535,13 @@ safety check that makes this an error about moved values:
 use std::thread::Thread;
 
 fn main() {
-    let vec = vec![1, 2, 3];
-
-    for i in 0..3 {
-        Thread::spawn(move || {
-            println!("{}", vec[i]);
+    let numbers = vec![1, 2, 3];
+    
+    let guards: Vec<_> = (0..3).map(|i| {
+        Thread::scoped(move || {
+            println!("{}", numbers[i]);
         });
-    }
+    }).collect();
 }
 ```
 
index db940947040d48f41c4811bb46c4aca7e8ae1244..781b40be768c86f03b05ce809ce1a9c7aead5145 100644 (file)
@@ -515,6 +515,9 @@ This last example is different because it is not possible to use the suffix
 syntax with a floating point literal ending in a period. `2.f64` would attempt
 to call a method named `f64` on `2`.
 
+The representation semantics of floating-point numbers are described in
+["Machine Types"](#machine-types).
+
 #### Boolean literals
 
 The two values of the boolean type are written `true` and `false`.
@@ -728,15 +731,20 @@ Rust syntax is restricted in two ways:
    pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
    requiring a distinctive token in front can solve the problem.
 
-## Syntax extensions useful for the macro author
+## Syntax extensions useful in macros
 
-* `log_syntax!` : print out the arguments at compile time
-* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging
 * `stringify!` : turn the identifier argument into a string literal
 * `concat!` : concatenates a comma-separated list of literals
-* `concat_idents!` : create a new identifier by concatenating the arguments
 
-The following attributes are used for quasiquoting in procedural macros:
+## Syntax extensions for macro debugging
+
+* `log_syntax!` : print out the arguments at compile time
+* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging
+
+## Quasiquoting
+
+The following syntax extensions are used for quasiquoting Rust syntax trees,
+usually in [procedural macros](book/plugins.html#syntax-extensions):
 
 * `quote_expr!`
 * `quote_item!`
@@ -745,6 +753,8 @@ The following attributes are used for quasiquoting in procedural macros:
 * `quote_tokens!`
 * `quote_ty!`
 
+Documentation is very limited at the moment.
+
 # Crates and source files
 
 Rust is a *compiled* language. Its semantics obey a *phase distinction*
@@ -2162,7 +2172,7 @@ fn needs_foo_or_bar() {
 
 // This function is only included when compiling for a unixish OS with a 32-bit
 // architecture
-#[cfg(all(unix, target_word_size = "32"))]
+#[cfg(all(unix, target_pointer_width = "32"))]
 fn on_32bit_unix() {
   // ...
 }
@@ -2188,11 +2198,11 @@ The following configurations must be defined by the implementation:
   `"unix"` or `"windows"`. The value of this configuration option is defined
   as a configuration itself, like `unix` or `windows`.
 * `target_os = "..."`. Operating system of the target, examples include
-  `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"` or
-  `"openbsd"`.
-* `target_word_size = "..."`. Target word size in bits. This is set to `"32"`
-  for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit
-  pointers.
+  `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
+  `"bitrig"` or `"openbsd"`.
+* `target_pointer_width = "..."`. Target pointer width in bits. This is set
+  to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
+  64-bit pointers.
 * `unix`. See `target_family`.
 * `windows`. See `target_family`.
 
@@ -3554,7 +3564,8 @@ Tuple types and values are denoted by listing the types or values of their
 elements, respectively, in a parenthesized, comma-separated list.
 
 Because tuple elements don't have a name, they can only be accessed by
-pattern-matching.
+pattern-matching or by using `N` directly as a field to access the
+`N`th element.
 
 An example of a tuple type and its use:
 
@@ -3563,6 +3574,7 @@ type Pair<'a> = (i32, &'a str);
 let p: Pair<'static> = (10, "hello");
 let (a, b) = p;
 assert!(b != "world");
+assert!(p.0 == 10);
 ```
 
 ### Array, and Slice types
index c2a25cd7a584ec39c85978737dc0e3c3770c2339..cd158283180a268381a35370837bd968f7753ed8 100644 (file)
@@ -56,6 +56,7 @@
 /* General structure */
 
 body {
+    background-color: white;
     margin: 0 auto;
     padding: 0 15px;
     font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
index aff365051a4eadfc67819f0e9c45487abd1b70ad..a226e4d0bf911ac97b57c420129c3ff515bb53aa 100644 (file)
@@ -192,19 +192,58 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may
 only appear at the root of your crate, not inside `mod`. This ensures that
 `$crate` is a single identifier.
 
-# A final note
+# The deep end
 
-Macros, as currently implemented, are not for the faint of heart. Even
-ordinary syntax errors can be more difficult to debug when they occur inside a
-macro, and errors caused by parse problems in generated code can be very
-tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
-states, invoking `trace_macros!(true)` will automatically print those
-intermediate states out, and passing the flag `--pretty expanded` as a
-command-line argument to the compiler will show the result of expansion.
+The introductory chapter mentioned recursive macros, but it did not give the
+full story. Recursive macros are useful for another reason: Each recursive
+invocation gives you another opportunity to pattern-match the macro's
+arguments.
+
+As an extreme example, it is possible, though hardly advisable, to implement
+the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
+within Rust's macro system.
+
+```rust
+#![feature(trace_macros)]
+
+macro_rules! bct {
+    // cmd 0:  d ... => ...
+    (0, $($ps:tt),* ; $_d:tt)
+        => (bct!($($ps),*, 0 ; ));
+    (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
+        => (bct!($($ps),*, 0 ; $($ds),*));
+
+    // cmd 1p:  1 ... => 1 ... p
+    (1, $p:tt, $($ps:tt),* ; 1)
+        => (bct!($($ps),*, 1, $p ; 1, $p));
+    (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
+        => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
+
+    // cmd 1p:  0 ... => 0 ...
+    (1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
+        => (bct!($($ps),*, 1, $p ; $($ds),*));
+
+    // halt on empty data string
+    ( $($ps:tt),* ; )
+        => (());
+}
+
+fn main() {
+    trace_macros!(true);
+# /* just check the definition
+    bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
+# */
+}
+```
+
+Exercise: use macros to reduce duplication in the above definition of the
+`bct!` macro.
+
+# Procedural macros
 
 If Rust's macro system can't do what you need, you may want to write a
 [compiler plugin](plugins.html) instead. Compared to `macro_rules!`
 macros, this is significantly more work, the interfaces are much less stable,
-and the warnings about debugging apply ten-fold. In exchange you get the
+and bugs can be much harder to track down. In exchange you get the
 flexibility of running arbitrary Rust code within the compiler. Syntax
 extension plugins are sometimes called *procedural macros* for this reason.
index 1f5d3eadae3b9204b7836a838d5f2ce91563cb42..f3c0195855c3436baecae176038888e748f96b96 100644 (file)
@@ -12,7 +12,7 @@ Rust has two distinct terms that relate to the module system: *crate* and
 *module*. A crate is synonymous with a *library* or *package* in other
 languages. Hence "Cargo" as the name of Rust's package management tool: you
 ship your crates to others with Cargo. Crates can produce an executable or a
-shared library, depending on the project.
+library, depending on the project.
 
 Each crate has an implicit *root module* that contains the code for that crate.
 You can then define a tree of sub-modules under that root module. Modules allow
index 68b36e7a4b7ca225573b1accd19cf31c2534cc91..cf60bd88c542be85ff5f6c90d20c5cd599a9827d 100644 (file)
@@ -223,6 +223,78 @@ let input = io::stdin().read_line()
                        .ok()
                        .expect("Failed to read line");
 ```
+
 `ok()` converts the `IoResult` 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.
+
+# Using `try!`
+
+When writing code that calls many functions that return the `Result` type, the
+error handling can be tedious. The `try!` macro hides some of the boilerplate
+of propagating errors up the call stack.
+
+It replaces this:
+
+```rust
+use std::fs::File;
+use std::io;
+use std::io::prelude::*;
+
+struct Info {
+    name: String,
+    age: i32,
+    rating: i32,
+}
+
+fn write_info(info: &Info) -> io::Result<()> {
+    let mut file = File::open("my_best_friends.txt").unwrap();
+
+    if let Err(e) = writeln!(&mut file, "name: {}", info.name) {
+        return Err(e)
+    }
+    if let Err(e) = writeln!(&mut file, "age: {}", info.age) {
+        return Err(e)
+    }
+    if let Err(e) = writeln!(&mut file, "rating: {}", info.rating) {
+        return Err(e)
+    }
+
+    return Ok(());
+}
+```
+
+With this:
+
+```rust
+use std::fs::File;
+use std::io;
+use std::io::prelude::*;
+
+struct Info {
+    name: String,
+    age: i32,
+    rating: i32,
+}
+
+fn write_info(info: &Info) -> io::Result<()> {
+    let mut file = try!(File::open("my_best_friends.txt"));
+
+    try!(writeln!(&mut file, "name: {}", info.name));
+    try!(writeln!(&mut file, "age: {}", info.age));
+    try!(writeln!(&mut file, "rating: {}", info.rating));
+
+    return Ok(());
+}
+```
+
+Wrapping an expression in `try!` will result in the unwrapped success (`Ok`)
+value, unless the result is `Err`, in which case `Err` is returned early from
+the enclosing function.
+
+It's worth noting that you can only use `try!` from a function that returns a
+`Result`, which means that you cannot use `try!` inside of `main()`, because
+`main()` doesn't return anything.
+
+`try!` makes use of [`FromError`](../std/error/#the-fromerror-trait) to determine
+what to return in the error case.
index 01f270f19512ad22c10a24caa86a4eda0e861d7a..a40374fe30fadde9235a6607f6f010307eaf0649 100644 (file)
@@ -91,7 +91,7 @@ fn main() {
 ```
 
 You've seen this code before, when we talked about standard input. We
-import the `std::io` module with `use`, and then our `main` function contains
+import the `std::old_io` module with `use`, and then our `main` function contains
 our program's logic. We print a little message announcing the game, ask the
 user to input a guess, get their input, and then print it out.
 
index a350df67b1759ebe47afc150dd917d393ce1e4cf..7dac49987d84908ac37dd4ce6cce80fdabfa3c6c 100644 (file)
@@ -34,6 +34,20 @@ if x == 5 {
 }
 ```
 
+If there is more than one case, use an `else if`:
+
+```rust
+let x = 5;
+
+if x == 5 {
+    println!("x is five!");
+} else if x == 6 {
+    println!("x is six!");
+} else {
+    println!("x is not five or six :(");
+}
+```
+
 This is all pretty standard. However, you can also do this:
 
 
index 45c08af04f8773c6be6469cf0b2b7031ab27c735..33dc1ba07ca86e63cd26fa2d8ce99d3d0e9f232c 100644 (file)
@@ -57,14 +57,13 @@ for i in 0..nums.len() {
 }
 ```
 
-This is strictly worse than using an actual iterator. The `.iter()` method on
-vectors returns an iterator which iterates through a reference to each element
-of the vector in turn. So write this:
+This is strictly worse than using an actual iterator. You can iterate over vectors
+directly, so write this:
 
 ```rust
 let nums = vec![1, 2, 3];
 
-for num in nums.iter() {
+for num in &nums {
     println!("{}", num);
 }
 ```
@@ -86,16 +85,17 @@ see it. This code works fine too:
 ```rust
 let nums = vec![1, 2, 3];
 
-for num in nums.iter() {
+for num in &nums {
     println!("{}", *num);
 }
 ```
 
-Now we're explicitly dereferencing `num`. Why does `iter()` give us references?
-Well, if it gave us the data itself, we would have to be its owner, which would
-involve making a copy of the data and giving us the copy. With references,
-we're just borrowing a reference to the data, and so it's just passing
-a reference, without needing to do the copy.
+Now we're explicitly dereferencing `num`. Why does `&nums` give us
+references?  Firstly, because we explicitly asked it to with
+`&`. Secondly, if it gave us the data itself, we would have to be its
+owner, which would involve making a copy of the data and giving us the
+copy. With references, we're just borrowing a reference to the data,
+and so it's just passing a reference, without needing to do the move.
 
 So, now that we've established that ranges are often not what you want, let's
 talk about what you do want instead.
@@ -230,9 +230,9 @@ let nums = (1..100).collect::<Vec<i32>>();
 Now, `collect()` will require that the range gives it some numbers, and so
 it will do the work of generating the sequence.
 
-Ranges are one of two basic iterators that you'll see. The other is `iter()`,
-which you've used before. `iter()` can turn a vector into a simple iterator
-that gives you each element in turn:
+Ranges are one of two basic iterators that you'll see. The other is `iter()`.
+`iter()` can turn a vector into a simple iterator that gives you each element
+in turn:
 
 ```rust
 let nums = [1, 2, 3];
index ce6fa3ce949cd7a1f0878ca79bf20358a5127ba1..7da36043f6cf17726a3641bab0381564aeb1ada1 100644 (file)
@@ -73,7 +73,7 @@ macro_rules! vec {
     };
 }
 # fn main() {
-#     assert_eq!(&[1,2,3], &vec![1,2,3]);
+#     assert_eq!([1,2,3], vec![1,2,3]);
 # }
 ```
 
@@ -189,14 +189,12 @@ shorthand for a data type could be valid as either an expression or a pattern.
 
 ## Repetition
 
-The repetition behavior can seem somewhat magical, especially when multiple
-names are bound at multiple nested levels of repetition. The two rules to keep
-in mind are:
+The repetition operator follows two principal rules:
 
-1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for
-all of the `$name`s it contains, in lockstep, and
+1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
+   it contains, in lockstep, and
 2. each `$name` must be under at least as many `$(...)*`s as it was matched
-against. If it is under more, it'll be duplicated, as appropriate.
+   against. If it is under more, it'll be duplicated, as appropriate.
 
 This baroque macro illustrates the duplication of variables from outer
 repetition levels.
@@ -226,6 +224,10 @@ That's most of the matcher syntax. These examples use `$(...)*`, which is a
 more" match. Both forms optionally include a separator, which can be any token
 except `+` or `*`.
 
+This system is based on
+"[Macro-by-Example](http://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
+(PDF link).
+
 # Hygiene
 
 Some languages implement macros using simple text substitution, which leads to
@@ -273,19 +275,26 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
 })
 ```
 
-This looks reasonable, but watch what happens in this example:
+Here's a simple use case that goes terribly wrong:
 
 ```text
 const char *state = "reticulating splines";
-LOG(state);
+LOG(state)
 ```
 
-The program will likely segfault, after it tries to execute
+This expands to
 
 ```text
-printf("log(%d): %s\n", state, state);
+const char *state = "reticulating splines";
+int state = get_log_state();
+if (state > 0) {
+    printf("log(%d): %s\n", state, state);
+}
 ```
 
+The second variable named `state` shadows the first one.  This is a problem
+because the print statement should refer to both of them.
+
 The equivalent Rust macro has the desired behavior.
 
 ```rust
@@ -357,6 +366,64 @@ fn main() {
 
 [items]: ../reference.html#items
 
+# Recursive macros
+
+A macro's expansion can include more macro invocations, including invocations
+of the very same macro being expanded.  These recursive macros are useful for
+processing tree-structured input, as illustrated by this (simplistic) HTML
+shorthand:
+
+```rust
+# #![allow(unused_must_use)]
+macro_rules! write_html {
+    ($w:expr, ) => (());
+
+    ($w:expr, $e:tt) => (write!($w, "{}", $e));
+
+    ($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{
+        write!($w, "<{}>", stringify!($tag));
+        write_html!($w, $($inner)*);
+        write!($w, "</{}>", stringify!($tag));
+        write_html!($w, $($rest)*);
+    }};
+}
+
+fn main() {
+#   // FIXME(#21826)
+    use std::fmt::Write;
+    let mut out = String::new();
+
+    write_html!(&mut out,
+        html[
+            head[title["Macros guide"]]
+            body[h1["Macros are the best!"]]
+        ]);
+
+    assert_eq!(out,
+        "<html><head><title>Macros guide</title></head>\
+         <body><h1>Macros are the best!</h1></body></html>");
+}
+```
+
+# Debugging macro code
+
+To see the results of expanding macros, run `rustc --pretty expanded`. The
+output represents a whole crate, so you can also feed it back in to `rustc`,
+which will sometimes produce better error messages than the original
+compilation. Note that the `--pretty expanded` output may have a different
+meaning if multiple variables of the same name (but different syntax contexts)
+are in play in the same scope. In this case `--pretty expanded,hygiene` will
+tell you about the syntax contexts.
+
+`rustc` provides two syntax extensions that help with macro debugging. For now,
+they are unstable and require feature gates.
+
+* `log_syntax!(...)` will print its arguments to standard output, at compile
+  time, and "expand" to nothing.
+
+* `trace_macros!(true)` will enable a compiler message every time a macro is
+  expanded. Use `trace_macros!(false)` later in expansion to turn it off.
+
 # Further reading
 
 The [advanced macros chapter][] goes into more detail about macro syntax. It
index 20f1406aebbabae512dc67639a7b8cfbaab5dfe5..a2a558094e1963c8f4b0c46423f3f69ef0eea45e 100644 (file)
@@ -38,8 +38,9 @@ string literal or a `String`.
 
 # String
 
-A `String` is a heap-allocated string. This string is growable, and is also
-guaranteed to be UTF-8.
+A `String` is a heap-allocated string. This string is growable, and is
+also guaranteed to be UTF-8. `String`s are commonly created by
+converting from a string slice using the `to_string` method.
 
 ```
 let mut s = "Hello".to_string();
@@ -49,7 +50,7 @@ s.push_str(", world.");
 println!("{}", s);
 ```
 
-You can coerce a `String` into a `&str` by dereferencing it:
+A reference to a `String` will automatically coerce to a string slice:
 
 ```
 fn takes_slice(slice: &str) {
@@ -58,7 +59,7 @@ fn takes_slice(slice: &str) {
 
 fn main() {
     let s = "Hello".to_string();
-    takes_slice(&*s);
+    takes_slice(&s);
 }
 ```
 
index 79502f3cd17f755768cabac2c00c36c2f594f03a..f609a0a918aa7628a6dc05372da67c168dd7335f 100644 (file)
@@ -146,14 +146,7 @@ a more involved macro example, see
 
 ## Tips and tricks
 
-To see the results of expanding syntax extensions, run
-`rustc --pretty expanded`. The output represents a whole crate, so you
-can also feed it back in to `rustc`, which will sometimes produce better
-error messages than the original compilation. Note that the
-`--pretty expanded` output may have a different meaning if multiple
-variables of the same name (but different syntax contexts) are in play
-in the same scope. In this case `--pretty expanded,hygiene` will tell
-you about the syntax contexts.
+Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable.
 
 You can use [`syntax::parse`](../syntax/parse/index.html) to turn token trees into
 higher-level syntax elements like expressions:
@@ -184,6 +177,11 @@ and return
 [`DummyResult`](../syntax/ext/base/struct.DummyResult.html),
 so that the compiler can continue and find further errors.
 
+To print syntax fragments for debugging, you can use
+[`span_note`](../syntax/ext/base/struct.ExtCtxt.html#method.span_note) together
+with
+[`syntax::print::pprust::*_to_string`](http://doc.rust-lang.org/syntax/print/pprust/index.html#functions).
+
 The example above produced an integer literal using
 [`AstBuilder::expr_uint`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint).
 As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of
index 9c649cd2273f8025117dd58f9f9eedf6f2b8e75d..0f46b4da0d6f971b6ae3371d4850a5b8774493f0 100644 (file)
@@ -361,16 +361,16 @@ duration a *lifetime*. Let's try a more complex example:
 
 ```{rust}
 fn main() {
-    let x = &mut 5;
+    let mut x = 5;
 
-    if *x < 10 {
+    if x < 10 {
         let y = &x;
 
         println!("Oh no: {}", y);
         return;
     }
 
-    *x -= 1;
+    x -= 1;
 
     println!("Oh no: {}", x);
 }
@@ -382,17 +382,18 @@ mutated, and therefore, lets us pass. This wouldn't work:
 
 ```{rust,ignore}
 fn main() {
-    let x = &mut 5;
+    let mut x = 5;
 
-    if *x < 10 {
+    if x < 10 {
         let y = &x;
-        *x -= 1;
+
+        x -= 1;
 
         println!("Oh no: {}", y);
         return;
     }
 
-    *x -= 1;
+    x -= 1;
 
     println!("Oh no: {}", x);
 }
@@ -401,12 +402,12 @@ fn main() {
 It gives this error:
 
 ```text
-test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed
-test.rs:5         *x -= 1;
-                  ^~
-test.rs:4:16: 4:18 note: borrow of `*x` occurs here
-test.rs:4         let y = &x;
-                          ^~
+test.rs:7:9: 7:15 error: cannot assign to `x` because it is borrowed
+test.rs:7         x -= 1;
+                  ^~~~~~
+test.rs:5:18: 5:19 note: borrow of `x` occurs here
+test.rs:5         let y = &x;
+                           ^
 ```
 
 As you might guess, this kind of analysis is complex for a human, and therefore
@@ -687,7 +688,9 @@ than the hundred `int`s that make up the `BigStruct`.
 
 This is an antipattern in Rust. Instead, write this:
 
-```{rust}
+```rust
+#![feature(box_syntax)]
+
 struct BigStruct {
     one: i32,
     two: i32,
@@ -706,10 +709,13 @@ fn main() {
         one_hundred: 100,
     });
 
-    let y = Box::new(foo(x));
+    let y = 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
index 9421dac7bf65d750a554e9c1f0a17de1bfe6a5c4..fc1ab9bf9e8dca6278f004d521ed8382050866eb 100644 (file)
@@ -79,12 +79,13 @@ fn main() {
 }
 ```
 
-This has some upsides: static dispatching of any method calls, allowing for
-inlining and hence usually higher performance. It also has some downsides:
-causing code bloat due to many copies of the same function existing in the
-binary, one for each type.
+This has a great upside: static dispatch allows function calls to be
+inlined because the callee is known at compile time, and inlining is
+the key to good optimization. Static dispatch is fast, but it comes at
+a tradeoff: 'code bloat', due to many copies of the same function
+existing in the binary, one for each type.
 
-Furthermore, compilers aren’t perfect and may “optimise” code to become slower.
+Furthermore, compilers aren’t perfect and may “optimize” code to become slower.
 For example, functions inlined too eagerly will bloat the instruction cache
 (cache rules everything around us). This is part of the reason that `#[inline]`
 and `#[inline(always)]` should be used carefully, and one reason why using a
@@ -92,8 +93,8 @@ dynamic dispatch is sometimes more efficient.
 
 However, the common case is that it is more efficient to use static dispatch,
 and one can always have a thin statically-dispatched wrapper function that does
-a dynamic, but not vice versa, meaning static calls are more flexible. The
-standard library tries to be statically dispatched where possible for this
+a dynamic dispatch, but not vice versa, meaning static calls are more flexible.
+The standard library tries to be statically dispatched where possible for this
 reason. 
 
 ## Dynamic dispatch
@@ -104,7 +105,7 @@ objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
 known at runtime. The methods of the trait can be called on a trait object via
 a special record of function pointers (created and managed by the compiler).
 
-A function that takes a trait object is not specialised to each of the types
+A function that takes a trait object is not specialized to each of the types
 that implements `Foo`: only one copy is generated, often (but not always)
 resulting in less code bloat. However, this comes at the cost of requiring
 slower virtual function calls, and effectively inhibiting any chance of
@@ -112,7 +113,7 @@ inlining and related optimisations from occurring.
 
 Trait objects are both simple and complicated: their core representation and
 layout is quite straight-forward, but there are some curly error messages and
-surprising behaviours to discover.
+surprising behaviors to discover.
 
 ### Obtaining a trait object
 
@@ -140,13 +141,13 @@ and casts are identical.
 
 This operation can be seen as "erasing" the compiler's knowledge about the
 specific type of the pointer, and hence trait objects are sometimes referred to
-"type erasure".
+as "type erasure".
 
 ### Representation
 
 Let's start simple, with the runtime representation of a trait object. The
 `std::raw` module contains structs with layouts that are the same as the
-complicated build-in types, [including trait objects][stdraw]:
+complicated built-in types, [including trait objects][stdraw]:
 
 ```rust
 # mod foo {
@@ -223,14 +224,14 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
 The `destructor` field in each vtable points to a function that will clean up
 any resources of the vtable's type, for `u8` it is trivial, but for `String` it
 will free the memory. This is necessary for owning trait objects like
-`Box<Foo>`, which need to clean-up both the `Box` allocation and as well as the
+`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
 internal type when they go out of scope. The `size` and `align` fields store
 the size of the erased type, and its alignment requirements; these are
 essentially unused at the moment since the information is embedded in the
-destructor, but will be used in future, as trait objects are progressively made
-more flexible.
+destructor, but will be used in the future, as trait objects are progressively
+made more flexible.
 
-Suppose we've got some values that implement `Foo`, the explicit form of
+Suppose we've got some values that implement `Foo`, then the explicit form of
 construction and use of `Foo` trait objects might look a bit like (ignoring the
 type mismatches: they're all just pointers anyway):
 
index 8ebebc98baf6b6d6bd4bb1f549e1400d33734d58..2c2e6a8c7c5acdf8079163bf675163a0ea7aff84 100644 (file)
@@ -25,8 +25,10 @@ compiled program, and exists for the entire duration it runs. The `string`
 binding is a reference to this statically allocated string. String slices
 have a fixed size, and cannot be mutated.
 
-A `String`, on the other hand, is an in-memory string.  This string is
-growable, and is also guaranteed to be UTF-8.
+A `String`, on the other hand, is a heap-allocated string. This string
+is growable, and is also guaranteed to be UTF-8. `String`s are
+commonly created by converting from a string slice using the
+`to_string` method.
 
 ```{rust}
 let mut s = "Hello".to_string(); // mut s: String
index 22792ff76355149b4ee8eb006fba37618b094caf..a212e3a04357eccc564097ab90b203d1afc38a8f 100644 (file)
@@ -96,6 +96,9 @@ There are a number of supported commands:
   highlights for example. If you want to simply check the presence of
   given node or attribute, use an empty string (`""`) as a `PATTERN`.
 
+* `@count PATH XPATH COUNT' checks for the occurrence of given XPath
+  in the given file. The number of occurrences must match the given count.
+
 All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
 checks if the given file does not exist, for example.
 
@@ -333,6 +336,11 @@ def check_tree_text(tree, path, pat, regexp):
     return ret
 
 
+def check_tree_count(tree, path, count):
+    path = normalize_xpath(path)
+    return len(tree.findall(path)) == count
+
+
 def check(target, commands):
     cache = CachedFiles(target)
     for c in commands:
@@ -360,6 +368,13 @@ def check(target, commands):
                 raise RuntimeError('Invalid number of @{} arguments \
                                     at line {}'.format(c.cmd, c.lineno))
 
+        elif c.cmd == 'count': # count test
+            if len(c.args) == 3: # @count <path> <pat> <count> = count test
+                ret = check_tree_count(cache.get_tree(c.args[0]), c.args[1], int(c.args[2]))
+            else:
+                raise RuntimeError('Invalid number of @{} arguments \
+                                    at line {}'.format(c.cmd, c.lineno))
+
         elif c.cmd == 'valid-html':
             raise RuntimeError('Unimplemented @valid-html at line {}'.format(c.lineno))
 
index b506aff94e7209372ba7197874cef1109fec0a21..ca59b1c7d34a2faeb8f967d73a55355aea9c2a00 100755 (executable)
@@ -18,7 +18,7 @@ LIB_PREFIX=lib
 
 OS=`uname -s`
 case $OS in
-    ("Linux"|"FreeBSD"|"DragonFly"|"OpenBSD")
+    ("Linux"|"FreeBSD"|"DragonFly"|"Bitrig"|"OpenBSD")
     BIN_SUF=
     LIB_SUF=.so
     ;;
index a4234159cb81c9ee624df8b7e4b10aab01aa0788..e5e8c9f11bd82691e823583bfc140d4c46d1664c 100644 (file)
@@ -57,7 +57,16 @@ else:
 args.extend(components)
 out = run(args)
 for lib in out.strip().replace("\n", ' ').split(' '):
-    lib = lib.strip()[2:] # chop of the leading '-l'
+    if len(lib) == 0:
+        continue
+    # in some cases we get extra spaces in between libs so ignore those
+    if len(lib) == 1 and lib == ' ':
+        continue
+    # not all libs strictly follow -lfoo, on Bitrig, there is -pthread
+    if lib[0:2] == '-l':
+        lib = lib.strip()[2:]
+    elif lib[0] == '-':
+        lib = lib.strip()[1:]
     f.write("#[link(name = \"" + lib + "\"")
     # LLVM libraries are all static libraries
     if 'LLVM' in lib:
index 264af5f9854cc81c5ec73306167840aab1187807..0349ccf9b66408bf80833afe3d4b96d68dd6ceef 100644 (file)
@@ -46,13 +46,13 @@ snapshot_files = {
         "winnt": ["bin/rustc.exe"],
         "freebsd": ["bin/rustc"],
         "dragonfly": ["bin/rustc"],
+        "bitrig": ["bin/rustc"],
         "openbsd": ["bin/rustc"],
         }
 
 winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"]
 winnt_runtime_deps_64 = ["libgcc_s_seh-1.dll", "libstdc++-6.dll"]
 
-
 def parse_line(n, line):
     global snapshotfile
 
@@ -101,6 +101,8 @@ def get_kernel(triple):
         return "freebsd"
     if os_name == "dragonfly":
         return "dragonfly"
+    if os_name == "bitrig":
+        return "bitrig"
     if os_name == "openbsd":
         return "openbsd"
     return "linux"
index 8cd27125646c82739d8cf1b2fe5518dcf74c52bc..88a3752c88a1d6774b8b288a2a12f2af0e566e61 100644 (file)
@@ -605,13 +605,6 @@ impl<T: Default + Sync + Send> Default for Arc<T> {
     fn default() -> Arc<T> { Arc::new(Default::default()) }
 }
 
-#[cfg(stage0)]
-impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
-    fn hash(&self, state: &mut H) {
-        (**self).hash(state)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Hash> Hash for Arc<T> {
     fn hash<H: Hasher>(&self, state: &mut H) {
index a3516bd667b7a18cb6e9f0653481511bc5f04779..a93872dfe36bd8d522bd9fa3e56e10715f386605 100644 (file)
@@ -105,15 +105,16 @@ impl<T : ?Sized> Box<T> {
     /// After this function call, pointer is owned by resulting box.
     /// In particular, it means that `Box` destructor calls destructor
     /// of `T` and releases memory. Since the way `Box` allocates and
-    /// releases memory is unspecified, so the only valid pointer to
-    /// pass to this function is the one taken from another `Box` with
-    /// `box::into_raw` function.
+    /// releases memory is unspecified, the only valid pointer to pass
+    /// to this function is the one taken from another `Box` with
+    /// `boxed::into_raw` function.
     ///
     /// Function is unsafe, because improper use of this function may
     /// lead to memory problems like double-free, for example if the
     /// function is called twice on the same raw pointer.
     #[unstable(feature = "alloc",
                reason = "may be renamed or moved out of Box scope")]
+    #[inline]
     pub unsafe fn from_raw(raw: *mut T) -> Self {
         mem::transmute(raw)
     }
@@ -141,6 +142,7 @@ pub unsafe fn from_raw(raw: *mut T) -> Self {
 /// ```
 #[unstable(feature = "alloc",
            reason = "may be renamed")]
+#[inline]
 pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
     mem::transmute(b)
 }
@@ -220,14 +222,6 @@ fn cmp(&self, other: &Box<T>) -> Ordering {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Eq> Eq for Box<T> {}
 
-#[cfg(stage0)]
-impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized + Hash> Hash for Box<T> {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
@@ -256,11 +250,12 @@ fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
         if self.is::<T>() {
             unsafe {
                 // Get the raw representation of the trait object
+                let raw = into_raw(self);
                 let to: TraitObject =
-                    mem::transmute::<Box<Any>, TraitObject>(self);
+                    mem::transmute::<*mut Any, TraitObject>(raw);
 
                 // Extract the data pointer
-                Ok(mem::transmute(to.data))
+                Ok(Box::from_raw(to.data as *mut T))
             }
         } else {
             Err(self)
index bc349ebebdeed0a317a30943c9aefa6142a096ff..82bd13475c74eabb6f106112edd5434c7411cc70 100644 (file)
@@ -73,6 +73,8 @@
 #![feature(unboxed_closures)]
 #![feature(unsafe_no_drop_flag)]
 #![feature(core)]
+#![feature(unique)]
+#![cfg_attr(test, feature(test, alloc, rustc_private))]
 #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
             feature(libc))]
 
index 9d39511543188736cd20c9935d80a9f0d3469e78..f57286bbf11c9af56ee608e8b9af720ddf00eaa4 100644 (file)
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
-
+#[cfg(not(test))]
+use boxed;
+#[cfg(test)]
+use std::boxed;
 use core::cell::Cell;
 use core::clone::Clone;
 use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
 use core::fmt;
 use core::hash::{Hasher, Hash};
 use core::marker;
-use core::mem::{transmute, min_align_of, size_of, forget};
+use core::mem::{min_align_of, size_of, forget};
 use core::nonzero::NonZero;
 use core::ops::{Deref, Drop};
 use core::option::Option;
@@ -201,7 +204,7 @@ pub fn new(value: T) -> Rc<T> {
                 // there is an implicit weak pointer owned by all the strong pointers, which
                 // ensures that the weak destructor never frees the allocation while the strong
                 // destructor is running, even if the weak pointer is stored inside the strong one.
-                _ptr: NonZero::new(transmute(box RcBox {
+                _ptr: NonZero::new(boxed::into_raw(box RcBox {
                     value: value,
                     strong: Cell::new(1),
                     weak: Cell::new(1)
@@ -592,14 +595,6 @@ fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
 }
 
 // FIXME (#18248) Make `T` `Sized?`
-#[cfg(stage0)]
-impl<S: Hasher, T: Hash<S>> Hash<S> for Rc<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Hash> Hash for Rc<T> {
     fn hash<H: Hasher>(&self, state: &mut H) {
index 14a9fd4f452793a1a5ffb1607fc8f00fc3a9aa40..694b5d23c490e5e4736aab26321f33c22ce3826d 100755 (executable)
@@ -5650,7 +5650,7 @@ else
     lt_cv_sys_max_cmd_len=8192;
     ;;
 
-  netbsd* | freebsd* | openbsd* | darwin* | dragonfly*)
+  netbsd* | freebsd* | openbsd* | darwin* | dragonfly* | bitrig*)
     # This has been around since 386BSD, at least.  Likely further.
     if test -x /sbin/sysctl; then
       lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
@@ -9332,7 +9332,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
       ;;
 
     # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
-    freebsd* | dragonfly* | openbsd*)
+    freebsd* | dragonfly* | bitrig* | openbsd*)
       archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
       hardcode_libdir_flag_spec='-R$libdir'
       hardcode_direct=yes
index 9503ec85d709d8f7fdad222ef3c4d8d85fdc6cd1..eaef55a59332a88c6bcb008a56214d48518c6546 100644 (file)
@@ -4741,7 +4741,7 @@ func_mode_link ()
            # These systems don't actually have a C library (as such)
            test "X$arg" = "X-lc" && continue
            ;;
-         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*)
            # Do not include libc due to us having libc/libc_r.
            test "X$arg" = "X-lc" && continue
            ;;
index 9f549fd7237711dce941f7ef0d37e0eec9e8db73..36c76dbad14aefcb20076f4d9c63613aa80fe221 100644 (file)
@@ -480,7 +480,7 @@ pub fn into_vec(self) -> Vec<T> { self.data }
     /// heap.push(3);
     ///
     /// let vec = heap.into_sorted_vec();
-    /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]);
+    /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
     /// ```
     pub fn into_sorted_vec(mut self) -> Vec<T> {
         let mut end = self.len();
index 11c576eab152551c274b9036b4ac99a5ee30ae39..5b19de42ac919240167e67892b48ba519dd55b63 100644 (file)
@@ -110,7 +110,7 @@ fn reverse_bits(byte: u8) -> u8 {
     result
 }
 
-// Take two BitV's, and return iterators of their words, where the shorter one
+// Take two BitVec's, and return iterators of their words, where the shorter one
 // has been padded with 0's
 fn match_words <'a,'b>(a: &'a BitVec, b: &'b BitVec) -> (MatchWords<'a>, MatchWords<'b>) {
     let a_len = a.storage.len();
@@ -640,13 +640,13 @@ pub fn any(&self) -> bool {
     /// let mut bv = BitVec::from_elem(3, true);
     /// bv.set(1, false);
     ///
-    /// assert_eq!(bv.to_bytes(), vec!(0b10100000));
+    /// assert_eq!(bv.to_bytes(), [0b10100000]);
     ///
     /// let mut bv = BitVec::from_elem(9, false);
     /// bv.set(2, true);
     /// bv.set(8, true);
     ///
-    /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
+    /// assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
     /// ```
     pub fn to_bytes(&self) -> Vec<u8> {
         fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 {
@@ -806,7 +806,7 @@ pub fn capacity(&self) -> usize {
     /// let mut bv = BitVec::from_bytes(&[0b01001011]);
     /// bv.grow(2, true);
     /// assert_eq!(bv.len(), 10);
-    /// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000));
+    /// assert_eq!(bv.to_bytes(), [0b01001011, 0b11000000]);
     /// ```
     pub fn grow(&mut self, n: usize, value: bool) {
         // Note: we just bulk set all the bits in the last word in this fn in multiple places
@@ -978,24 +978,13 @@ fn cmp(&self, other: &BitVec) -> Ordering {
 impl fmt::Debug for BitVec {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         for bit in self {
-            try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 }));
+            try!(write!(fmt, "{}", if bit { 1 } else { 0 }));
         }
         Ok(())
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(stage0)]
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitVec {
-    fn hash(&self, state: &mut S) {
-        self.nbits.hash(state);
-        for elem in self.blocks() {
-            elem.hash(state);
-        }
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl hash::Hash for BitVec {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         self.nbits.hash(state);
@@ -1763,7 +1752,7 @@ pub fn remove(&mut self, value: &usize) -> bool {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for BitSet {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "BitSet {{"));
+        try!(write!(fmt, "{{"));
         let mut first = true;
         for n in self {
             if !first {
@@ -1776,16 +1765,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(stage0)]
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitSet {
-    fn hash(&self, state: &mut S) {
-        for pos in self {
-            pos.hash(state);
-        }
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl hash::Hash for BitSet {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         for pos in self {
@@ -2305,12 +2285,12 @@ fn test_from_bytes() {
     fn test_to_bytes() {
         let mut bv = BitVec::from_elem(3, true);
         bv.set(1, false);
-        assert_eq!(bv.to_bytes(), vec!(0b10100000));
+        assert_eq!(bv.to_bytes(), [0b10100000]);
 
         let mut bv = BitVec::from_elem(9, false);
         bv.set(2, true);
         bv.set(8, true);
-        assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
+        assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
     }
 
     #[test]
@@ -2675,7 +2655,7 @@ fn test_bit_set_show() {
         s.insert(10);
         s.insert(50);
         s.insert(2);
-        assert_eq!("BitSet {1, 2, 10, 50}", format!("{:?}", s));
+        assert_eq!("{1, 2, 10, 50}", format!("{:?}", s));
     }
 
     #[test]
@@ -2695,7 +2675,7 @@ fn test_bit_set_iterator() {
         let bit_vec: BitSet = usizes.into_iter().collect();
 
         let idxs: Vec<_> = bit_vec.iter().collect();
-        assert_eq!(idxs, vec![0, 2, 3]);
+        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();
index 901d7a73b51ed27bbc051ccc09a261fc3b5e3353..f3c44a84ee50ac5f0fc7c210383bfa7d84e22c02 100644 (file)
@@ -132,7 +132,7 @@ fn to_owned(&self) -> T { self.clone() }
 /// ```rust
 /// use std::borrow::Cow;
 ///
-/// fn abs_all(input: &mut Cow<[int]>) {
+/// fn abs_all(input: &mut Cow<[i32]>) {
 ///     for i in 0..input.len() {
 ///         let v = input[i];
 ///         if v < 0 {
@@ -282,16 +282,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(stage0)]
-impl<'a, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, B> where B: Hash<S> + ToOwned
-{
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        Hash::hash(&**self, state)
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
 {
     #[inline]
diff --git a/src/libcollections/borrow_stage0.rs b/src/libcollections/borrow_stage0.rs
deleted file mode 100644 (file)
index c1d74b1..0000000
+++ /dev/null
@@ -1,313 +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.
-
-//! A module for working with borrowed data.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use core::clone::Clone;
-use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
-use core::hash::{Hash, Hasher};
-use core::marker::Sized;
-use core::ops::Deref;
-use core::option::Option;
-
-use fmt;
-use alloc::{rc, arc};
-
-use self::Cow::*;
-
-/// A trait for borrowing data.
-///
-/// In general, there may be several ways to "borrow" a piece of data.  The
-/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
-/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
-/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
-///
-/// When writing generic code, it is often desirable to abstract over all ways
-/// of borrowing data from a given type. That is the role of the `Borrow`
-/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`.  A given
-/// type can be borrowed as multiple different types. In particular, `Vec<T>:
-/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait Borrow<Borrowed: ?Sized> {
-    /// Immutably borrow from an owned value.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn borrow(&self) -> &Borrowed;
-}
-
-/// A trait for mutably borrowing data.
-///
-/// Similar to `Borrow`, but for mutable borrows.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
-    /// Mutably borrow from an owned value.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn borrow_mut(&mut self) -> &mut Borrowed;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Borrow<T> for T {
-    fn borrow(&self) -> &T { self }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> BorrowMut<T> for T {
-    fn borrow_mut(&mut self) -> &mut T { self }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> Borrow<T> for &'a T {
-    fn borrow(&self) -> &T { &**self }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
-    fn borrow(&self) -> &T { &**self }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
-    fn borrow_mut(&mut self) -> &mut T { &mut **self }
-}
-
-impl<T> Borrow<T> for rc::Rc<T> {
-    fn borrow(&self) -> &T { &**self }
-}
-
-impl<T> Borrow<T> for arc::Arc<T> {
-    fn borrow(&self) -> &T { &**self }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
-    fn borrow(&self) -> &B {
-        &**self
-    }
-}
-
-/// A generalization of Clone to borrowed data.
-///
-/// Some types make it possible to go from borrowed to owned, usually by
-/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
-/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
-/// from any borrow of a given type.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait ToOwned {
-    #[stable(feature = "rust1", since = "1.0.0")]
-    type Owned: Borrow<Self>;
-
-    /// Create owned data from borrowed data, usually by copying.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn to_owned(&self) -> Self::Owned;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ToOwned for T where T: Clone {
-    type Owned = T;
-    fn to_owned(&self) -> T { self.clone() }
-}
-
-/// A clone-on-write smart pointer.
-///
-/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
-/// can enclose and provide immutable access to borrowed data, and clone the
-/// data lazily when mutation or ownership is required. The type is designed to
-/// work with general borrowed data via the `Borrow` trait.
-///
-/// `Cow` implements both `Deref`, which means that you can call
-/// non-mutating methods directly on the data it encloses. If mutation
-/// is desired, `to_mut` will obtain a mutable references to an owned
-/// value, cloning if necessary.
-///
-/// # Example
-///
-/// ```rust
-/// use std::borrow::Cow;
-///
-/// fn abs_all(input: &mut Cow<[int]>) {
-///     for i in 0..input.len() {
-///         let v = input[i];
-///         if v < 0 {
-///             // clones into a vector the first time (if not already owned)
-///             input.to_mut()[i] = -v;
-///         }
-///     }
-/// }
-/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
-pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
-    /// Borrowed data.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    Borrowed(&'a B),
-
-    /// Owned data.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    Owned(<B as ToOwned>::Owned)
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
-    fn clone(&self) -> Cow<'a, B> {
-        match *self {
-            Borrowed(b) => Borrowed(b),
-            Owned(ref o) => {
-                let b: &B = o.borrow();
-                Owned(b.to_owned())
-            },
-        }
-    }
-}
-
-impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
-    /// Acquire a mutable reference to the owned form of the data.
-    ///
-    /// Copies the data if it is not already owned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned where <B as ToOwned>::Owned: 'a {
-        match *self {
-            Borrowed(borrowed) => {
-                *self = Owned(borrowed.to_owned());
-                self.to_mut()
-            }
-            Owned(ref mut owned) => owned
-        }
-    }
-
-    /// Extract the owned data.
-    ///
-    /// Copies the data if it is not already owned.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_owned(self) -> <B as ToOwned>::Owned {
-        match self {
-            Borrowed(borrowed) => borrowed.to_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")]
-impl<'a, B: ?Sized> Deref for Cow<'a, B> where
-    B: ToOwned, <B as ToOwned>::Owned: 'a
-{
-    type Target = B;
-
-    fn deref(&self) -> &B {
-        match *self {
-            Borrowed(borrowed) => borrowed,
-            Owned(ref owned) => owned.borrow()
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned, <B as ToOwned>::Owned: 'a {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> Ord for Cow<'a, B> where
-    B: Ord + ToOwned, <B as ToOwned>::Owned: 'a
-{
-    #[inline]
-    fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
-        Ord::cmp(&**self, &**other)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
-    B: PartialEq<C> + ToOwned, C: ToOwned,
-    <B as ToOwned>::Owned: 'a, <C as ToOwned>::Owned: 'b,
-{
-    #[inline]
-    fn eq(&self, other: &Cow<'b, C>) -> bool {
-        PartialEq::eq(&**self, &**other)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where
-    B: PartialOrd + ToOwned, <B as ToOwned>::Owned: 'a
-{
-    #[inline]
-    fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
-        PartialOrd::partial_cmp(&**self, &**other)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
-    B: fmt::Debug + ToOwned,
-    <B as ToOwned>::Owned: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Borrowed(ref b) => fmt::Debug::fmt(b, f),
-            Owned(ref o) => fmt::Debug::fmt(o, f),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
-    B: fmt::Display + ToOwned,
-    <B as ToOwned>::Owned: fmt::Display,
-{
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Borrowed(ref b) => fmt::Display::fmt(b, f),
-            Owned(ref o) => fmt::Display::fmt(o, f),
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, B> where
-    B: Hash<S> + ToOwned, <B as ToOwned>::Owned: 'a
-{
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        Hash::hash(&**self, state)
-    }
-}
-
-/// Trait for moving into a `Cow`
-#[stable(feature = "rust1", since = "1.0.0")]
-pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
-    /// Moves `self` into `Cow`
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn into_cow(self) -> Cow<'a, B>;
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a,  B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
-    fn into_cow(self) -> Cow<'a, B> {
-        self
-    }
-}
index 7823f536c7a213a8f5f3b2b8e0c7a6a6fad81c73..8a3a1fcb9f387a8bc060a4f29eb0983a2ae9372c 100644 (file)
@@ -347,7 +347,7 @@ pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
             let result = stack.with(move |pusher, node| {
                 // Same basic logic as found in `find`, but with PartialSearchStack mediating the
                 // actual nodes for us
-                return match Node::search(node, &key) {
+                match Node::search(node, &key) {
                     Found(mut handle) => {
                         // Perfect match, swap the values and return the old one
                         mem::swap(handle.val_mut(), &mut value);
@@ -372,7 +372,7 @@ pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
                 }
             });
             match result {
-                Finished(ret) => { return ret; },
+                Finished(ret) => return ret,
                 Continue((new_stack, renewed_key, renewed_val)) => {
                     stack = new_stack;
                     key = renewed_key;
@@ -439,7 +439,7 @@ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where K: Borrow<Q>, Q:
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                return match Node::search(node, key) {
+                match Node::search(node, key) {
                     Found(handle) => {
                         // Perfect match. Terminate the stack here, and remove the entry
                         Finished(Some(pusher.seal(handle).remove()))
@@ -852,16 +852,6 @@ fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
     }
 }
 
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
-    fn hash(&self, state: &mut S) {
-        for elt in self {
-            elt.hash(state);
-        }
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -909,7 +899,7 @@ fn cmp(&self, other: &BTreeMap<K, V>) -> Ordering {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "BTreeMap {{"));
+        try!(write!(f, "{{"));
 
         for (i, (k, v)) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1291,7 +1281,7 @@ pub fn into_iter(self) -> IntoIter<K, V> {
     /// a.insert(2, "b");
     ///
     /// let keys: Vec<usize> = a.keys().cloned().collect();
-    /// assert_eq!(keys, vec![1,2,]);
+    /// assert_eq!(keys, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
@@ -1313,7 +1303,7 @@ fn first<A, B>((a, _): (A, B)) -> A { a }
     /// a.insert(2, "b");
     ///
     /// let values: Vec<&str> = a.values().cloned().collect();
-    /// assert_eq!(values, vec!["a","b"]);
+    /// assert_eq!(values, ["a", "b"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
@@ -1570,7 +1560,7 @@ pub fn entry(&mut self, mut key: K) -> Entry<K, V> {
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                return match Node::search(node, &key) {
+                match Node::search(node, &key) {
                     Found(handle) => {
                         // Perfect match
                         Finished(Occupied(OccupiedEntry {
index f0fc12da7275e000d814d796db75a0f58c2a48f2..4a80d75575e6db431b400987e05bf0b4c4d9d383 100644 (file)
@@ -1085,7 +1085,7 @@ pub fn into_iter(self) -> MoveTraversal<K, V> {
                     vals: RawItems::from_slice(self.vals()),
                     edges: RawItems::from_slice(self.edges()),
 
-                    ptr: *self.keys as *mut u8,
+                    ptr: Unique::new(*self.keys as *mut u8),
                     capacity: self.capacity(),
                     is_leaf: self.is_leaf()
                 },
@@ -1136,12 +1136,12 @@ unsafe fn push_edge(&mut self, edge: Node<K, V>) {
     // This must be followed by insert_edge on an internal node.
     #[inline]
     unsafe fn insert_kv(&mut self, index: usize, key: K, val: V) -> &mut V {
-        ptr::copy_memory(
+        ptr::copy(
             self.keys_mut().as_mut_ptr().offset(index as isize + 1),
             self.keys().as_ptr().offset(index as isize),
             self.len() - index
         );
-        ptr::copy_memory(
+        ptr::copy(
             self.vals_mut().as_mut_ptr().offset(index as isize + 1),
             self.vals().as_ptr().offset(index as isize),
             self.len() - index
@@ -1158,7 +1158,7 @@ unsafe fn insert_kv(&mut self, index: usize, key: K, val: V) -> &mut V {
     // This can only be called immediately after a call to insert_kv.
     #[inline]
     unsafe fn insert_edge(&mut self, index: usize, edge: Node<K, V>) {
-        ptr::copy_memory(
+        ptr::copy(
             self.edges_mut().as_mut_ptr().offset(index as isize + 1),
             self.edges().as_ptr().offset(index as isize),
             self.len() - index
@@ -1191,12 +1191,12 @@ unsafe fn remove_kv(&mut self, index: usize) -> (K, V) {
         let key = ptr::read(self.keys().get_unchecked(index));
         let val = ptr::read(self.vals().get_unchecked(index));
 
-        ptr::copy_memory(
+        ptr::copy(
             self.keys_mut().as_mut_ptr().offset(index as isize),
             self.keys().as_ptr().offset(index as isize + 1),
             self.len() - index - 1
         );
-        ptr::copy_memory(
+        ptr::copy(
             self.vals_mut().as_mut_ptr().offset(index as isize),
             self.vals().as_ptr().offset(index as isize + 1),
             self.len() - index - 1
@@ -1212,7 +1212,7 @@ unsafe fn remove_kv(&mut self, index: usize) -> (K, V) {
     unsafe fn remove_edge(&mut self, index: usize) -> Node<K, V> {
         let edge = ptr::read(self.edges().get_unchecked(index));
 
-        ptr::copy_memory(
+        ptr::copy(
             self.edges_mut().as_mut_ptr().offset(index as isize),
             self.edges().as_ptr().offset(index as isize + 1),
             self.len() - index + 1
@@ -1239,18 +1239,18 @@ fn split(&mut self) -> (K, V, Node<K, V>) {
         unsafe {
             right._len = self.len() / 2;
             let right_offset = self.len() - right.len();
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 right.keys_mut().as_mut_ptr(),
                 self.keys().as_ptr().offset(right_offset as isize),
                 right.len()
             );
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 right.vals_mut().as_mut_ptr(),
                 self.vals().as_ptr().offset(right_offset as isize),
                 right.len()
             );
             if !self.is_leaf() {
-                ptr::copy_nonoverlapping_memory(
+                ptr::copy_nonoverlapping(
                     right.edges_mut().as_mut_ptr(),
                     self.edges().as_ptr().offset(right_offset as isize),
                     right.len() + 1
@@ -1280,18 +1280,18 @@ fn absorb(&mut self, key: K, val: V, mut right: Node<K, V>) {
             ptr::write(self.keys_mut().get_unchecked_mut(old_len), key);
             ptr::write(self.vals_mut().get_unchecked_mut(old_len), val);
 
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 self.keys_mut().as_mut_ptr().offset(old_len as isize + 1),
                 right.keys().as_ptr(),
                 right.len()
             );
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 self.vals_mut().as_mut_ptr().offset(old_len as isize + 1),
                 right.vals().as_ptr(),
                 right.len()
             );
             if !self.is_leaf() {
-                ptr::copy_nonoverlapping_memory(
+                ptr::copy_nonoverlapping(
                     self.edges_mut().as_mut_ptr().offset(old_len as isize + 1),
                     right.edges().as_ptr(),
                     right.len() + 1
@@ -1354,11 +1354,14 @@ struct MoveTraversalImpl<K, V> {
     edges: RawItems<Node<K, V>>,
 
     // For deallocation when we are done iterating.
-    ptr: *mut u8,
+    ptr: Unique<u8>,
     capacity: usize,
     is_leaf: bool
 }
 
+unsafe impl<K: Sync, V: Sync> Sync for MoveTraversalImpl<K, V> {}
+unsafe impl<K: Send, V: Send> Send for MoveTraversalImpl<K, V> {}
+
 impl<K, V> TraversalImpl for MoveTraversalImpl<K, V> {
     type Item = (K, V);
     type Edge = Node<K, V>;
@@ -1401,7 +1404,7 @@ fn drop(&mut self) {
 
         let (alignment, size) =
                 calculate_allocation_generic::<K, V>(self.capacity, self.is_leaf);
-        unsafe { heap::deallocate(self.ptr, size, alignment) };
+        unsafe { heap::deallocate(*self.ptr, size, alignment) };
     }
 }
 
@@ -1425,12 +1428,12 @@ pub enum TraversalItem<K, V, E> {
 /// A traversal over a node's entries and edges
 pub type Traversal<'a, K, V> = AbsTraversal<ElemsAndEdges<Zip<slice::Iter<'a, K>,
                                                               slice::Iter<'a, V>>,
-                                                              slice::Iter<'a, Node<K, V>>>>;
+                                                          slice::Iter<'a, Node<K, V>>>>;
 
 /// A mutable traversal over a node's entries and edges
 pub type MutTraversal<'a, K, V> = AbsTraversal<ElemsAndEdges<Zip<slice::Iter<'a, K>,
                                                                  slice::IterMut<'a, V>>,
-                                                                 slice::IterMut<'a, Node<K, V>>>>;
+                                                             slice::IterMut<'a, Node<K, V>>>>;
 
 /// An owning traversal over a node's entries and edges
 pub type MoveTraversal<K, V> = AbsTraversal<MoveTraversalImpl<K, V>>;
index 929b2f58043035105097de82e38a1702575f2477..bc2e68b999a55e29ce02c218e60d3e7003e28da3 100644 (file)
@@ -121,7 +121,7 @@ impl<T> BTreeSet<T> {
     /// }
     ///
     /// let v: Vec<usize> = set.iter().cloned().collect();
-    /// assert_eq!(v, vec![1,2,3,4]);
+    /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
@@ -138,7 +138,7 @@ pub fn iter(&self) -> Iter<T> {
     /// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
     ///
     /// let v: Vec<usize> = set.into_iter().collect();
-    /// assert_eq!(v, vec![1,2,3,4]);
+    /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
@@ -197,7 +197,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(3);
     ///
     /// let diff: Vec<usize> = a.difference(&b).cloned().collect();
-    /// assert_eq!(diff, vec![1]);
+    /// assert_eq!(diff, [1]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
@@ -220,7 +220,7 @@ pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
     /// b.insert(3);
     ///
     /// let sym_diff: Vec<usize> = a.symmetric_difference(&b).cloned().collect();
-    /// assert_eq!(sym_diff, vec![1,3]);
+    /// assert_eq!(sym_diff, [1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
@@ -244,7 +244,7 @@ pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
     /// b.insert(3);
     ///
     /// let intersection: Vec<usize> = a.intersection(&b).cloned().collect();
-    /// assert_eq!(intersection, vec![2]);
+    /// assert_eq!(intersection, [2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
@@ -266,7 +266,7 @@ pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
     /// b.insert(2);
     ///
     /// let union: Vec<usize> = a.union(&b).cloned().collect();
-    /// assert_eq!(union, vec![1,2]);
+    /// assert_eq!(union, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
@@ -534,7 +534,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a - &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![1, 2]);
+    /// assert_eq!(result_vec, [1, 2]);
     /// ```
     fn sub(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.difference(rhs).cloned().collect()
@@ -557,7 +557,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a ^ &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![1, 4]);
+    /// assert_eq!(result_vec, [1, 4]);
     /// ```
     fn bitxor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.symmetric_difference(rhs).cloned().collect()
@@ -580,7 +580,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a & &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![2, 3]);
+    /// assert_eq!(result_vec, [2, 3]);
     /// ```
     fn bitand(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.intersection(rhs).cloned().collect()
@@ -603,7 +603,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a | &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![1, 2, 3, 4, 5]);
+    /// assert_eq!(result_vec, [1, 2, 3, 4, 5]);
     /// ```
     fn bitor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.union(rhs).cloned().collect()
@@ -613,7 +613,7 @@ fn bitor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for BTreeSet<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "BTreeSet {{"));
+        try!(write!(f, "{{"));
 
         for (i, x) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -911,7 +911,7 @@ fn test_show() {
 
         let set_str = format!("{:?}", set);
 
-        assert_eq!(set_str, "BTreeSet {1, 2}");
-        assert_eq!(format!("{:?}", empty), "BTreeSet {}");
+        assert_eq!(set_str, "{1, 2}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 }
index 0c95742606083fbe33402ca667d840ed620c406c..62dd91915211b85a37aa1295c52ffa6b4439e6b8 100644 (file)
@@ -36,7 +36,7 @@ impl<E> Copy for EnumSet<E> {}
 #[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 {
-        try!(write!(fmt, "EnumSet {{"));
+        try!(write!(fmt, "{{"));
         let mut first = true;
         for e in self {
             if !first {
@@ -314,11 +314,11 @@ fn test_new() {
     #[test]
     fn test_show() {
         let mut e = EnumSet::new();
-        assert!(format!("{:?}", e) == "EnumSet {}");
+        assert!(format!("{:?}", e) == "{}");
         e.insert(A);
-        assert!(format!("{:?}", e) == "EnumSet {A}");
+        assert!(format!("{:?}", e) == "{A}");
         e.insert(C);
-        assert!(format!("{:?}", e) == "EnumSet {A, C}");
+        assert!(format!("{:?}", e) == "{A, C}");
     }
 
     #[test]
@@ -428,19 +428,19 @@ fn test_iterator() {
 
         e1.insert(A);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A], elems);
+        assert_eq!([A], elems);
 
         e1.insert(C);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,C], elems);
+        assert_eq!([A,C], elems);
 
         e1.insert(C);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,C], elems);
+        assert_eq!([A,C], elems);
 
         e1.insert(B);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,B,C], elems);
+        assert_eq!([A,B,C], elems);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -458,35 +458,35 @@ fn test_operators() {
 
         let e_union = e1 | e2;
         let elems: ::vec::Vec<_> = e_union.iter().collect();
-        assert_eq!(vec![A,B,C], elems);
+        assert_eq!([A,B,C], elems);
 
         let e_intersection = e1 & e2;
         let elems: ::vec::Vec<_> = e_intersection.iter().collect();
-        assert_eq!(vec![C], elems);
+        assert_eq!([C], elems);
 
         // Another way to express intersection
         let e_intersection = e1 - (e1 - e2);
         let elems: ::vec::Vec<_> = e_intersection.iter().collect();
-        assert_eq!(vec![C], elems);
+        assert_eq!([C], elems);
 
         let e_subtract = e1 - e2;
         let elems: ::vec::Vec<_> = e_subtract.iter().collect();
-        assert_eq!(vec![A], elems);
+        assert_eq!([A], elems);
 
         // Bitwise XOR of two sets, aka symmetric difference
         let e_symmetric_diff = e1 ^ e2;
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems);
+        assert_eq!([A,B], elems);
 
         // Another way to express symmetric difference
         let e_symmetric_diff = (e1 - e2) | (e2 - e1);
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems);
+        assert_eq!([A,B], elems);
 
         // Yet another way to express symmetric difference
         let e_symmetric_diff = (e1 | e2) - (e1 & e2);
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems);
+        assert_eq!([A,B], elems);
     }
 
     #[test]
index 1b5018f4ad73df637c96ec9bd7bdb5ae2262f069..98673af3c68a84ab3b6e7b3a9cea8094ec8d2796 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 pub use core::fmt::{Formatter, Result, Write, rt};
-pub use core::fmt::{Show, String, Octal, Binary};
+pub use core::fmt::{Octal, Binary};
 pub use core::fmt::{Display, Debug};
 pub use core::fmt::{LowerHex, UpperHex, Pointer};
 pub use core::fmt::{LowerExp, UpperExp};
index 6569ab9c05acd768f56d4d4d5d9b9ddd32c65943..7b66bfee34f2121b15f4e06ae47e832ed4a7edcf 100644 (file)
@@ -30,6 +30,7 @@
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unsafe_destructor)]
+#![feature(unique)]
 #![feature(unsafe_no_drop_flag)]
 #![cfg_attr(test, feature(rand, rustc_private, test))]
 #![cfg_attr(test, allow(deprecated))] // rand
 pub mod binary_heap;
 mod bit;
 mod btree;
-pub mod linked_list;
+pub mod borrow;
 pub mod enum_set;
 pub mod fmt;
-pub mod vec_deque;
+pub mod linked_list;
 pub mod slice;
 pub mod str;
 pub mod string;
 pub mod vec;
+pub mod vec_deque;
 pub mod vec_map;
 
-#[cfg(stage0)]
-#[path = "borrow_stage0.rs"]
-pub mod borrow;
-
-#[cfg(not(stage0))]
-pub mod borrow;
-
 #[unstable(feature = "collections",
            reason = "RFC 509")]
 pub mod bit_vec {
index c142819a5189671bf8400aed0fe5c0fe357a48c6..9b5fbfc25114c046012f4f7e2e2748c004017146 100644 (file)
@@ -28,8 +28,6 @@
 use core::default::Default;
 use core::fmt;
 use core::hash::{Hasher, Hash};
-#[cfg(stage0)]
-use core::hash::Writer;
 use core::iter::{self, FromIterator, IntoIterator};
 use core::mem;
 use core::ptr;
@@ -53,8 +51,8 @@ struct Rawlink<T> {
 }
 
 impl<T> Copy for Rawlink<T> {}
-unsafe impl<T:'static+Send> Send for Rawlink<T> {}
-unsafe impl<T:Send+Sync> Sync for Rawlink<T> {}
+unsafe impl<T:Send> Send for Rawlink<T> {}
+unsafe impl<T:Sync> Sync for Rawlink<T> {}
 
 struct Node<T> {
     next: Link<T>,
@@ -779,7 +777,7 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// {
     ///     let vec: Vec<_> = list.into_iter().collect();
-    ///     assert_eq!(vec, vec![1, 2, 3, 4]);
+    ///     assert_eq!(vec, [1, 2, 3, 4]);
     /// }
     /// ```
     #[inline]
@@ -920,7 +918,7 @@ fn clone(&self) -> LinkedList<A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "LinkedList ["));
+        try!(write!(f, "["));
 
         for (i, e) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -932,17 +930,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(stage0)]
-impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for LinkedList<A> {
-    fn hash(&self, state: &mut S) {
-        self.len().hash(state);
-        for elt in self {
-            elt.hash(state);
-        }
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl<A: Hash> Hash for LinkedList<A> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.len().hash(state);
@@ -1286,7 +1273,7 @@ fn test_insert_prev() {
         }
         check_links(&m);
         assert_eq!(m.len(), 3 + len * 2);
-        assert_eq!(m.into_iter().collect::<Vec<_>>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]);
+        assert_eq!(m.into_iter().collect::<Vec<_>>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]);
     }
 
     #[test]
@@ -1400,10 +1387,10 @@ fn test_fuzz() {
     #[test]
     fn test_show() {
         let list: LinkedList<_> = (0..10).collect();
-        assert_eq!(format!("{:?}", list), "LinkedList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+        assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
 
         let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
-        assert_eq!(format!("{:?}", list), "LinkedList [\"just\", \"one\", \"test\", \"more\"]");
+        assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]");
     }
 
     #[cfg(test)]
index ebcfb8d1cf84e2a4d421e2fc000c2cf767e8e559..e9764547628c052cd22db69dbf5424e619881db4 100644 (file)
@@ -26,7 +26,7 @@
 ///
 /// ```
 /// let v = vec![1; 3];
-/// assert_eq!(v, vec![1, 1, 1]);
+/// assert_eq!(v, [1, 1, 1]);
 /// ```
 ///
 /// Note that unlike array expressions this syntax supports all elements
index 776b8b3af147c262b31fafccd74c9b376f070279..d4c53739686142cfa6ffb16dc7db15bd840a4a95 100644 (file)
@@ -790,7 +790,7 @@ fn binary_search_elem(&self, x: &Self::Item) -> Result<usize, usize> where Self:
     fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
     /// Convert `self` into a vector without clones or allocation.
-    #[unstable(feature = "collections")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
 }
 
@@ -1331,12 +1331,10 @@ fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> O
 
             if i != j {
                 let tmp = ptr::read(read_ptr);
-                ptr::copy_memory(buf_v.offset(j + 1),
-                                 &*buf_v.offset(j),
-                                 (i - j) as usize);
-                ptr::copy_nonoverlapping_memory(buf_v.offset(j),
-                                                &tmp,
-                                                1);
+                ptr::copy(buf_v.offset(j + 1),
+                          &*buf_v.offset(j),
+                          (i - j) as usize);
+                ptr::copy_nonoverlapping(buf_v.offset(j), &tmp, 1);
                 mem::forget(tmp);
             }
         }
@@ -1409,10 +1407,10 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
                 // j + 1 could be `len` (for the last `i`), but in
                 // that case, `i == j` so we don't copy. The
                 // `.offset(j)` is always in bounds.
-                ptr::copy_memory(buf_dat.offset(j + 1),
-                                 &*buf_dat.offset(j),
-                                 i - j as usize);
-                ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
+                ptr::copy(buf_dat.offset(j + 1),
+                          &*buf_dat.offset(j),
+                          i - j as usize);
+                ptr::copy_nonoverlapping(buf_dat.offset(j), read_ptr, 1);
             }
         }
     }
@@ -1460,11 +1458,11 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
                     if left == right_start {
                         // the number remaining in this run.
                         let elems = (right_end as usize - right as usize) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*right, elems);
+                        ptr::copy_nonoverlapping(out, &*right, elems);
                         break;
                     } else if right == right_end {
                         let elems = (right_start as usize - left as usize) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*left, elems);
+                        ptr::copy_nonoverlapping(out, &*left, elems);
                         break;
                     }
 
@@ -1478,7 +1476,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
                     } else {
                         step(&mut left)
                     };
-                    ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
+                    ptr::copy_nonoverlapping(out, &*to_copy, 1);
                     step(&mut out);
                 }
             }
@@ -1492,7 +1490,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
     // write the result to `v` in one go, so that there are never two copies
     // of the same object in `v`.
     unsafe {
-        ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
+        ptr::copy_nonoverlapping(v.as_mut_ptr(), &*buf_dat, len);
     }
 
     // increment the pointer, returning the old pointer.
@@ -1779,10 +1777,10 @@ fn test_swap_remove() {
         let mut v = vec![1, 2, 3, 4, 5];
         let mut e = v.swap_remove(0);
         assert_eq!(e, 1);
-        assert_eq!(v, vec![5, 2, 3, 4]);
+        assert_eq!(v, [5, 2, 3, 4]);
         e = v.swap_remove(3);
         assert_eq!(e, 4);
-        assert_eq!(v, vec![5, 2, 3]);
+        assert_eq!(v, [5, 2, 3]);
     }
 
     #[test]
@@ -1890,7 +1888,7 @@ fn test_dedup_shared() {
     fn test_retain() {
         let mut v = vec![1, 2, 3, 4, 5];
         v.retain(is_odd);
-        assert_eq!(v, vec![1, 3, 5]);
+        assert_eq!(v, [1, 3, 5]);
     }
 
     #[test]
@@ -2159,45 +2157,45 @@ fn test_concat() {
         let v: [Vec<i32>; 0] = [];
         let c = v.concat();
         assert_eq!(c, []);
-        let d = [vec![1], vec![2,3]].concat();
-        assert_eq!(d, vec![1, 2, 3]);
+        let d = [vec![1], vec![2, 3]].concat();
+        assert_eq!(d, [1, 2, 3]);
 
         let v: &[&[_]] = &[&[1], &[2, 3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 3]);
         let v: &[&[_]] = &[&[1], &[2], &[3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
     }
 
     #[test]
     fn test_connect() {
         let v: [Vec<i32>; 0] = [];
-        assert_eq!(v.connect(&0), vec![]);
-        assert_eq!([vec![1], vec![2, 3]].connect(&0), vec![1, 0, 2, 3]);
-        assert_eq!([vec![1], vec![2], vec![3]].connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect(&0), []);
+        assert_eq!([vec![1i], vec![2, 3]].connect(&0), [1, 0, 2, 3]);
+        assert_eq!([vec![1i], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]);
 
         let v: [&[_]; 2] = [&[1], &[2, 3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 3]);
         let v: [&[_]; 3] = [&[1], &[2], &[3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
     }
 
     #[test]
     fn test_insert() {
         let mut a = vec![1, 2, 4];
         a.insert(2, 3);
-        assert_eq!(a, vec![1, 2, 3, 4]);
+        assert_eq!(a, [1, 2, 3, 4]);
 
         let mut a = vec![1, 2, 3];
         a.insert(0, 0);
-        assert_eq!(a, vec![0, 1, 2, 3]);
+        assert_eq!(a, [0, 1, 2, 3]);
 
         let mut a = vec![1, 2, 3];
         a.insert(3, 4);
-        assert_eq!(a, vec![1, 2, 3, 4]);
+        assert_eq!(a, [1, 2, 3, 4]);
 
         let mut a = vec![];
         a.insert(0, 1);
-        assert_eq!(a, vec![1]);
+        assert_eq!(a, [1]);
     }
 
     #[test]
@@ -2212,16 +2210,16 @@ fn test_remove() {
         let mut a = vec![1, 2, 3, 4];
 
         assert_eq!(a.remove(2), 3);
-        assert_eq!(a, vec![1, 2, 4]);
+        assert_eq!(a, [1, 2, 4]);
 
         assert_eq!(a.remove(2), 4);
-        assert_eq!(a, vec![1, 2]);
+        assert_eq!(a, [1, 2]);
 
         assert_eq!(a.remove(0), 1);
-        assert_eq!(a, vec![2]);
+        assert_eq!(a, [2]);
 
         assert_eq!(a.remove(0), 2);
-        assert_eq!(a, vec![]);
+        assert_eq!(a, []);
     }
 
     #[test]
index ec0a487acdc77c734c2ae207624c869e95708e25..c58cca828d8c39a04c9fc542aa7b0ff3ec54a8ad 100644 (file)
 //
 // ignore-lexer-test FIXME #15679
 
-//! Unicode string manipulation (`str` type)
+//! Unicode string manipulation (the `str` type).
 //!
-//! # Basic Usage
+//! 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
+//! string (see below). As the word "borrowed" implies, this type of string is owned elsewhere, and
+//! this string cannot be moved out of.
 //!
-//! Rust's string type is one of the core primitive types of the language. While
-//! represented by the name `str`, the name `str` is not actually a valid type in
-//! Rust. Each string must also be decorated with a pointer. `String` is used
-//! for an owned string, so there is only one commonly-used `str` type in Rust:
-//! `&str`.
+//! # Examples
 //!
-//! `&str` is the borrowed string type. This type of string can only be created
-//! from other strings, unless it is a static string (see below). As the word
-//! "borrowed" implies, this type of string is owned elsewhere, and this string
-//! cannot be moved out of.
+//! Here's some code that uses a `&str`:
 //!
-//! As an example, here's some code that uses a string.
-//!
-//! ```rust
-//! fn main() {
-//!     let borrowed_string = "This string is borrowed with the 'static lifetime";
-//! }
 //! ```
+//! let s = "Hello, world.";
+//! ```
+//!
+//! This `&str` is a `&'static str`, which is the type of string literals. They're `'static`
+//! because literals are available for the entire lifetime of the program.
 //!
-//! From the example above, you can guess that Rust's string literals have the
-//! `'static` lifetime. This is akin to C's concept of a static string.
-//! More precisely, string literals are immutable views with a 'static lifetime
-//! (otherwise known as the lifetime of the entire program), and thus have the
-//! type `&'static str`.
+//! You can get a non-`'static` `&str` by taking a slice of a `String`:
+//!
+//! ```
+//! # let some_string = "Hello, world.".to_string();
+//! let s = &some_string;
+//! ```
 //!
 //! # Representation
 //!
-//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a
-//! stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
-//! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
-//! not null-terminated and can thus contain null bytes.
+//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as a stream of UTF-8
+//! bytes. All [strings](../../reference.html#literals) are guaranteed to be validly encoded UTF-8
+//! sequences. Additionally, strings are not null-terminated and can thus contain null bytes.
 //!
-//! The actual representation of strings have direct mappings to slices: `&str`
-//! is the same as `&[u8]`.
+//! The actual representation of `str`s have direct mappings to slices: `&str` is the same as
+//! `&[u8]`.
 
 #![doc(primitive = "str")]
 #![stable(feature = "rust1", since = "1.0.0")]
@@ -82,6 +77,8 @@
 pub use core::str::{from_utf8, CharEq, Chars, CharIndices, Bytes};
 pub use core::str::{from_utf8_unchecked, from_c_str, ParseBoolError};
 pub use unicode::str::{Words, Graphemes, GraphemeIndices};
+pub use core::str::Pattern;
+pub use core::str::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep};
 
 /*
 Section: Creating a string
@@ -164,8 +161,9 @@ enum DecompositionType {
     Compatible
 }
 
-/// External iterator for a string's decomposition's characters.
-/// Use with the `std::iter` module.
+/// External iterator for a string decomposition's characters.
+///
+/// For use with the `std::iter` module.
 #[derive(Clone)]
 #[unstable(feature = "collections")]
 pub struct Decompositions<'a> {
@@ -254,8 +252,9 @@ enum RecompositionState {
     Finished
 }
 
-/// External iterator for a string's recomposition's characters.
-/// Use with the `std::iter` module.
+/// External iterator for a string recomposition's characters.
+///
+/// For use with the `std::iter` module.
 #[derive(Clone)]
 #[unstable(feature = "collections")]
 pub struct Recompositions<'a> {
@@ -352,7 +351,8 @@ fn next(&mut self) -> Option<char> {
 }
 
 /// External iterator for a string's UTF16 codeunits.
-/// Use with the `std::iter` module.
+///
+/// For use with the `std::iter` module.
 #[derive(Clone)]
 #[unstable(feature = "collections")]
 pub struct Utf16Units<'a> {
@@ -428,23 +428,21 @@ fn escape_unicode(&self) -> String {
 
     /// Replaces all occurrences of one string with another.
     ///
-    /// # Arguments
-    ///
-    /// * `from` - The string to replace
-    /// * `to` - The replacement string
-    ///
-    /// # Return value
-    ///
-    /// The original string with all occurrences of `from` replaced with `to`.
+    /// `replace` takes two arguments, a sub-`&str` to find in `self`, and a second `&str` to
+    /// replace it with. If the original `&str` isn't found, no change occurs.
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let s = "this is old";
     ///
     /// assert_eq!(s.replace("old", "new"), "this is new");
+    /// ```
     ///
-    /// // not found, so no change.
+    /// When a `&str` isn't found:
+    ///
+    /// ```
+    /// let s = "this is old";
     /// assert_eq!(s.replace("cookie monster", "little lamb"), s);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -518,59 +516,56 @@ fn nfkc_chars(&self) -> Recompositions {
         }
     }
 
-    /// Returns true if a string contains a string pattern.
+    /// Returns `true` if `self` contains another `&str`.
     ///
-    /// # Arguments
-    ///
-    /// - pat - The string pattern to look for
-    ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// assert!("bananas".contains("nana"));
+    ///
+    /// assert!(!"bananas".contains("foobar"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn contains(&self, pat: &str) -> bool {
+    fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
         core_str::StrExt::contains(&self[..], pat)
     }
 
-    /// Returns true if a string contains a char pattern.
-    ///
-    /// # Arguments
+    /// Returns `true` if `self` contains a `char`.
     ///
-    /// - pat - The char pattern to look for
-    ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// assert!("hello".contains_char('e'));
+    ///
+    /// assert!(!"hello".contains_char('z'));
     /// ```
-    #[unstable(feature = "collections",
-               reason = "might get removed in favour of a more generic contains()")]
-    fn contains_char<P: CharEq>(&self, pat: P) -> bool {
+    #[unstable(feature = "collections")]
+    #[deprecated(since = "1.0.0", reason = "use `contains()` with a char")]
+    fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
         core_str::StrExt::contains_char(&self[..], pat)
     }
 
-    /// An iterator over the characters of `self`. Note, this iterates
-    /// over Unicode code-points, not Unicode graphemes.
+    /// An iterator over the codepoints of `self`.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let v: Vec<char> = "abc åäö".chars().collect();
-    /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
+    ///
+    /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn chars(&self) -> Chars {
         core_str::StrExt::chars(&self[..])
     }
 
-    /// An iterator over the bytes of `self`
+    /// An iterator over the bytes of `self`.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let v: Vec<u8> = "bors".bytes().collect();
+    ///
     /// assert_eq!(v, b"bors".to_vec());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -579,180 +574,238 @@ fn bytes(&self) -> Bytes {
     }
 
     /// An iterator over the characters of `self` and their byte offsets.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let v: Vec<(usize, char)> = "abc".char_indices().collect();
+    /// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')];
+    ///
+    /// assert_eq!(v, b);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn char_indices(&self) -> CharIndices {
         core_str::StrExt::char_indices(&self[..])
     }
 
     /// An iterator over substrings of `self`, separated by characters
-    /// matched by the pattern `pat`.
+    /// matched by a pattern.
     ///
-    /// # Example
+    /// The pattern can be a simple `&str`, or a closure that determines
+    /// the split.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// Simple `&str` patterns:
+    ///
+    /// ```
     /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
-    /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
     ///
+    /// let v: Vec<&str> = "".split('X').collect();
+    /// assert_eq!(v, [""]);
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
     /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["abc", "def", "ghi"]);
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
-    /// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]);
-    ///
-    /// let v: Vec<&str> = "".split('X').collect();
-    /// assert_eq!(v, vec![""]);
+    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn split<P: CharEq>(&self, pat: P) -> Split<P> {
+    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 the pattern `pat`, restricted to splitting at most `count`
-    /// times.
+    /// An iterator over substrings of `self`, separated by characters matched by a pattern,
+    /// restricted to splitting at most `count` times.
     ///
-    /// # Example
+    /// The pattern can be a simple `&str`, or a closure that determines
+    /// the split.
     ///
-    /// ```rust
-    /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
-    /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]);
+    /// # Examples
     ///
-    /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["abc", "def2ghi"]);
+    /// Simple `&str` patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
+    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
-    /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]);
+    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
     ///
     /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
-    /// assert_eq!(v, vec!["abcXdef"]);
+    /// assert_eq!(v, ["abcXdef"]);
     ///
     /// let v: Vec<&str> = "".splitn(1, 'X').collect();
-    /// assert_eq!(v, vec![""]);
+    /// assert_eq!(v, [""]);
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect();
+    /// assert_eq!(v, ["abc", "def2ghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn splitn<P: CharEq>(&self, count: usize, pat: P) -> SplitN<P> {
+    fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
         core_str::StrExt::splitn(&self[..], count, pat)
     }
 
     /// An iterator over substrings of `self`, separated by characters
-    /// matched by the pattern `pat`.
+    /// matched by a pattern.
     ///
-    /// Equivalent to `split`, except that the trailing substring
-    /// is skipped if empty (terminator semantics).
+    /// Equivalent to `split`, except that the trailing substring is skipped if empty.
     ///
-    /// # Example
+    /// The pattern can be a simple `&str`, or a closure that determines
+    /// the split.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// Simple `&str` patterns:
+    ///
+    /// ```
     /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
-    /// assert_eq!(v, vec!["A", "B"]);
+    /// assert_eq!(v, ["A", "B"]);
     ///
     /// let v: Vec<&str> = "A..B..".split_terminator('.').collect();
-    /// assert_eq!(v, vec!["A", "", "B", ""]);
-    ///
-    /// let v: Vec<&str> = "Mary had a little lamb".split(' ').rev().collect();
-    /// assert_eq!(v, vec!["lamb", "little", "a", "had", "Mary"]);
+    /// assert_eq!(v, ["A", "", "B", ""]);
+    /// ```
     ///
-    /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).rev().collect();
-    /// assert_eq!(v, vec!["ghi", "def", "abc"]);
+    /// More complex patterns with a lambda:
     ///
-    /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect();
-    /// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]);
     /// ```
-    #[unstable(feature = "collections", reason = "might get removed")]
-    fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
+    /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect();
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
+    /// ```
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
         core_str::StrExt::split_terminator(&self[..], pat)
     }
 
-    /// An iterator over substrings of `self`, separated by characters
-    /// matched by the pattern `pat`, starting from the end of the string.
+    /// An iterator over substrings of `self`, separated by characters matched by a pattern,
+    /// starting from the end of the string.
+    ///
     /// Restricted to splitting at most `count` times.
     ///
-    /// # Example
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// ```rust
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
-    /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]);
+    /// # Examples
     ///
-    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["ghi", "abc1def"]);
+    /// Simple `&str` patterns:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
+    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
-    /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
+    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect();
+    /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn rsplitn<P: CharEq>(&self, count: usize, pat: P) -> RSplitN<P> {
+    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> {
         core_str::StrExt::rsplitn(&self[..], count, pat)
     }
 
-    /// An iterator over the start and end indices of the disjoint
-    /// matches of the pattern `pat` within `self`.
+    /// An iterator over the start and end indices of the disjoint matches of a `&str` within
+    /// `self`.
     ///
-    /// That is, each returned value `(start, end)` satisfies
-    /// `self.slice(start, end) == sep`. For matches of `sep` within
-    /// `self` that overlap, only the indices corresponding to the
-    /// first match are returned.
+    /// That is, each returned value `(start, end)` satisfies `self.slice(start, end) == sep`. For
+    /// matches of `sep` within `self` that overlap, only the indices corresponding to the first
+    /// match are returned.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
-    /// assert_eq!(v, vec![(0,3), (6,9), (12,15)]);
+    /// assert_eq!(v, [(0,3), (6,9), (12,15)]);
     ///
     /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
-    /// assert_eq!(v, vec![(1,4), (4,7)]);
+    /// assert_eq!(v, [(1,4), (4,7)]);
     ///
     /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
-    /// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
+    /// assert_eq!(v, [(0, 3)]); // only the first `aba`
     /// ```
     #[unstable(feature = "collections",
                reason = "might have its iterator type changed")]
-    fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> {
+    // NB: Right now MatchIndices yields `(usize, usize)`,
+    // but it would be more consistent and useful to return `(usize, &str)`
+    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 the pattern `sep`.
+    /// An iterator over the substrings of `self` separated by a `&str`.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect();
-    /// assert_eq!(v, vec!["", "XXX", "YYY", ""]);
+    /// assert_eq!(v, ["", "XXX", "YYY", ""]);
     ///
     /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
-    /// assert_eq!(v, vec!["1", "", "2"]);
+    /// assert_eq!(v, ["1", "", "2"]);
     /// ```
-    #[unstable(feature = "collections",
-               reason = "might get removed in the future in favor of a more generic split()")]
-    fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a> {
+    #[unstable(feature = "collections")]
+    #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")]
+    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 (subsequences separated
-    /// by `\n`). This does not include the empty string after a
-    /// trailing `\n`.
+    /// An iterator over the lines of a string, separated by `\n`.
     ///
-    /// # Example
+    /// This does not include the empty string after a trailing `\n`.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// ```
+    /// let four_lines = "foo\nbar\n\nbaz";
+    /// let v: Vec<&str> = four_lines.lines().collect();
+    ///
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
+    /// ```
+    ///
+    /// Leaving off the trailing character:
+    ///
+    /// ```
     /// let four_lines = "foo\nbar\n\nbaz\n";
     /// let v: Vec<&str> = four_lines.lines().collect();
-    /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
+    ///
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines(&self) -> Lines {
         core_str::StrExt::lines(&self[..])
     }
 
-    /// An iterator over the lines of a string, separated by either
-    /// `\n` or `\r\n`. As with `.lines()`, this does not include an
-    /// empty trailing line.
+    /// An iterator over the lines of a string, separated by either `\n` or `\r\n`.
     ///
-    /// # Example
+    /// As with `.lines()`, this does not include an empty trailing line.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// ```
+    /// let four_lines = "foo\r\nbar\n\r\nbaz";
+    /// let v: Vec<&str> = four_lines.lines_any().collect();
+    ///
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
+    /// ```
+    ///
+    /// Leaving off the trailing character:
+    ///
+    /// ```
     /// let four_lines = "foo\r\nbar\n\r\nbaz\n";
     /// let v: Vec<&str> = four_lines.lines_any().collect();
-    /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
+    ///
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines_any(&self) -> LinesAny {
@@ -777,26 +830,25 @@ fn lines_any(&self) -> LinesAny {
     #[deprecated(since = "1.0.0", reason = "use slice notation [..a] instead")]
     fn slice_to(&self, end: usize) -> &str;
 
-    /// Returns a slice of the string from the character range
-    /// [`begin`..`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 to the `end`-th code point. This does not detect or
-    /// handle edge cases such as leaving a combining character as the
-    /// first code point of the string.
+    /// That is, start at the `begin`-th code point of the string and continue to the `end`-th code
+    /// point. This does not detect or handle edge cases such as leaving a combining character as
+    /// the first code point of the string.
     ///
-    /// Due to the design of UTF-8, this operation is `O(end)`.
-    /// See `slice`, `slice_to` and `slice_from` for `O(1)`
-    /// variants that use byte indices rather than code point
-    /// indices.
+    /// Due to the design of UTF-8, this operation is `O(end)`. See `slice`, `slice_to` and
+    /// `slice_from` for `O(1)` variants that use byte indices rather than code point indices.
     ///
-    /// Panics if `begin` > `end` or the either `begin` or `end` are
-    /// beyond the last character of the string.
+    /// # Panics
     ///
-    /// # Example
+    /// Panics if `begin` > `end` or the either `begin` or `end` are beyond the last character of
+    /// the string.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// ```
     /// let s = "Löwe 老虎 Léopard";
+    ///
     /// assert_eq!(s.slice_chars(0, 4), "Löwe");
     /// assert_eq!(s.slice_chars(5, 7), "老虎");
     /// ```
@@ -806,112 +858,145 @@ fn slice_chars(&self, begin: usize, end: usize) -> &str {
         core_str::StrExt::slice_chars(&self[..], begin, end)
     }
 
-    /// Takes a bytewise (not UTF-8) slice from a string.
+    /// Takes a bytewise slice from a string.
     ///
     /// Returns the substring from [`begin`..`end`).
     ///
-    /// Caller must check both UTF-8 character boundaries and the boundaries of
-    /// the entire slice as well.
+    /// # Unsafety
+    ///
+    /// Caller must check both UTF-8 character boundaries and the boundaries of the entire slice as
+    /// well.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
+    /// unsafe {
+    ///     assert_eq!(s.slice_unchecked(0, 21), "Löwe 老虎 Léopard");
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
         core_str::StrExt::slice_unchecked(&self[..], begin, end)
     }
 
-    /// Returns true if the pattern `pat` is a prefix of the string.
+    /// Returns `true` if the given `&str` is a prefix of the string.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// assert!("banana".starts_with("ba"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn starts_with(&self, pat: &str) -> bool {
+    fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
         core_str::StrExt::starts_with(&self[..], pat)
     }
 
-    /// Returns true if the pattern `pat` is a suffix of the string.
+    /// Returns true if the given `&str` is a suffix of the string.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```rust
     /// assert!("banana".ends_with("nana"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn ends_with(&self, pat: &str) -> bool {
+    fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
+        where P::Searcher: ReverseSearcher<'a>
+    {
         core_str::StrExt::ends_with(&self[..], pat)
     }
 
-    /// Returns a string with all pre- and suffixes that match
-    /// the pattern `pat` repeatedly removed.
+    /// Returns a string with all pre- and suffixes that match a pattern repeatedly removed.
     ///
-    /// # Arguments
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// * pat - a string pattern
+    /// # Examples
     ///
-    /// # Example
+    /// Simple `&str` patterns:
     ///
-    /// ```rust
+    /// ```
     /// assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
+    ///
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!("12foo1bar12".trim_matches(x), "foo1bar");
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
     /// assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn trim_matches<P: CharEq>(&self, pat: P) -> &str {
+    fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: DoubleEndedSearcher<'a>
+    {
         core_str::StrExt::trim_matches(&self[..], pat)
     }
 
-    /// Returns a string with all prefixes that match
-    /// the pattern `pat` repeatedly removed.
+    /// Returns a string with all prefixes that match a pattern repeatedly removed.
     ///
-    /// # Arguments
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// * pat - a string pattern
+    /// # Examples
     ///
-    /// # Example
+    /// Simple `&str` patterns:
     ///
-    /// ```rust
+    /// ```
     /// assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
+    ///
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
     /// assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn trim_left_matches<P: CharEq>(&self, pat: P) -> &str {
+    fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
         core_str::StrExt::trim_left_matches(&self[..], pat)
     }
 
-    /// Returns a string with all suffixes that match
-    /// the pattern `pat` repeatedly removed.
+    /// Returns a string with all suffixes that match a pattern repeatedly removed.
     ///
-    /// # Arguments
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// * pat - a string pattern
+    /// # Examples
     ///
-    /// # Example
+    /// Simple `&str` patterns:
     ///
-    /// ```rust
+    /// ```
     /// assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
     /// let x: &[_] = &['1', '2'];
     /// assert_eq!("12foo1bar12".trim_right_matches(x), "12foo1bar");
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
     /// assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn trim_right_matches<P: CharEq>(&self, pat: P) -> &str {
+    fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>
+    {
         core_str::StrExt::trim_right_matches(&self[..], pat)
     }
 
-    /// Check that `index`-th byte lies at the start and/or end of a
-    /// UTF-8 code point sequence.
+    /// Check that `index`-th byte lies at the start and/or end of a UTF-8 code point sequence.
     ///
-    /// The start and end of the string (when `index == self.len()`)
-    /// are considered to be boundaries.
+    /// The start and end of the string (when `index == self.len()`) are considered to be
+    /// boundaries.
+    ///
+    /// # Panics
     ///
     /// Panics if `index` is greater than `self.len()`.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let s = "Löwe 老虎 Léopard";
     /// assert!(s.is_char_boundary(0));
     /// // start of `老`
@@ -930,19 +1015,21 @@ fn is_char_boundary(&self, index: usize) -> bool {
         core_str::StrExt::is_char_boundary(&self[..], index)
     }
 
-    /// Pluck a character out of a string and return the index of the next
-    /// character.
+    /// Given a byte position, return the next char and its index.
     ///
-    /// This function can be used to iterate over the Unicode characters of a
-    /// string.
+    /// This can be used to iterate over the Unicode characters of a string.
     ///
-    /// # Example
+    /// # Panics
     ///
-    /// This example manually iterates through the characters of a
-    /// string; this should normally be done by `.chars()` or
-    /// `.char_indices`.
+    /// If `i` is greater than or equal to the length of the string.
+    /// If `i` is not the index of the beginning of a valid UTF-8 character.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// This example manually iterates through the characters of a string; this should normally be
+    /// done by `.chars()` or `.char_indices()`.
+    ///
+    /// ```
     /// use std::str::CharRange;
     ///
     /// let s = "中华Việt Nam";
@@ -968,28 +1055,13 @@ fn is_char_boundary(&self, index: usize) -> bool {
     /// 14: a
     /// 15: m
     /// ```
-    ///
-    /// # Arguments
-    ///
-    /// * s - The string
-    /// * i - The byte offset of the char to extract
-    ///
-    /// # Return value
-    ///
-    /// A record {ch: char, next: usize} containing the char value and the byte
-    /// index of the next Unicode character.
-    ///
-    /// # Panics
-    ///
-    /// If `i` is greater than or equal to the length of the string.
-    /// If `i` is not the index of the beginning of a valid UTF-8 character.
     #[unstable(feature = "collections",
                reason = "naming is uncertain with container conventions")]
     fn char_range_at(&self, start: usize) -> CharRange {
         core_str::StrExt::char_range_at(&self[..], start)
     }
 
-    /// Given a byte position and a str, return the previous char and its position.
+    /// Given a byte position, return the previous `char` and its position.
     ///
     /// This function can be used to iterate over a Unicode string in reverse.
     ///
@@ -999,50 +1071,89 @@ fn char_range_at(&self, start: usize) -> CharRange {
     ///
     /// If `i` is greater than the length of the string.
     /// If `i` is not an index following a valid UTF-8 character.
+    ///
+    /// # Examples
+    ///
+    /// This example manually iterates through the characters of a string; this should normally be
+    /// done by `.chars().rev()` or `.char_indices()`.
+    ///
+    /// ```
+    /// use std::str::CharRange;
+    ///
+    /// let s = "中华Việt Nam";
+    /// let mut i = s.len();
+    /// while i < 0 {
+    ///     let CharRange {ch, next} = s.char_range_at_reverse(i);
+    ///     println!("{}: {}", i, ch);
+    ///     i = next;
+    /// }
+    /// ```
+    ///
+    /// This outputs:
+    ///
+    /// ```text
+    /// 16: m
+    /// 15: a
+    /// 14: N
+    /// 13:
+    /// 12: t
+    /// 11: ệ
+    /// 8: i
+    /// 7: V
+    /// 6: 华
+    /// 3: 中
+    /// ```
     #[unstable(feature = "collections",
                reason = "naming is uncertain with container conventions")]
     fn char_range_at_reverse(&self, start: usize) -> CharRange {
         core_str::StrExt::char_range_at_reverse(&self[..], start)
     }
 
-    /// Plucks the character starting at the `i`th byte of a string.
+    /// Given a byte position, return the `char` at that position.
     ///
-    /// # Example
+    /// # Panics
     ///
-    /// ```rust
+    /// If `i` is greater than or equal to the length of the string.
+    /// If `i` is not the index of the beginning of a valid UTF-8 character.
+    ///
+    /// # Examples
+    ///
+    /// ```
     /// let s = "abπc";
     /// assert_eq!(s.char_at(1), 'b');
     /// assert_eq!(s.char_at(2), 'π');
-    /// assert_eq!(s.char_at(4), 'c');
     /// ```
-    ///
-    /// # Panics
-    ///
-    /// If `i` is greater than or equal to the length of the string.
-    /// If `i` is not the index of the beginning of a valid UTF-8 character.
     #[unstable(feature = "collections",
                reason = "naming is uncertain with container conventions")]
     fn char_at(&self, i: usize) -> char {
         core_str::StrExt::char_at(&self[..], i)
     }
 
-    /// Plucks the character ending at the `i`th byte of a string.
+    /// Given a byte position, return the `char` at that position, counting from the end.
     ///
     /// # Panics
     ///
     /// If `i` is greater than the length of the string.
     /// If `i` is not an index following a valid UTF-8 character.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = "abπc";
+    /// assert_eq!(s.char_at_reverse(1), 'a');
+    /// assert_eq!(s.char_at_reverse(2), 'b');
+    /// ```
     #[unstable(feature = "collections",
                reason = "naming is uncertain with container conventions")]
     fn char_at_reverse(&self, i: usize) -> char {
         core_str::StrExt::char_at_reverse(&self[..], i)
     }
 
-    /// Work with the byte buffer of a string as a byte slice.
+    /// Convert `self` to a byte slice.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// assert_eq!("bors".as_bytes(), b"bors");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -1050,102 +1161,125 @@ fn as_bytes(&self) -> &[u8] {
         core_str::StrExt::as_bytes(&self[..])
     }
 
-    /// Returns the byte index of the first character of `self` that
-    /// matches the pattern `pat`.
+    /// Returns the byte index of the first character of `self` that matches the pattern, if it
+    /// exists.
     ///
-    /// # Return value
+    /// Returns `None` if it doesn't exist.
     ///
-    /// `Some` containing the byte index of the last matching character
-    /// or `None` if there is no match
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// Simple `&str` patterns:
+    ///
+    /// ```
     /// let s = "Löwe 老虎 Léopard";
     ///
     /// assert_eq!(s.find('L'), Some(0));
     /// assert_eq!(s.find('é'), Some(14));
     ///
-    /// // the first space
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
+    ///
     /// assert_eq!(s.find(|c: char| c.is_whitespace()), Some(5));
+    /// ```
     ///
-    /// // neither are found
+    /// Not finding the pattern:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
     /// let x: &[_] = &['1', '2'];
+    ///
     /// assert_eq!(s.find(x), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn find<P: CharEq>(&self, pat: P) -> Option<usize> {
+    fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
         core_str::StrExt::find(&self[..], pat)
     }
 
-    /// Returns the byte index of the last character of `self` that
-    /// matches the pattern `pat`.
+    /// Returns the byte index of the last character of `self` that matches the pattern, if it
+    /// exists.
     ///
-    /// # Return value
+    /// Returns `None` if it doesn't exist.
     ///
-    /// `Some` containing the byte index of the last matching character
-    /// or `None` if there is no match.
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// Simple `&str` patterns:
+    ///
+    /// ```
     /// let s = "Löwe 老虎 Léopard";
     ///
     /// assert_eq!(s.rfind('L'), Some(13));
     /// assert_eq!(s.rfind('é'), Some(14));
+    /// ```
+    ///
+    /// More complex patterns with a lambda:
+    ///
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
     ///
-    /// // the second space
     /// assert_eq!(s.rfind(|c: char| c.is_whitespace()), Some(12));
+    /// ```
+    ///
+    /// Not finding the pattern:
     ///
-    /// // searches for an occurrence of either `1` or `2`, but neither are found
+    /// ```
+    /// let s = "Löwe 老虎 Léopard";
     /// let x: &[_] = &['1', '2'];
+    ///
     /// assert_eq!(s.rfind(x), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn rfind<P: CharEq>(&self, pat: P) -> Option<usize> {
+    fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
+        where P::Searcher: ReverseSearcher<'a>
+    {
         core_str::StrExt::rfind(&self[..], pat)
     }
 
-    /// Returns the byte index of the first matching substring
+    /// Returns the byte index of the first matching substring if it exists.
     ///
-    /// # Arguments
+    /// Returns `None` if it doesn't exist.
     ///
-    /// * `needle` - The string to search for
+    /// The pattern can be a simple `&str`, or a closure that determines the split.
     ///
-    /// # Return value
-    ///
-    /// `Some` containing the byte index of the first matching substring
-    /// or `None` if there is no match.
-    ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// 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",
-               reason = "might get removed in favor of a more generic find in the future")]
-    fn find_str(&self, needle: &str) -> Option<usize> {
+    #[unstable(feature = "collections")]
+    #[deprecated(since = "1.0.0", reason = "use `find()` with a `&str`")]
+    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 string slice and returns
-    /// it. This does not allocate a new string; instead, it returns a
-    /// slice that point one character beyond the character that was
-    /// shifted. If the string does not contain any characters,
-    /// None is returned instead.
+    /// Retrieves the first character from a `&str` and returns it.
     ///
-    /// # Example
+    /// This does not allocate a new string; instead, it returns a slice that points one character
+    /// beyond the character that was shifted.
     ///
-    /// ```rust
+    /// If the slice does not contain any characters, None is returned instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
     /// let s = "Löwe 老虎 Léopard";
     /// let (c, s1) = s.slice_shift_char().unwrap();
+    ///
     /// assert_eq!(c, 'L');
     /// assert_eq!(s1, "öwe 老虎 Léopard");
     ///
     /// let (c, s2) = s1.slice_shift_char().unwrap();
+    ///
     /// assert_eq!(c, 'ö');
     /// assert_eq!(s2, "we 老虎 Léopard");
     /// ```
@@ -1157,11 +1291,13 @@ fn slice_shift_char(&self) -> Option<(char, &str)> {
 
     /// Returns the byte offset of an inner slice relative to an enclosing outer slice.
     ///
+    /// # Panics
+    ///
     /// Panics if `inner` is not a direct slice contained within self.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// let string = "a\nb\nc";
     /// let lines: Vec<&str> = string.lines().collect();
     ///
@@ -1175,11 +1311,17 @@ fn subslice_offset(&self, inner: &str) -> usize {
         core_str::StrExt::subslice_offset(&self[..], inner)
     }
 
-    /// Return an unsafe pointer to the strings buffer.
+    /// Return an unsafe pointer to the `&str`'s buffer.
+    ///
+    /// The caller must ensure that the string outlives this pointer, and that it is not
+    /// reallocated (e.g. by pushing to the string).
+    ///
+    /// # Examples
     ///
-    /// The caller must ensure that the string outlives this pointer,
-    /// and that it is not reallocated (e.g. by pushing to the
-    /// string).
+    /// ```
+    /// let s = "Hello";
+    /// let p = s.as_ptr();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn as_ptr(&self) -> *const u8 {
@@ -1193,13 +1335,13 @@ fn utf16_units(&self) -> Utf16Units {
         Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
     }
 
-    /// Return the number of bytes in this string
+    /// Returns the length of `self` in bytes.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// assert_eq!("foo".len(), 3);
-    /// assert_eq!("ƒoo".len(), 4);
+    /// assert_eq!("ƒoo".len(), 4); // fancy f!
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -1207,9 +1349,9 @@ fn len(&self) -> usize {
         core_str::StrExt::len(&self[..])
     }
 
-    /// Returns true if this slice contains no bytes
+    /// Returns true if this slice has a length of zero bytes.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// assert!("".is_empty());
@@ -1220,12 +1362,21 @@ fn is_empty(&self) -> bool {
         core_str::StrExt::is_empty(&self[..])
     }
 
-    /// Parse this string into the specified type.
+    /// Parses `self` into the specified type.
+    ///
+    /// # Failure
+    ///
+    /// Will return `Err` if it's not possible to parse `self` into the type.
     ///
     /// # Example
     ///
     /// ```
     /// assert_eq!("4".parse::<u32>(), Ok(4));
+    /// ```
+    ///
+    /// Failing:
+    ///
+    /// ```
     /// assert!("j".parse::<u32>().is_err());
     /// ```
     #[inline]
@@ -1234,23 +1385,26 @@ fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
         core_str::StrExt::parse(&self[..])
     }
 
-    /// Returns an iterator over the
-    /// [grapheme clusters](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
-    /// of the string.
+    /// Returns an iterator over the [grapheme clusters][graphemes] of `self`.
+    ///
+    /// [graphemes]: http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries
     ///
     /// If `is_extended` is true, the iterator is over the *extended grapheme clusters*;
     /// otherwise, the iterator is over the *legacy grapheme clusters*.
     /// [UAX#29](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
     /// recommends extended grapheme cluster boundaries for general processing.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// 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);
+    ///
     /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::<Vec<&str>>();
     /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
+    ///
     /// assert_eq!(gr2.as_slice(), b);
     /// ```
     #[unstable(feature = "collections",
@@ -1259,14 +1413,15 @@ fn graphemes(&self, is_extended: bool) -> Graphemes {
         UnicodeStr::graphemes(&self[..], is_extended)
     }
 
-    /// Returns an iterator over the grapheme clusters of self and their byte offsets.
-    /// See `graphemes()` method for more information.
+    /// Returns an iterator over the grapheme clusters of `self` and their byte offsets. See
+    /// `graphemes()` for more information.
     ///
-    /// # Example
+    /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// 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);
     /// ```
     #[unstable(feature = "collections",
@@ -1275,16 +1430,18 @@ fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
         UnicodeStr::grapheme_indices(&self[..], is_extended)
     }
 
-    /// An iterator over the words of a string (subsequences separated
-    /// by any sequence of whitespace). Sequences of whitespace are
-    /// collapsed, so empty "words" are not included.
+    /// An iterator over the non-empty words of `self`.
     ///
-    /// # Example
+    /// A 'word' is a subsequence separated by any sequence of whitespace. Sequences of whitespace
+    /// are collapsed, so empty "words" are not included.
     ///
-    /// ```rust
+    /// # Examples
+    ///
+    /// ```
     /// let some_words = " Mary   had\ta little  \n\t lamb";
     /// let v: Vec<&str> = some_words.words().collect();
-    /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
+    ///
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
     /// ```
     #[unstable(feature = "str_words",
                reason = "the precise algorithm to use is unclear")]
@@ -1292,34 +1449,55 @@ fn words(&self) -> Words {
         UnicodeStr::words(&self[..])
     }
 
-    /// Returns a string's displayed width in columns, treating control
-    /// characters as zero-width.
+    /// Returns a string's displayed width in columns.
+    ///
+    /// Control characters have zero width.
     ///
-    /// `is_cjk` determines behavior for characters in the Ambiguous category:
-    /// if `is_cjk` is `true`, these are 2 columns wide; otherwise, they are 1.
-    /// In CJK locales, `is_cjk` should be `true`, else it should be `false`.
-    /// [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/)
-    /// recommends that these characters be treated as 1 column (i.e.,
-    /// `is_cjk` = `false`) if the locale is unknown.
+    /// `is_cjk` determines behavior for characters in the Ambiguous category: if `is_cjk` is
+    /// `true`, these are 2 columns wide; otherwise, they are 1. In CJK locales, `is_cjk` should be
+    /// `true`, else it should be `false`. [Unicode Standard Annex
+    /// #11](http://www.unicode.org/reports/tr11/) recommends that these characters be treated as 1
+    /// column (i.e., `is_cjk` = `false`) if the locale is unknown.
     #[unstable(feature = "collections",
                reason = "this functionality may only be provided by libunicode")]
     fn width(&self, is_cjk: bool) -> usize {
         UnicodeStr::width(&self[..], is_cjk)
     }
 
-    /// Returns a string with leading and trailing whitespace removed.
+    /// Returns a `&str` with leading and trailing whitespace removed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(s.trim(), "Hello\tworld");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim(&self) -> &str {
         UnicodeStr::trim(&self[..])
     }
 
-    /// Returns a string with leading whitespace removed.
+    /// Returns a `&str` with leading whitespace removed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(s.trim_left(), "Hello\tworld\t");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_left(&self) -> &str {
         UnicodeStr::trim_left(&self[..])
     }
 
-    /// Returns a string with trailing whitespace removed.
+    /// Returns a `&str` with trailing whitespace removed.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s = " Hello\tworld\t";
+    /// assert_eq!(s.trim_right(), " Hello\tworld");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn trim_right(&self) -> &str {
         UnicodeStr::trim_right(&self[..])
@@ -2222,17 +2400,17 @@ 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();
-        assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+        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();
-        assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+        assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
         // Unicode
         let split: Vec<&str> = data.splitn(3, 'ä').collect();
-        assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+        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();
-        assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+        assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
     }
 
     #[test]
@@ -2240,17 +2418,17 @@ fn test_split_char_iterator_no_trailing() {
         let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
         let split: Vec<&str> = data.split('\n').collect();
-        assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
+        assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
 
         let split: Vec<&str> = data.split_terminator('\n').collect();
-        assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
+        assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
     }
 
     #[test]
     fn test_words() {
         let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
         let words: Vec<&str> = data.words().collect();
-        assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
+        assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
     }
 
     #[test]
@@ -2335,11 +2513,11 @@ macro_rules! t {
     fn test_lines() {
         let data = "\nMäry häd ä little lämb\n\nLittle lämb\n";
         let lines: Vec<&str> = data.lines().collect();
-        assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
+        assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
 
         let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
         let lines: Vec<&str> = data.lines().collect();
-        assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
+        assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
     }
 
     #[test]
@@ -2887,22 +3065,6 @@ fn split_unicode_ascii(b: &mut Bencher) {
         b.iter(|| assert_eq!(s.split('V').count(), 3));
     }
 
-    #[bench]
-    fn split_unicode_not_ascii(b: &mut Bencher) {
-        struct NotAscii(char);
-        impl CharEq for NotAscii {
-            fn matches(&mut self, c: char) -> bool {
-                let NotAscii(cc) = *self;
-                cc == c
-            }
-            fn only_ascii(&self) -> bool { false }
-        }
-        let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
-
-        b.iter(|| assert_eq!(s.split(NotAscii('V')).count(), 3));
-    }
-
-
     #[bench]
     fn split_ascii(b: &mut Bencher) {
         let s = "Mary had a little lamb, Little lamb, little-lamb.";
@@ -2911,23 +3073,6 @@ fn split_ascii(b: &mut Bencher) {
         b.iter(|| assert_eq!(s.split(' ').count(), len));
     }
 
-    #[bench]
-    fn split_not_ascii(b: &mut Bencher) {
-        struct NotAscii(char);
-        impl CharEq for NotAscii {
-            #[inline]
-            fn matches(&mut self, c: char) -> bool {
-                let NotAscii(cc) = *self;
-                cc == c
-            }
-            fn only_ascii(&self) -> bool { false }
-        }
-        let s = "Mary had a little lamb, Little lamb, little-lamb.";
-        let len = s.split(' ').count();
-
-        b.iter(|| assert_eq!(s.split(NotAscii(' ')).count(), len));
-    }
-
     #[bench]
     fn split_extern_fn(b: &mut Bencher) {
         let s = "Mary had a little lamb, Little lamb, little-lamb.";
index 3b179d0b94c97cccddcdef0ddd6c7c070270cfc1..94abffa3db61cf6c33d24e87807af67e419fe1a1 100644 (file)
@@ -120,7 +120,7 @@ pub fn from_str(string: &str) -> String {
     /// let invalid_vec = vec![240, 144, 128];
     /// let s = String::from_utf8(invalid_vec).err().unwrap();
     /// assert_eq!(s.utf8_error(), Utf8Error::TooShort);
-    /// assert_eq!(s.into_bytes(), vec![240, 144, 128]);
+    /// assert_eq!(s.into_bytes(), [240, 144, 128]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -340,7 +340,7 @@ pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
     /// ```
     /// let s = String::from_str("hello");
     /// let bytes = s.into_bytes();
-    /// assert_eq!(bytes, vec![104, 101, 108, 108, 111]);
+    /// assert_eq!(bytes, [104, 101, 108, 108, 111]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -568,9 +568,9 @@ pub fn remove(&mut self, idx: usize) -> char {
 
         let CharRange { ch, next } = self.char_range_at(idx);
         unsafe {
-            ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize),
-                             self.vec.as_ptr().offset(next as isize),
-                             len - next);
+            ptr::copy(self.vec.as_mut_ptr().offset(idx as isize),
+                      self.vec.as_ptr().offset(next as isize),
+                      len - next);
             self.vec.set_len(len - (next - idx));
         }
         ch
@@ -598,12 +598,12 @@ pub fn insert(&mut self, idx: usize, ch: char) {
         let amt = ch.encode_utf8(&mut bits).unwrap();
 
         unsafe {
-            ptr::copy_memory(self.vec.as_mut_ptr().offset((idx + amt) as isize),
-                             self.vec.as_ptr().offset(idx as isize),
-                             len - idx);
-            ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize),
-                             bits.as_ptr(),
-                             amt);
+            ptr::copy(self.vec.as_mut_ptr().offset((idx + amt) as isize),
+                      self.vec.as_ptr().offset(idx as isize),
+                      len - idx);
+            ptr::copy(self.vec.as_mut_ptr().offset(idx as isize),
+                      bits.as_ptr(),
+                      amt);
             self.vec.set_len(len + amt);
         }
     }
@@ -619,7 +619,7 @@ pub fn insert(&mut self, idx: usize, ch: char) {
     /// let mut s = String::from_str("hello");
     /// unsafe {
     ///     let vec = s.as_mut_vec();
-    ///     assert!(vec == &mut vec![104, 101, 108, 108, 111]);
+    ///     assert!(vec == &[104, 101, 108, 108, 111]);
     ///     vec.reverse();
     /// }
     /// assert_eq!(s.as_slice(), "olleh");
@@ -834,16 +834,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
-#[cfg(stage0)]
-impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
-    #[inline]
-    fn hash(&self, hasher: &mut H) {
-        (**self).hash(hasher)
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl hash::Hash for String {
     #[inline]
     fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
index 1cc2a5235abec1a1af6a5cfe6a7361a758d7910c..e18fa8c3082d103672a27aeb71addb2d0ac6cfad 100644 (file)
@@ -93,7 +93,7 @@
 /// for x in vec.iter() {
 ///     println!("{}", x);
 /// }
-/// assert_eq!(vec, vec![7, 1, 2, 3]);
+/// assert_eq!(vec, [7, 1, 2, 3]);
 /// ```
 ///
 /// The `vec!` macro is provided to make initialization more convenient:
 /// ```
 /// let mut vec = vec![1, 2, 3];
 /// vec.push(4);
-/// assert_eq!(vec, vec![1, 2, 3, 4]);
+/// assert_eq!(vec, [1, 2, 3, 4]);
 /// ```
 ///
 /// Use a `Vec<T>` as an efficient stack:
@@ -242,7 +242,7 @@ pub fn with_capacity(capacity: usize) -> Vec<T> {
     ///
     ///         // Put everything back together into a Vec
     ///         let rebuilt = Vec::from_raw_parts(p, len, cap);
-    ///         assert_eq!(rebuilt, vec![4, 5, 6]);
+    ///         assert_eq!(rebuilt, [4, 5, 6]);
     ///     }
     /// }
     /// ```
@@ -267,7 +267,7 @@ pub unsafe fn from_raw_parts(ptr: *mut T, length: usize,
     pub unsafe fn from_raw_buf(ptr: *const T, elts: usize) -> Vec<T> {
         let mut dst = Vec::with_capacity(elts);
         dst.set_len(elts);
-        ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
+        ptr::copy_nonoverlapping(dst.as_mut_ptr(), ptr, elts);
         dst
     }
 
@@ -388,7 +388,7 @@ pub fn shrink_to_fit(&mut self) {
     pub fn into_boxed_slice(mut self) -> Box<[T]> {
         self.shrink_to_fit();
         unsafe {
-            let xs: Box<[T]> = mem::transmute(&mut *self);
+            let xs: Box<[T]> = Box::from_raw(&mut *self);
             mem::forget(self);
             xs
         }
@@ -404,7 +404,7 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
     /// ```
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.truncate(2);
-    /// assert_eq!(vec, vec![1, 2]);
+    /// assert_eq!(vec, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
@@ -505,10 +505,10 @@ pub unsafe fn set_len(&mut self, len: usize) {
     /// let mut v = vec!["foo", "bar", "baz", "qux"];
     ///
     /// assert_eq!(v.swap_remove(1), "bar");
-    /// assert_eq!(v, vec!["foo", "qux", "baz"]);
+    /// assert_eq!(v, ["foo", "qux", "baz"]);
     ///
     /// assert_eq!(v.swap_remove(0), "foo");
-    /// assert_eq!(v, vec!["baz", "qux"]);
+    /// assert_eq!(v, ["baz", "qux"]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -531,9 +531,9 @@ pub fn swap_remove(&mut self, index: usize) -> T {
     /// ```
     /// let mut vec = vec![1, 2, 3];
     /// vec.insert(1, 4);
-    /// assert_eq!(vec, vec![1, 4, 2, 3]);
+    /// assert_eq!(vec, [1, 4, 2, 3]);
     /// vec.insert(4, 5);
-    /// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
+    /// assert_eq!(vec, [1, 4, 2, 3, 5]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, index: usize, element: T) {
@@ -548,7 +548,7 @@ pub fn insert(&mut self, index: usize, element: T) {
                 let p = self.as_mut_ptr().offset(index as isize);
                 // Shift everything over to make space. (Duplicating the
                 // `index`th element into two consecutive places.)
-                ptr::copy_memory(p.offset(1), &*p, len - index);
+                ptr::copy(p.offset(1), &*p, len - index);
                 // Write it in, overwriting the first copy of the `index`th
                 // element.
                 ptr::write(&mut *p, element);
@@ -569,7 +569,7 @@ pub fn insert(&mut self, index: usize, element: T) {
     /// ```
     /// let mut v = vec![1, 2, 3];
     /// assert_eq!(v.remove(1), 2);
-    /// assert_eq!(v, vec![1, 3]);
+    /// assert_eq!(v, [1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, index: usize) -> T {
@@ -585,7 +585,7 @@ pub fn remove(&mut self, index: usize) -> T {
                 ret = ptr::read(ptr);
 
                 // Shift everything down to fill in that spot.
-                ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
+                ptr::copy(ptr, &*ptr.offset(1), len - index - 1);
             }
             self.set_len(len - 1);
             ret
@@ -603,7 +603,7 @@ pub fn remove(&mut self, index: usize) -> T {
     /// ```
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.retain(|&x| x%2 == 0);
-    /// assert_eq!(vec, vec![2, 4]);
+    /// assert_eq!(vec, [2, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
@@ -636,7 +636,7 @@ pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
     /// ```rust
     /// let mut vec = vec!(1, 2);
     /// vec.push(3);
-    /// assert_eq!(vec, vec!(1, 2, 3));
+    /// assert_eq!(vec, [1, 2, 3]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -674,7 +674,7 @@ pub fn push(&mut self, value: T) {
     /// ```rust
     /// let mut vec = vec![1, 2, 3];
     /// assert_eq!(vec.pop(), Some(3));
-    /// assert_eq!(vec, vec![1, 2]);
+    /// assert_eq!(vec, [1, 2]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -701,8 +701,8 @@ pub fn pop(&mut self) -> Option<T> {
     /// let mut vec = vec![1, 2, 3];
     /// let mut vec2 = vec![4, 5, 6];
     /// vec.append(&mut vec2);
-    /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
-    /// assert_eq!(vec2, vec![]);
+    /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
+    /// assert_eq!(vec2, []);
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -718,7 +718,7 @@ pub fn append(&mut self, other: &mut Self) {
         self.reserve(other.len());
         let len = self.len();
         unsafe {
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 self.get_unchecked_mut(len),
                 other.as_ptr(),
                 other.len());
@@ -1019,8 +1019,8 @@ pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
     /// ```
     /// let mut vec = vec![1,2,3];
     /// let vec2 = vec.split_off(1);
-    /// assert_eq!(vec, vec![1]);
-    /// assert_eq!(vec2, vec![2, 3]);
+    /// assert_eq!(vec, [1]);
+    /// assert_eq!(vec2, [2, 3]);
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -1036,7 +1036,7 @@ pub fn split_off(&mut self, at: usize) -> Self {
             self.set_len(at);
             other.set_len(other_len);
 
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 other.as_mut_ptr(),
                 self.as_ptr().offset(at as isize),
                 other.len());
@@ -1057,11 +1057,11 @@ impl<T: Clone> Vec<T> {
     /// ```
     /// let mut vec = vec!["hello"];
     /// vec.resize(3, "world");
-    /// assert_eq!(vec, vec!["hello", "world", "world"]);
+    /// assert_eq!(vec, ["hello", "world", "world"]);
     ///
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.resize(2, 0);
-    /// assert_eq!(vec, vec![1, 2]);
+    /// assert_eq!(vec, [1, 2]);
     /// ```
     #[unstable(feature = "collections",
                reason = "matches collection reform specification; waiting for dust to settle")]
@@ -1085,7 +1085,7 @@ pub fn resize(&mut self, new_len: usize, value: T) {
     /// ```
     /// let mut vec = vec![1];
     /// vec.push_all(&[2, 3, 4]);
-    /// assert_eq!(vec, vec![1, 2, 3, 4]);
+    /// assert_eq!(vec, [1, 2, 3, 4]);
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -1121,7 +1121,7 @@ impl<T: PartialEq> Vec<T> {
     ///
     /// vec.dedup();
     ///
-    /// assert_eq!(vec, vec![1, 2, 3, 2]);
+    /// assert_eq!(vec, [1, 2, 3, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn dedup(&mut self) {
@@ -1303,15 +1303,7 @@ fn clone_from(&mut self, other: &Vec<T>) {
     }
 }
 
-#[cfg(stage0)]
-impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        Hash::hash(&**self, state)
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl<T: Hash> Hash for Vec<T> {
     #[inline]
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
@@ -1501,69 +1493,34 @@ fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
     }
 }
 
-impl<A, B> PartialEq<Vec<B>> for Vec<A> where A: PartialEq<B> {
-    #[inline]
-    fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
-    #[inline]
-    fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
-}
-
-macro_rules! impl_eq {
-    ($lhs:ty, $rhs:ty) => {
-        impl<'b, A, B> PartialEq<$rhs> for $lhs where A: PartialEq<B> {
-            #[inline]
-            fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-
-        impl<'b, A, B> PartialEq<$lhs> for $rhs where B: PartialEq<A> {
-            #[inline]
-            fn eq(&self, other: &$lhs) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) }
-        }
+__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! { CowVec<'a, A>, &'b [B], Clone }
+__impl_slice_eq2! { CowVec<'a, A>, &'b mut [B], Clone }
+__impl_slice_eq2! { CowVec<'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! { CowVec<'a, A>, [B; $N], Clone }
+            // __impl_slice_eq2! { CowVec<'a, A>, &'b [B; $N], Clone }
+            // __impl_slice_eq2! { CowVec<'a, A>, &'b mut [B; $N], Clone }
+        )+
     }
 }
 
-impl_eq! { Vec<A>, &'b [B] }
-impl_eq! { Vec<A>, &'b mut [B] }
-
-impl<'a, A, B> PartialEq<Vec<B>> for Cow<'a, [A]> where A: PartialEq<B> + Clone {
-    #[inline]
-    fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
-    #[inline]
-    fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
+array_impls! {
+     0  1  2  3  4  5  6  7  8  9
+    10 11 12 13 14 15 16 17 18 19
+    20 21 22 23 24 25 26 27 28 29
+    30 31 32
 }
 
-impl<'a, A, B> PartialEq<Cow<'a, [A]>> for Vec<B> where A: Clone, B: PartialEq<A> {
-    #[inline]
-    fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) }
-    #[inline]
-    fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) }
-}
-
-macro_rules! impl_eq_for_cowvec {
-    ($rhs:ty) => {
-        impl<'a, 'b, A, B> PartialEq<$rhs> for Cow<'a, [A]> where A: PartialEq<B> + Clone {
-            #[inline]
-            fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-
-        impl<'a, 'b, A, B> PartialEq<Cow<'a, [A]>> for $rhs where A: Clone, B: PartialEq<A> {
-            #[inline]
-            fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) }
-            #[inline]
-            fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) }
-        }
-    }
-}
-
-impl_eq_for_cowvec! { &'b [B] }
-impl_eq_for_cowvec! { &'b mut [B] }
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: PartialOrd> PartialOrd for Vec<T> {
     #[inline]
@@ -1599,9 +1556,7 @@ impl<T> AsSlice<T> for Vec<T> {
     fn as_slice(&self) -> &[T] {
         unsafe {
             let p = *self.ptr;
-            if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
-                assume(p != 0 as *mut T);
-            }
+            assume(p != 0 as *mut T);
             mem::transmute(RawSlice {
                 data: p,
                 len: self.len
@@ -1800,6 +1755,9 @@ pub struct Drain<'a, T:'a> {
     marker: PhantomData<&'a T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
+unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Drain<'a, T> {
     type Item = T;
@@ -2150,7 +2108,7 @@ fn test_split_at_mut() {
             }
         }
 
-        assert!(values == vec![2, 3, 5, 6, 7]);
+        assert_eq!(values, [2, 3, 5, 6, 7]);
     }
 
     #[test]
@@ -2192,7 +2150,7 @@ fn test_clone_from() {
     fn test_retain() {
         let mut vec = vec![1, 2, 3, 4];
         vec.retain(|&x| x % 2 == 0);
-        assert!(vec == vec![2, 4]);
+        assert_eq!(vec, [2, 4]);
     }
 
     #[test]
@@ -2252,13 +2210,13 @@ fn test_unsafe_ptrs() {
             let a = [1, 2, 3];
             let ptr = a.as_ptr();
             let b = Vec::from_raw_buf(ptr, 3);
-            assert_eq!(b, vec![1, 2, 3]);
+            assert_eq!(b, [1, 2, 3]);
 
             // Test on-heap copy-from-buf.
             let c = vec![1, 2, 3, 4, 5];
             let ptr = c.as_ptr();
             let d = Vec::from_raw_buf(ptr, 5);
-            assert_eq!(d, vec![1, 2, 3, 4, 5]);
+            assert_eq!(d, [1, 2, 3, 4, 5]);
         }
     }
 
@@ -2420,7 +2378,7 @@ fn test_move_items() {
         for i in vec {
             vec2.push(i);
         }
-        assert!(vec2 == vec![1, 2, 3]);
+        assert_eq!(vec2, [1, 2, 3]);
     }
 
     #[test]
@@ -2430,7 +2388,7 @@ fn test_move_items_reverse() {
         for i in vec.into_iter().rev() {
             vec2.push(i);
         }
-        assert!(vec2 == vec![3, 2, 1]);
+        assert_eq!(vec2, [3, 2, 1]);
     }
 
     #[test]
@@ -2440,7 +2398,7 @@ fn test_move_items_zero_sized() {
         for i in vec {
             vec2.push(i);
         }
-        assert!(vec2 == vec![(), (), ()]);
+        assert_eq!(vec2, [(), (), ()]);
     }
 
     #[test]
@@ -2480,7 +2438,7 @@ fn test_drain_items_zero_sized() {
     fn test_into_boxed_slice() {
         let xs = vec![1, 2, 3];
         let ys = xs.into_boxed_slice();
-        assert_eq!(ys, [1, 2, 3]);
+        assert_eq!(&*ys, [1, 2, 3]);
     }
 
     #[test]
@@ -2488,16 +2446,16 @@ fn test_append() {
         let mut vec = vec![1, 2, 3];
         let mut vec2 = vec![4, 5, 6];
         vec.append(&mut vec2);
-        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(vec2, vec![]);
+        assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
+        assert_eq!(vec2, []);
     }
 
     #[test]
     fn test_split_off() {
         let mut vec = vec![1, 2, 3, 4, 5, 6];
         let vec2 = vec.split_off(4);
-        assert_eq!(vec, vec![1, 2, 3, 4]);
-        assert_eq!(vec2, vec![5, 6]);
+        assert_eq!(vec, [1, 2, 3, 4]);
+        assert_eq!(vec2, [5, 6]);
     }
 
     #[bench]
index 3ba22a41ff74097d73626b926a0bcda8b971486e..abcc0cef9f1feae7ad86e659f1475133de50a471 100644 (file)
@@ -24,7 +24,6 @@
 use core::default::Default;
 use core::fmt;
 use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
-use core::marker;
 use core::mem;
 use core::num::{Int, UnsignedInt};
 use core::ops::{Index, IndexMut};
@@ -32,7 +31,6 @@
 use core::raw::Slice as RawSlice;
 
 use core::hash::{Hash, Hasher};
-#[cfg(stage0)] use core::hash::Writer;
 use core::cmp;
 
 use alloc::heap;
@@ -60,12 +58,6 @@ pub struct VecDeque<T> {
     ptr: Unique<T>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Send> Send for VecDeque<T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Sync> Sync for VecDeque<T> {}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for VecDeque<T> {
     fn clone(&self) -> VecDeque<T> {
@@ -135,7 +127,7 @@ unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
                       self.cap);
         debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
                       self.cap);
-        ptr::copy_memory(
+        ptr::copy(
             self.ptr.offset(dst as isize),
             self.ptr.offset(src as isize),
             len);
@@ -148,7 +140,7 @@ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
                       self.cap);
         debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
                       self.cap);
-        ptr::copy_nonoverlapping_memory(
+        ptr::copy_nonoverlapping(
             self.ptr.offset(dst as isize),
             self.ptr.offset(src as isize),
             len);
@@ -546,9 +538,7 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
         IterMut {
             tail: self.tail,
             head: self.head,
-            cap: self.cap,
-            ptr: *self.ptr,
-            marker: marker::PhantomData,
+            ring: unsafe { self.buffer_as_mut_slice() },
         }
     }
 
@@ -1344,22 +1334,22 @@ pub fn split_off(&mut self, at: usize) -> Self {
                 // `at` lies in the first half.
                 let amount_in_first = first_len - at;
 
-                ptr::copy_nonoverlapping_memory(*other.ptr,
-                                                first_half.as_ptr().offset(at as isize),
-                                                amount_in_first);
+                ptr::copy_nonoverlapping(*other.ptr,
+                                         first_half.as_ptr().offset(at as isize),
+                                         amount_in_first);
 
                 // just take all of the second half.
-                ptr::copy_nonoverlapping_memory(other.ptr.offset(amount_in_first as isize),
-                                                second_half.as_ptr(),
-                                                second_len);
+                ptr::copy_nonoverlapping(other.ptr.offset(amount_in_first as isize),
+                                         second_half.as_ptr(),
+                                         second_len);
             } else {
                 // `at` lies in the second half, need to factor in the elements we skipped
                 // in the first half.
                 let offset = at - first_len;
                 let amount_in_second = second_len - offset;
-                ptr::copy_nonoverlapping_memory(*other.ptr,
-                                                second_half.as_ptr().offset(offset as isize),
-                                                amount_in_second);
+                ptr::copy_nonoverlapping(*other.ptr,
+                                         second_half.as_ptr().offset(offset as isize),
+                                         amount_in_second);
             }
         }
 
@@ -1516,17 +1506,12 @@ fn idx(&mut self, j: usize) -> Option<&'a T> {
     }
 }
 
-// FIXME This was implemented differently from Iter because of a problem
-//       with returning the mutable reference. I couldn't find a way to
-//       make the lifetime checker happy so, but there should be a way.
 /// `VecDeque` mutable iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T:'a> {
-    ptr: *mut T,
+    ring: &'a mut [T],
     tail: usize,
     head: usize,
-    cap: usize,
-    marker: marker::PhantomData<&'a mut T>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1539,16 +1524,17 @@ fn next(&mut self) -> Option<&'a mut T> {
             return None;
         }
         let tail = self.tail;
-        self.tail = wrap_index(self.tail + 1, self.cap);
+        self.tail = wrap_index(self.tail + 1, self.ring.len());
 
         unsafe {
-            Some(&mut *self.ptr.offset(tail as isize))
+            let elem = self.ring.get_unchecked_mut(tail);
+            Some(&mut *(elem as *mut _))
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = count(self.tail, self.head, self.cap);
+        let len = count(self.tail, self.head, self.ring.len());
         (len, Some(len))
     }
 }
@@ -1560,10 +1546,11 @@ fn next_back(&mut self) -> Option<&'a mut T> {
         if self.tail == self.head {
             return None;
         }
-        self.head = wrap_index(self.head - 1, self.cap);
+        self.head = wrap_index(self.head - 1, self.ring.len());
 
         unsafe {
-            Some(&mut *self.ptr.offset(self.head as isize))
+            let elem = self.ring.get_unchecked_mut(self.head);
+            Some(&mut *(elem as *mut _))
         }
     }
 }
@@ -1675,17 +1662,6 @@ fn cmp(&self, other: &VecDeque<A>) -> Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(stage0)]
-impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for VecDeque<A> {
-    fn hash(&self, state: &mut S) {
-        self.len().hash(state);
-        for elt in self {
-            elt.hash(state);
-        }
-    }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl<A: Hash> Hash for VecDeque<A> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         self.len().hash(state);
@@ -1766,7 +1742,7 @@ fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "VecDeque ["));
+        try!(write!(f, "["));
 
         for (i, e) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -2117,7 +2093,7 @@ fn test_swap() {
         let mut d: VecDeque<_> = (0..5).collect();
         d.pop_front();
         d.swap(0, 3);
-        assert_eq!(d.iter().cloned().collect::<Vec<_>>(), vec!(4, 2, 3, 1));
+        assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]);
     }
 
     #[test]
@@ -2447,12 +2423,12 @@ fn test_ord() {
     #[test]
     fn test_show() {
         let ringbuf: VecDeque<_> = (0..10).collect();
-        assert_eq!(format!("{:?}", ringbuf), "VecDeque [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+        assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
 
         let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter()
                                                                         .cloned()
                                                                         .collect();
-        assert_eq!(format!("{:?}", ringbuf), "VecDeque [\"just\", \"one\", \"test\", \"more\"]");
+        assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]");
     }
 
     #[test]
@@ -2880,17 +2856,17 @@ fn test_append() {
 
         // normal append
         a.append(&mut b);
-        assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(b.iter().cloned().collect(), vec![]);
+        assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+        assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
 
         // append nothing to something
         a.append(&mut b);
-        assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(b.iter().cloned().collect(), vec![]);
+        assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+        assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
 
         // append something to nothing
         b.append(&mut a);
-        assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(a.iter().cloned().collect(), vec![]);
+        assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+        assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []);
     }
 }
index 54589a3142345833b443956f65a17227b35fe915..5a0aa750bf5670dc1a569ca9f9c5e9715c17c884 100644 (file)
 
 use core::prelude::*;
 
-use core::cmp::Ordering;
+use core::cmp::{max, Ordering};
 use core::default::Default;
 use core::fmt;
 use core::hash::{Hash, Hasher};
-#[cfg(stage0)] use core::hash::Writer;
 use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
 use core::iter;
-use core::mem::replace;
+use core::mem::{replace, swap};
 use core::ops::{Index, IndexMut};
 
 use {vec, slice};
@@ -113,21 +112,7 @@ fn clone_from(&mut self, source: &VecMap<V>) {
     }
 }
 
-#[cfg(stage0)]
-impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
-    fn hash(&self, state: &mut S) {
-        // In order to not traverse the `VecMap` twice, count the elements
-        // during iteration.
-        let mut count: usize = 0;
-        for elt in self {
-            elt.hash(state);
-            count += 1;
-        }
-        count.hash(state);
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 impl<V: Hash> Hash for VecMap<V> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         // In order to not traverse the `VecMap` twice, count the elements
@@ -323,7 +308,7 @@ pub fn iter_mut<'r>(&'r mut self) -> IterMut<'r, V> {
     ///
     /// let vec: Vec<(usize, &str)> = map.into_iter().collect();
     ///
-    /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
+    /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<V> {
@@ -335,6 +320,95 @@ fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
         IntoIter { iter: self.v.into_iter().enumerate().filter_map(filter) }
     }
 
+    /// Moves all elements from `other` into the map while overwriting existing keys.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecMap;
+    ///
+    /// let mut a = VecMap::new();
+    /// a.insert(1, "a");
+    /// a.insert(2, "b");
+    ///
+    /// let mut b = VecMap::new();
+    /// b.insert(3, "c");
+    /// b.insert(4, "d");
+    ///
+    /// a.append(&mut b);
+    ///
+    /// assert_eq!(a.len(), 4);
+    /// assert_eq!(b.len(), 0);
+    /// assert_eq!(a[1], "a");
+    /// assert_eq!(a[2], "b");
+    /// assert_eq!(a[3], "c");
+    /// assert_eq!(a[4], "d");
+    /// ```
+    #[unstable(feature = "collections",
+               reason = "recently added as part of collections reform 2")]
+    pub fn append(&mut self, other: &mut Self) {
+        self.extend(other.drain());
+    }
+
+    /// Splits the collection into two at the given key.
+    ///
+    /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
+    /// and the returned `Self` contains elements `[at, max_key)`.
+    ///
+    /// Note that the capacity of `self` does not change.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecMap;
+    ///
+    /// let mut a = VecMap::new();
+    /// a.insert(1, "a");
+    /// a.insert(2, "b");
+    /// a.insert(3, "c");
+    /// a.insert(4, "d");
+    ///
+    /// let b = a.split_off(3);
+    ///
+    /// assert_eq!(a[1], "a");
+    /// assert_eq!(a[2], "b");
+    ///
+    /// assert_eq!(b[3], "c");
+    /// assert_eq!(b[4], "d");
+    /// ```
+    #[unstable(feature = "collections",
+               reason = "recently added as part of collections reform 2")]
+    pub fn split_off(&mut self, at: usize) -> Self {
+        let mut other = VecMap::new();
+
+        if at == 0 {
+            // Move all elements to other
+            swap(self, &mut other);
+            return other
+        } else if at > self.v.len() {
+            // No elements to copy
+            return other;
+        }
+
+        // Look up the index of the first non-None item
+        let first_index = self.v.iter().position(|el| el.is_some());
+        let start_index = match first_index {
+            Some(index) => max(at, index),
+            None => {
+                // self has no elements
+                return other;
+            }
+        };
+
+        // Fill the new VecMap with `None`s until `start_index`
+        other.v.extend((0..start_index).map(|_| None));
+
+        // Move elements beginning with `start_index` from `self` into `other`
+        other.v.extend(self.v[start_index..].iter_mut().map(|el| el.take()));
+
+        other
+    }
+
     /// Returns an iterator visiting all key-value pairs in ascending order of
     /// the keys, emptying (but not consuming) the original `VecMap`.
     /// The iterator's element type is `(usize, &'r V)`. Keeps the allocated memory for reuse.
@@ -351,7 +425,7 @@ fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
     ///
     /// let vec: Vec<(usize, &str)> = map.drain().collect();
     ///
-    /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
+    /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
     /// ```
     #[unstable(feature = "collections",
                reason = "matches collection reform specification, waiting for dust to settle")]
@@ -665,7 +739,7 @@ fn cmp(&self, other: &VecMap<V>) -> Ordering {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<V: fmt::Debug> fmt::Debug for VecMap<V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "VecMap {{"));
+        try!(write!(f, "{{"));
 
         for (i, (k, v)) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1152,10 +1226,89 @@ fn test_drain_iterator() {
 
         let vec: Vec<_> = map.drain().collect();
 
-        assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
+        assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
         assert_eq!(map.len(), 0);
     }
 
+    #[test]
+    fn test_append() {
+        let mut a = VecMap::new();
+        a.insert(1, "a");
+        a.insert(2, "b");
+        a.insert(3, "c");
+
+        let mut b = VecMap::new();
+        b.insert(3, "d");  // Overwrite element from a
+        b.insert(4, "e");
+        b.insert(5, "f");
+
+        a.append(&mut b);
+
+        assert_eq!(a.len(), 5);
+        assert_eq!(b.len(), 0);
+        // Capacity shouldn't change for possible reuse
+        assert!(b.capacity() >= 4);
+
+        assert_eq!(a[1], "a");
+        assert_eq!(a[2], "b");
+        assert_eq!(a[3], "d");
+        assert_eq!(a[4], "e");
+        assert_eq!(a[5], "f");
+    }
+
+    #[test]
+    fn test_split_off() {
+        // Split within the key range
+        let mut a = VecMap::new();
+        a.insert(1, "a");
+        a.insert(2, "b");
+        a.insert(3, "c");
+        a.insert(4, "d");
+
+        let b = a.split_off(3);
+
+        assert_eq!(a.len(), 2);
+        assert_eq!(b.len(), 2);
+
+        assert_eq!(a[1], "a");
+        assert_eq!(a[2], "b");
+
+        assert_eq!(b[3], "c");
+        assert_eq!(b[4], "d");
+
+        // Split at 0
+        a.clear();
+        a.insert(1, "a");
+        a.insert(2, "b");
+        a.insert(3, "c");
+        a.insert(4, "d");
+
+        let b = a.split_off(0);
+
+        assert_eq!(a.len(), 0);
+        assert_eq!(b.len(), 4);
+        assert_eq!(b[1], "a");
+        assert_eq!(b[2], "b");
+        assert_eq!(b[3], "c");
+        assert_eq!(b[4], "d");
+
+        // Split behind max_key
+        a.clear();
+        a.insert(1, "a");
+        a.insert(2, "b");
+        a.insert(3, "c");
+        a.insert(4, "d");
+
+        let b = a.split_off(5);
+
+        assert_eq!(a.len(), 4);
+        assert_eq!(b.len(), 0);
+        assert_eq!(a[1], "a");
+        assert_eq!(a[2], "b");
+        assert_eq!(a[3], "c");
+        assert_eq!(a[4], "d");
+    }
+
     #[test]
     fn test_show() {
         let mut map = VecMap::new();
@@ -1165,8 +1318,8 @@ fn test_show() {
         map.insert(3, 4);
 
         let map_str = format!("{:?}", map);
-        assert!(map_str == "VecMap {1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "VecMap {}");
+        assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
index afb5d95c9f8d79219b122a529749d35a35ceafab..0d98cff7e6a5e58b9ceea647a80a08490d56e293 100644 (file)
@@ -19,8 +19,7 @@
 use fmt;
 use hash::{Hash, self};
 use iter::IntoIterator;
-use marker::Copy;
-use ops::Deref;
+use marker::{Copy, Sized};
 use option::Option;
 use slice::{Iter, IterMut, SliceExt};
 
@@ -35,13 +34,6 @@ macro_rules! array_impls {
                 }
             }
 
-            #[cfg(stage0)]
-            impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for [T; $N] {
-                fn hash(&self, state: &mut S) {
-                    Hash::hash(&self[..], state)
-                }
-            }
-            #[cfg(not(stage0))]
             #[stable(feature = "rust1", since = "1.0.0")]
             impl<T: Hash> Hash for [T; $N] {
                 fn hash<H: hash::Hasher>(&self, state: &mut H) {
@@ -76,47 +68,13 @@ fn into_iter(self) -> IterMut<'a, T> {
                 }
             }
 
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
-                #[inline]
-                fn eq(&self, other: &[B; $N]) -> bool {
-                    &self[..] == &other[..]
-                }
-                #[inline]
-                fn ne(&self, other: &[B; $N]) -> bool {
-                    &self[..] != &other[..]
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<'a, A, B, Rhs> PartialEq<Rhs> for [A; $N] where
-                A: PartialEq<B>,
-                Rhs: Deref<Target=[B]>,
-            {
-                #[inline(always)]
-                fn eq(&self, other: &Rhs) -> bool {
-                    PartialEq::eq(&self[..], &**other)
-                }
-                #[inline(always)]
-                fn ne(&self, other: &Rhs) -> bool {
-                    PartialEq::ne(&self[..], &**other)
-                }
-            }
-
-            #[stable(feature = "rust1", since = "1.0.0")]
-            impl<'a, A, B, Lhs> PartialEq<[B; $N]> for Lhs where
-                A: PartialEq<B>,
-                Lhs: Deref<Target=[A]>
-            {
-                #[inline(always)]
-                fn eq(&self, other: &[B; $N]) -> bool {
-                    PartialEq::eq(&**self, &other[..])
-                }
-                #[inline(always)]
-                fn ne(&self, other: &[B; $N]) -> bool {
-                    PartialEq::ne(&**self, &other[..])
-                }
-            }
+            // NOTE: some less important impls are omitted to reduce code bloat
+            __impl_slice_eq1! { [A; $N], [B; $N] }
+            __impl_slice_eq2! { [A; $N], [B] }
+            __impl_slice_eq2! { [A; $N], &'b [B] }
+            __impl_slice_eq2! { [A; $N], &'b mut [B] }
+            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
+            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
 
             #[stable(feature = "rust1", since = "1.0.0")]
             impl<T:Eq> Eq for [T; $N] { }
index 6afe5b2257d279736daa4db1799d48a679f3e53b..38e2bd98ef9e3d64629f9e247850a376c5d2ba6a 100644 (file)
@@ -15,7 +15,7 @@
 //! types.
 //!
 //! This module defines atomic versions of a select number of primitive
-//! types, including `AtomicBool`, `AtomicIsize`, `AtomicUsize`, and `AtomicOption`.
+//! types, including `AtomicBool`, `AtomicIsize`, and `AtomicUsize`.
 //! Atomic types present operations that, when used correctly, synchronize
 //! updates between threads.
 //!
index eb138e6142b80e36e5c4217225ed301dcfcea2d1..b8a22c30f9e1ed14a9146b22772af699adc45901 100644 (file)
 use clone::Clone;
 use cmp::PartialEq;
 use default::Default;
-use marker::{Copy, Send};
+use marker::{Copy, Send, Sync};
 use ops::{Deref, DerefMut, Drop};
 use option::Option;
 use option::Option::{None, Some};
@@ -660,6 +660,8 @@ pub struct UnsafeCell<T> {
     pub value: T,
 }
 
+impl<T> !Sync for UnsafeCell<T> {}
+
 impl<T> UnsafeCell<T> {
     /// Construct a new instance of `UnsafeCell` which will wrap the specified
     /// value.
index c45fac1bc9490be142f1b9a0e5ac1dc277124628..8e27ae1cea97039342dceb76b1e04b541d6faa41 100644 (file)
 use slice::SliceExt;
 
 // UTF-8 ranges and tags for encoding characters
-static TAG_CONT: u8    = 0b1000_0000u8;
-static TAG_TWO_B: u8   = 0b1100_0000u8;
-static TAG_THREE_B: u8 = 0b1110_0000u8;
-static TAG_FOUR_B: u8  = 0b1111_0000u8;
-static MAX_ONE_B: u32   =     0x80u32;
-static MAX_TWO_B: u32   =    0x800u32;
-static MAX_THREE_B: u32 =  0x10000u32;
+const TAG_CONT: u8    = 0b1000_0000u8;
+const TAG_TWO_B: u8   = 0b1100_0000u8;
+const TAG_THREE_B: u8 = 0b1110_0000u8;
+const TAG_FOUR_B: u8  = 0b1111_0000u8;
+const MAX_ONE_B: u32   =     0x80u32;
+const MAX_TWO_B: u32   =    0x800u32;
+const MAX_THREE_B: u32 =  0x10000u32;
 
 /*
     Lu  Uppercase_Letter        an uppercase letter
@@ -398,11 +398,14 @@ fn escape_default(self) -> EscapeDefault {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn len_utf8(self) -> usize {
         let code = self as u32;
-        match () {
-            _ if code < MAX_ONE_B   => 1,
-            _ if code < MAX_TWO_B   => 2,
-            _ if code < MAX_THREE_B => 3,
-            _  => 4,
+        if code < MAX_ONE_B {
+            1
+        } else if code < MAX_TWO_B {
+            2
+        } else if code < MAX_THREE_B {
+            3
+        } else {
+            4
         }
     }
 
diff --git a/src/libcore/cmp_macros.rs b/src/libcore/cmp_macros.rs
new file mode 100644 (file)
index 0000000..18357ba
--- /dev/null
@@ -0,0 +1,50 @@
+// 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.
+
+// Utility macros for implementing PartialEq on slice-like types
+
+#![doc(hidden)]
+
+#[macro_export]
+macro_rules! __impl_slice_eq1 {
+    ($Lhs: ty, $Rhs: ty) => {
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, 'b, A, 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[..] }
+        }
+    }
+}
+
+#[macro_export]
+macro_rules! __impl_slice_eq2 {
+    ($Lhs: ty, $Rhs: ty) => {
+        __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[..] }
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
+            #[inline]
+            fn eq(&self, other: &$Lhs) -> bool { &self[..] == &other[..] }
+            #[inline]
+            fn ne(&self, other: &$Lhs) -> bool { &self[..] != &other[..] }
+        }
+    }
+}
index 7f7264a04684b61426996c16ea82fd1683e3b913..f92e631c1f25c4becc028f0056484346b26fa603 100644 (file)
@@ -40,10 +40,10 @@ pub enum ExponentFormat {
 pub enum SignificantDigits {
     /// At most the given number of digits will be printed, truncating any
     /// trailing zeroes.
-    DigMax(uint),
+    DigMax(usize),
 
     /// Precisely the given number of digits will be printed.
-    DigExact(uint)
+    DigExact(usize)
 }
 
 /// How to emit the sign of a number.
@@ -240,27 +240,27 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
                     // If reached left end of number, have to
                     // insert additional digit:
                     if i < 0
-                    || buf[i as uint] == b'-'
-                    || buf[i as uint] == b'+' {
-                        for j in (i as uint + 1..end).rev() {
+                    || buf[i as usize] == b'-'
+                    || buf[i as usize] == b'+' {
+                        for j in (i as usize + 1..end).rev() {
                             buf[j + 1] = buf[j];
                         }
-                        buf[(i + 1) as uint] = value2ascii(1);
+                        buf[(i + 1) as usize] = value2ascii(1);
                         end += 1;
                         break;
                     }
 
                     // Skip the '.'
-                    if buf[i as uint] == b'.' { i -= 1; continue; }
+                    if buf[i as usize] == b'.' { i -= 1; continue; }
 
                     // Either increment the digit,
                     // or set to 0 if max and carry the 1.
-                    let current_digit = ascii2value(buf[i as uint]);
+                    let current_digit = ascii2value(buf[i as usize]);
                     if current_digit < (radix - 1) {
-                        buf[i as uint] = value2ascii(current_digit+1);
+                        buf[i as usize] = value2ascii(current_digit+1);
                         break;
                     } else {
-                        buf[i as uint] = value2ascii(0);
+                        buf[i as usize] = value2ascii(0);
                         i -= 1;
                     }
                 }
@@ -311,7 +311,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
 
             struct Filler<'a> {
                 buf: &'a mut [u8],
-                end: &'a mut uint,
+                end: &'a mut usize,
             }
 
             impl<'a> fmt::Write for Filler<'a> {
index a2c1bbc03317e9da08451e0b2b2d6194d385568b..117b829fdff9b5bf79ed6e4d686cfa45239b21b4 100644 (file)
@@ -110,11 +110,11 @@ fn write_fmt(&mut self, args: Arguments) -> Result {
 /// traits.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Formatter<'a> {
-    flags: uint,
+    flags: u32,
     fill: char,
     align: rt::v1::Alignment,
-    width: Option<uint>,
-    precision: Option<uint>,
+    width: Option<usize>,
+    precision: Option<usize>,
 
     buf: &'a mut (Write+'a),
     curarg: slice::Iter<'a, ArgumentV1<'a>>,
@@ -140,7 +140,7 @@ pub struct ArgumentV1<'a> {
 
 impl<'a> ArgumentV1<'a> {
     #[inline(never)]
-    fn show_uint(x: &uint, f: &mut Formatter) -> Result {
+    fn show_usize(x: &usize, f: &mut Formatter) -> Result {
         Display::fmt(x, f)
     }
 
@@ -158,13 +158,13 @@ pub fn new<'b, T>(x: &'b T,
 
     #[doc(hidden)]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn from_uint(x: &uint) -> ArgumentV1 {
-        ArgumentV1::new(x, ArgumentV1::show_uint)
+    pub fn from_usize(x: &usize) -> ArgumentV1 {
+        ArgumentV1::new(x, ArgumentV1::show_usize)
     }
 
-    fn as_uint(&self) -> Option<uint> {
-        if self.formatter as uint == ArgumentV1::show_uint as uint {
-            Some(unsafe { *(self.value as *const _ as *const uint) })
+    fn as_usize(&self) -> Option<usize> {
+        if self.formatter as usize == ArgumentV1::show_usize as usize {
+            Some(unsafe { *(self.value as *const _ as *const usize) })
         } else {
             None
         }
@@ -194,7 +194,7 @@ pub fn new_v1(pieces: &'a [&'a str],
     /// The `pieces` array must be at least as long as `fmt` to construct
     /// a valid Arguments structure. Also, any `Count` within `fmt` that is
     /// `CountIsParam` or `CountIsNextParam` has to point to an argument
-    /// created with `argumentuint`. However, failing to do so doesn't cause
+    /// created with `argumentusize`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
     #[doc(hidden)] #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -246,16 +246,6 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
     }
 }
 
-/// Format trait for the `:?` format. Useful for debugging, all types
-/// should implement this.
-#[deprecated(since = "1.0.0", reason = "renamed to Debug")]
-#[unstable(feature = "old_fmt")]
-pub trait Show {
-    /// Formats the value using the given formatter.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
-}
-
 /// Format trait for the `:?` format. Useful for debugging, all types
 /// should implement this.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -269,22 +259,6 @@ pub trait Debug {
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
-#[allow(deprecated)]
-impl<T: Show + ?Sized> Debug for T {
-    #[allow(deprecated)]
-    fn fmt(&self, f: &mut Formatter) -> Result { Show::fmt(self, f) }
-}
-
-/// When a value can be semantically expressed as a String, this trait may be
-/// used. It corresponds to the default format, `{}`.
-#[deprecated(since = "1.0.0", reason = "renamed to Display")]
-#[unstable(feature = "old_fmt")]
-pub trait String {
-    /// Formats the value using the given formatter.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
-}
-
 /// When a value can be semantically expressed as a String, this trait may be
 /// used. It corresponds to the default format, `{}`.
 #[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
@@ -297,12 +271,6 @@ pub trait Display {
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
-#[allow(deprecated)]
-impl<T: String + ?Sized> Display for T {
-    #[allow(deprecated)]
-    fn fmt(&self, f: &mut Formatter) -> Result { String::fmt(self, f) }
-}
-
 /// Format trait for the `o` character
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Octal {
@@ -434,15 +402,15 @@ fn run(&mut self, arg: &rt::v1::Argument) -> Result {
         (value.formatter)(value.value, self)
     }
 
-    fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<uint> {
+    fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
         match *cnt {
             rt::v1::Count::Is(n) => Some(n),
             rt::v1::Count::Implied => None,
             rt::v1::Count::Param(i) => {
-                self.args[i].as_uint()
+                self.args[i].as_usize()
             }
             rt::v1::Count::NextParam => {
-                self.curarg.next().and_then(|arg| arg.as_uint())
+                self.curarg.next().and_then(|arg| arg.as_usize())
             }
         }
     }
@@ -476,12 +444,12 @@ pub fn pad_integral(&mut self,
         let mut sign = None;
         if !is_positive {
             sign = Some('-'); width += 1;
-        } else if self.flags & (1 << (FlagV1::SignPlus as uint)) != 0 {
+        } else if self.flags & (1 << (FlagV1::SignPlus as u32)) != 0 {
             sign = Some('+'); width += 1;
         }
 
         let mut prefixed = false;
-        if self.flags & (1 << (FlagV1::Alternate as uint)) != 0 {
+        if self.flags & (1 << (FlagV1::Alternate as u32)) != 0 {
             prefixed = true; width += prefix.char_len();
         }
 
@@ -511,7 +479,7 @@ pub fn pad_integral(&mut self,
             }
             // The sign and prefix goes before the padding if the fill character
             // is zero
-            Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as uint)) != 0 => {
+            Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 => {
                 self.fill = '0';
                 try!(write_prefix(self));
                 self.with_padding(min - width, Alignment::Right, |f| {
@@ -581,7 +549,7 @@ pub fn pad(&mut self, s: &str) -> Result {
 
     /// Runs a callback, emitting the correct padding either before or
     /// afterwards depending on whether right or left alignment is requested.
-    fn with_padding<F>(&mut self, padding: uint, default: Alignment,
+    fn with_padding<F>(&mut self, padding: usize, default: Alignment,
                        f: F) -> Result
         where F: FnOnce(&mut Formatter) -> Result,
     {
@@ -629,7 +597,7 @@ pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
 
     /// Flags for formatting (packed version of rt::Flag)
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn flags(&self) -> usize { self.flags }
+    pub fn flags(&self) -> u32 { self.flags }
 
     /// Character used as 'fill' whenever there is alignment
     #[unstable(feature = "core", reason = "method was just created")]
@@ -641,11 +609,11 @@ pub fn align(&self) -> Alignment { self.align }
 
     /// Optionally specified integer width that the output should be
     #[unstable(feature = "core", reason = "method was just created")]
-    pub fn width(&self) -> Option<uint> { self.width }
+    pub fn width(&self) -> Option<usize> { self.width }
 
     /// Optionally specified precision for numeric types
     #[unstable(feature = "core", reason = "method was just created")]
-    pub fn precision(&self) -> Option<uint> { self.precision }
+    pub fn precision(&self) -> Option<usize> { self.precision }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -731,9 +699,9 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        f.flags |= 1 << (FlagV1::Alternate as uint);
-        let ret = LowerHex::fmt(&(*self as uint), f);
-        f.flags &= !(1 << (FlagV1::Alternate as uint));
+        f.flags |= 1 << (FlagV1::Alternate as u32);
+        let ret = LowerHex::fmt(&(*self as u32), f);
+        f.flags &= !(1 << (FlagV1::Alternate as u32));
         ret
     }
 }
@@ -889,7 +857,7 @@ 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 {
-        if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 {
+        if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
             try!(write!(f, "["));
         }
         let mut is_first = true;
@@ -901,7 +869,7 @@ fn fmt(&self, f: &mut Formatter) -> Result {
             }
             try!(write!(f, "{:?}", *x))
         }
-        if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 {
+        if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
             try!(write!(f, "]"));
         }
         Ok(())
index 1222126b5e0cdef73c0a3bccc4ce5dff3630c90f..0175e21c8da6152b47bfbbae924118a19bc3bc64 100644 (file)
@@ -214,7 +214,7 @@ macro_rules! integer {
         show! { $Uint with $SU }
     }
 }
-integer! { int, uint, "i", "u" }
+integer! { isize, usize, "i", "u" }
 integer! { i8, u8 }
 integer! { i16, u16 }
 integer! { i32, u32 }
index 0c9bb6316e0d805ecbcc08a05c1c6bb2fa67bc5e..7f6dea905dafd45ec351f20d8e1a21de91356e29 100644 (file)
@@ -33,7 +33,7 @@ pub struct FormatSpec {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub align: Alignment,
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub flags: uint,
+    pub flags: u32,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub precision: Count,
     #[stable(feature = "rust1", since = "1.0.0")]
index 2e83334b93732378c960019def28bbef57e2ee77..edc4b7e10ee49b04b024a3b3076d2f425f12358a 100644 (file)
@@ -20,7 +20,7 @@
 //!
 //! #[derive(Hash)]
 //! struct Person {
-//!     id: uint,
+//!     id: u32,
 //!     name: String,
 //!     phone: u64,
 //! }
@@ -38,7 +38,7 @@
 //! use std::hash::{hash, Hash, Hasher, SipHasher};
 //!
 //! struct Person {
-//!     id: uint,
+//!     id: u32,
 //!     name: String,
 //!     phone: u64,
 //! }
@@ -73,7 +73,6 @@
 /// to compute the hash. Specific implementations of this trait may specialize
 /// for particular instances of `H` in order to be able to optimize the hashing
 /// behavior.
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hash {
     /// Feeds this value into the state given, updating the hasher as necessary.
@@ -89,72 +88,40 @@ fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
     }
 }
 
-/// A hashable type.
-///
-/// The `H` type parameter is an abstract hash state that is used by the `Hash`
-/// to compute the hash. Specific implementations of this trait may specialize
-/// for particular instances of `H` in order to be able to optimize the hashing
-/// behavior.
-#[cfg(stage0)]
-pub trait Hash<H: Hasher> {
-    /// Feeds this value into the state given, updating the hasher as necessary.
-    fn hash(&self, state: &mut H);
-}
-
 /// A trait which represents the ability to hash an arbitrary stream of bytes.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Hasher {
-    /// Result type of one run of hashing generated by this hasher.
-    #[cfg(stage0)]
-    type Output;
-
-    /// Resets this hasher back to its initial state (as if it were just
-    /// created).
-    #[cfg(stage0)]
-    fn reset(&mut self);
-
-    /// Completes a round of hashing, producing the output hash generated.
-    #[cfg(stage0)]
-    fn finish(&self) -> Self::Output;
-
     /// Completes a round of hashing, producing the output hash generated.
-    #[cfg(not(stage0))]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn finish(&self) -> u64;
 
     /// Writes some data into this `Hasher`
-    #[cfg(not(stage0))]
     #[stable(feature = "rust1", since = "1.0.0")]
     fn write(&mut self, bytes: &[u8]);
 
     /// Write a single `u8` into this hasher
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_u8(&mut self, i: u8) { self.write(&[i]) }
     /// Write a single `u16` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_u16(&mut self, i: u16) {
         self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
     }
     /// Write a single `u32` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_u32(&mut self, i: u32) {
         self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
     }
     /// Write a single `u64` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_u64(&mut self, i: u64) {
         self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
     }
     /// Write a single `usize` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_usize(&mut self, i: usize) {
@@ -166,58 +133,31 @@ fn write_usize(&mut self, i: usize) {
     }
 
     /// Write a single `i8` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
     /// Write a single `i16` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
     /// Write a single `i32` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
     /// Write a single `i64` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
     /// Write a single `isize` into this hasher.
-    #[cfg(not(stage0))]
     #[inline]
     #[unstable(feature = "hash", reason = "module was recently redesigned")]
     fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
 }
 
-/// A common bound on the `Hasher` parameter to `Hash` implementations in order
-/// to generically hash an aggregate.
-#[unstable(feature = "hash",
-           reason = "this trait will likely be replaced by io::Writer")]
-#[allow(missing_docs)]
-#[cfg(stage0)]
-pub trait Writer {
-    fn write(&mut self, bytes: &[u8]);
-}
-
 /// Hash a value with the default SipHasher algorithm (two initial keys of 0).
 ///
 /// The specified value will be hashed with this hasher and then the resulting
 /// hash will be returned.
-#[cfg(stage0)]
-pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
-    let mut h: H = Default::default();
-    value.hash(&mut h);
-    h.finish()
-}
-
-/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
-///
-/// The specified value will be hashed with this hasher and then the resulting
-/// hash will be returned.
-#[cfg(not(stage0))]
 #[unstable(feature = "hash", reason = "module was recently redesigned")]
 pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
     let mut h: H = Default::default();
@@ -227,145 +167,6 @@ pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
 
 //////////////////////////////////////////////////////////////////////////////
 
-#[cfg(stage0)]
-mod impls {
-    use prelude::*;
-
-    use mem;
-    use num::Int;
-    use super::*;
-
-    macro_rules! impl_hash {
-        ($ty:ident, $uty:ident) => {
-            impl<S: Writer + Hasher> Hash<S> for $ty {
-                #[inline]
-                fn hash(&self, state: &mut S) {
-                    let a: [u8; ::$ty::BYTES] = unsafe {
-                        mem::transmute(*self)
-                    };
-                    state.write(&a)
-                }
-            }
-        }
-    }
-
-    impl_hash! { u8, u8 }
-    impl_hash! { u16, u16 }
-    impl_hash! { u32, u32 }
-    impl_hash! { u64, u64 }
-    impl_hash! { uint, uint }
-    impl_hash! { i8, u8 }
-    impl_hash! { i16, u16 }
-    impl_hash! { i32, u32 }
-    impl_hash! { i64, u64 }
-    impl_hash! { int, uint }
-
-    impl<S: Writer + Hasher> Hash<S> for bool {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (*self as u8).hash(state);
-        }
-    }
-
-    impl<S: Writer + Hasher> Hash<S> for char {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (*self as u32).hash(state);
-        }
-    }
-
-    impl<S: Writer + Hasher> Hash<S> for str {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            state.write(self.as_bytes());
-            0xffu8.hash(state)
-        }
-    }
-
-    macro_rules! impl_hash_tuple {
-        () => (
-            impl<S: Hasher> Hash<S> for () {
-                #[inline]
-                fn hash(&self, _state: &mut S) {}
-            }
-        );
-
-        ( $($name:ident)+) => (
-            impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
-                #[inline]
-                #[allow(non_snake_case)]
-                fn hash(&self, state: &mut S) {
-                    match *self {
-                        ($(ref $name,)*) => {
-                            $(
-                                $name.hash(state);
-                            )*
-                        }
-                    }
-                }
-            }
-        );
-    }
-
-    impl_hash_tuple! {}
-    impl_hash_tuple! { A }
-    impl_hash_tuple! { A B }
-    impl_hash_tuple! { A B C }
-    impl_hash_tuple! { A B C D }
-    impl_hash_tuple! { A B C D E }
-    impl_hash_tuple! { A B C D E F }
-    impl_hash_tuple! { A B C D E F G }
-    impl_hash_tuple! { A B C D E F G H }
-    impl_hash_tuple! { A B C D E F G H I }
-    impl_hash_tuple! { A B C D E F G H I J }
-    impl_hash_tuple! { A B C D E F G H I J K }
-    impl_hash_tuple! { A B C D E F G H I J K L }
-
-    impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            self.len().hash(state);
-            for elt in self {
-                elt.hash(state);
-            }
-        }
-    }
-
-
-    impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (**self).hash(state);
-        }
-    }
-
-    impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            (**self).hash(state);
-        }
-    }
-
-    impl<S: Writer + Hasher, T> Hash<S> for *const T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            // NB: raw-pointer Hash does _not_ dereference
-            // to the target; it just gives you the pointer-bytes.
-            (*self as uint).hash(state);
-        }
-    }
-
-    impl<S: Writer + Hasher, T> Hash<S> for *mut T {
-        #[inline]
-        fn hash(&self, state: &mut S) {
-            // NB: raw-pointer Hash does _not_ dereference
-            // to the target; it just gives you the pointer-bytes.
-            (*self as uint).hash(state);
-        }
-    }
-}
-
-#[cfg(not(stage0))]
 mod impls {
     use prelude::*;
 
index ce8917cc20589a93b0edddccc6ede9ed5fe7e329..39bcbacdff182c23b137037d007099a58ca17ed8 100644 (file)
@@ -16,8 +16,6 @@
 use default::Default;
 
 use super::Hasher;
-#[cfg(stage0)]
-use super::Writer;
 
 /// An implementation of SipHash 2-4.
 ///
 pub struct SipHasher {
     k0: u64,
     k1: u64,
-    length: uint, // how many bytes we've processed
+    length: usize, // how many bytes we've processed
     v0: u64,      // hash state
     v1: u64,
     v2: u64,
     v3: u64,
     tail: u64, // unprocessed bytes le
-    ntail: uint,  // how many bytes in tail are valid
+    ntail: usize,  // how many bytes in tail are valid
 }
 
 // sadly, these macro definitions can't appear later,
@@ -175,26 +173,9 @@ fn write(&mut self, msg: &[u8]) {
     }
 }
 
-#[cfg(stage0)]
-impl Writer for SipHasher {
-    #[inline]
-    fn write(&mut self, msg: &[u8]) {
-        self.write(msg)
-    }
-}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Hasher for SipHasher {
-    #[cfg(stage0)]
-    type Output = u64;
-
-    #[cfg(stage0)]
-    fn reset(&mut self) {
-        self.reset();
-    }
-
     #[inline]
-    #[cfg(not(stage0))]
     fn write(&mut self, msg: &[u8]) {
         self.write(msg)
     }
index b2ee95963878edb13af4a4b99c9cf529377b13f4..e7af0be88a0859bae60fa9c76f5d02040151667c 100644 (file)
@@ -293,7 +293,7 @@ pub struct TyDesc {
     ///     }
     /// }
     /// ```
-    #[unstable(feature = "core")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
 
     /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
@@ -323,13 +323,12 @@ pub struct TyDesc {
     /// }
     /// ```
     ///
-    #[unstable(feature = "core")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
 
     /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
     /// bytes of memory starting at `dst` to `c`.
-    #[unstable(feature = "core",
-               reason = "uncertain about naming and semantics")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
index 8fb10b5b2dc2a53ca3d40709ce7c2abcd46b6e66..8f767e62678e6b92788181b23e70542daf15b1cb 100644 (file)
@@ -68,7 +68,7 @@
 use ops::{Add, Deref, FnMut};
 use option::Option;
 use option::Option::{Some, None};
-use marker::Sized;
+use marker::{Send, Sized, Sync};
 use usize;
 
 /// An interface for dealing with "external iterators". These types of iterators
@@ -86,6 +86,7 @@
 #[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;
 
@@ -122,9 +123,11 @@ pub trait FromIterator<A> {
 /// Conversion into an `Iterator`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
+    /// The type of the elements being iterated
     #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
+    /// A container for iterating over elements of type Item
     #[stable(feature = "rust1", since = "1.0.0")]
     type IntoIter: Iterator<Item=Self::Item>;
 
@@ -579,8 +582,8 @@ fn collect<B: FromIterator<Self::Item>>(self) -> B {
     /// ```
     /// let vec = vec![1, 2, 3, 4];
     /// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0);
-    /// assert_eq!(even, vec![2, 4]);
-    /// assert_eq!(odd, vec![1, 3]);
+    /// assert_eq!(even, [2, 4]);
+    /// assert_eq!(odd, [1, 3]);
     /// ```
     #[unstable(feature = "core",
                reason = "recently added as part of collections reform")]
@@ -978,7 +981,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     #[unstable(feature = "core", reason = "recent addition")]
     fn cloned(self) -> Cloned<Self> where
         Self::Item: Deref,
-        <Self::Item as Deref>::Output: Clone,
+        <Self::Item as Deref>::Target: Clone,
     {
         Cloned { it: self }
     }
@@ -1783,6 +1786,10 @@ pub struct Peekable<I: Iterator> {
     peeked: Option<I::Item>,
 }
 
+// FIXME: after #22828 being fixed, the following unsafe impl should be removed
+unsafe impl<I: Iterator> Sync for Peekable<I> where I: Sync, I::Item: Sync {}
+unsafe impl<I: Iterator> Send for Peekable<I> where I: Send, I::Item: Send {}
+
 impl<I: Iterator + Clone> Clone for Peekable<I> where I::Item: Clone {
     fn clone(&self) -> Peekable<I> {
         Peekable {
@@ -2592,7 +2599,29 @@ pub struct RangeStep<A> {
     rev: bool,
 }
 
-/// Return an iterator over the range [start, stop) by `step`. It handles overflow by stopping.
+/// Return an iterator over the range [start, stop) by `step`.
+///
+/// It handles overflow by stopping.
+///
+/// # Examples
+///
+/// ```
+/// use std::iter::range_step;
+///
+/// for i in range_step(0, 10, 2) {
+///     println!("{}", i);
+/// }
+/// ```
+///
+/// This prints:
+///
+/// ```text
+/// 0
+/// 2
+/// 4
+/// 6
+/// 8
+/// ```
 #[inline]
 #[unstable(feature = "core",
            reason = "likely to be replaced by range notation and adapters")]
@@ -2633,7 +2662,30 @@ pub struct RangeStepInclusive<A> {
     done: bool,
 }
 
-/// Return an iterator over the range [start, stop] by `step`. It handles overflow by stopping.
+/// Return an iterator over the range [start, stop] by `step`.
+///
+/// It handles overflow by stopping.
+///
+/// # Examples
+///
+/// ```
+/// use std::iter::range_step_inclusive;
+///
+/// for i in range_step_inclusive(0, 10, 2) {
+///     println!("{}", i);
+/// }
+/// ```
+///
+/// This prints:
+///
+/// ```text
+/// 0
+/// 2
+/// 4
+/// 6
+/// 8
+/// 10
+/// ```
 #[inline]
 #[unstable(feature = "core",
            reason = "likely to be replaced by range notation and adapters")]
index 3c58480ff0cfa1d70275b9f04bf6931782575468..a9d699735908529c52614531693ecc54adacbed7 100644 (file)
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(rustc_attrs)]
+#![feature(optin_builtin_traits)]
 
 #[macro_use]
 mod macros;
 
+#[macro_use]
+mod cmp_macros;
+
 #[path = "num/float_macros.rs"]
 #[macro_use]
 mod float_macros;
index 943365d8454d4629ed65a6757aa17ef28817e961..94ca9ec37b49b515523e2e6ed713e1df3c6074cb 100644 (file)
@@ -15,7 +15,7 @@ macro_rules! panic {
         panic!("explicit panic")
     );
     ($msg:expr) => ({
-        static _MSG_FILE_LINE: (&'static str, &'static str, usize) = ($msg, file!(), line!());
+        static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
         ::core::panicking::panic(&_MSG_FILE_LINE)
     });
     ($fmt:expr, $($arg:tt)*) => ({
@@ -23,7 +23,7 @@ macro_rules! panic {
         // used inside a dead function. Just `#[allow(dead_code)]` is
         // insufficient, since the user may have
         // `#[forbid(dead_code)]` and which cannot be overridden.
-        static _FILE_LINE: (&'static str, usize) = (file!(), line!());
+        static _FILE_LINE: (&'static str, u32) = (file!(), line!());
         ::core::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
     });
 }
index d284eb341792b4d363c3cd6896346b7db581a32d..6c934a998de2d4cb5d64ce35d135ce12f312bc0d 100644 (file)
 use hash::Hash;
 use hash::Hasher;
 
-/// Types able to be transferred across thread boundaries.
-#[unstable(feature = "core",
-           reason = "will be overhauled with new lifetime rules; see RFC 458")]
-#[lang="send"]
-#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-#[cfg(stage0)]
-pub unsafe trait Send: 'static {
-    // empty.
-}
 /// Types able to be transferred across thread boundaries.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang="send"]
 #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-#[cfg(not(stage0))]
 pub unsafe trait Send : MarkerTrait {
     // empty.
 }
 
+impl<T> !Send for *const T { }
+impl<T> !Send for *mut T { }
+impl !Send for Managed { }
+
 /// Types with a constant size known at compile-time.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang="sized"]
@@ -214,6 +208,10 @@ pub unsafe trait Sync : MarkerTrait {
     // Empty
 }
 
+impl<T> !Sync for *const T { }
+impl<T> !Sync for *mut T { }
+impl !Sync for Managed { }
+
 /// A type which is considered "not POD", meaning that it is not
 /// implicitly copyable. This is typically embedded in other types to
 /// ensure that they are never copied, even if they lack a destructor.
@@ -233,13 +231,6 @@ pub unsafe trait Sync : MarkerTrait {
 
 macro_rules! impls{
     ($t: ident) => (
-        #[cfg(stage0)]
-        impl<T:?Sized, S: Hasher> Hash<S> for $t<T> {
-            #[inline]
-            fn hash(&self, _: &mut S) {
-            }
-        }
-        #[cfg(not(stage0))]
         impl<T:?Sized> Hash for $t<T> {
             #[inline]
             fn hash<H: Hasher>(&self, _: &mut H) {
@@ -348,14 +339,6 @@ impl<T:?Sized> MarkerTrait for T { }
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
 
-#[cfg(stage0)] // built into the trait matching system after stage0
-impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
-
-/// Specific to stage0. You should not be seeing these docs!
-#[cfg(stage0)]
-#[lang="covariant_type"] // only relevant to stage0
-pub struct PhantomData<T:?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>`
@@ -374,14 +357,12 @@ impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
 /// here! For now, please see [RFC 738][738] for more information.
 ///
 /// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
-#[cfg(not(stage0))]
 #[lang="phantom_data"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct PhantomData<T:?Sized>;
 
 impls! { PhantomData }
 
-#[cfg(not(stage0))]
 mod impls {
     use super::{Send, Sync, Sized};
 
@@ -417,7 +398,6 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 #[unstable(feature = "core", reason = "deprecated")]
 #[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
 #[lang="covariant_type"]
-#[cfg(not(stage0))]
 pub struct CovariantType<T>;
 
 /// Old-style marker trait. Deprecated.
index 740997b7a249d5a6fcdf472c2e5c277f472a0327..2aa8ec0c548d958b4c20eeb8b57ca68908b469fb 100644 (file)
@@ -203,9 +203,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
         let mut t: T = uninitialized();
 
         // Perform the swap, `&mut` pointers never alias
-        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
-        ptr::copy_nonoverlapping_memory(x, &*y, 1);
-        ptr::copy_nonoverlapping_memory(y, &t, 1);
+        ptr::copy_nonoverlapping(&mut t, &*x, 1);
+        ptr::copy_nonoverlapping(x, &*y, 1);
+        ptr::copy_nonoverlapping(y, &t, 1);
 
         // y and t now point to the same thing, but we need to completely forget `t`
         // because it's no longer relevant.
index 7612469c8088bbfe3c30579d02e28f48aa4482fd..b1039f79f23de1989343683d2d4cc99cd528a906 100644 (file)
@@ -1672,6 +1672,7 @@ fn from_str_radix(src: &str, radix: u32)
                 let is_signed_ty = (0 as $T) > Int::min_value();
 
                 match src.slice_shift_char() {
+                    Some(('-', "")) => Err(PIE { kind: Empty }),
                     Some(('-', src)) if is_signed_ty => {
                         // The number is negative
                         let mut result = 0;
index fbd7f840da6e15748e2972899771deaa7b5307d5..c382ac46d5db9895a99241e95d32291f3da1650e 100644 (file)
@@ -184,6 +184,7 @@ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
 #[lang="add"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Add<RHS=Self> {
+    /// The resulting type after applying the `+` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -237,6 +238,7 @@ fn add(self, other: $t) -> $t { self + other }
 #[lang="sub"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Sub<RHS=Self> {
+    /// The resulting type after applying the `-` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -290,6 +292,7 @@ fn sub(self, other: $t) -> $t { self - other }
 #[lang="mul"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Mul<RHS=Self> {
+    /// The resulting type after applying the `*` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -343,6 +346,7 @@ fn mul(self, other: $t) -> $t { self * other }
 #[lang="div"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Div<RHS=Self> {
+    /// The resulting type after applying the `/` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -396,6 +400,7 @@ fn div(self, other: $t) -> $t { self / other }
 #[lang="rem"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Rem<RHS=Self> {
+    /// The resulting type after applying the `%` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output = Self;
 
@@ -468,6 +473,7 @@ fn rem(self, other: $t) -> $t {
 #[lang="neg"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Neg {
+    /// The resulting type after applying the `-` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -544,6 +550,7 @@ fn neg(self) -> $t { -(self as $t_signed) as $t }
 #[lang="not"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Not {
+    /// The resulting type after applying the `!` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -597,6 +604,7 @@ fn not(self) -> $t { !self }
 #[lang="bitand"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitAnd<RHS=Self> {
+    /// The resulting type after applying the `&` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -650,6 +658,7 @@ fn bitand(self, rhs: $t) -> $t { self & rhs }
 #[lang="bitor"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitOr<RHS=Self> {
+    /// The resulting type after applying the `|` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -703,6 +712,7 @@ fn bitor(self, rhs: $t) -> $t { self | rhs }
 #[lang="bitxor"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitXor<RHS=Self> {
+    /// The resulting type after applying the `^` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -756,6 +766,7 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
 #[lang="shl"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Shl<RHS> {
+    /// The resulting type after applying the `<<` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -827,6 +838,7 @@ macro_rules! shl_impl_all {
 #[lang="shr"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Shr<RHS> {
+    /// The resulting type after applying the `>>` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -900,6 +912,7 @@ macro_rules! shr_impl_all {
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Index<Idx: ?Sized> {
+    /// The returned type after indexing
     type Output: ?Sized;
 
     /// The method for the indexing (`Foo[Bar]`) operation
@@ -1047,6 +1060,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 #[lang="deref"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
+    /// The resulting type after dereferencing
     #[stable(feature = "rust1", since = "1.0.0")]
     type Target: ?Sized;
 
@@ -1122,6 +1136,7 @@ fn deref_mut(&mut self) -> &mut T { *self }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
 pub trait Fn<Args> {
+    /// The returned type after the call operator is used.
     type Output;
 
     /// This is called when the call operator is used.
@@ -1133,6 +1148,7 @@ pub trait Fn<Args> {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
 pub trait FnMut<Args> {
+    /// The returned type after the call operator is used.
     type Output;
 
     /// This is called when the call operator is used.
@@ -1144,6 +1160,7 @@ pub trait FnMut<Args> {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
 pub trait FnOnce<Args> {
+    /// The returned type after the call operator is used.
     type Output;
 
     /// This is called when the call operator is used.
index abfef72a5dbc33b735a67416a191f2e1b093600c..1ecbd8fae8cdb664b5f9549a358ea6c7cb7b7b01 100644 (file)
@@ -556,7 +556,7 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     /// ```
     /// let x = Some("string");
     /// let v: Vec<&str> = x.into_iter().collect();
-    /// assert_eq!(v, vec!["string"]);
+    /// assert_eq!(v, ["string"]);
     ///
     /// let x = None;
     /// let v: Vec<&str> = x.into_iter().collect();
index 61b4284e1dd9c08aa617571da9e4d08356846ed0..c1c8ac9cc1fa789441485d917af8e5b558c59f2d 100644 (file)
 
 #[cold] #[inline(never)] // this is the slow path, always
 #[lang="panic"]
-pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
+pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
     let (expr, file, line) = *expr_file_line;
     panic_fmt(format_args!("{}", expr), &(file, line))
 }
 
 #[cold] #[inline(never)]
 #[lang="panic_bounds_check"]
-fn panic_bounds_check(file_line: &(&'static str, uint),
-                     index: uint, len: uint) -> ! {
+fn panic_bounds_check(file_line: &(&'static str, u32),
+                     index: usize, len: usize) -> ! {
     panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
                            len, index), file_line)
 }
 
 #[cold] #[inline(never)]
-pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
+pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
     #[allow(improper_ctypes)]
     extern {
         #[lang = "panic_fmt"]
         fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
     }
     let (file, line) = *file_line;
-    unsafe { panic_impl(fmt, file, line) }
+    unsafe { panic_impl(fmt, file, line as uint) }
 }
index 16b84dcf18e24aed5952b17cfbf1b7f45b1648c0..0625c3c7d6018e26d4e36f2c0a43246cd6794d88 100644 (file)
 
 // FIXME #19649: intrinsic docs don't render, so these have no docs :(
 
-#[unstable(feature = "core")]
-pub use intrinsics::copy_nonoverlapping_memory;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use intrinsics::copy_nonoverlapping_memory as copy_nonoverlapping;
 
-#[unstable(feature = "core")]
-pub use intrinsics::copy_memory;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use intrinsics::copy_memory as copy;
 
-#[unstable(feature = "core",
-           reason = "uncertain about naming and semantics")]
-pub use intrinsics::set_memory;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use intrinsics::set_memory as write_bytes;
 
+extern "rust-intrinsic" {
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `copy_nonoverlapping`")]
+    pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `copy`")]
+    pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
+
+    #[unstable(feature = "core",
+               reason = "uncertain about naming and semantics")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `write_bytes`")]
+    pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
+}
 
 /// Creates a null raw pointer.
 ///
@@ -150,8 +162,9 @@ pub fn null_mut<T>() -> *mut T { 0 as *mut 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) {
-    set_memory(dst, 0, count);
+    write_bytes(dst, 0, count);
 }
 
 /// Swaps the values at two mutable locations of the same type, without
@@ -169,9 +182,9 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     let t: *mut T = &mut tmp;
 
     // Perform the swap
-    copy_nonoverlapping_memory(t, &*x, 1);
-    copy_memory(x, &*y, 1); // `x` and `y` may overlap
-    copy_nonoverlapping_memory(y, &*t, 1);
+    copy_nonoverlapping(t, &*x, 1);
+    copy(x, &*y, 1); // `x` and `y` may overlap
+    copy_nonoverlapping(y, &*t, 1);
 
     // y and t now point to the same thing, but we need to completely forget `tmp`
     // because it's no longer relevant.
@@ -207,7 +220,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
     let mut tmp: T = mem::uninitialized();
-    copy_nonoverlapping_memory(&mut tmp, src, 1);
+    copy_nonoverlapping(&mut tmp, src, 1);
     tmp
 }
 
@@ -224,7 +237,7 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     let tmp = read(&*dest);
 
     // Now zero out `dest`:
-    zero_memory(dest, 1);
+    write_bytes(dest, 0, 1);
 
     tmp
 }
@@ -248,8 +261,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 
 /// Methods on raw pointers
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait PtrExt: Sized {
-    type Target;
+pub trait PtrExt {
+    /// The type which is being pointed at
+    type Target: ?Sized;
 
     /// Returns true if the pointer is null.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -278,13 +292,14 @@ pub trait PtrExt: Sized {
     /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
     /// the pointer is used.
     #[stable(feature = "rust1", since = "1.0.0")]
-    unsafe fn offset(self, count: isize) -> Self;
+    unsafe fn offset(self, count: isize) -> Self where Self::Target: Sized;
 }
 
 /// Methods on mutable raw pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait MutPtrExt {
-    type Target;
+    /// The type which is being pointed at
+    type Target: ?Sized;
 
     /// Returns `None` if the pointer is null, or else returns a mutable
     /// reference to the value wrapped in `Some`.
@@ -300,7 +315,7 @@ pub trait MutPtrExt {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PtrExt for *const T {
+impl<T: ?Sized> PtrExt for *const T {
     type Target = T;
 
     #[inline]
@@ -309,7 +324,7 @@ fn is_null(self) -> bool { self == 0 as *const T }
 
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    unsafe fn offset(self, count: isize) -> *const T {
+    unsafe fn offset(self, count: isize) -> *const T where T: Sized {
         intrinsics::offset(self, count)
     }
 
@@ -327,7 +342,7 @@ unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PtrExt for *mut T {
+impl<T: ?Sized> PtrExt for *mut T {
     type Target = T;
 
     #[inline]
@@ -336,7 +351,7 @@ fn is_null(self) -> bool { self == 0 as *mut T }
 
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    unsafe fn offset(self, count: isize) -> *mut T {
+    unsafe fn offset(self, count: isize) -> *mut T where T: Sized {
         intrinsics::offset(self, count) as *mut T
     }
 
@@ -354,7 +369,7 @@ unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> MutPtrExt for *mut T {
+impl<T: ?Sized> MutPtrExt for *mut T {
     type Target = T;
 
     #[inline]
@@ -372,33 +387,25 @@ unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> {
 
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialEq for *const T {
+impl<T: ?Sized> PartialEq for *const T {
     #[inline]
-    fn eq(&self, other: &*const T) -> bool {
-        *self == *other
-    }
-    #[inline]
-    fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
+    fn eq(&self, other: &*const T) -> bool { *self == *other }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Eq for *const T {}
+impl<T: ?Sized> Eq for *const T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialEq for *mut T {
-    #[inline]
-    fn eq(&self, other: &*mut T) -> bool {
-        *self == *other
-    }
+impl<T: ?Sized> PartialEq for *mut T {
     #[inline]
-    fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
+    fn eq(&self, other: &*mut T) -> bool { *self == *other }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Eq for *mut T {}
+impl<T: ?Sized> Eq for *mut T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for *const T {
+impl<T: ?Sized> Clone for *const T {
     #[inline]
     fn clone(&self) -> *const T {
         *self
@@ -406,7 +413,7 @@ fn clone(&self) -> *const T {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for *mut T {
+impl<T: ?Sized> Clone for *mut T {
     #[inline]
     fn clone(&self) -> *mut T {
         *self
@@ -450,7 +457,7 @@ fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
 
 // Comparison for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Ord for *const T {
+impl<T: ?Sized> Ord for *const T {
     #[inline]
     fn cmp(&self, other: &*const T) -> Ordering {
         if self < other {
@@ -464,7 +471,7 @@ fn cmp(&self, other: &*const T) -> Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialOrd for *const T {
+impl<T: ?Sized> PartialOrd for *const T {
     #[inline]
     fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -484,7 +491,7 @@ fn ge(&self, other: &*const T) -> bool { *self >= *other }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Ord for *mut T {
+impl<T: ?Sized> Ord for *mut T {
     #[inline]
     fn cmp(&self, other: &*mut T) -> Ordering {
         if self < other {
@@ -498,7 +505,7 @@ fn cmp(&self, other: &*mut T) -> Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialOrd for *mut T {
+impl<T: ?Sized> PartialOrd for *mut T {
     #[inline]
     fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -525,8 +532,8 @@ fn ge(&self, other: &*mut T) -> bool { *self >= *other }
 /// modified without a unique path to the `Unique` reference. Useful
 /// for building abstractions like `Vec<T>` or `Box<T>`, which
 /// internally use raw pointers to manage the memory that they own.
-#[unstable(feature = "core", reason = "recently added to this module")]
-pub struct Unique<T:?Sized> {
+#[unstable(feature = "unique")]
+pub struct Unique<T: ?Sized> {
     pointer: NonZero<*const T>,
     _marker: PhantomData<T>,
 }
@@ -535,39 +542,37 @@ pub struct Unique<T:?Sized> {
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "core", reason = "recently added to this module")]
+#[unstable(feature = "unique")]
 unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "core", reason = "recently added to this module")]
+#[unstable(feature = "unique")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
-impl<T:?Sized> Unique<T> {
+impl<T: ?Sized> Unique<T> {
     /// Create a new `Unique`.
-    #[unstable(feature = "core",
-               reason = "recently added to this module")]
+    #[unstable(feature = "unique")]
     pub unsafe fn new(ptr: *mut T) -> Unique<T> {
         Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
     }
 
     /// Dereference the content.
-    #[unstable(feature = "core",
-               reason = "recently added to this module")]
+    #[unstable(feature = "unique")]
     pub unsafe fn get(&self) -> &T {
         &**self.pointer
     }
 
     /// Mutably dereference the content.
-    #[unstable(feature = "core",
-               reason = "recently added to this module")]
+    #[unstable(feature = "unique")]
     pub unsafe fn get_mut(&mut self) -> &mut T {
         &mut ***self
     }
 }
 
+#[unstable(feature = "unique")]
 impl<T:?Sized> Deref for Unique<T> {
     type Target = *mut T;
 
index 23e936a75d7097e04f972a3da25796a285090711..bca73782491bf5fe30571f61665babdbf2163767 100644 (file)
@@ -548,11 +548,11 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     /// ```
     /// let x: Result<u32, &str> = Ok(5);
     /// let v: Vec<u32> = x.into_iter().collect();
-    /// assert_eq!(v, vec![5]);
+    /// assert_eq!(v, [5]);
     ///
     /// let x: Result<u32, &str> = Err("nothing!");
     /// let v: Vec<u32> = x.into_iter().collect();
-    /// assert_eq!(v, vec![]);
+    /// assert_eq!(v, []);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
index a86da53b372a9bfc2b14969f445fc7ad1be40465..91cad4330f20464441fdf623ee39219dcf81f58c 100644 (file)
@@ -51,7 +51,7 @@
 use ptr::PtrExt;
 use mem;
 use mem::size_of;
-use marker::{Sized, self};
+use marker::{Send, Sized, Sync, self};
 use raw::Repr;
 // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
 use raw::Slice as RawSlice;
@@ -657,6 +657,8 @@ impl<'a, T> Iterator for $name<'a, T> {
             fn next(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
                 unsafe {
+                    ::intrinsics::assume(!self.ptr.is_null());
+                    ::intrinsics::assume(!self.end.is_null());
                     if self.ptr == self.end {
                         None
                     } else {
@@ -693,6 +695,8 @@ impl<'a, T> DoubleEndedIterator for $name<'a, T> {
             fn next_back(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
                 unsafe {
+                    ::intrinsics::assume(!self.ptr.is_null());
+                    ::intrinsics::assume(!self.end.is_null());
                     if self.end == self.ptr {
                         None
                     } else {
@@ -736,6 +740,9 @@ pub struct Iter<'a, T: 'a> {
     _marker: marker::PhantomData<&'a T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
+unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
+
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<usize>> for Iter<'a, T> {
     type Output = [T];
@@ -826,6 +833,8 @@ pub struct IterMut<'a, T: 'a> {
     _marker: marker::PhantomData<&'a mut T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
+unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
 
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<usize>> for IterMut<'a, T> {
@@ -1496,7 +1505,7 @@ pub trait MutableByteVector {
     impl MutableByteVector for [u8] {
         #[inline]
         fn set_memory(&mut self, value: u8) {
-            unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) };
+            unsafe { ptr::write_bytes(self.as_mut_ptr(), value, self.len()) };
         }
     }
 
@@ -1510,9 +1519,9 @@ pub fn copy_memory(dst: &mut [u8], src: &[u8]) {
         // `dst` is unaliasable, so we know statically it doesn't overlap
         // with `src`.
         unsafe {
-            ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(),
-                                            src.as_ptr(),
-                                            len_src);
+            ptr::copy_nonoverlapping(dst.as_mut_ptr(),
+                                     src.as_ptr(),
+                                     len_src);
         }
     }
 }
index eec997b9f10fc76f3090ae58a4d59b5655c1f2b5..7e51f8e8503b411e4c62ba740aff3d23a0e112a7 100644 (file)
@@ -16,7 +16,7 @@
 
 #![doc(primitive = "str")]
 
-use self::Searcher::{Naive, TwoWay, TwoWayLong};
+use self::OldSearcher::{TwoWay, TwoWayLong};
 
 use clone::Clone;
 use cmp::{self, Eq};
 use slice::{self, SliceExt};
 use usize;
 
+pub use self::pattern::Pattern;
+pub use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher, SearchStep};
+
+mod pattern;
+
 macro_rules! delegate_iter {
     (exact $te:ty : $ti:ty) => {
         delegate_iter!{$te : $ti}
@@ -70,7 +75,7 @@ fn next_back(&mut self) -> Option<$te> {
     };
     (pattern $te:ty : $ti:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, P: CharEq> Iterator for $ti {
+        impl<'a, P: Pattern<'a>> Iterator for $ti {
             type Item = $te;
 
             #[inline]
@@ -83,7 +88,8 @@ fn size_hint(&self) -> (usize, Option<usize>) {
             }
         }
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, P: CharEq> DoubleEndedIterator for $ti {
+        impl<'a, P: Pattern<'a>> DoubleEndedIterator for $ti
+        where P::Searcher: DoubleEndedSearcher<'a> {
             #[inline]
             fn next_back(&mut self) -> Option<$te> {
                 self.0.next_back()
@@ -92,7 +98,8 @@ fn next_back(&mut self) -> Option<$te> {
     };
     (pattern forward $te:ty : $ti:ty) => {
         #[stable(feature = "rust1", since = "1.0.0")]
-        impl<'a, P: CharEq> Iterator for $ti {
+        impl<'a, P: Pattern<'a>> Iterator for $ti
+        where P::Searcher: DoubleEndedSearcher<'a> {
             type Item = $te;
 
             #[inline]
@@ -235,8 +242,10 @@ pub unsafe fn from_c_str(s: *const i8) -> &'static str {
 }
 
 /// Something that can be used to compare against a character
-#[unstable(feature = "core",
-           reason = "definition may change as pattern-related methods are stabilized")]
+#[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;
@@ -245,6 +254,7 @@ pub trait CharEq {
     fn only_ascii(&self) -> bool;
 }
 
+#[allow(deprecated) /* for CharEq */ ]
 impl CharEq for char {
     #[inline]
     fn matches(&mut self, c: char) -> bool { *self == c }
@@ -253,6 +263,7 @@ fn matches(&mut self, c: char) -> bool { *self == c }
     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) }
@@ -261,13 +272,16 @@ fn matches(&mut self, c: char) -> bool { (*self)(c) }
     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())
     }
@@ -337,6 +351,7 @@ fn unwrap_or_0(opt: Option<&u8>) -> u8 {
 /// Reads the next code point out of a byte iterator (assuming a
 /// UTF-8-like encoding).
 #[unstable(feature = "core")]
+#[inline]
 pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
     // Decode UTF-8
     let x = match bytes.next() {
@@ -368,6 +383,38 @@ pub fn next_code_point(bytes: &mut slice::Iter<u8>) -> Option<u32> {
     Some(ch)
 }
 
+/// Reads the last code point out of a byte iterator (assuming a
+/// UTF-8-like encoding).
+#[unstable(feature = "core")]
+#[inline]
+pub fn next_code_point_reverse(bytes: &mut slice::Iter<u8>) -> Option<u32> {
+    // Decode UTF-8
+    let w = match bytes.next_back() {
+        None => return None,
+        Some(&next_byte) if next_byte < 128 => return Some(next_byte as u32),
+        Some(&back_byte) => back_byte,
+    };
+
+    // Multibyte case follows
+    // Decode from a byte combination out of: [x [y [z w]]]
+    let mut ch;
+    let z = unwrap_or_0(bytes.next_back());
+    ch = utf8_first_byte!(z, 2);
+    if utf8_is_cont_byte!(z) {
+        let y = unwrap_or_0(bytes.next_back());
+        ch = utf8_first_byte!(y, 3);
+        if utf8_is_cont_byte!(y) {
+            let x = unwrap_or_0(bytes.next_back());
+            ch = utf8_first_byte!(x, 4);
+            ch = utf8_acc_cont_byte!(ch, y);
+        }
+        ch = utf8_acc_cont_byte!(ch, z);
+    }
+    ch = utf8_acc_cont_byte!(ch, w);
+
+    Some(ch)
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Iterator for Chars<'a> {
     type Item = char;
@@ -393,33 +440,12 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 impl<'a> DoubleEndedIterator for Chars<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<char> {
-        let w = match self.iter.next_back() {
-            None => return None,
-            Some(&back_byte) if back_byte < 128 => return Some(back_byte as char),
-            Some(&back_byte) => back_byte,
-        };
-
-        // Multibyte case follows
-        // Decode from a byte combination out of: [x [y [z w]]]
-        let mut ch;
-        let z = unwrap_or_0(self.iter.next_back());
-        ch = utf8_first_byte!(z, 2);
-        if utf8_is_cont_byte!(z) {
-            let y = unwrap_or_0(self.iter.next_back());
-            ch = utf8_first_byte!(y, 3);
-            if utf8_is_cont_byte!(y) {
-                let x = unwrap_or_0(self.iter.next_back());
-                ch = utf8_first_byte!(x, 4);
-                ch = utf8_acc_cont_byte!(ch, y);
+        next_code_point_reverse(&mut self.iter).map(|ch| {
+            // str invariant says `ch` is a valid Unicode Scalar Value
+            unsafe {
+                mem::transmute(ch)
             }
-            ch = utf8_acc_cont_byte!(ch, z);
-        }
-        ch = utf8_acc_cont_byte!(ch, w);
-
-        // str invariant says `ch` is a valid Unicode Scalar Value
-        unsafe {
-            Some(mem::transmute(ch))
-        }
+        })
     }
 }
 
@@ -495,22 +521,20 @@ extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
 }
 
 /// An iterator over the substrings of a string, separated by `sep`.
-#[derive(Clone)]
-struct CharSplits<'a, Sep> {
+struct CharSplits<'a, P: Pattern<'a>> {
     /// The slice remaining to be iterated
-    string: &'a str,
-    sep: Sep,
+    start: usize,
+    end: usize,
+    matcher: P::Searcher,
     /// Whether an empty string at the end is allowed
     allow_trailing_empty: bool,
-    only_ascii: bool,
     finished: bool,
 }
 
 /// An iterator over the substrings of a string, separated by `sep`,
 /// splitting at most `count` times.
-#[derive(Clone)]
-struct CharSplitsN<'a, Sep> {
-    iter: CharSplits<'a, Sep>,
+struct CharSplitsN<'a, P: Pattern<'a>> {
+    iter: CharSplits<'a, P>,
     /// The number of splits remaining
     count: usize,
     invert: bool,
@@ -528,12 +552,15 @@ pub struct LinesAny<'a> {
     inner: Map<Lines<'a>, fn(&str) -> &str>,
 }
 
-impl<'a, Sep> CharSplits<'a, Sep> {
+impl<'a, P: Pattern<'a>> CharSplits<'a, P> {
     #[inline]
     fn get_end(&mut self) -> Option<&'a str> {
-        if !self.finished && (self.allow_trailing_empty || self.string.len() > 0) {
+        if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) {
             self.finished = true;
-            Some(self.string)
+            unsafe {
+                let string = self.matcher.haystack().slice_unchecked(self.start, self.end);
+                Some(string)
+            }
         } else {
             None
         }
@@ -541,33 +568,18 @@ fn get_end(&mut self) -> Option<&'a str> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, Sep: CharEq> Iterator for CharSplits<'a, Sep> {
+impl<'a, P: Pattern<'a>> Iterator for CharSplits<'a, P> {
     type Item = &'a str;
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
         if self.finished { return None }
 
-        let mut next_split = None;
-        if self.only_ascii {
-            for (idx, byte) in self.string.bytes().enumerate() {
-                if self.sep.matches(byte as char) && byte < 128u8 {
-                    next_split = Some((idx, idx + 1));
-                    break;
-                }
-            }
-        } else {
-            for (idx, ch) in self.string.char_indices() {
-                if self.sep.matches(ch) {
-                    next_split = Some((idx, self.string.char_range_at(idx).next));
-                    break;
-                }
-            }
-        }
-        match next_split {
+        let haystack = self.matcher.haystack();
+        match self.matcher.next_match() {
             Some((a, b)) => unsafe {
-                let elt = self.string.slice_unchecked(0, a);
-                self.string = self.string.slice_unchecked(b, self.string.len());
+                let elt = haystack.slice_unchecked(self.start, a);
+                self.start = b;
                 Some(elt)
             },
             None => self.get_end(),
@@ -576,7 +588,8 @@ fn next(&mut self) -> Option<&'a str> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, Sep: CharEq> DoubleEndedIterator for CharSplits<'a, Sep> {
+impl<'a, P: Pattern<'a>> DoubleEndedIterator for CharSplits<'a, P>
+where P::Searcher: DoubleEndedSearcher<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a str> {
         if self.finished { return None }
@@ -588,37 +601,25 @@ fn next_back(&mut self) -> Option<&'a str> {
                 _ => if self.finished { return None }
             }
         }
-        let len = self.string.len();
-        let mut next_split = None;
-
-        if self.only_ascii {
-            for (idx, byte) in self.string.bytes().enumerate().rev() {
-                if self.sep.matches(byte as char) && byte < 128u8 {
-                    next_split = Some((idx, idx + 1));
-                    break;
-                }
-            }
-        } else {
-            for (idx, ch) in self.string.char_indices().rev() {
-                if self.sep.matches(ch) {
-                    next_split = Some((idx, self.string.char_range_at(idx).next));
-                    break;
-                }
-            }
-        }
-        match next_split {
+
+        let haystack = self.matcher.haystack();
+        match self.matcher.next_match_back() {
             Some((a, b)) => unsafe {
-                let elt = self.string.slice_unchecked(b, len);
-                self.string = self.string.slice_unchecked(0, a);
+                let elt = haystack.slice_unchecked(b, self.end);
+                self.end = a;
                 Some(elt)
             },
-            None => { self.finished = true; Some(self.string) }
+            None => unsafe {
+                self.finished = true;
+                Some(haystack.slice_unchecked(self.start, self.end))
+            },
         }
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, Sep: CharEq> Iterator for CharSplitsN<'a, Sep> {
+impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P>
+where P::Searcher: DoubleEndedSearcher<'a> {
     type Item = &'a str;
 
     #[inline]
@@ -632,32 +633,6 @@ fn next(&mut self) -> Option<&'a str> {
     }
 }
 
-/// The internal state of an iterator that searches for matches of a substring
-/// within a larger string using naive search
-#[derive(Clone)]
-struct NaiveSearcher {
-    position: usize
-}
-
-impl NaiveSearcher {
-    fn new() -> NaiveSearcher {
-        NaiveSearcher { position: 0 }
-    }
-
-    fn next(&mut self, haystack: &[u8], needle: &[u8]) -> Option<(usize, usize)> {
-        while self.position + needle.len() <= haystack.len() {
-            if &haystack[self.position .. self.position + needle.len()] == needle {
-                let match_pos = self.position;
-                self.position += needle.len(); // add 1 for all matches
-                return Some((match_pos, match_pos + needle.len()));
-            } else {
-                self.position += 1;
-            }
-        }
-        None
-    }
-}
-
 /// The internal state of an iterator that searches for matches of a substring
 /// within a larger string using two-way search
 #[derive(Clone)]
@@ -743,6 +718,7 @@ struct TwoWaySearcher {
 
 */
 impl TwoWaySearcher {
+    #[allow(dead_code)]
     fn new(needle: &[u8]) -> TwoWaySearcher {
         let (crit_pos_false, period_false) = TwoWaySearcher::maximal_suffix(needle, false);
         let (crit_pos_true, period_true) = TwoWaySearcher::maximal_suffix(needle, true);
@@ -852,6 +828,7 @@ fn next(&mut self, haystack: &[u8], needle: &[u8], long_period: bool)
     // Specifically, returns (i, p), where i is the starting index of v in some
     // critical factorization (u, v) and p = period(v)
     #[inline]
+    #[allow(dead_code)]
     fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) {
         let mut left = -1; // Corresponds to i in the paper
         let mut right = 0; // Corresponds to j in the paper
@@ -896,20 +873,26 @@ fn maximal_suffix(arr: &[u8], reversed: bool) -> (usize, usize) {
 /// The internal state of an iterator that searches for matches of a substring
 /// within a larger string using a dynamically chosen search algorithm
 #[derive(Clone)]
-enum Searcher {
-    Naive(NaiveSearcher),
+// NB: This is kept around for convenience because
+// it is planned to be used again in the future
+enum OldSearcher {
     TwoWay(TwoWaySearcher),
-    TwoWayLong(TwoWaySearcher)
+    TwoWayLong(TwoWaySearcher),
 }
 
-impl Searcher {
-    fn new(haystack: &[u8], needle: &[u8]) -> Searcher {
+impl OldSearcher {
+    #[allow(dead_code)]
+    fn new(haystack: &[u8], needle: &[u8]) -> OldSearcher {
+        if needle.len() == 0 {
+            // Handle specially
+            unimplemented!()
         // FIXME: Tune this.
         // FIXME(#16715): This unsigned integer addition will probably not
         // overflow because that would mean that the memory almost solely
         // consists of the needle. Needs #16715 to be formally fixed.
-        if needle.len() + 20 > haystack.len() {
-            Naive(NaiveSearcher::new())
+        } else if needle.len() + 20 > haystack.len() {
+            // Use naive searcher
+            unimplemented!()
         } else {
             let searcher = TwoWaySearcher::new(needle);
             if searcher.memory == usize::MAX { // If the period is long
@@ -921,67 +904,59 @@ fn new(haystack: &[u8], needle: &[u8]) -> Searcher {
     }
 }
 
-/// An iterator over the start and end indices of the matches of a
-/// substring within a larger string
 #[derive(Clone)]
-#[unstable(feature = "core", reason = "type may be removed")]
-pub struct MatchIndices<'a> {
+// NB: This is kept around for convenience because
+// it is planned to be used again in the future
+struct OldMatchIndices<'a, 'b> {
     // constants
     haystack: &'a str,
-    needle: &'a str,
-    searcher: Searcher
+    needle: &'b str,
+    searcher: OldSearcher
 }
 
-/// An iterator over the substrings of a string separated by a given
-/// search string
-#[derive(Clone)]
+// FIXME: #21637 Prevents a Clone impl
+/// An iterator over the start and end indices of the matches of a
+/// substring within a larger string
 #[unstable(feature = "core", reason = "type may be removed")]
-pub struct SplitStr<'a> {
-    it: MatchIndices<'a>,
-    last_end: usize,
-    finished: bool
-}
+pub struct MatchIndices<'a, P: Pattern<'a>>(P::Searcher);
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Iterator for MatchIndices<'a> {
+impl<'a, P: Pattern<'a>> Iterator for MatchIndices<'a, P> {
     type Item = (usize, usize);
 
     #[inline]
     fn next(&mut self) -> Option<(usize, usize)> {
-        match self.searcher {
-            Naive(ref mut searcher)
-                => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes()),
-            TwoWay(ref mut searcher)
-                => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), false),
-            TwoWayLong(ref mut searcher)
-                => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), true)
-        }
+        self.0.next_match()
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Iterator for SplitStr<'a> {
+/// 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>);
+impl<'a, P: Pattern<'a>> Iterator for SplitStr<'a, P> {
     type Item = &'a str;
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
-        if self.finished { return None; }
+        Iterator::next(&mut self.0)
+    }
+}
 
-        match self.it.next() {
-            Some((from, to)) => {
-                let ret = Some(&self.it.haystack[self.last_end .. from]);
-                self.last_end = to;
-                ret
-            }
-            None => {
-                self.finished = true;
-                Some(&self.it.haystack[self.last_end .. self.it.haystack.len()])
-            }
+impl<'a, 'b>  OldMatchIndices<'a, 'b> {
+    #[inline]
+    #[allow(dead_code)]
+    fn next(&mut self) -> Option<(usize, usize)> {
+        match self.searcher {
+            TwoWay(ref mut searcher)
+                => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), false),
+            TwoWayLong(ref mut searcher)
+                => searcher.next(self.haystack.as_bytes(), self.needle.as_bytes(), true),
         }
     }
 }
 
-
 /*
 Section: Comparing strings
 */
@@ -1298,28 +1273,39 @@ fn as_slice(&self) -> &str { Str::as_slice(*self) }
 }
 
 /// Return type of `StrExt::split`
-#[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Split<'a, P>(CharSplits<'a, P>);
-delegate_iter!{pattern &'a str : Split<'a, P>}
+pub struct Split<'a, P: Pattern<'a>>(CharSplits<'a, P>);
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, P: Pattern<'a>> Iterator for Split<'a, P> {
+    type Item = &'a str;
+
+    #[inline]
+    fn next(&mut self) -> Option<&'a str> {
+        self.0.next()
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, P: Pattern<'a>> DoubleEndedIterator for Split<'a, P>
+where P::Searcher: DoubleEndedSearcher<'a> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.0.next_back()
+    }
+}
 
 /// Return type of `StrExt::split_terminator`
-#[derive(Clone)]
-#[unstable(feature = "core",
-           reason = "might get removed in favour of a constructor method on Split")]
-pub struct SplitTerminator<'a, P>(CharSplits<'a, P>);
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SplitTerminator<'a, P: Pattern<'a>>(CharSplits<'a, P>);
 delegate_iter!{pattern &'a str : SplitTerminator<'a, P>}
 
 /// Return type of `StrExt::splitn`
-#[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SplitN<'a, P>(CharSplitsN<'a, P>);
+pub struct SplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>);
 delegate_iter!{pattern forward &'a str : SplitN<'a, P>}
 
 /// Return type of `StrExt::rsplitn`
-#[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct RSplitN<'a, P>(CharSplitsN<'a, P>);
+pub struct RSplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>);
 delegate_iter!{pattern forward &'a str : RSplitN<'a, P>}
 
 /// Methods for string slices
@@ -1328,36 +1314,40 @@ pub trait StrExt {
     // NB there are no docs here are they're all located on the StrExt trait in
     // libcollections, not here.
 
-    fn contains(&self, pat: &str) -> bool;
-    fn contains_char<P: CharEq>(&self, pat: P) -> bool;
+    fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool;
+    fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool;
     fn chars<'a>(&'a self) -> Chars<'a>;
     fn bytes<'a>(&'a self) -> Bytes<'a>;
     fn char_indices<'a>(&'a self) -> CharIndices<'a>;
-    fn split<'a, P: CharEq>(&'a self, pat: P) -> Split<'a, P>;
-    fn splitn<'a, P: CharEq>(&'a self, count: usize, pat: P) -> SplitN<'a, P>;
-    fn split_terminator<'a, P: CharEq>(&'a self, pat: P) -> SplitTerminator<'a, P>;
-    fn rsplitn<'a, P: CharEq>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>;
-    fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a>;
-    fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a>;
+    fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P>;
+    fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P>;
+    fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P>;
+    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>;
+    fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P>;
+    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;
     fn slice_chars<'a>(&'a self, begin: usize, end: usize) -> &'a str;
     unsafe fn slice_unchecked<'a>(&'a self, begin: usize, end: usize) -> &'a str;
-    fn starts_with(&self, pat: &str) -> bool;
-    fn ends_with(&self, pat: &str) -> bool;
-    fn trim_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str;
-    fn trim_left_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str;
-    fn trim_right_matches<'a, P: CharEq>(&'a self, pat: P) -> &'a str;
+    fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool;
+    fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
+        where P::Searcher: ReverseSearcher<'a>;
+    fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: DoubleEndedSearcher<'a>;
+    fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str;
+    fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>;
     fn is_char_boundary(&self, index: usize) -> bool;
     fn char_range_at(&self, start: usize) -> CharRange;
     fn char_range_at_reverse(&self, start: usize) -> CharRange;
     fn char_at(&self, i: usize) -> char;
     fn char_at_reverse(&self, i: usize) -> char;
     fn as_bytes<'a>(&'a self) -> &'a [u8];
-    fn find<P: CharEq>(&self, pat: P) -> Option<usize>;
-    fn rfind<P: CharEq>(&self, pat: P) -> Option<usize>;
-    fn find_str(&self, pat: &str) -> Option<usize>;
+    fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
+    fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
+        where P::Searcher: ReverseSearcher<'a>;
+    fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>;
     fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
     fn subslice_offset(&self, inner: &str) -> usize;
     fn as_ptr(&self) -> *const u8;
@@ -1375,13 +1365,13 @@ fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
 
 impl StrExt for str {
     #[inline]
-    fn contains(&self, needle: &str) -> bool {
-        self.find_str(needle).is_some()
+    fn contains<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        pat.is_contained_in(self)
     }
 
     #[inline]
-    fn contains_char<P: CharEq>(&self, pat: P) -> bool {
-        self.find(pat).is_some()
+    fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        pat.is_contained_in(self)
     }
 
     #[inline]
@@ -1400,18 +1390,18 @@ fn char_indices(&self) -> CharIndices {
     }
 
     #[inline]
-    fn split<P: CharEq>(&self, pat: P) -> Split<P> {
+    fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
         Split(CharSplits {
-            string: self,
-            only_ascii: pat.only_ascii(),
-            sep: pat,
+            start: 0,
+            end: self.len(),
+            matcher: pat.into_searcher(self),
             allow_trailing_empty: true,
             finished: false,
         })
     }
 
     #[inline]
-    fn splitn<P: CharEq>(&self, count: usize, pat: P) -> SplitN<P> {
+    fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
         SplitN(CharSplitsN {
             iter: self.split(pat).0,
             count: count,
@@ -1420,7 +1410,7 @@ fn splitn<P: CharEq>(&self, count: usize, pat: P) -> SplitN<P> {
     }
 
     #[inline]
-    fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
+    fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
         SplitTerminator(CharSplits {
             allow_trailing_empty: false,
             ..self.split(pat).0
@@ -1428,7 +1418,7 @@ fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
     }
 
     #[inline]
-    fn rsplitn<P: CharEq>(&self, count: usize, pat: P) -> RSplitN<P> {
+    fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> {
         RSplitN(CharSplitsN {
             iter: self.split(pat).0,
             count: count,
@@ -1437,22 +1427,14 @@ fn rsplitn<P: CharEq>(&self, count: usize, pat: P) -> RSplitN<P> {
     }
 
     #[inline]
-    fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a> {
-        assert!(!sep.is_empty());
-        MatchIndices {
-            haystack: self,
-            needle: sep,
-            searcher: Searcher::new(self.as_bytes(), sep.as_bytes())
-        }
+    fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
+        MatchIndices(pat.into_searcher(self))
     }
 
     #[inline]
-    fn split_str<'a>(&'a self, sep: &'a str) -> SplitStr<'a> {
-        SplitStr {
-            it: self.match_indices(sep),
-            last_end: 0,
-            finished: false
-        }
+    #[allow(deprecated) /* for SplitStr */ ]
+    fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
+        SplitStr(self.split(pat))
     }
 
     #[inline]
@@ -1500,54 +1482,69 @@ fn slice_chars(&self, begin: usize, end: usize) -> &str {
     #[inline]
     unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
         mem::transmute(Slice {
-            data: self.as_ptr().offset(begin as isize),
+            data: self.as_ptr().offset(begin as int),
             len: end - begin,
         })
     }
 
     #[inline]
-    fn starts_with(&self, needle: &str) -> bool {
-        let n = needle.len();
-        self.len() >= n && needle.as_bytes() == &self.as_bytes()[..n]
+    fn starts_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
+        pat.is_prefix_of(self)
     }
 
     #[inline]
-    fn ends_with(&self, needle: &str) -> bool {
-        let (m, n) = (self.len(), needle.len());
-        m >= n && needle.as_bytes() == &self.as_bytes()[m-n..]
+    fn ends_with<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        pat.is_suffix_of(self)
     }
 
     #[inline]
-    fn trim_matches<P: CharEq>(&self, mut pat: P) -> &str {
-        let cur = match self.find(|c: char| !pat.matches(c)) {
-            None => "",
-            Some(i) => unsafe { self.slice_unchecked(i, self.len()) }
-        };
-        match cur.rfind(|c: char| !pat.matches(c)) {
-            None => "",
-            Some(i) => {
-                let right = cur.char_range_at(i).next;
-                unsafe { cur.slice_unchecked(0, right) }
-            }
+    fn trim_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: DoubleEndedSearcher<'a>
+    {
+        let mut i = 0;
+        let mut j = 0;
+        let mut matcher = pat.into_searcher(self);
+        if let Some((a, b)) = matcher.next_reject() {
+            i = a;
+            j = b; // Rember earliest known match, correct it below if
+                   // last match is different
+        }
+        if let Some((_, b)) = matcher.next_reject_back() {
+            j = b;
+        }
+        unsafe {
+            // Searcher is known to return valid indices
+            self.slice_unchecked(i, j)
         }
     }
 
     #[inline]
-    fn trim_left_matches<P: CharEq>(&self, mut pat: P) -> &str {
-        match self.find(|c: char| !pat.matches(c)) {
-            None => "",
-            Some(first) => unsafe { self.slice_unchecked(first, self.len()) }
+    fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
+        let mut i = self.len();
+        let mut matcher = pat.into_searcher(self);
+        if let Some((a, _)) = matcher.next_reject() {
+            i = a;
+        }
+        unsafe {
+            // Searcher is known to return valid indices
+            self.slice_unchecked(i, self.len())
         }
     }
 
     #[inline]
-    fn trim_right_matches<P: CharEq>(&self, mut pat: P) -> &str {
-        match self.rfind(|c: char| !pat.matches(c)) {
-            None => "",
-            Some(last) => {
-                let next = self.char_range_at(last).next;
-                unsafe { self.slice_unchecked(0, next) }
-            }
+    fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        let mut j = 0;
+        let mut matcher = pat.into_searcher(self);
+        if let Some((_, b)) = matcher.next_reject_back() {
+            j = b;
+        }
+        unsafe {
+            // Searcher is known to return valid indices
+            self.slice_unchecked(0, j)
         }
     }
 
@@ -1612,36 +1609,18 @@ fn as_bytes(&self) -> &[u8] {
         unsafe { mem::transmute(self) }
     }
 
-    fn find<P: CharEq>(&self, mut pat: P) -> Option<usize> {
-        if pat.only_ascii() {
-            self.bytes().position(|b| pat.matches(b as char))
-        } else {
-            for (index, c) in self.char_indices() {
-                if pat.matches(c) { return Some(index); }
-            }
-            None
-        }
+    fn find<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
+        pat.into_searcher(self).next_match().map(|(i, _)| i)
     }
 
-    fn rfind<P: CharEq>(&self, mut pat: P) -> Option<usize> {
-        if pat.only_ascii() {
-            self.bytes().rposition(|b| pat.matches(b as char))
-        } else {
-            for (index, c) in self.char_indices().rev() {
-                if pat.matches(c) { return Some(index); }
-            }
-            None
-        }
+    fn rfind<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize>
+        where P::Searcher: ReverseSearcher<'a>
+    {
+        pat.into_searcher(self).next_match_back().map(|(i, _)| i)
     }
 
-    fn find_str(&self, needle: &str) -> Option<usize> {
-        if needle.is_empty() {
-            Some(0)
-        } else {
-            self.match_indices(needle)
-                .next()
-                .map(|(start, _end)| start)
-        }
+    fn find_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> Option<usize> {
+        self.find(pat)
     }
 
     #[inline]
diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs
new file mode 100644 (file)
index 0000000..1f669c6
--- /dev/null
@@ -0,0 +1,495 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(deprecated) /* for CharEq */ ]
+
+use prelude::*;
+use super::CharEq;
+
+// Pattern
+
+/// A string pattern.
+///
+/// A `Pattern<'a>` expresses that the implementing type
+/// can be used as a string pattern for searching in a `&'a str`.
+///
+/// For example, both `'a'` and `"aa"` are patterns that
+/// would match at index `1` in the string `"baaaab"`.
+///
+/// The trait itself acts as a builder for an associated
+/// `Searcher` type, which does the actual work of finding
+/// occurences of the pattern in a string.
+pub trait Pattern<'a>: Sized {
+    /// Associated searcher for this pattern
+    type Searcher: Searcher<'a>;
+
+    /// Construct the associated searcher from
+    /// `self` and the `haystack` to search in.
+    fn into_searcher(self, haystack: &'a str) -> Self::Searcher;
+
+    /// Check whether the pattern matches anywhere in the haystack
+    #[inline]
+    fn is_contained_in(self, haystack: &'a str) -> bool {
+        self.into_searcher(haystack).next_match().is_some()
+    }
+
+    /// Check whether the pattern matches at the front of the haystack
+    #[inline]
+    fn is_prefix_of(self, haystack: &'a str) -> bool {
+        match self.into_searcher(haystack).next() {
+            SearchStep::Match(0, _) => true,
+            _ => false,
+        }
+    }
+
+    /// Check whether the pattern matches at the back of the haystack
+    #[inline]
+    fn is_suffix_of(self, haystack: &'a str) -> bool
+        where Self::Searcher: ReverseSearcher<'a>
+    {
+        match self.into_searcher(haystack).next_back() {
+            SearchStep::Match(_, j) if haystack.len() == j => true,
+            _ => false,
+        }
+    }
+}
+
+// Searcher
+
+/// Result of calling `Searcher::next()` or `ReverseSearcher::next_back()`.
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum SearchStep {
+    /// Expresses that a match of the pattern has been found at
+    /// `haystack[a..b]`.
+    Match(usize, usize),
+    /// Expresses that `haystack[a..b]` has been rejected as a possible match
+    /// of the pattern.
+    ///
+    /// Note that there might be more than one `Reject` betwen two `Match`es,
+    /// there is no requirement for them to be combined into one.
+    Reject(usize, usize),
+    /// Expresses that every byte of the haystack has been visted, ending
+    /// the iteration.
+    Done
+}
+
+/// A searcher for a string pattern.
+///
+/// This trait provides methods for searching for non-overlapping
+/// matches of a pattern starting from the front (left) of a string.
+///
+/// It will be implemented by associated `Searcher`
+/// types of the `Pattern` trait.
+///
+/// The trait is marked unsafe because the indices returned by the
+/// `next()` methods are required to lie on valid utf8 boundaries in
+/// the haystack. This enables consumers of this trait to
+/// slice the haystack without additional runtime checks.
+pub unsafe trait Searcher<'a> {
+    /// Getter for the underlaying string to be searched in
+    ///
+    /// Will always return the same `&str`
+    fn haystack(&self) -> &'a str;
+
+    /// Performs the next search step starting from the front.
+    ///
+    /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
+    /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
+    ///   pattern, even partially.
+    /// - Returns `Done` if every byte of the haystack has been visited
+    ///
+    /// The stream of `Match` and `Reject` values up to a `Done`
+    /// will contain index ranges that are adjacent, non-overlapping,
+    /// covering the whole haystack, and laying on utf8 boundaries.
+    ///
+    /// A `Match` result needs to contain the whole matched pattern,
+    /// however `Reject` results may be split up into arbitrary
+    /// many adjacent fragments. Both ranges may have zero length.
+    ///
+    /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
+    /// might produce the stream
+    /// `[Reject(0, 1), Reject(1, 2), Match(2, 5), Reject(5, 8)]`
+    fn next(&mut self) -> SearchStep;
+
+    /// Find the next `Match` result. See `next()`
+    #[inline]
+    fn next_match(&mut self) -> Option<(usize, usize)> {
+        loop {
+            match self.next() {
+                SearchStep::Match(a, b) => return Some((a, b)),
+                SearchStep::Done => return None,
+                _ => continue,
+            }
+        }
+    }
+
+    /// Find the next `Reject` result. See `next()`
+    #[inline]
+    fn next_reject(&mut self) -> Option<(usize, usize)> {
+        loop {
+            match self.next() {
+                SearchStep::Reject(a, b) => return Some((a, b)),
+                SearchStep::Done => return None,
+                _ => continue,
+            }
+        }
+    }
+}
+
+/// A reverse searcher for a string pattern.
+///
+/// This trait provides methods for searching for non-overlapping
+/// matches of a pattern starting from the back (right) of a string.
+///
+/// It will be implemented by associated `Searcher`
+/// types of the `Pattern` trait if the pattern supports searching
+/// for it from the back.
+///
+/// The index ranges returned by this trait are not required
+/// to exactly match those of the forward search in reverse.
+///
+/// For the reason why this trait is marked unsafe, see them
+/// parent trait `Searcher`.
+pub unsafe trait ReverseSearcher<'a>: Searcher<'a> {
+    /// Performs the next search step starting from the back.
+    ///
+    /// - Returns `Match(a, b)` if `haystack[a..b]` matches the pattern.
+    /// - Returns `Reject(a, b)` if `haystack[a..b]` can not match the
+    ///   pattern, even partially.
+    /// - Returns `Done` if every byte of the haystack has been visited
+    ///
+    /// The stream of `Match` and `Reject` values up to a `Done`
+    /// will contain index ranges that are adjacent, non-overlapping,
+    /// covering the whole haystack, and laying on utf8 boundaries.
+    ///
+    /// A `Match` result needs to contain the whole matched pattern,
+    /// however `Reject` results may be split up into arbitrary
+    /// many adjacent fragments. Both ranges may have zero length.
+    ///
+    /// As an example, the pattern `"aaa"` and the haystack `"cbaaaaab"`
+    /// might produce the stream
+    /// `[Reject(7, 8), Match(4, 7), Reject(1, 4), Reject(0, 1)]`
+    fn next_back(&mut self) -> SearchStep;
+
+    /// Find the next `Match` result. See `next_back()`
+    #[inline]
+    fn next_match_back(&mut self) -> Option<(usize, usize)>{
+        loop {
+            match self.next_back() {
+                SearchStep::Match(a, b) => return Some((a, b)),
+                SearchStep::Done => return None,
+                _ => continue,
+            }
+        }
+    }
+
+    /// Find the next `Reject` result. See `next_back()`
+    #[inline]
+    fn next_reject_back(&mut self) -> Option<(usize, usize)>{
+        loop {
+            match self.next_back() {
+                SearchStep::Reject(a, b) => return Some((a, b)),
+                SearchStep::Done => return None,
+                _ => continue,
+            }
+        }
+    }
+}
+
+/// A marker trait to express that a `ReverseSearcher`
+/// can be used for a `DoubleEndedIterator` implementation.
+///
+/// For this, the impl of `Searcher` and `ReverseSearcher` need
+/// to follow these conditions:
+///
+/// - All results of `next()` need to be identical
+///   to the results of `next_back()` in reverse order.
+/// - `next()` and `next_back()` need to behave as
+///   the two ends of a range of values, that is they
+///   can not "walk past each other".
+///
+/// # Example
+///
+/// `char::Searcher` is a `DoubleEndedSearcher` because searching for a
+/// `char` only requires looking at one at a time, which behaves the same
+/// from both ends.
+///
+/// `(&str)::Searcher` is not a `DoubleEndedSearcher` because
+/// the pattern `"aa"` in the haystack `"aaa"` matches as either
+/// `"[aa]a"` or `"a[aa]"`, depending from which side it is searched.
+pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
+
+// Impl for a CharEq wrapper
+
+struct CharEqPattern<C: CharEq>(C);
+
+struct CharEqSearcher<'a, C: CharEq> {
+    char_eq: C,
+    haystack: &'a str,
+    char_indices: super::CharIndices<'a>,
+    #[allow(dead_code)]
+    ascii_only: bool,
+}
+
+impl<'a, C: CharEq> Pattern<'a> for CharEqPattern<C> {
+    type Searcher = CharEqSearcher<'a, C>;
+
+    #[inline]
+    fn into_searcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> {
+        CharEqSearcher {
+            ascii_only: self.0.only_ascii(),
+            haystack: haystack,
+            char_eq: self.0,
+            char_indices: haystack.char_indices(),
+        }
+    }
+}
+
+unsafe impl<'a, C: CharEq> Searcher<'a> for CharEqSearcher<'a, C> {
+    #[inline]
+    fn haystack(&self) -> &'a str {
+        self.haystack
+    }
+
+    #[inline]
+    fn next(&mut self) -> SearchStep {
+        let s = &mut self.char_indices;
+        // Compare lengths of the internal byte slice iterator
+        // to find length of current char
+        let (pre_len, _) = s.iter.iter.size_hint();
+        if let Some((i, c)) = s.next() {
+            let (len, _) = s.iter.iter.size_hint();
+            let char_len = pre_len - len;
+            if self.char_eq.matches(c) {
+                return SearchStep::Match(i, i + char_len);
+            } else {
+                return SearchStep::Reject(i, i + char_len);
+            }
+        }
+        SearchStep::Done
+    }
+}
+
+unsafe impl<'a, C: CharEq> ReverseSearcher<'a> for CharEqSearcher<'a, C> {
+    #[inline]
+    fn next_back(&mut self) -> SearchStep {
+        let s = &mut self.char_indices;
+        // Compare lengths of the internal byte slice iterator
+        // to find length of current char
+        let (pre_len, _) = s.iter.iter.size_hint();
+        if let Some((i, c)) = s.next_back() {
+            let (len, _) = s.iter.iter.size_hint();
+            let char_len = pre_len - len;
+            if self.char_eq.matches(c) {
+                return SearchStep::Match(i, i + char_len);
+            } else {
+                return SearchStep::Reject(i, i + char_len);
+            }
+        }
+        SearchStep::Done
+    }
+}
+
+impl<'a, C: CharEq> DoubleEndedSearcher<'a> for CharEqSearcher<'a, C> {}
+
+// Impl for &str
+
+// Todo: Optimize the naive implementation here
+
+#[derive(Clone)]
+struct StrSearcher<'a, 'b> {
+    haystack: &'a str,
+    needle: &'b str,
+    start: usize,
+    end: usize,
+    done: bool,
+}
+
+/// Non-allocating substring search.
+///
+/// Will handle the pattern `""` as returning empty matches at each utf8
+/// boundary.
+impl<'a, 'b> Pattern<'a> for &'b str {
+    type Searcher = StrSearcher<'a, 'b>;
+
+    #[inline]
+    fn into_searcher(self, haystack: &'a str) -> StrSearcher<'a, 'b> {
+        StrSearcher {
+            haystack: haystack,
+            needle: self,
+            start: 0,
+            end: haystack.len(),
+            done: false,
+        }
+    }
+}
+
+unsafe impl<'a, 'b> Searcher<'a> for StrSearcher<'a, 'b>  {
+    #[inline]
+    fn haystack(&self) -> &'a str {
+        self.haystack
+    }
+
+    #[inline]
+    fn next(&mut self) -> SearchStep {
+        str_search_step(self,
+        |m: &mut StrSearcher| {
+            // Forward step for empty needle
+            let current_start = m.start;
+            if !m.done {
+                m.start = m.haystack.char_range_at(current_start).next;
+            }
+            SearchStep::Match(current_start, current_start)
+        },
+        |m: &mut StrSearcher| {
+            // Forward step for nonempty needle
+            let current_start = m.start;
+            // Compare byte window because this might break utf8 boundaries
+            let possible_match = &m.haystack.as_bytes()[m.start .. m.start + m.needle.len()];
+            if possible_match == m.needle.as_bytes() {
+                m.start += m.needle.len();
+                SearchStep::Match(current_start, m.start)
+            } else {
+                // Skip a char
+                let haystack_suffix = &m.haystack[m.start..];
+                m.start += haystack_suffix.chars().next().unwrap().len_utf8();
+                SearchStep::Reject(current_start, m.start)
+            }
+        })
+    }
+}
+
+unsafe impl<'a, 'b> ReverseSearcher<'a> for StrSearcher<'a, 'b>  {
+    #[inline]
+    fn next_back(&mut self) -> SearchStep {
+        str_search_step(self,
+        |m: &mut StrSearcher| {
+            // Backward step for empty needle
+            let current_end = m.end;
+            if !m.done {
+                m.end = m.haystack.char_range_at_reverse(current_end).next;
+            }
+            SearchStep::Match(current_end, current_end)
+        },
+        |m: &mut StrSearcher| {
+            // Backward step for nonempty needle
+            let current_end = m.end;
+            // Compare byte window because this might break utf8 boundaries
+            let possible_match = &m.haystack.as_bytes()[m.end - m.needle.len() .. m.end];
+            if possible_match == m.needle.as_bytes() {
+                m.end -= m.needle.len();
+                SearchStep::Match(m.end, current_end)
+            } else {
+                // Skip a char
+                let haystack_prefix = &m.haystack[..m.end];
+                m.end -= haystack_prefix.chars().rev().next().unwrap().len_utf8();
+                SearchStep::Reject(m.end, current_end)
+            }
+        })
+    }
+}
+
+// Helper function for encapsulating the common control flow
+// of doing a search step from the front or doing a search step from the back
+fn str_search_step<F, G>(mut m: &mut StrSearcher,
+                         empty_needle_step: F,
+                         nonempty_needle_step: G) -> SearchStep
+    where F: FnOnce(&mut StrSearcher) -> SearchStep,
+          G: FnOnce(&mut StrSearcher) -> SearchStep
+{
+    if m.done {
+        SearchStep::Done
+    } else if m.needle.len() == 0 && m.start <= m.end {
+        // Case for needle == ""
+        if m.start == m.end {
+            m.done = true;
+        }
+        empty_needle_step(&mut m)
+    } else if m.start + m.needle.len() <= m.end {
+        // Case for needle != ""
+        nonempty_needle_step(&mut m)
+    } else if m.start < m.end {
+        // Remaining slice shorter than needle, reject it
+        m.done = true;
+        SearchStep::Reject(m.start, m.end)
+    } else {
+        m.done = true;
+        SearchStep::Done
+    }
+}
+
+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)
+        }
+
+        #[inline]
+        fn is_contained_in(self, haystack: &'a str) -> bool {
+            let $s = self;
+            $e.is_contained_in(haystack)
+        }
+
+        #[inline]
+        fn is_prefix_of(self, haystack: &'a str) -> bool {
+            let $s = self;
+            $e.is_prefix_of(haystack)
+        }
+
+        // FIXME: #21750
+        /*#[inline]
+        fn is_suffix_of(self, haystack: &'a str) -> bool
+            where $t: ReverseSearcher<'a>
+        {
+            let $s = self;
+            $e.is_suffix_of(haystack)
+        }*/
+    }
+}
+
+// CharEq delegation impls
+
+/// 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));
+}
+
+/// 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));
+}
+
+/// Searches for chars that match the given predicate
+impl<'a, F> Pattern<'a> for F where F: FnMut(char) -> bool {
+    type Searcher =   <CharEqPattern<Self> as Pattern<'a>>::Searcher;
+    associated_items!(<CharEqPattern<Self> as Pattern<'a>>::Searcher,
+                      s, CharEqPattern(s));
+}
+
+// Deref-forward impl
+
+use ops::Deref;
+
+/// Delegates to the next deref coercion of `Self` that implements `Pattern`
+impl<'a, 'b, P: 'b + ?Sized, T: Deref<Target = P> + ?Sized> Pattern<'a> for &'b T
+    where &'b P: Pattern<'a>
+{
+    type Searcher =   <&'b P as Pattern<'a>>::Searcher;
+    associated_items!(<&'b P as Pattern<'a>>::Searcher,
+                      s, (&**s));
+}
index bc8461b0b9e09cf9c8c43d8a5d4752be40731959..bc3995439a0173c782f158f56daa1c835dd3b7ac 100644 (file)
@@ -170,42 +170,42 @@ mod u32 {
     use test::Bencher;
     use core::fmt::radix;
     use std::rand::{weak_rng, Rng};
-    use std::old_io::util::NullWriter;
+    use std::io::{Write, sink};
 
     #[bench]
     fn format_bin(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:b}", rng.gen::<u32>()) })
+        b.iter(|| { write!(&mut sink(), "{:b}", rng.gen::<u32>()) })
     }
 
     #[bench]
     fn format_oct(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:o}", rng.gen::<u32>()) })
+        b.iter(|| { write!(&mut sink(), "{:o}", rng.gen::<u32>()) })
     }
 
     #[bench]
     fn format_dec(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{}", rng.gen::<u32>()) })
+        b.iter(|| { write!(&mut sink(), "{}", rng.gen::<u32>()) })
     }
 
     #[bench]
     fn format_hex(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:x}", rng.gen::<u32>()) })
+        b.iter(|| { write!(&mut sink(), "{:x}", rng.gen::<u32>()) })
     }
 
     #[bench]
     fn format_show(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:?}", rng.gen::<u32>()) })
+        b.iter(|| { write!(&mut sink(), "{:?}", rng.gen::<u32>()) })
     }
 
     #[bench]
     fn format_base_36(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{}", radix(rng.gen::<u32>(), 36)) })
+        b.iter(|| { write!(&mut sink(), "{}", radix(rng.gen::<u32>(), 36)) })
     }
 }
 
@@ -213,41 +213,41 @@ mod i32 {
     use test::Bencher;
     use core::fmt::radix;
     use std::rand::{weak_rng, Rng};
-    use std::old_io::util::NullWriter;
+    use std::io::{Write, sink};
 
     #[bench]
     fn format_bin(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:b}", rng.gen::<i32>()) })
+        b.iter(|| { write!(&mut sink(), "{:b}", rng.gen::<i32>()) })
     }
 
     #[bench]
     fn format_oct(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:o}", rng.gen::<i32>()) })
+        b.iter(|| { write!(&mut sink(), "{:o}", rng.gen::<i32>()) })
     }
 
     #[bench]
     fn format_dec(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{}", rng.gen::<i32>()) })
+        b.iter(|| { write!(&mut sink(), "{}", rng.gen::<i32>()) })
     }
 
     #[bench]
     fn format_hex(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:x}", rng.gen::<i32>()) })
+        b.iter(|| { write!(&mut sink(), "{:x}", rng.gen::<i32>()) })
     }
 
     #[bench]
     fn format_show(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{:?}", rng.gen::<i32>()) })
+        b.iter(|| { write!(&mut sink(), "{:?}", rng.gen::<i32>()) })
     }
 
     #[bench]
     fn format_base_36(b: &mut Bencher) {
         let mut rng = weak_rng();
-        b.iter(|| { write!(&mut NullWriter, "{}", radix(rng.gen::<i32>(), 36)) })
+        b.iter(|| { write!(&mut sink(), "{}", radix(rng.gen::<i32>(), 36)) })
     }
 }
index 39a590c73074332d91a6de9319df3a52e2e70546..8a27400389f4ada601d595879b3b0ed651c46ff4 100644 (file)
@@ -74,7 +74,7 @@ fn test_multi_iter() {
 fn test_counter_from_iter() {
     let it = count(0, 5).take(10);
     let xs: Vec<int> = FromIterator::from_iter(it);
-    assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+    assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
 }
 
 #[test]
@@ -82,7 +82,7 @@ fn test_iterator_chain() {
     let xs = [0, 1, 2, 3, 4, 5];
     let ys = [30, 40, 50, 60];
     let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
-    let mut it = xs.iter().chain(ys.iter());
+    let it = xs.iter().chain(ys.iter());
     let mut i = 0;
     for &x in it {
         assert_eq!(x, expected[i]);
@@ -91,7 +91,7 @@ fn test_iterator_chain() {
     assert_eq!(i, expected.len());
 
     let ys = count(30, 10).take(4);
-    let mut it = xs.iter().cloned().chain(ys);
+    let it = xs.iter().cloned().chain(ys);
     let mut i = 0;
     for x in it {
         assert_eq!(x, expected[i]);
@@ -104,13 +104,13 @@ fn test_iterator_chain() {
 fn test_filter_map() {
     let it = count(0, 1).take(10)
         .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
-    assert!(it.collect::<Vec<uint>>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]);
+    assert_eq!(it.collect::<Vec<uint>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
 }
 
 #[test]
 fn test_iterator_enumerate() {
     let xs = [0, 1, 2, 3, 4, 5];
-    let mut it = xs.iter().enumerate();
+    let it = xs.iter().enumerate();
     for (i, &x) in it {
         assert_eq!(i, x);
     }
@@ -152,7 +152,7 @@ fn test_iterator_peekable() {
 fn test_iterator_take_while() {
     let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
     let ys = [0, 1, 2, 3, 5, 13];
-    let mut it = xs.iter().take_while(|&x| *x < 15);
+    let it = xs.iter().take_while(|&x| *x < 15);
     let mut i = 0;
     for x in it {
         assert_eq!(*x, ys[i]);
@@ -165,7 +165,7 @@ fn test_iterator_take_while() {
 fn test_iterator_skip_while() {
     let xs = [0, 1, 2, 3, 5, 13, 15, 16, 17, 19];
     let ys = [15, 16, 17, 19];
-    let mut it = xs.iter().skip_while(|&x| *x < 15);
+    let it = xs.iter().skip_while(|&x| *x < 15);
     let mut i = 0;
     for x in it {
         assert_eq!(*x, ys[i]);
@@ -231,7 +231,7 @@ fn add(old: &mut int, new: &uint) -> Option<f64> {
     let xs = [0, 1, 2, 3, 4];
     let ys = [0f64, 1.0, 3.0, 6.0, 10.0];
 
-    let mut it = xs.iter().scan(0, add);
+    let it = xs.iter().scan(0, add);
     let mut i = 0;
     for x in it {
         assert_eq!(x, ys[i]);
@@ -244,7 +244,7 @@ fn add(old: &mut int, new: &uint) -> Option<f64> {
 fn test_iterator_flat_map() {
     let xs = [0, 3, 6];
     let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
-    let mut it = xs.iter().flat_map(|&x| count(x, 1).take(3));
+    let it = xs.iter().flat_map(|&x| count(x, 1).take(3));
     let mut i = 0;
     for x in it {
         assert_eq!(x, ys[i]);
@@ -279,7 +279,7 @@ fn count(st: &mut uint) -> Option<uint> {
         }
     }
 
-    let mut it = Unfold::new(0, count);
+    let it = Unfold::new(0, count);
     let mut i = 0;
     for counted in it {
         assert_eq!(counted, i);
@@ -730,12 +730,12 @@ fn test_random_access_cycle() {
 
 #[test]
 fn test_double_ended_range() {
-    assert!((11..14).rev().collect::<Vec<_>>() == vec![13, 12, 11]);
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
     for _ in (10..0).rev() {
         panic!("unreachable");
     }
 
-    assert!((11..14).rev().collect::<Vec<_>>() == vec![13, 12, 11]);
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
     for _ in (10..0).rev() {
         panic!("unreachable");
     }
@@ -743,10 +743,9 @@ fn test_double_ended_range() {
 
 #[test]
 fn test_range() {
-    assert!((0..5).collect::<Vec<_>>() == vec![0, 1, 2, 3, 4]);
-    assert!((-10..-1).collect::<Vec<_>>() ==
-               vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
-    assert!((0..5).rev().collect::<Vec<_>>() == vec![4, 3, 2, 1, 0]);
+    assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+    assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
+    assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
     assert_eq!((200..-5).count(), 0);
     assert_eq!((200..-5).rev().count(), 0);
     assert_eq!((200..200).count(), 0);
@@ -767,38 +766,28 @@ fn test_range_inclusive() {
             vec![5, 4, 3, 2, 1, 0]);
     assert_eq!(range_inclusive(200, -5).count(), 0);
     assert_eq!(range_inclusive(200, -5).rev().count(), 0);
-    assert!(range_inclusive(200, 200).collect::<Vec<int>>() == vec![200]);
-    assert!(range_inclusive(200, 200).rev().collect::<Vec<int>>() == vec![200]);
+    assert_eq!(range_inclusive(200, 200).collect::<Vec<int>>(), [200]);
+    assert_eq!(range_inclusive(200, 200).rev().collect::<Vec<int>>(), [200]);
 }
 
 #[test]
 fn test_range_step() {
-    assert!(range_step(0, 20, 5).collect::<Vec<int>>() ==
-            vec![0, 5, 10, 15]);
-    assert!(range_step(20, 0, -5).collect::<Vec<int>>() ==
-            vec![20, 15, 10, 5]);
-    assert!(range_step(20, 0, -6).collect::<Vec<int>>() ==
-            vec![20, 14, 8, 2]);
-    assert!(range_step(200u8, 255, 50).collect::<Vec<u8>>() ==
-            vec![200u8, 250]);
-    assert!(range_step(200, -5, 1).collect::<Vec<int>>() == vec![]);
-    assert!(range_step(200, 200, 1).collect::<Vec<int>>() == vec![]);
+    assert_eq!(range_step(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15]);
+    assert_eq!(range_step(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5]);
+    assert_eq!(range_step(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]);
+    assert_eq!(range_step(200u8, 255, 50).collect::<Vec<u8>>(), [200u8, 250]);
+    assert_eq!(range_step(200i, -5, 1).collect::<Vec<int>>(), []);
+    assert_eq!(range_step(200i, 200, 1).collect::<Vec<int>>(), []);
 }
 
 #[test]
 fn test_range_step_inclusive() {
-    assert!(range_step_inclusive(0, 20, 5).collect::<Vec<int>>() ==
-            vec![0, 5, 10, 15, 20]);
-    assert!(range_step_inclusive(20, 0, -5).collect::<Vec<int>>() ==
-            vec![20, 15, 10, 5, 0]);
-    assert!(range_step_inclusive(20, 0, -6).collect::<Vec<int>>() ==
-            vec![20, 14, 8, 2]);
-    assert!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>() ==
-            vec![200u8, 250]);
-    assert!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>() ==
-            vec![]);
-    assert!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>() ==
-            vec![200]);
+    assert_eq!(range_step_inclusive(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15, 20]);
+    assert_eq!(range_step_inclusive(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5, 0]);
+    assert_eq!(range_step_inclusive(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]);
+    assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>(), [200u8, 250]);
+    assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>(), []);
+    assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>(), [200]);
 }
 
 #[test]
index 2dfd81f32c2703869f43d32657089860b80ca7db..03924910e0485d12acf5f4c86798842dacac6fe6 100644 (file)
 #![feature(int_uint)]
 #![feature(unboxed_closures)]
 #![feature(unsafe_destructor)]
+#![feature(core)]
+#![feature(test)]
+#![feature(rand)]
+#![feature(unicode)]
+#![feature(std_misc)]
+#![feature(libc)]
+#![feature(hash)]
+#![feature(io)]
+#![feature(collections)]
 #![allow(deprecated)] // rand
 
 extern crate core;
index 5aeb330b78b54023ac388d83d22f5eeff636b319..73000670c61aa839e975fb39829b45eb39be2789 100644 (file)
@@ -103,7 +103,7 @@ impl Foo for int {}
     }
 
     unsafe {
-        assert!(vec![76u8] == transmute::<_, Vec<u8>>("L".to_string()));
+        assert_eq!([76u8], transmute::<_, Vec<u8>>("L".to_string()));
     }
 }
 
index be4c83d23e8b33796600da56907aa81a3a7a5a11..f60570eaaf417941f4e54b4cf6beb5b60f5b8dc2 100644 (file)
@@ -54,7 +54,7 @@ fn test_match_option_empty_vec() {
 fn test_match_option_vec() {
     let a = Some(vec![1, 2, 3, 4]);
     match a {
-        Some(v) => assert_eq!(v, vec![1, 2, 3, 4]),
+        Some(v) => assert_eq!(v, [1, 2, 3, 4]),
         None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
     }
 }
index 2c6efc0040fae82bb3adb7247ae9506e7ed6b972..03f6e51a3498a4c72f1ce88639172695add9b5cc 100644 (file)
@@ -122,4 +122,9 @@ fn test_int_from_str_overflow() {
         assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
         assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
     }
+
+    #[test]
+    fn test_int_from_minus_sign() {
+        assert_eq!("-".parse::<i32>().ok(), None);
+    }
 }
index 57456bfb1a79ba04ce4b68c77999d37c2b507a90..c8a54ef59abda2c0676e72bd196db6090ae220c8 100644 (file)
@@ -156,7 +156,7 @@ fn test_ptr_subtraction() {
             m_ptr = m_ptr.offset(-1);
         }
 
-        assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]);
+        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
     }
 }
 
index 375564c39bb5b1846f5a4d0f7fd27310ead2cb07..019f935911f7a78315f834be60b88c8928835c13 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,6 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[test]
+fn test_pattern_deref_forward() {
+    let data = "aabcdaa";
+    assert!(data.contains("bcd"));
+    assert!(data.contains(&"bcd"));
+    assert!(data.contains(&&"bcd"));
+    assert!(data.contains(&"bcd".to_string()));
+    assert!(data.contains(&&"bcd".to_string()));
+}
+
+#[test]
+fn test_empty_match_indices() {
+    let data = "aä中!";
+    let vec: Vec<_> = data.match_indices("").collect();
+    assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
+}
+
 #[test]
 fn test_bool_from_str() {
     assert_eq!("true".parse().ok(), Some(true));
@@ -52,20 +69,20 @@ fn test_rsplitn_char_iterator() {
 
     let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+    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();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
     // Unicode
     let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+    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();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 }
 
 #[test]
@@ -73,33 +90,33 @@ fn test_split_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
     let split: Vec<&str> = data.split(' ').collect();
-    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
-    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     // Unicode
     let split: Vec<&str> = data.split('ä').collect();
-    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 
     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 
     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
-    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 
     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 }
 
 #[test]
@@ -108,16 +125,265 @@ fn test_rev_split_char_iterator_no_trailing() {
 
     let mut split: Vec<&str> = data.split('\n').rev().collect();
     split.reverse();
-    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
+    assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
 
     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
     split.reverse();
-    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
+    assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
 }
 
 #[test]
 fn test_utf16_code_units() {
     use unicode::str::Utf16Encoder;
     assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
-               vec![0xE9, 0xD83D, 0xDCA9])
+               [0xE9, 0xD83D, 0xDCA9])
+}
+
+#[test]
+fn starts_with_in_unicode() {
+    assert!(!"├── Cargo.toml".starts_with("# "));
+}
+
+#[test]
+fn starts_short_long() {
+    assert!(!"".starts_with("##"));
+    assert!(!"##".starts_with("####"));
+    assert!("####".starts_with("##"));
+    assert!(!"##ä".starts_with("####"));
+    assert!("####ä".starts_with("##"));
+    assert!(!"##".starts_with("####ä"));
+    assert!("##ä##".starts_with("##ä"));
+
+    assert!("".starts_with(""));
+    assert!("ä".starts_with(""));
+    assert!("#ä".starts_with(""));
+    assert!("##ä".starts_with(""));
+    assert!("ä###".starts_with(""));
+    assert!("#ä##".starts_with(""));
+    assert!("##ä#".starts_with(""));
+}
+
+#[test]
+fn contains_weird_cases() {
+    assert!("* \t".contains_char(' '));
+    assert!(!"* \t".contains_char('?'));
+    assert!(!"* \t".contains_char('\u{1F4A9}'));
+}
+
+#[test]
+fn trim_ws() {
+    assert_eq!(" \t  a \t  ".trim_left_matches(|c: char| c.is_whitespace()),
+                    "a \t  ");
+    assert_eq!(" \t  a \t  ".trim_right_matches(|c: char| c.is_whitespace()),
+               " \t  a");
+    assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
+                    "a");
+    assert_eq!(" \t   \t  ".trim_left_matches(|c: char| c.is_whitespace()),
+                         "");
+    assert_eq!(" \t   \t  ".trim_right_matches(|c: char| c.is_whitespace()),
+               "");
+    assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
+               "");
+}
+
+mod pattern {
+    use std::str::Pattern;
+    use std::str::{Searcher, ReverseSearcher, DoubleEndedSearcher};
+    use std::str::SearchStep::{self, Match, Reject, Done};
+
+    macro_rules! make_test {
+        ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
+            mod $name {
+                use std::str::Pattern;
+                use std::str::{Searcher, ReverseSearcher, DoubleEndedSearcher};
+                use std::str::SearchStep::{self, Match, Reject, Done};
+                use super::{cmp_search_to_vec};
+                #[test]
+                fn fwd() {
+                    cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
+                }
+                #[test]
+                fn bwd() {
+                    cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
+                }
+            }
+        }
+    }
+
+    fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
+                                             right: Vec<SearchStep>)
+    where P::Searcher: ReverseSearcher<'a>
+    {
+        let mut searcher = pat.into_searcher(haystack);
+        let mut v = vec![];
+        loop {
+            match if !rev {searcher.next()} else {searcher.next_back()} {
+                Match(a, b) => v.push(Match(a, b)),
+                Reject(a, b) => v.push(Reject(a, b)),
+                Done => break,
+            }
+        }
+        if rev {
+            v.reverse();
+        }
+        assert_eq!(v, right);
+    }
+
+    make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
+        Reject(0, 1),
+        Match (1, 3),
+        Reject(3, 4),
+        Match (4, 6),
+        Reject(6, 7),
+    ]);
+    make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
+        Match(0, 0),
+        Match(1, 1),
+        Match(2, 2),
+        Match(3, 3),
+        Match(4, 4),
+        Match(5, 5),
+        Match(6, 6),
+        Match(7, 7),
+    ]);
+    make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
+        Reject(0, 3),
+        Reject(3, 6),
+        Reject(6, 9),
+    ]);
+    make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
+        Match(0, 0),
+        Match(3, 3),
+        Match(6, 6),
+        Match(9, 9),
+    ]);
+    make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
+        Match(0, 0),
+    ]);
+    make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
+    ]);
+    make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
+        Reject(0, 1),
+        Match (1, 2),
+        Match (2, 3),
+        Reject(3, 4),
+        Match (4, 5),
+        Match (5, 6),
+        Reject(6, 7),
+    ]);
+    make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
+        Reject(0, 3),
+        Reject(3, 6),
+        Reject(6, 9),
+    ]);
+    make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
+        Reject(0, 1),
+        Reject(1, 2),
+        Reject(2, 3),
+    ]);
+
+}
+
+mod bench {
+    macro_rules! make_test_inner {
+        ($s:ident, $code:expr, $name:ident, $str:expr) => {
+            #[bench]
+            fn $name(bencher: &mut Bencher) {
+                let mut $s = $str;
+                black_box(&mut $s);
+                bencher.iter(|| $code);
+            }
+        }
+    }
+
+    macro_rules! make_test {
+        ($name:ident, $s:ident, $code:expr) => {
+            mod $name {
+                use test::Bencher;
+                use test::black_box;
+
+                // Short strings: 65 bytes each
+                make_test_inner!($s, $code, short_ascii,
+                    "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
+                make_test_inner!($s, $code, short_mixed,
+                    "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
+                make_test_inner!($s, $code, short_pile_of_poo,
+                    "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
+                make_test_inner!($s, $code, long_lorem_ipsum,"\
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
+ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
+eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
+sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
+tempus vel, gravida nec quam.
+
+In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
+sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
+diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
+lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
+eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
+interdum. Curabitur ut nisi justo.
+
+Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
+mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
+lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
+est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
+felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
+ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
+feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
+Aliquam sit amet placerat lorem.
+
+Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
+mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
+Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
+lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
+suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
+cursus accumsan.
+
+Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
+feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
+vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
+leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
+malesuada sollicitudin quam eu fermentum!");
+            }
+        }
+    }
+
+    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!(match_indices_a_str, s, s.match_indices("a").count());
+
+    make_test!(split_str_a_str, s, s.split_str("a").count());
+
+    make_test!(trim_ascii_char, s, {
+        use std::ascii::AsciiExt;
+        s.trim_matches(|c: char| c.is_ascii())
+    });
+    make_test!(trim_left_ascii_char, s, {
+        use std::ascii::AsciiExt;
+        s.trim_left_matches(|c: char| c.is_ascii())
+    });
+    make_test!(trim_right_ascii_char, s, {
+        use std::ascii::AsciiExt;
+        s.trim_right_matches(|c: char| c.is_ascii())
+    });
+
+    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_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!(split_space_char, s, s.split(' ').count());
+    make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
+
+    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());
 }
index 24660b3f396c105031903ceb43822ff6b690cb66..2ce52cdec2560a92ee1e32559e2ae4392b73e37e 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(int_uint)]
 #![feature(libc)]
 #![feature(staged_api)]
+#![feature(unique)]
 
 #[cfg(test)] #[macro_use] extern crate log;
 
index be77622ac1db7c52335525cefd8753423177258f..4e25e51e9a466075c58b49ae0207413b88a8b426 100644 (file)
@@ -24,7 +24,6 @@
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
-#![feature(int_uint)]
 #![feature(staged_api)]
 #![feature(unicode)]
 
@@ -65,7 +64,7 @@ pub struct FormatSpec<'a> {
     /// Optionally specified alignment
     pub align: Alignment,
     /// Packed version of various flags provided
-    pub flags: uint,
+    pub flags: u32,
     /// The integer precision to use
     pub precision: Count<'a>,
     /// The string width requested for the resulting format
@@ -82,7 +81,7 @@ pub enum Position<'a> {
     /// The argument will be in the next position. This is the default.
     ArgumentNext,
     /// The argument is located at a specific index.
-    ArgumentIs(uint),
+    ArgumentIs(usize),
     /// The argument has a name.
     ArgumentNamed(&'a str),
 }
@@ -121,11 +120,11 @@ pub enum Flag {
 #[derive(Copy, PartialEq)]
 pub enum Count<'a> {
     /// The count is specified explicitly.
-    CountIs(uint),
+    CountIs(usize),
     /// The count is specified by the argument with the given name.
     CountIsName(&'a str),
     /// The count is specified by the argument at the given index.
-    CountIsParam(uint),
+    CountIsParam(usize),
     /// The count is specified by the next parameter.
     CountIsNextParam,
     /// The count is implied and cannot be explicitly specified.
@@ -237,7 +236,7 @@ fn ws(&mut self) {
 
     /// Parses all of a string which is to be considered a "raw literal" in a
     /// format string. This is everything outside of the braces.
-    fn string(&mut self, start: uint) -> &'a str {
+    fn string(&mut self, start: usize) -> &'a str {
         loop {
             // we may not consume the character, so clone the iterator
             match self.cur.clone().next() {
@@ -314,13 +313,13 @@ fn format(&mut self) -> FormatSpec<'a> {
         }
         // Sign flags
         if self.consume('+') {
-            spec.flags |= 1 << (FlagSignPlus as uint);
+            spec.flags |= 1 << (FlagSignPlus as u32);
         } else if self.consume('-') {
-            spec.flags |= 1 << (FlagSignMinus as uint);
+            spec.flags |= 1 << (FlagSignMinus as u32);
         }
         // Alternate marker
         if self.consume('#') {
-            spec.flags |= 1 << (FlagAlternate as uint);
+            spec.flags |= 1 << (FlagAlternate as u32);
         }
         // Width and precision
         let mut havewidth = false;
@@ -333,7 +332,7 @@ fn format(&mut self) -> FormatSpec<'a> {
                 spec.width = CountIsParam(0);
                 havewidth = true;
             } else {
-                spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
+                spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
             }
         }
         if !havewidth {
@@ -413,7 +412,7 @@ fn word(&mut self) -> &'a str {
 
     /// Optionally parses an integer at the current position. This doesn't deal
     /// with overflow at all, it's just accumulating digits.
-    fn integer(&mut self) -> Option<uint> {
+    fn integer(&mut self) -> Option<usize> {
         let mut cur = 0;
         let mut found = false;
         loop {
@@ -617,7 +616,7 @@ fn format_flags() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: (1 << FlagSignMinus as uint),
+                flags: (1 << FlagSignMinus as u32),
                 precision: CountImplied,
                 width: CountImplied,
                 ty: "",
@@ -628,7 +627,7 @@ fn format_flags() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: (1 << FlagSignPlus as uint) | (1 << FlagAlternate as uint),
+                flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
                 precision: CountImplied,
                 width: CountImplied,
                 ty: "",
index fdd7f7395c2b7af5955aa3f52f7cecd52e9cff74..4e329897e1ab21958e6dd520aabdaea04b3b34ff 100644 (file)
@@ -784,7 +784,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
 
         // FIXME: #5516 should be graphemes not codepoints
         // wrapped description
-        row.push_str(&desc_rows.connect(&desc_sep[..])[]);
+        row.push_str(&desc_rows.connect(&desc_sep[..]));
 
         row
     });
index acd52c752e8aa1b29e79505937f332cc2f311dcb..09fbf4935e4c1e7a86ade0c5bdb543854bb313a8 100644 (file)
@@ -463,7 +463,7 @@ pub fn escape(&self) -> String {
     fn pre_escaped_content(self) -> Cow<'a, str> {
         match self {
             EscStr(s) => s,
-            LabelStr(s) => if s.contains_char('\\') {
+            LabelStr(s) => if s.contains('\\') {
                 (&*s).escape_default().into_cow()
             } else {
                 s
index 383108a3bc0e452656f67bbd8ff24bb38226f71b..74a95b3aba056cdd194a1637b1950d5f5ba5bafa 100644 (file)
@@ -76,6 +76,7 @@
 //! one from Berkeley after the lawsuits died down and the CSRG dissolved.
 
 #![allow(bad_style, raw_pointer_derive)]
+#![cfg_attr(target_os = "nacl", allow(unused_imports))]
 #[cfg(feature = "cargo-build")] extern crate "std" as core;
 #[cfg(not(feature = "cargo-build"))] extern crate core;
 
 // you can write more-platform-agnostic code if you stick to just these
 // symbols.
 
-pub use types::common::c95::{FILE, c_void, fpos_t};
-pub use types::common::c99::{int8_t, int16_t, int32_t, int64_t};
-pub use types::common::c99::{uint8_t, uint16_t, uint32_t, uint64_t};
-pub use types::common::posix88::{DIR, dirent_t};
-pub use types::os::common::posix01::{timeval};
-pub use types::os::common::bsd44::{addrinfo, in_addr, in6_addr, sockaddr_storage};
-pub use types::os::common::bsd44::{ip_mreq, ip6_mreq, sockaddr, sockaddr_un};
-pub use types::os::common::bsd44::{sa_family_t, sockaddr_in, sockaddr_in6, socklen_t};
-pub use types::os::arch::c95::{c_char, c_double, c_float, c_int, c_uint};
-pub use types::os::arch::c95::{c_long, c_short, c_uchar, c_ulong, wchar_t};
-pub use types::os::arch::c95::{c_ushort, clock_t, ptrdiff_t, c_schar};
-pub use types::os::arch::c95::{size_t, time_t, suseconds_t};
-pub use types::os::arch::c99::{c_longlong, c_ulonglong};
-pub use types::os::arch::c99::{intptr_t, uintptr_t};
-pub use types::os::arch::c99::{intmax_t, uintmax_t};
-pub use types::os::arch::posix88::{dev_t, ino_t, mode_t};
-pub use types::os::arch::posix88::{off_t, pid_t, ssize_t};
-
-pub use consts::os::c95::{_IOFBF, _IOLBF, _IONBF, BUFSIZ, EOF};
-pub use consts::os::c95::{EXIT_FAILURE, EXIT_SUCCESS};
-pub use consts::os::c95::{FILENAME_MAX, FOPEN_MAX, L_tmpnam};
-pub use consts::os::c95::{RAND_MAX, SEEK_CUR, SEEK_END};
-pub use consts::os::c95::{SEEK_SET, TMP_MAX};
-pub use consts::os::posix88::{F_OK, O_APPEND, O_CREAT, O_EXCL};
-pub use consts::os::posix88::{O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
-pub use consts::os::posix88::{R_OK, S_IEXEC, S_IFBLK, S_IFCHR};
-pub use consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG, S_IFLNK};
-pub use consts::os::posix88::{S_IREAD, S_IRUSR, S_IRWXU, S_IWUSR};
-pub use consts::os::posix88::{STDERR_FILENO, STDIN_FILENO, S_IXUSR};
-pub use consts::os::posix88::{STDOUT_FILENO, W_OK, X_OK};
-pub use consts::os::bsd44::{AF_INET, AF_INET6, SOCK_STREAM, SOCK_DGRAM, SOCK_RAW};
-pub use consts::os::bsd44::{IPPROTO_IP, IPPROTO_IPV6, IPPROTO_TCP, TCP_NODELAY};
-pub use consts::os::bsd44::{SOL_SOCKET, SO_KEEPALIVE, SO_ERROR};
-pub use consts::os::bsd44::{SO_REUSEADDR, SO_BROADCAST, SHUT_WR, IP_MULTICAST_LOOP};
-pub use consts::os::bsd44::{IP_ADD_MEMBERSHIP, IP_DROP_MEMBERSHIP};
-pub use consts::os::bsd44::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP};
-pub use consts::os::bsd44::{IP_MULTICAST_TTL, IP_TTL, IP_HDRINCL, SHUT_RD};
-pub use consts::os::extra::{IPPROTO_RAW};
-
-pub use funcs::c95::ctype::{isalnum, isalpha, iscntrl, isdigit};
-pub use funcs::c95::ctype::{islower, isprint, ispunct, isspace};
-pub use funcs::c95::ctype::{isupper, isxdigit, tolower, toupper};
-
-pub use funcs::c95::stdio::{fclose, feof, ferror, fflush, fgetc};
-pub use funcs::c95::stdio::{fgetpos, fgets, fopen, fputc, fputs};
-pub use funcs::c95::stdio::{fread, freopen, fseek, fsetpos, ftell};
-pub use funcs::c95::stdio::{fwrite, perror, puts, remove, rename, rewind};
-pub use funcs::c95::stdio::{setbuf, setvbuf, tmpfile, ungetc};
-
-pub use funcs::c95::stdlib::{abs, atof, atoi, calloc, exit, _exit, atexit};
-pub use funcs::c95::stdlib::{free, getenv, labs, malloc, rand};
-pub use funcs::c95::stdlib::{realloc, srand, strtod, strtol};
-pub use funcs::c95::stdlib::{strtoul, system};
-
-pub use funcs::c95::string::{memchr, memcmp};
-pub use funcs::c95::string::{strcat, strchr, strcmp};
-pub use funcs::c95::string::{strcoll, strcpy, strcspn, strerror};
-pub use funcs::c95::string::{strlen, strncat, strncmp, strncpy};
-pub use funcs::c95::string::{strpbrk, strrchr, strspn, strstr};
-pub use funcs::c95::string::{strtok, strxfrm};
-
-pub use funcs::posix88::fcntl::{open, creat};
-pub use funcs::posix88::stat_::{chmod, fstat, mkdir, stat};
-pub use funcs::posix88::stdio::{fdopen, fileno, pclose, popen};
-pub use funcs::posix88::unistd::{access, chdir, close, dup, dup2};
-pub use funcs::posix88::unistd::{execv, execve, execvp, getcwd};
-pub use funcs::posix88::unistd::{getpid, isatty, lseek, pipe, read};
-pub use funcs::posix88::unistd::{rmdir, unlink, write};
-
-pub use funcs::bsd43::{socket, setsockopt, bind, send, recv, recvfrom};
-pub use funcs::bsd43::{listen, sendto, accept, connect, getpeername, getsockname};
-pub use funcs::bsd43::{shutdown};
+pub use types::common::c95::*;
+pub use types::common::c99::*;
+pub use types::common::posix88::*;
+pub use types::os::common::posix01::*;
+pub use types::os::common::bsd44::*;
+pub use types::os::arch::c95::*;
+pub use types::os::arch::c99::*;
+pub use types::os::arch::posix88::*;
+pub use types::os::arch::posix01::*;
+pub use types::os::arch::extra::*;
+
+pub use consts::os::c95::*;
+pub use consts::os::posix88::*;
+pub use consts::os::posix01::*;
+pub use consts::os::bsd44::*;
+pub use consts::os::extra::*;
+
+pub use funcs::c95::ctype::*;
+pub use funcs::c95::stdio::*;
+pub use funcs::c95::stdlib::*;
+pub use funcs::c95::string::*;
+pub use funcs::posix88::fcntl::*;
+pub use funcs::posix88::stat_::*;
+pub use funcs::posix88::stdio::*;
+pub use funcs::posix88::unistd::*;
+
+pub use funcs::bsd43::*;
 
 // But we also reexport most everything
 // if you're interested in writing platform-specific code.
 //
 // So the following exports don't follow any particular plan.
 
-#[cfg(unix)] pub use consts::os::sysconf::{_SC_PAGESIZE};
-#[cfg(unix)] pub use consts::os::posix88::{PROT_READ, PROT_WRITE, PROT_EXEC};
-#[cfg(unix)] pub use consts::os::posix88::{MAP_FIXED, MAP_FILE, MAP_ANON, MAP_PRIVATE, MAP_FAILED};
-#[cfg(unix)] pub use consts::os::posix88::{EACCES, EBADF, EINVAL, ENODEV, ENOMEM};
-#[cfg(unix)] pub use consts::os::posix88::{ECONNREFUSED, ECONNRESET, EPERM, EPIPE};
-#[cfg(unix)] pub use consts::os::posix88::{ENOTCONN, ECONNABORTED, EADDRNOTAVAIL, EINTR};
-#[cfg(unix)] pub use consts::os::posix88::{EADDRINUSE, ENOENT, EISDIR, EAGAIN, EWOULDBLOCK};
-#[cfg(unix)] pub use consts::os::posix88::{ECANCELED, SIGINT, EINPROGRESS};
-#[cfg(unix)] pub use consts::os::posix88::{ENOSYS, ENOTTY, ETIMEDOUT, EMFILE};
-#[cfg(unix)] pub use consts::os::posix88::{SIGTERM, SIGKILL, SIGPIPE, PROT_NONE};
-#[cfg(unix)] pub use consts::os::posix01::{SIG_IGN, F_GETFL, F_SETFL};
-#[cfg(unix)] pub use consts::os::bsd44::{AF_UNIX};
-#[cfg(unix)] pub use consts::os::extra::{O_NONBLOCK};
-
-#[cfg(unix)] pub use types::os::common::posix01::{pthread_t, timespec, timezone};
-
-#[cfg(unix)] pub use types::os::arch::posix88::{uid_t, gid_t};
-#[cfg(unix)] pub use types::os::arch::posix01::{pthread_attr_t};
-#[cfg(unix)] pub use types::os::arch::posix01::{stat, utimbuf};
-#[cfg(unix)] pub use types::os::common::bsd44::{ifaddrs};
-#[cfg(unix)] pub use funcs::posix88::unistd::{sysconf, setgid, setsid, setuid, pread, pwrite};
-#[cfg(unix)] pub use funcs::posix88::unistd::{getgid, getuid, getsid};
-#[cfg(unix)] pub use funcs::posix88::unistd::{_PC_NAME_MAX, utime, nanosleep, pathconf, link};
-#[cfg(unix)] pub use funcs::posix88::unistd::{chown};
-#[cfg(unix)] pub use funcs::posix88::mman::{mmap, munmap, mprotect};
-#[cfg(unix)] pub use funcs::posix88::dirent::{opendir, readdir_r, closedir};
-#[cfg(unix)] pub use funcs::posix88::fcntl::{fcntl};
-#[cfg(unix)] pub use funcs::posix88::net::{if_nametoindex};
-#[cfg(unix)] pub use funcs::posix01::stat_::{lstat};
-#[cfg(unix)] pub use funcs::posix01::unistd::{fsync, ftruncate};
-#[cfg(unix)] pub use funcs::posix01::unistd::{readlink, symlink};
-#[cfg(unix)] pub use funcs::bsd43::{getifaddrs, freeifaddrs};
-
-#[cfg(windows)] pub use consts::os::c95::{WSAECONNREFUSED, WSAECONNRESET, WSAEACCES};
-#[cfg(windows)] pub use consts::os::c95::{WSAEWOULDBLOCK, WSAENOTCONN, WSAECONNABORTED};
-#[cfg(windows)] pub use consts::os::c95::{WSAEADDRNOTAVAIL, WSAEADDRINUSE, WSAEINTR};
-#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS, WSAEINVAL, WSAEMFILE};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_INSUFFICIENT_BUFFER};
-#[cfg(windows)] pub use consts::os::extra::{O_BINARY, O_NOINHERIT, PAGE_NOACCESS};
-#[cfg(windows)] pub use consts::os::extra::{PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE};
-#[cfg(windows)] pub use consts::os::extra::{PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE};
-#[cfg(windows)] pub use consts::os::extra::{MEM_COMMIT, MEM_RESERVE, MEM_RELEASE};
-#[cfg(windows)] pub use consts::os::extra::{FILE_MAP_READ, FILE_MAP_WRITE, FILE_MAP_EXECUTE};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_ALREADY_EXISTS, ERROR_NO_DATA};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_NAME};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_BROKEN_PIPE, ERROR_INVALID_FUNCTION};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_CALL_NOT_IMPLEMENTED};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_NOTHING_TO_TERMINATE};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_INVALID_HANDLE};
-#[cfg(windows)] pub use consts::os::extra::{TRUE, FALSE, INFINITE};
-#[cfg(windows)] pub use consts::os::extra::{PROCESS_TERMINATE, PROCESS_QUERY_INFORMATION};
-#[cfg(windows)] pub use consts::os::extra::{STILL_ACTIVE, DETACHED_PROCESS};
-#[cfg(windows)] pub use consts::os::extra::{CREATE_NEW_PROCESS_GROUP, CREATE_UNICODE_ENVIRONMENT};
-#[cfg(windows)] pub use consts::os::extra::{FILE_BEGIN, FILE_END, FILE_CURRENT};
-#[cfg(windows)] pub use consts::os::extra::{FILE_GENERIC_READ, FILE_GENERIC_WRITE};
-#[cfg(windows)] pub use consts::os::extra::{FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_DELETE};
-#[cfg(windows)] pub use consts::os::extra::{TRUNCATE_EXISTING, CREATE_ALWAYS, OPEN_EXISTING};
-#[cfg(windows)] pub use consts::os::extra::{CREATE_NEW, FILE_APPEND_DATA, FILE_WRITE_DATA};
-#[cfg(windows)] pub use consts::os::extra::{OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL};
-#[cfg(windows)] pub use consts::os::extra::{FILE_FLAG_BACKUP_SEMANTICS, INVALID_HANDLE_VALUE};
-#[cfg(windows)] pub use consts::os::extra::{MOVEFILE_REPLACE_EXISTING};
-#[cfg(windows)] pub use consts::os::extra::{GENERIC_READ, GENERIC_WRITE};
-#[cfg(windows)] pub use consts::os::extra::{VOLUME_NAME_DOS};
-#[cfg(windows)] pub use consts::os::extra::{PIPE_ACCESS_DUPLEX, FILE_FLAG_FIRST_PIPE_INSTANCE};
-#[cfg(windows)] pub use consts::os::extra::{FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE};
-#[cfg(windows)] pub use consts::os::extra::{PIPE_READMODE_BYTE, PIPE_WAIT};
-#[cfg(windows)] pub use consts::os::extra::{PIPE_UNLIMITED_INSTANCES, ERROR_ACCESS_DENIED};
-#[cfg(windows)] pub use consts::os::extra::{FILE_WRITE_ATTRIBUTES, FILE_READ_ATTRIBUTES};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_BUSY, ERROR_IO_PENDING};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_PIPE_CONNECTED, WAIT_OBJECT_0};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_NOT_FOUND};
-#[cfg(windows)] pub use consts::os::extra::{ERROR_OPERATION_ABORTED};
-#[cfg(windows)] pub use consts::os::extra::{FIONBIO};
-#[cfg(windows)] pub use types::os::common::bsd44::{SOCKET};
-#[cfg(windows)] pub use types::os::common::posix01::{stat, utimbuf};
-#[cfg(windows)] pub use types::os::arch::extra::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES};
-#[cfg(windows)] pub use types::os::arch::extra::{LPCSTR, WORD, DWORD, BYTE, FILETIME};
-#[cfg(windows)] pub use types::os::arch::extra::{LARGE_INTEGER, LPVOID, LONG};
-#[cfg(windows)] pub use types::os::arch::extra::{time64_t, OVERLAPPED, LPCWSTR};
-#[cfg(windows)] pub use types::os::arch::extra::{LPOVERLAPPED, SIZE_T, LPDWORD};
-#[cfg(windows)] pub use types::os::arch::extra::{SECURITY_ATTRIBUTES, WIN32_FIND_DATAW};
-#[cfg(windows)] pub use funcs::c95::string::{wcslen};
-#[cfg(windows)] pub use funcs::posix88::stat_::{wstat, wutime, wchmod, wrmdir};
-#[cfg(windows)] pub use funcs::bsd43::{closesocket};
-#[cfg(windows)] pub use funcs::extra::kernel32::{GetCurrentDirectoryW, GetLastError};
-#[cfg(windows)] pub use funcs::extra::kernel32::{GetEnvironmentVariableW, SetEnvironmentVariableW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{GetModuleFileNameW, SetCurrentDirectoryW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{GetSystemInfo, VirtualAlloc, VirtualFree};
-#[cfg(windows)] pub use funcs::extra::kernel32::{CreateFileMappingW, MapViewOfFile};
-#[cfg(windows)] pub use funcs::extra::kernel32::{UnmapViewOfFile, CloseHandle};
-#[cfg(windows)] pub use funcs::extra::kernel32::{WaitForSingleObject, GetSystemTimeAsFileTime};
-#[cfg(windows)] pub use funcs::extra::kernel32::{QueryPerformanceCounter};
-#[cfg(windows)] pub use funcs::extra::kernel32::{QueryPerformanceFrequency};
-#[cfg(windows)] pub use funcs::extra::kernel32::{GetExitCodeProcess, TerminateProcess};
-#[cfg(windows)] pub use funcs::extra::kernel32::{ReadFile, WriteFile, SetFilePointerEx};
-#[cfg(windows)] pub use funcs::extra::kernel32::{SetEndOfFile, CreateFileW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{CreateDirectoryW, FindFirstFileW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{FindNextFileW, FindClose, DeleteFileW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{CreateHardLinkW, CreateEventW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{FlushFileBuffers, CreateNamedPipeW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{SetNamedPipeHandleState, WaitNamedPipeW};
-#[cfg(windows)] pub use funcs::extra::kernel32::{GetOverlappedResult, ConnectNamedPipe};
-#[cfg(windows)] pub use funcs::extra::kernel32::{DisconnectNamedPipe, OpenProcess};
-#[cfg(windows)] pub use funcs::extra::kernel32::{MoveFileExW, VirtualProtect};
-#[cfg(windows)] pub use funcs::extra::kernel32::{RemoveDirectoryW};
-#[cfg(windows)] pub use funcs::extra::msvcrt::{get_osfhandle, open_osfhandle};
-#[cfg(windows)] pub use funcs::extra::winsock::{ioctlsocket};
-
-#[cfg(any(target_os = "linux",
-          target_os = "android",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "openbsd"))]
-pub use consts::os::posix01::{CLOCK_REALTIME, CLOCK_MONOTONIC};
-
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub use funcs::posix01::unistd::{fdatasync};
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub use types::os::arch::extra::{sockaddr_ll};
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub use consts::os::extra::{AF_PACKET};
-
-#[cfg(all(unix, not(any(target_os = "freebsd", target_os = "openbsd"))))]
-pub use consts::os::extra::{MAP_STACK};
-
-#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-pub use consts::os::bsd44::{TCP_KEEPIDLE};
-
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-pub use consts::os::bsd44::{TCP_KEEPALIVE};
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-pub use consts::os::extra::{F_FULLFSYNC};
-
-#[cfg(any(target_os = "macos", target_os = "ios"))]
-pub use types::os::arch::extra::{mach_timebase_info};
-
-
-#[cfg(not(windows))]
+#[cfg(unix)] pub use consts::os::sysconf::*;
+
+#[cfg(unix)] pub use funcs::posix88::mman::*;
+#[cfg(unix)] pub use funcs::posix88::dirent::*;
+#[cfg(unix)] pub use funcs::posix88::net::*;
+#[cfg(unix)] pub use funcs::posix01::stat_::*;
+#[cfg(unix)] pub use funcs::posix01::unistd::*;
+
+
+#[cfg(windows)] pub use funcs::extra::kernel32::*;
+#[cfg(windows)] pub use funcs::extra::winsock::*;
+#[cfg(windows)] pub use funcs::extra::msvcrt::*;
+
+// On NaCl, these libraries are static. Thus it would be a Bad Idea to link them
+// in when creating a test crate.
+#[cfg(not(any(windows, all(target_os = "nacl", test))))]
 #[link(name = "c")]
 #[link(name = "m")]
 extern {}
 
+// libnacl provides functions that require a trip through the IRT to work.
+// ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip
+// to the kernel.
+#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))]
+#[link(name = "nacl", kind = "static")]
+extern {}
+
+// pnaclmm provides a number of functions that the toolchain's Clang emits calls
+// to when codegening atomic ops. All the functions within wrap various atomic
+// operations.
+// Yes, it could be linked by rustc explicitly, however by linking it here
+// instead we save a bit of time where bins are involved (by not running the
+// optimizations on the whole pnaclmm foreach binary built).
+#[cfg(all(target_os = "nacl", not(feature = "cargo-build"), not(test)))]
+#[link(name = "pnaclmm", kind = "static")]
+extern {}
+
 pub mod types {
 
     // Types tend to vary *per architecture* so we pull their definitions out
@@ -361,7 +212,7 @@ pub mod bsd44 {}
 
     // Standard types that are scalar but vary by OS and arch.
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))]
     pub mod os {
         pub mod common {
             pub mod posix01 {
@@ -369,7 +220,10 @@ pub mod posix01 {
                 use types::os::arch::c95::{c_char, c_ulong, size_t,
                                                  time_t, suseconds_t, c_long};
 
+                #[cfg(not(target_os = "nacl"))]
                 pub type pthread_t = c_ulong;
+                #[cfg(target_os = "nacl")]
+                pub type pthread_t = *mut c_void;
 
                 #[repr(C)]
                 #[derive(Copy)] pub struct glob_t {
@@ -466,10 +320,10 @@ pub mod bsd44 {
                     #[cfg(target_os = "linux")]
                     pub ai_canonname: *mut c_char,
 
-                    #[cfg(target_os = "android")]
+                    #[cfg(any(target_os = "android", target_os = "nacl"))]
                     pub ai_canonname: *mut c_char,
 
-                    #[cfg(target_os = "android")]
+                    #[cfg(any(target_os = "android", target_os = "nacl"))]
                     pub ai_addr: *mut sockaddr,
 
                     pub ai_next: *mut addrinfo,
@@ -498,7 +352,8 @@ pub mod bsd44 {
                   target_arch = "arm",
                   target_arch = "mips",
                   target_arch = "mipsel",
-                  target_arch = "powerpc"))]
+                  target_arch = "powerpc",
+                  target_arch = "le32"))]
         pub mod arch {
             pub mod c95 {
                 pub type c_char = i8;
@@ -530,7 +385,8 @@ pub mod c99 {
             #[cfg(any(target_arch = "x86",
                       target_arch = "mips",
                       target_arch = "mipsel",
-                      target_arch = "powerpc"))]
+                      target_arch = "powerpc",
+                      target_arch = "le32"))]
             pub mod posix88 {
                 pub type off_t = i32;
                 pub type dev_t = u64;
@@ -555,6 +411,7 @@ pub mod posix88 {
                 pub type ssize_t = i32;
             }
             #[cfg(any(target_arch = "x86",
+                      target_arch = "le32",
                       target_arch = "powerpc"))]
             pub mod posix01 {
                 use types::os::arch::c95::{c_short, c_long, time_t};
@@ -1322,7 +1179,7 @@ pub mod extra {
         }
     }
 
-    #[cfg(target_os = "openbsd")]
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
     pub mod os {
         pub mod common {
             pub mod posix01 {
@@ -1333,6 +1190,24 @@ pub mod posix01 {
 
                 pub type pthread_t = uintptr_t;
 
+                #[cfg(target_os = "bitrig")]
+                #[repr(C)]
+                #[derive(Copy)] pub struct glob_t {
+                    pub gl_pathc:  c_int,
+                    pub gl_matchc: c_int,
+                    pub gl_offs:   c_int,
+                    pub gl_flags:  c_int,
+                    pub gl_pathv:  *mut *mut c_char,
+                    pub __unused1: *mut c_void,
+                    pub __unused2: *mut c_void,
+                    pub __unused3: *mut c_void,
+                    pub __unused4: *mut c_void,
+                    pub __unused5: *mut c_void,
+                    pub __unused6: *mut c_void,
+                    pub __unused7: *mut c_void,
+                }
+
+                #[cfg(target_os = "openbsd")]
                 #[repr(C)]
                 #[derive(Copy)] pub struct glob_t {
                     pub gl_pathc:  c_int,
@@ -1451,7 +1326,6 @@ pub mod bsd44 {
                     pub ifa_dstaddr: *mut sockaddr,
                     pub ifa_data: *mut c_void
                 }
-
             }
         }
 
@@ -1485,15 +1359,15 @@ pub mod c99 {
                 pub type uintmax_t = u64;
             }
             pub mod posix88 {
+                use types::os::arch::c95::{c_long};
                 pub type off_t = i64;
-                pub type dev_t = u32;
-                pub type ino_t = u64;
+                pub type dev_t = i32;
                 pub type pid_t = i32;
                 pub type uid_t = u32;
                 pub type gid_t = u32;
                 pub type useconds_t = u32;
                 pub type mode_t = u32;
-                pub type ssize_t = i64;
+                pub type ssize_t = c_long;
             }
             pub mod posix01 {
                 use types::common::c95::{c_void};
@@ -1503,7 +1377,7 @@ pub mod posix01 {
                 use types::os::arch::posix88::{mode_t, off_t};
                 use types::os::arch::posix88::{uid_t};
 
-                pub type nlink_t = u32;
+                pub type nlink_t = uint32_t;
                 pub type blksize_t = uint32_t;
                 pub type ino_t = uint64_t;
                 pub type blkcnt_t = i64;
@@ -2461,7 +2335,7 @@ pub mod bsd44 {
             pub const SHUT_RDWR: c_int = 2;
         }
         pub mod extra {
-            use SOCKET;
+            use types::os::common::bsd44::SOCKET;
             use types::os::arch::c95::{c_int, c_long};
             use types::os::arch::extra::{WORD, DWORD, BOOL, HANDLE};
 
@@ -2696,7 +2570,7 @@ pub mod sysconf {
     }
 
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))]
     pub mod os {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
@@ -2723,6 +2597,7 @@ pub mod c99 {
                   target_arch = "x86_64",
                   target_arch = "arm",
                   target_arch = "aarch64",
+                  target_arch = "le32",
                   target_arch = "powerpc"))]
         pub mod posix88 {
             use types::os::arch::c95::c_int;
@@ -3146,6 +3021,7 @@ pub mod posix88 {
 
             pub const EDQUOT: c_int = 1133;
         }
+        #[cfg(not(target_os = "nacl"))]
         pub mod posix01 {
             use types::os::arch::c95::{c_int, size_t};
 
@@ -3156,7 +3032,6 @@ pub mod posix01 {
             pub const F_SETFL : c_int = 4;
 
             pub const SIGTRAP : c_int = 5;
-            pub const SIGPIPE: c_int = 13;
             pub const SIG_IGN: size_t = 1;
 
             pub const GLOB_ERR      : c_int = 1 << 0;
@@ -3228,12 +3103,81 @@ pub mod posix01 {
             pub const CLOCK_REALTIME: c_int = 0;
             pub const CLOCK_MONOTONIC: c_int = 1;
         }
+        #[cfg(target_os = "nacl")]
+        pub mod posix01 {
+            use types::os::arch::c95::{c_int, size_t};
+
+            pub const F_DUPFD : c_int = 0;
+            pub const F_GETFD : c_int = 1;
+            pub const F_SETFD : c_int = 2;
+            pub const F_GETFL : c_int = 3;
+            pub const F_SETFL : c_int = 4;
+
+            pub const SIGTRAP : c_int = 5;
+            pub const SIG_IGN: size_t = 1;
+
+            pub const GLOB_ERR      : c_int = 1 << 0;
+            pub const GLOB_MARK     : c_int = 1 << 1;
+            pub const GLOB_NOSORT   : c_int = 1 << 2;
+            pub const GLOB_DOOFFS   : c_int = 1 << 3;
+            pub const GLOB_NOCHECK  : c_int = 1 << 4;
+            pub const GLOB_APPEND   : c_int = 1 << 5;
+            pub const GLOB_NOESCAPE : c_int = 1 << 6;
+
+            pub const GLOB_NOSPACE  : c_int = 1;
+            pub const GLOB_ABORTED  : c_int = 2;
+            pub const GLOB_NOMATCH  : c_int = 3;
+
+            pub const POSIX_MADV_NORMAL : c_int = 0;
+            pub const POSIX_MADV_RANDOM : c_int = 1;
+            pub const POSIX_MADV_SEQUENTIAL : c_int = 2;
+            pub const POSIX_MADV_WILLNEED : c_int = 3;
+            pub const POSIX_MADV_DONTNEED : c_int = 4;
+
+            pub const _SC_MQ_PRIO_MAX : c_int = 28;
+            pub const _SC_IOV_MAX : c_int = 60;
+            pub const _SC_GETGR_R_SIZE_MAX : c_int = 69;
+            pub const _SC_GETPW_R_SIZE_MAX : c_int = 70;
+            pub const _SC_LOGIN_NAME_MAX : c_int = 71;
+            pub const _SC_TTY_NAME_MAX : c_int = 72;
+            pub const _SC_THREADS : c_int = 67;
+            pub const _SC_THREAD_SAFE_FUNCTIONS : c_int = 68;
+            pub const _SC_THREAD_DESTRUCTOR_ITERATIONS : c_int = 73;
+            pub const _SC_THREAD_KEYS_MAX : c_int = 74;
+            pub const _SC_THREAD_STACK_MIN : c_int = 75;
+            pub const _SC_THREAD_THREADS_MAX : c_int = 76;
+            pub const _SC_THREAD_ATTR_STACKADDR : c_int = 77;
+            pub const _SC_THREAD_ATTR_STACKSIZE : c_int = 78;
+            pub const _SC_THREAD_PRIORITY_SCHEDULING : c_int = 79;
+            pub const _SC_THREAD_PRIO_INHERIT : c_int = 80;
+            pub const _SC_THREAD_PRIO_PROTECT : c_int = 81;
+            pub const _SC_THREAD_PROCESS_SHARED : c_int = 82;
+            pub const _SC_ATEXIT_MAX : c_int = 87;
+            pub const _SC_XOPEN_VERSION : c_int = 89;
+            pub const _SC_XOPEN_XCU_VERSION : c_int = 90;
+            pub const _SC_XOPEN_UNIX : c_int = 91;
+            pub const _SC_XOPEN_CRYPT : c_int = 92;
+            pub const _SC_XOPEN_ENH_I18N : c_int = 93;
+            pub const _SC_XOPEN_SHM : c_int = 94;
+            pub const _SC_XOPEN_LEGACY : c_int = 129;
+            pub const _SC_XOPEN_REALTIME : c_int = 130;
+            pub const _SC_XOPEN_REALTIME_THREADS : c_int = 131;
+
+            pub const PTHREAD_CREATE_JOINABLE: c_int = 1;
+            pub const PTHREAD_CREATE_DETACHED: c_int = 0;
+
+            pub const PTHREAD_STACK_MIN: size_t = 1024;
+
+            pub const CLOCK_REALTIME: c_int = 0;
+            pub const CLOCK_MONOTONIC: c_int = 1;
+        }
         pub mod posix08 {
         }
         #[cfg(any(target_arch = "arm",
                   target_arch = "aarch64",
                   target_arch = "x86",
                   target_arch = "x86_64",
+                  target_arch = "le32",
                   target_arch = "powerpc"))]
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
@@ -3331,6 +3275,7 @@ pub mod bsd44 {
                   target_arch = "x86_64",
                   target_arch = "arm",
                   target_arch = "aarch64",
+                  target_arch = "le32",
                   target_arch = "powerpc"))]
         pub mod extra {
             use types::os::arch::c95::c_int;
@@ -3446,6 +3391,14 @@ pub mod sysconf {
             pub const _SC_XBS5_ILP32_OFFBIG : c_int = 126;
             pub const _SC_XBS5_LPBIG_OFFBIG : c_int = 128;
         }
+        #[cfg(target_os = "nacl")]
+        pub mod sysconf {
+            use types::os::arch::c95::c_int;
+
+            pub static _SC_SENDMSG_MAX_SIZE : c_int = 0;
+            pub static _SC_NPROCESSORS_ONLN : c_int = 1;
+            pub static _SC_PAGESIZE : c_int = 2;
+        }
         #[cfg(target_os = "android")]
         pub mod sysconf {
             use types::os::arch::c95::c_int;
@@ -3687,7 +3640,6 @@ pub mod posix01 {
             pub const F_SETFL : c_int = 4;
 
             pub const SIGTRAP : c_int = 5;
-            pub const SIGPIPE: c_int = 13;
             pub const SIG_IGN: size_t = 1;
 
             pub const GLOB_APPEND   : c_int = 0x0001;
@@ -3892,7 +3844,7 @@ pub mod sysconf {
         }
     }
 
-    #[cfg(target_os = "openbsd")]
+    #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
     pub mod os {
         pub mod c95 {
             use types::os::arch::c95::{c_int, c_uint};
@@ -3980,11 +3932,11 @@ pub mod posix88 {
             pub const MCL_CURRENT : c_int = 0x0001;
             pub const MCL_FUTURE : c_int = 0x0002;
 
-            pub const MS_SYNC : c_int = 0x0002; // changed
             pub const MS_ASYNC : c_int = 0x0001;
-            pub const MS_INVALIDATE : c_int = 0x0004; // changed
+            pub const MS_SYNC : c_int = 0x0002;
+            pub const MS_INVALIDATE : c_int = 0x0004;
 
-            pub const EPERM : c_int = 1; // not checked
+            pub const EPERM : c_int = 1;
             pub const ENOENT : c_int = 2;
             pub const ESRCH : c_int = 3;
             pub const EINTR : c_int = 4;
@@ -4066,25 +4018,17 @@ pub mod posix88 {
             pub const EFTYPE : c_int = 79;
             pub const EAUTH : c_int = 80;
             pub const ENEEDAUTH : c_int = 81;
-            pub const EIDRM : c_int = 82;
-            pub const ENOMSG : c_int = 83;
-            pub const EOVERFLOW : c_int = 84;
-            pub const ECANCELED : c_int = 85;
-            pub const EILSEQ : c_int = 86;
-            pub const ENOATTR : c_int = 87;
-            pub const EDOOFUS : c_int = 88;
-            pub const EBADMSG : c_int = 89;
-            pub const EMULTIHOP : c_int = 90;
-            pub const ENOLINK : c_int = 91;
-            pub const EPROTO : c_int = 92;
-            pub const ENOMEDIUM : c_int = 93;
-            pub const EUNUSED94 : c_int = 94;
-            pub const EUNUSED95 : c_int = 95;
-            pub const EUNUSED96 : c_int = 96;
-            pub const EUNUSED97 : c_int = 97;
-            pub const EUNUSED98 : c_int = 98;
-            pub const EASYNC : c_int = 99;
-            pub const ELAST : c_int = 99;
+            pub const EIPSEC : c_int = 82;
+            pub const ENOATTR : c_int = 83;
+            pub const EILSEQ : c_int = 84;
+            pub const ENOMEDIUM : c_int = 85;
+            pub const EMEDIUMTYPE : c_int = 86;
+            pub const EOVERFLOW : c_int = 87;
+            pub const ECANCELED : c_int = 88;
+            pub const EIDRM : c_int = 89;
+            pub const ENOMSG : c_int = 90;
+            pub const ENOTSUP : c_int = 91;
+            pub const ELAST : c_int = 91; // must be equal to largest errno
         }
         pub mod posix01 {
             use types::os::arch::c95::{c_int, size_t};
@@ -4094,9 +4038,14 @@ pub mod posix01 {
             pub const F_SETFD : c_int = 2;
             pub const F_GETFL : c_int = 3;
             pub const F_SETFL : c_int = 4;
+            pub const F_GETOWN : c_int = 5;
+            pub const F_SETOWN : c_int = 6;
+            pub const F_GETLK : c_int = 7;
+            pub const F_SETLK : c_int = 8;
+            pub const F_SETLKW : c_int = 9;
+            pub const F_DUPFD_CLOEXEC : c_int = 10;
 
             pub const SIGTRAP : c_int = 5;
-            pub const SIGPIPE: c_int = 13;
             pub const SIG_IGN: size_t = 1;
 
             pub const GLOB_APPEND   : c_int = 0x0001;
@@ -4105,11 +4054,12 @@ pub mod posix01 {
             pub const GLOB_MARK     : c_int = 0x0008;
             pub const GLOB_NOCHECK  : c_int = 0x0010;
             pub const GLOB_NOSORT   : c_int = 0x0020;
-            pub const GLOB_NOESCAPE : c_int = 0x1000; // changed
+            pub const GLOB_NOESCAPE : c_int = 0x1000;
 
             pub const GLOB_NOSPACE  : c_int = -1;
             pub const GLOB_ABORTED  : c_int = -2;
             pub const GLOB_NOMATCH  : c_int = -3;
+            pub const GLOB_NOSYS : c_int = -4;
 
             pub const POSIX_MADV_NORMAL : c_int = 0;
             pub const POSIX_MADV_RANDOM : c_int = 1;
@@ -4117,7 +4067,7 @@ pub mod posix01 {
             pub const POSIX_MADV_WILLNEED : c_int = 3;
             pub const POSIX_MADV_DONTNEED : c_int = 4;
 
-            pub const _SC_IOV_MAX : c_int = 51; // all changed...
+            pub const _SC_IOV_MAX : c_int = 51;
             pub const _SC_GETGR_R_SIZE_MAX : c_int = 100;
             pub const _SC_GETPW_R_SIZE_MAX : c_int = 101;
             pub const _SC_LOGIN_NAME_MAX : c_int = 102;
@@ -4144,14 +4094,13 @@ pub mod posix01 {
             pub const _SC_XOPEN_SHM : c_int = 30;
             pub const _SC_XOPEN_UNIX : c_int = 123;
             pub const _SC_XOPEN_VERSION : c_int = 125;
-            //pub const _SC_XOPEN_XCU_VERSION : c_int = ;
 
-            pub const PTHREAD_CREATE_JOINABLE: c_int = 0;
-            pub const PTHREAD_CREATE_DETACHED: c_int = 1;
-            pub const PTHREAD_STACK_MIN: size_t = 2048;
+            pub const PTHREAD_CREATE_JOINABLE : c_int = 0;
+            pub const PTHREAD_CREATE_DETACHED : c_int = 1;
+            pub const PTHREAD_STACK_MIN : size_t = 2048;
 
-            pub const CLOCK_REALTIME: c_int = 0;
-            pub const CLOCK_MONOTONIC: c_int = 3;
+            pub const CLOCK_REALTIME : c_int = 0;
+            pub const CLOCK_MONOTONIC : c_int = 3;
         }
         pub mod posix08 {
         }
@@ -4163,23 +4112,11 @@ pub mod bsd44 {
             pub const MADV_SEQUENTIAL : c_int = 2;
             pub const MADV_WILLNEED : c_int = 3;
             pub const MADV_DONTNEED : c_int = 4;
-            pub const MADV_FREE : c_int = 6; // changed
-            //pub const MADV_NOSYNC : c_int = ;
-            //pub const MADV_AUTOSYNC : c_int = ;
-            //pub const MADV_NOCORE : c_int = ;
-            //pub const MADV_CORE : c_int = ;
-            //pub const MADV_PROTECT : c_int = ;
-
-            //pub const MINCORE_INCORE : c_int =  ;
-            //pub const MINCORE_REFERENCED : c_int = ;
-            //pub const MINCORE_MODIFIED : c_int = ;
-            //pub const MINCORE_REFERENCED_OTHER : c_int = ;
-            //pub const MINCORE_MODIFIED_OTHER : c_int = ;
-            //pub const MINCORE_SUPER : c_int = ;
+            pub const MADV_FREE : c_int = 6;
 
-            pub const AF_INET: c_int = 2;
-            pub const AF_INET6: c_int = 24; // changed
             pub const AF_UNIX: c_int = 1;
+            pub const AF_INET: c_int = 2;
+            pub const AF_INET6: c_int = 24;
             pub const SOCK_STREAM: c_int = 1;
             pub const SOCK_DGRAM: c_int = 2;
             pub const SOCK_RAW: c_int = 3;
@@ -4192,13 +4129,10 @@ pub mod bsd44 {
             pub const IP_HDRINCL: c_int = 2;
             pub const IP_ADD_MEMBERSHIP: c_int = 12;
             pub const IP_DROP_MEMBERSHIP: c_int = 13;
-            // don't exist, keep same as IP_ADD_MEMBERSHIP
-            pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
-            // don't exist, keep same as IP_DROP_MEMBERSHIP
-            pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
+            pub const IPV6_ADD_MEMBERSHIP: c_int = 12; // don't exist
+            pub const IPV6_DROP_MEMBERSHIP: c_int = 13; // don't exist
 
-            pub const TCP_NODELAY: c_int = 1;
-            //pub const TCP_KEEPIDLE: c_int = ;
+            pub const TCP_NODELAY: c_int = 0x01;
             pub const SOL_SOCKET: c_int = 0xffff;
             pub const SO_KEEPALIVE: c_int = 0x0008;
             pub const SO_BROADCAST: c_int = 0x0020;
@@ -4214,20 +4148,21 @@ pub mod bsd44 {
         pub mod extra {
             use types::os::arch::c95::c_int;
 
+            pub const O_DSYNC : c_int = 128; // same as SYNC
             pub const O_SYNC : c_int = 128;
             pub const O_NONBLOCK : c_int = 4;
-            pub const CTL_KERN: c_int = 1;
-            pub const KERN_PROC: c_int = 66;
+            pub const CTL_KERN : c_int = 1;
+            pub const KERN_PROC : c_int = 66;
 
             pub const MAP_COPY : c_int = 0x0002;
-            pub const MAP_RENAME : c_int = 0x0000; // changed
-            pub const MAP_NORESERVE : c_int = 0x0000; // changed
-            pub const MAP_HASSEMAPHORE : c_int = 0x0000; // changed
-            //pub const MAP_STACK : c_int = ;
-            //pub const MAP_NOSYNC : c_int = ;
-            //pub const MAP_NOCORE : c_int = ;
+            pub const MAP_RENAME : c_int = 0x0000;
+            pub const MAP_NORESERVE : c_int = 0x0000;
+            pub const MAP_NOEXTEND : c_int = 0x0000;
+            pub const MAP_HASSEMAPHORE : c_int = 0x0000;
 
             pub const IPPROTO_RAW : c_int = 255;
+
+            pub const PATH_MAX: c_int = 1024;
         }
         pub mod sysconf {
             use types::os::arch::c95::c_int;
@@ -4259,31 +4194,31 @@ pub mod sysconf {
             pub const _SC_2_UPE : c_int = 25;
             pub const _SC_STREAM_MAX : c_int = 26;
             pub const _SC_TZNAME_MAX : c_int = 27;
-            pub const _SC_ASYNCHRONOUS_IO : c_int = 45; // changed...
+            pub const _SC_PAGESIZE : c_int = 28;
+            pub const _SC_FSYNC : c_int = 29;
+            pub const _SC_SEM_NSEMS_MAX : c_int = 31;
+            pub const _SC_SEM_VALUE_MAX : c_int = 32;
+            pub const _SC_AIO_LISTIO_MAX : c_int = 42;
+            pub const _SC_AIO_MAX : c_int = 43;
+            pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44;
+            pub const _SC_ASYNCHRONOUS_IO : c_int = 45;
+            pub const _SC_DELAYTIMER_MAX : c_int = 50;
             pub const _SC_MAPPED_FILES : c_int = 53;
             pub const _SC_MEMLOCK : c_int = 54;
             pub const _SC_MEMLOCK_RANGE : c_int = 55;
             pub const _SC_MEMORY_PROTECTION : c_int = 56;
             pub const _SC_MESSAGE_PASSING : c_int = 57;
+            pub const _SC_MQ_OPEN_MAX : c_int = 58;
             pub const _SC_PRIORITIZED_IO : c_int = 60;
             pub const _SC_PRIORITY_SCHEDULING : c_int = 61;
             pub const _SC_REALTIME_SIGNALS : c_int = 64;
+            pub const _SC_RTSIG_MAX : c_int = 66;
             pub const _SC_SEMAPHORES : c_int = 67;
-            pub const _SC_FSYNC : c_int = 29;
             pub const _SC_SHARED_MEMORY_OBJECTS : c_int = 68;
-            pub const _SC_SYNCHRONIZED_IO : c_int = 75;
-            pub const _SC_TIMERS : c_int = 94; // ...changed
-            pub const _SC_AIO_LISTIO_MAX : c_int = 42;
-            pub const _SC_AIO_MAX : c_int = 43;
-            pub const _SC_AIO_PRIO_DELTA_MAX : c_int = 44;
-            pub const _SC_DELAYTIMER_MAX : c_int = 50; // changed...
-            pub const _SC_MQ_OPEN_MAX : c_int = 58;
-            pub const _SC_PAGESIZE : c_int = 28;
-            pub const _SC_RTSIG_MAX : c_int = 66;
-            pub const _SC_SEM_NSEMS_MAX : c_int = 31;
-            pub const _SC_SEM_VALUE_MAX : c_int = 32;
             pub const _SC_SIGQUEUE_MAX : c_int = 70;
+            pub const _SC_SYNCHRONIZED_IO : c_int = 75;
             pub const _SC_TIMER_MAX : c_int = 93;
+            pub const _SC_TIMERS : c_int = 94;
         }
     }
 
@@ -4501,7 +4436,6 @@ pub mod posix01 {
             pub const F_SETFL : c_int = 4;
 
             pub const SIGTRAP : c_int = 5;
-            pub const SIGPIPE: c_int = 13;
             pub const SIG_IGN: size_t = 1;
 
             pub const GLOB_APPEND   : c_int = 0x0001;
@@ -5005,7 +4939,9 @@ pub mod mman {
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
-              target_os = "openbsd"))]
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "nacl"))]
     pub mod posix88 {
         pub mod stat_ {
             use types::os::arch::c95::{c_char, c_int};
@@ -5019,9 +4955,11 @@ pub mod stat_ {
                 #[cfg(any(target_os = "linux",
                           target_os = "freebsd",
                           target_os = "dragonfly",
+                          target_os = "bitrig",
                           target_os = "openbsd",
                           target_os = "android",
-                          target_os = "ios"))]
+                          target_os = "ios",
+                          target_os = "nacl"))]
                 pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
 
                 #[cfg(target_os = "macos")]
@@ -5029,14 +4967,17 @@ pub mod stat_ {
                 pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
 
                 pub fn mkdir(path: *const c_char, mode: mode_t) -> c_int;
+                #[cfg(not(target_os = "nacl"))]
                 pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int;
 
                 #[cfg(any(target_os = "linux",
                           target_os = "freebsd",
                           target_os = "dragonfly",
+                          target_os = "bitrig",
                           target_os = "openbsd",
                           target_os = "android",
-                          target_os = "ios"))]
+                          target_os = "ios",
+                          target_os = "nacl"))]
                 pub fn stat(path: *const c_char, buf: *mut stat) -> c_int;
 
                 #[cfg(target_os = "macos")]
@@ -5108,6 +5049,7 @@ pub mod unistd {
 
             pub const _PC_NAME_MAX: c_int = 4;
 
+            #[cfg(not(target_os = "nacl"))]
             extern {
                 pub fn access(path: *const c_char, amode: c_int) -> c_int;
                 pub fn alarm(seconds: c_uint) -> c_uint;
@@ -5129,7 +5071,7 @@ pub fn execvp(c: *const c_char,
                 pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
                 pub fn getegid() -> gid_t;
                 pub fn geteuid() -> uid_t;
-                pub fn getgid() -> gid_t ;
+                pub fn getgid() -> gid_t;
                 pub fn getgroups(ngroups_max: c_int, groups: *mut gid_t)
                                  -> c_int;
                 pub fn getlogin() -> *mut c_char;
@@ -5170,6 +5112,57 @@ pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t,
                               offset: off_t) -> ssize_t;
                 pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int;
             }
+            #[cfg(target_os = "nacl")]
+            extern {
+                pub fn access(path: *const c_char, amode: c_int) -> c_int;
+                pub fn chdir(dir: *const c_char) -> c_int;
+                pub fn chown(path: *const c_char, uid: uid_t,
+                             gid: gid_t) -> c_int;
+                pub fn close(fd: c_int) -> c_int;
+                pub fn dup(fd: c_int) -> c_int;
+                pub fn dup2(src: c_int, dst: c_int) -> c_int;
+                pub fn execv(prog: *const c_char,
+                             argv: *mut *const c_char) -> c_int;
+                pub fn execve(prog: *const c_char, argv: *mut *const c_char,
+                              envp: *mut *const c_char)
+                              -> c_int;
+                pub fn execvp(c: *const c_char,
+                              argv: *mut *const c_char) -> c_int;
+                pub fn fork() -> pid_t;
+                pub fn getcwd(buf: *mut c_char, size: size_t) -> *mut c_char;
+                pub fn getegid() -> gid_t;
+                pub fn geteuid() -> uid_t;
+                pub fn getgid() -> gid_t;
+                pub fn getlogin() -> *mut c_char;
+                pub fn getopt(argc: c_int, argv: *mut *const c_char,
+                              optstr: *const c_char) -> c_int;
+                pub fn getuid() -> uid_t;
+                pub fn getsid(pid: pid_t) -> pid_t;
+                pub fn isatty(fd: c_int) -> c_int;
+                pub fn link(src: *const c_char, dst: *const c_char) -> c_int;
+                pub fn lseek(fd: c_int, offset: off_t, whence: c_int)
+                             -> off_t;
+                pub fn pipe(fds: *mut c_int) -> c_int;
+                pub fn read(fd: c_int, buf: *mut c_void, count: size_t)
+                            -> ssize_t;
+                pub fn rmdir(path: *const c_char) -> c_int;
+                pub fn setgid(gid: gid_t) -> c_int;
+                pub fn setuid(uid: uid_t) -> c_int;
+                pub fn sleep(secs: c_uint) -> c_uint;
+                pub fn usleep(secs: c_uint) -> c_int;
+                pub fn nanosleep(rqtp: *const timespec,
+                                 rmtp: *mut timespec) -> c_int;
+                pub fn sysconf(name: c_int) -> c_long;
+                pub fn ttyname(fd: c_int) -> *mut c_char;
+                pub fn unlink(c: *const c_char) -> c_int;
+                pub fn write(fd: c_int, buf: *const c_void, count: size_t)
+                             -> ssize_t;
+                pub fn pread(fd: c_int, buf: *mut c_void, count: size_t,
+                             offset: off_t) -> ssize_t;
+                pub fn pwrite(fd: c_int, buf: *const c_void, count: size_t,
+                              offset: off_t) -> ssize_t;
+                pub fn utime(file: *const c_char, buf: *const utimbuf) -> c_int;
+            }
         }
 
         pub mod signal {
@@ -5186,12 +5179,24 @@ pub mod mman {
             use types::os::arch::c95::{size_t, c_int, c_char};
             use types::os::arch::posix88::{mode_t, off_t};
 
+            #[cfg(not(target_os = "nacl"))]
             extern {
                 pub fn mlock(addr: *const c_void, len: size_t) -> c_int;
                 pub fn munlock(addr: *const c_void, len: size_t) -> c_int;
                 pub fn mlockall(flags: c_int) -> c_int;
                 pub fn munlockall() -> c_int;
 
+                pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int)
+                                -> c_int;
+
+                pub fn msync(addr: *mut c_void, len: size_t, flags: c_int)
+                             -> c_int;
+                pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t)
+                                -> c_int;
+                pub fn shm_unlink(name: *const c_char) -> c_int;
+            }
+
+            extern {
                 pub fn mmap(addr: *mut c_void,
                             len: size_t,
                             prot: c_int,
@@ -5201,14 +5206,6 @@ pub fn mmap(addr: *mut c_void,
                             -> *mut c_void;
                 pub fn munmap(addr: *mut c_void, len: size_t) -> c_int;
 
-                pub fn mprotect(addr: *mut c_void, len: size_t, prot: c_int)
-                                -> c_int;
-
-                pub fn msync(addr: *mut c_void, len: size_t, flags: c_int)
-                             -> c_int;
-                pub fn shm_open(name: *const c_char, oflag: c_int, mode: mode_t)
-                                -> c_int;
-                pub fn shm_unlink(name: *const c_char) -> c_int;
             }
         }
 
@@ -5228,7 +5225,9 @@ pub mod net {
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
-              target_os = "openbsd"))]
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "nacl"))]
     pub mod posix01 {
         pub mod stat_ {
             use types::os::arch::c95::{c_char, c_int};
@@ -5238,9 +5237,11 @@ pub mod stat_ {
                 #[cfg(any(target_os = "linux",
                           target_os = "freebsd",
                           target_os = "dragonfly",
+                          target_os = "bitrig",
                           target_os = "openbsd",
                           target_os = "android",
-                          target_os = "ios"))]
+                          target_os = "ios",
+                          target_os = "nacl"))]
                 pub fn lstat(path: *const c_char, buf: *mut stat) -> c_int;
 
                 #[cfg(target_os = "macos")]
@@ -5312,6 +5313,7 @@ pub mod mman {
             use types::common::c95::{c_void};
             use types::os::arch::c95::{c_int, size_t};
 
+            #[cfg(not(target_os = "nacl"))]
             extern {
                 pub fn posix_madvise(addr: *mut c_void,
                                      len: size_t,
@@ -5347,7 +5349,9 @@ pub mod net {
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
-              target_os = "openbsd"))]
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "nacl"))]
     pub mod posix08 {
         pub mod unistd {
         }
@@ -5434,6 +5438,7 @@ pub fn sendto(socket: SOCKET, buf: *const c_void, len: c_int,
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     pub mod bsd44 {
         use types::common::c95::{c_void};
@@ -5463,10 +5468,11 @@ pub fn madvise(addr: *mut c_void, len: size_t, advice: c_int)
                            -> c_int;
             pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar)
                            -> c_int;
+            pub fn realpath(pathname: *const c_char, resolved: *mut c_char)
+                            -> *mut c_char;
         }
     }
 
-
     #[cfg(any(target_os = "linux", target_os = "android"))]
     pub mod bsd44 {
         use types::common::c95::{c_void};
@@ -5483,6 +5489,13 @@ pub fn mincore(addr: *mut c_void, len: size_t, vec: *mut c_uchar)
         }
     }
 
+    #[cfg(target_os = "nacl")]
+    pub mod bsd44 {
+        use types::os::arch::c95::c_int;
+        extern {
+            pub fn getdtablesize() -> c_int;
+        }
+    }
 
     #[cfg(target_os = "windows")]
     pub mod bsd44 {
@@ -5500,11 +5513,12 @@ pub fn _NSGetExecutablePath(buf: *mut c_char, bufsize: *mut u32)
 
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     pub mod extra {
     }
 
-    #[cfg(any(target_os = "linux", target_os = "android"))]
+    #[cfg(any(target_os = "linux", target_os = "android", target_os = "nacl"))]
     pub mod extra {
     }
 
index c2c7f20ce9cdfcff7ead7cf1f79caaf23ff2962e..5e80bc5db2e41967512edd22373b6cf53f74ba81 100644 (file)
        html_playground_url = "http://play.rust-lang.org/")]
 #![deny(missing_docs)]
 
+#![feature(alloc)]
 #![feature(staged_api)]
 #![feature(box_syntax)]
 #![feature(int_uint)]
 #![feature(std_misc)]
 #![feature(env)]
 
+use std::boxed;
 use std::cell::RefCell;
 use std::fmt;
 use std::old_io::LineBufferedWriter;
 /// logging statement should be run.
 static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL;
 
-static mut DIRECTIVES: *const Vec<directive::LogDirective> =
-    0 as *const Vec<directive::LogDirective>;
+static mut DIRECTIVES: *mut Vec<directive::LogDirective> =
+    0 as *mut Vec<directive::LogDirective>;
 
 /// Optional filter.
-static mut FILTER: *const String = 0 as *const _;
+static mut FILTER: *mut String = 0 as *mut _;
 
 /// Debug log level
 pub const DEBUG: u32 = 4;
@@ -342,7 +344,7 @@ pub struct LogRecord<'a> {
     pub file: &'a str,
 
     /// The line number of where the LogRecord originated.
-    pub line: uint,
+    pub line: u32,
 }
 
 #[doc(hidden)]
@@ -350,7 +352,7 @@ pub struct LogRecord<'a> {
 pub struct LogLocation {
     pub module_path: &'static str,
     pub file: &'static str,
-    pub line: uint,
+    pub line: u32,
 }
 
 /// Tests whether a given module's name is enabled for a particular level of
@@ -419,23 +421,23 @@ fn init() {
 
         assert!(FILTER.is_null());
         match filter {
-            Some(f) => FILTER = mem::transmute(box f),
+            Some(f) => FILTER = boxed::into_raw(box f),
             None => {}
         }
 
         assert!(DIRECTIVES.is_null());
-        DIRECTIVES = mem::transmute(box directives);
+        DIRECTIVES = boxed::into_raw(box directives);
 
         // Schedule the cleanup for the globals for when the runtime exits.
         rt::at_exit(move || {
             assert!(!DIRECTIVES.is_null());
             let _directives: Box<Vec<directive::LogDirective>> =
-                mem::transmute(DIRECTIVES);
-            DIRECTIVES = ptr::null();
+                Box::from_raw(DIRECTIVES);
+            DIRECTIVES = ptr::null_mut();
 
             if !FILTER.is_null() {
-                let _filter: Box<String> = mem::transmute(FILTER);
-                FILTER = 0 as *const _;
+                let _filter: Box<String> = Box::from_raw(FILTER);
+                FILTER = 0 as *mut _;
             }
         });
     }
index 7588bf7c5158e7f27114784bbe2d025ec8dbfdbe..583c658dfe0582f3b02847e71aab3d4770620237 100644 (file)
@@ -32,6 +32,8 @@
 #![deprecated(reason = "use the crates.io `rand` library instead",
               since = "1.0.0-alpha")]
 
+#![cfg_attr(test, feature(test, rand))]
+
 #![allow(deprecated)]
 
 #[macro_use]
index 230fda11ab5ac58c9744787fd73a65826485e35c..c52465a889907b57c4357f19d4a801677ab8b6c5 100644 (file)
@@ -45,7 +45,7 @@ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64>
 /// let mut w = SeekableMemWriter::new();
 /// w.write(&[0, 1, 2]);
 ///
-/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// assert_eq!(w.unwrap(), [0, 1, 2]);
 /// ```
 pub struct SeekableMemWriter {
     buf: Vec<u8>,
index 4af322089d53d40d7d3bea7ece5bed39ff48437a..c48dd7a6ee89406fe26a978264a17ba81dd6c9f3 100644 (file)
@@ -32,6 +32,8 @@
 #![feature(rustc_private)]
 #![feature(staged_api)]
 
+#![cfg_attr(test, feature(test))]
+
 extern crate serialize;
 #[macro_use] extern crate log;
 
index fe9a81bb7c984f60d7b2b40e12b9f9106ddfd4ce..26cb4f917c5669d5114364f506625fc1476043bc 100644 (file)
@@ -40,6 +40,7 @@
 #![feature(staged_api)]
 #![feature(std_misc)]
 #![feature(unicode)]
+#![feature(os)]
 #![cfg_attr(test, feature(test))]
 
 extern crate arena;
index dc81e89902bb4c093b42d8c65386c7707777510f..a4f69e651df60a9e1738c4034d9018f12417b40f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -405,8 +405,8 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
-    fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
-        match self.cx.tcx.def_map.borrow()[path_id].clone() {
+    fn check_def(&mut self, sp: Span, id: ast::NodeId) {
+        match self.cx.tcx.def_map.borrow()[id].full_def() {
             def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => {
                 self.cx.span_lint(IMPROPER_CTYPES, sp,
                                   "found rust type `isize` in foreign module, while \
@@ -418,7 +418,7 @@ fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
                                    libc::c_uint or libc::c_ulong should be used");
             }
             def::DefTy(..) => {
-                let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty_id) {
+                let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) {
                     Some(&ty::atttce_resolved(t)) => t,
                     _ => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
                 };
@@ -437,9 +437,8 @@ fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
 
 impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
     fn visit_ty(&mut self, ty: &ast::Ty) {
-        match ty.node {
-            ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id),
-            _ => (),
+        if let ast::TyPath(..) = ty.node {
+            self.check_def(ty.span, ty.id);
         }
         visit::walk_ty(self, ty);
     }
@@ -588,7 +587,7 @@ fn get_lints(&self) -> LintArray {
     }
 
     fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        if !attr::contains_name(&item.attrs[], "automatically_derived") {
+        if !attr::contains_name(&item.attrs, "automatically_derived") {
             return
         }
         let did = match item.node {
@@ -652,7 +651,7 @@ fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
 
         if !attr::is_used(attr) {
             cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
-            if KNOWN_ATTRIBUTES.contains(&(&attr.name()[], AttributeType::CrateLevel)) {
+            if KNOWN_ATTRIBUTES.contains(&(&attr.name(), AttributeType::CrateLevel)) {
                 let msg = match attr.node.style {
                     ast::AttrOuter => "crate-level attribute should be an inner \
                                        attribute: add an exclamation mark: #![foo]",
@@ -683,8 +682,8 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
         match s.node {
             ast::StmtSemi(ref expr, _) => {
                 match expr.node {
-                    ast::ExprPath(_) => cx.span_lint(PATH_STATEMENTS, s.span,
-                                                     "path statement with no effect"),
+                    ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span,
+                                                      "path statement with no effect"),
                     _ => ()
                 }
             }
@@ -732,7 +731,7 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
             ty::ty_enum(did, _) => {
                 if ast_util::is_local(did) {
                     if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
-                        warned |= check_must_use(cx, &it.attrs[], s.span);
+                        warned |= check_must_use(cx, &it.attrs, s.span);
                     }
                 } else {
                     let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
@@ -784,7 +783,7 @@ fn is_camel_case(ident: ast::Ident) -> bool {
 
             // start with a non-lowercase letter rather than non-uppercase
             // ones (some scripts don't have a concept of upper/lowercase)
-            ident.len() > 0 && !ident.char_at(0).is_lowercase() && !ident.contains_char('_')
+            ident.len() > 0 && !ident.char_at(0).is_lowercase() && !ident.contains('_')
         }
 
         fn to_camel_case(s: &str) -> String {
@@ -1001,7 +1000,8 @@ fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) {
 
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         if let &ast::PatIdent(_, ref path1, _) = &p.node {
-            if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) {
+            let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
+            if let Some(def::DefLocal(_)) = def {
                 self.check_snake_case(cx, "variable", path1.node, p.span);
             }
         }
@@ -1066,8 +1066,8 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
 
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
-        match (&p.node, cx.tcx.def_map.borrow().get(&p.id)) {
-            (&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => {
+        match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
+            (&ast::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
                 NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
                                                       path1.node, p.span);
             }
@@ -1093,7 +1093,7 @@ fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str,
             if !necessary {
                 cx.span_lint(UNUSED_PARENS, value.span,
                              &format!("unnecessary parentheses around {}",
-                                     msg)[])
+                                     msg))
             }
         }
 
@@ -1227,15 +1227,18 @@ fn get_lints(&self) -> LintArray {
     fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
         let def_map = cx.tcx.def_map.borrow();
         if let ast::PatStruct(_, ref v, _) = pat.node {
-            for fieldpat in v.iter()
-                             .filter(|fieldpat| !fieldpat.node.is_shorthand)
-                             .filter(|fieldpat| def_map.get(&fieldpat.node.pat.id)
-                                                == Some(&def::DefLocal(fieldpat.node.pat.id))) {
+            let field_pats = v.iter()
+                              .filter(|fieldpat| !fieldpat.node.is_shorthand)
+                              .filter(|fieldpat| {
+                let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
+                def == Some(def::DefLocal(fieldpat.node.pat.id))
+            });
+            for fieldpat in field_pats {
                 if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node {
                     if ident.node.as_str() == fieldpat.node.ident.as_str() {
                         cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
                                      &format!("the `{}:` in this pattern is redundant and can \
-                                              be removed", ident.node.as_str())[])
+                                              be removed", ident.node.as_str()))
                     }
                 }
             }
@@ -1269,27 +1272,61 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
 }
 
 declare_lint! {
-    UNSAFE_BLOCKS,
+    UNSAFE_CODE,
     Allow,
-    "usage of an `unsafe` block"
+    "usage of `unsafe` code"
 }
 
 #[derive(Copy)]
-pub struct UnsafeBlocks;
+pub struct UnsafeCode;
 
-impl LintPass for UnsafeBlocks {
+impl LintPass for UnsafeCode {
     fn get_lints(&self) -> LintArray {
-        lint_array!(UNSAFE_BLOCKS)
+        lint_array!(UNSAFE_CODE)
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         if let ast::ExprBlock(ref blk) = e.node {
             // Don't warn about generated blocks, that'll just pollute the output.
             if blk.rules == ast::UnsafeBlock(ast::UserProvided) {
-                cx.span_lint(UNSAFE_BLOCKS, blk.span, "usage of an `unsafe` block");
+                cx.span_lint(UNSAFE_CODE, blk.span, "usage of an `unsafe` block");
             }
         }
     }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        match it.node {
+            ast::ItemTrait(ast::Unsafety::Unsafe, _, _, _) =>
+                cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"),
+
+            ast::ItemImpl(ast::Unsafety::Unsafe, _, _, _, _, _) =>
+                cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"),
+
+            _ => return,
+        }
+    }
+
+    fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl,
+                _: &ast::Block, span: Span, _: ast::NodeId) {
+        match fk {
+            visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _) =>
+                cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
+
+            visit::FkMethod(_, _, m) => {
+                if let ast::Method_::MethDecl(_, _, _, _, ast::Unsafety::Unsafe, _, _, _) = m.node {
+                    cx.span_lint(UNSAFE_CODE, m.span, "implementation of an `unsafe` method")
+                }
+            },
+
+            _ => (),
+        }
+    }
+
+    fn check_ty_method(&mut self, cx: &Context, ty_method: &ast::TypeMethod) {
+        if let ast::TypeMethod { unsafety: ast::Unsafety::Unsafe, span, ..} = *ty_method {
+            cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method")
+        }
+    }
 }
 
 declare_lint! {
@@ -1339,7 +1376,7 @@ fn get_lints(&self) -> LintArray {
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         if let ast::ExprMatch(_, ref arms, _) = e.node {
             for a in arms {
-                self.check_unused_mut_pat(cx, &a.pats[])
+                self.check_unused_mut_pat(cx, &a.pats)
             }
         }
     }
@@ -1460,7 +1497,7 @@ fn check_missing_docs_attrs(&self,
         });
         if !has_doc {
             cx.span_lint(MISSING_DOCS, sp,
-                &format!("missing documentation for {}", desc)[]);
+                &format!("missing documentation for {}", desc));
         }
     }
 }
@@ -1496,7 +1533,7 @@ fn check_struct_def_post(&mut self, _: &Context,
     }
 
     fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) {
-        self.check_missing_docs_attrs(cx, None, &krate.attrs[],
+        self.check_missing_docs_attrs(cx, None, &krate.attrs,
                                      krate.span, "crate");
     }
 
@@ -1510,7 +1547,7 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
             ast::ItemTy(..) => "a type alias",
             _ => return
         };
-        self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs[],
+        self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs,
                                      it.span, desc);
     }
 
@@ -1523,30 +1560,38 @@ fn check_fn(&mut self, cx: &Context,
 
             // Otherwise, doc according to privacy. This will also check
             // doc for default methods defined on traits.
-            self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs[],
+            self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs,
                                           m.span, "a method");
         }
     }
 
     fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) {
-        self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs[],
+        self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs,
                                      tm.span, "a type method");
     }
 
+    fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) {
+        if let ast::TraitItem::TypeTraitItem(ref ty) = *it {
+            let assoc_ty = &ty.ty_param;
+            self.check_missing_docs_attrs(cx, Some(assoc_ty.id), &ty.attrs,
+                                          assoc_ty.span, "an associated type");
+        }
+    }
+
     fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) {
         if let ast::NamedField(_, vis) = sf.node.kind {
             if vis == ast::Public || self.in_variant {
                 let cur_struct_def = *self.struct_def_stack.last()
                     .expect("empty struct_def_stack");
                 self.check_missing_docs_attrs(cx, Some(cur_struct_def),
-                                              &sf.node.attrs[], sf.span,
+                                              &sf.node.attrs, sf.span,
                                               "a struct field")
             }
         }
     }
 
     fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) {
-        self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs[],
+        self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs,
                                      v.span, "a variant");
         assert!(!self.in_variant);
         self.in_variant = true;
@@ -1804,7 +1849,7 @@ fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
                 continue
             }
             visited.insert(cfg_id);
-            let node_id = cfg.graph.node_data(idx).id;
+            let node_id = cfg.graph.node_data(idx).id();
 
             // is this a recursive call?
             if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
@@ -1857,10 +1902,7 @@ fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>,
                                       _: ast::Ident,
                                       id: ast::NodeId) -> bool {
             tcx.def_map.borrow().get(&id)
-                .map_or(false, |def| {
-                    let did = def.def_id();
-                    ast_util::is_local(did) && did.node == fn_id
-                })
+                .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
         }
 
         // check if the method call `id` refers to method `method_id`
index 068c179d3431fe7c18087fd92dd1dc7a9a475f54..d344ee8c881c5ab4fa796f64f80f9ae2264ffcb2 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -105,7 +105,7 @@ pub fn new() -> LintStore {
     }
 
     pub fn get_lints<'t>(&'t self) -> &'t [(&'static Lint, bool)] {
-        &self.lints[]
+        &self.lints
     }
 
     pub fn get_lint_groups<'t>(&'t self) -> Vec<(&'static str, Vec<LintId>, bool)> {
@@ -206,7 +206,7 @@ macro_rules! add_lint_group {
                      UnusedImportBraces,
                      NonShorthandFieldPatterns,
                      UnusedUnsafe,
-                     UnsafeBlocks,
+                     UnsafeCode,
                      UnusedMut,
                      UnusedAllocation,
                      MissingCopyImplementations,
@@ -276,7 +276,7 @@ pub fn process_command_line(&mut self, sess: &Session) {
                              .collect::<Vec<()>>();
                         }
                         None => sess.err(&format!("unknown {} flag: {}",
-                                                 level.as_str(), lint_name)[]),
+                                                 level.as_str(), lint_name)),
                     }
                 }
             }
@@ -527,7 +527,7 @@ fn with_lint_attrs<F>(&mut self,
                     self.tcx.sess.span_err(span,
                                            &format!("{}({}) overruled by outer forbid({})",
                                                    level.as_str(), lint_name,
-                                                   lint_name)[]);
+                                                   lint_name));
                 } else if now != level {
                     let src = self.lints.get_level_source(lint_id).1;
                     self.level_stack.push((lint_id, (now, src)));
@@ -562,7 +562,7 @@ fn visit_ids<F>(&mut self, f: F) where
 
 impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> {
     fn visit_item(&mut self, it: &ast::Item) {
-        self.with_lint_attrs(&it.attrs[], |cx| {
+        self.with_lint_attrs(&it.attrs, |cx| {
             run_lints!(cx, check_item, it);
             cx.visit_ids(|v| v.visit_item(it));
             visit::walk_item(cx, it);
@@ -570,7 +570,7 @@ fn visit_item(&mut self, it: &ast::Item) {
     }
 
     fn visit_foreign_item(&mut self, it: &ast::ForeignItem) {
-        self.with_lint_attrs(&it.attrs[], |cx| {
+        self.with_lint_attrs(&it.attrs, |cx| {
             run_lints!(cx, check_foreign_item, it);
             visit::walk_foreign_item(cx, it);
         })
@@ -595,7 +595,7 @@ fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v ast::FnDecl,
                 body: &'v ast::Block, span: Span, id: ast::NodeId) {
         match fk {
             visit::FkMethod(_, _, m) => {
-                self.with_lint_attrs(&m.attrs[], |cx| {
+                self.with_lint_attrs(&m.attrs, |cx| {
                     run_lints!(cx, check_fn, fk, decl, body, span, id);
                     cx.visit_ids(|v| {
                         v.visit_fn(fk, decl, body, span, id);
@@ -611,7 +611,7 @@ fn visit_fn(&mut self, fk: FnKind<'v>, decl: &'v ast::FnDecl,
     }
 
     fn visit_ty_method(&mut self, t: &ast::TypeMethod) {
-        self.with_lint_attrs(&t.attrs[], |cx| {
+        self.with_lint_attrs(&t.attrs, |cx| {
             run_lints!(cx, check_ty_method, t);
             visit::walk_ty_method(cx, t);
         })
@@ -628,14 +628,14 @@ fn visit_struct_def(&mut self,
     }
 
     fn visit_struct_field(&mut self, s: &ast::StructField) {
-        self.with_lint_attrs(&s.node.attrs[], |cx| {
+        self.with_lint_attrs(&s.node.attrs, |cx| {
             run_lints!(cx, check_struct_field, s);
             visit::walk_struct_field(cx, s);
         })
     }
 
     fn visit_variant(&mut self, v: &ast::Variant, g: &ast::Generics) {
-        self.with_lint_attrs(&v.node.attrs[], |cx| {
+        self.with_lint_attrs(&v.node.attrs, |cx| {
             run_lints!(cx, check_variant, v, g);
             visit::walk_variant(cx, v, g);
             run_lints!(cx, check_variant_post, v, g);
@@ -779,7 +779,7 @@ pub fn check_crate(tcx: &ty::ctxt,
     let mut cx = Context::new(tcx, krate, exported_items);
 
     // Visit the whole crate.
-    cx.with_lint_attrs(&krate.attrs[], |cx| {
+    cx.with_lint_attrs(&krate.attrs, |cx| {
         cx.visit_id(ast::CRATE_NODE_ID);
         cx.visit_ids(|v| {
             v.visited_outermost = true;
index bdcc10ebceca061899bf93a64540a42c37de4253..021827b0101c81f7dee8caf04ab20ca6bcc9cac5 100644 (file)
@@ -185,14 +185,6 @@ fn eq(&self, other: &LintId) -> bool {
 
 impl Eq for LintId { }
 
-#[cfg(stage0)]
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for LintId {
-    fn hash(&self, state: &mut S) {
-        let ptr = self.lint as *const Lint;
-        ptr.hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl hash::Hash for LintId {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         let ptr = self.lint as *const Lint;
index d48a404176ace37d2727925a3fd958ea309f32c4..46155925b3c72dab922b635ad1b00fd6a67d6f31 100644 (file)
@@ -61,7 +61,7 @@ fn dump_crates(cstore: &CStore) {
 }
 
 fn should_link(i: &ast::Item) -> bool {
-    !attr::contains_name(&i.attrs[], "no_link")
+    !attr::contains_name(&i.attrs, "no_link")
 }
 
 struct CrateInfo {
@@ -81,11 +81,13 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
     };
     if s.len() == 0 {
         err("crate name must not be empty");
+    } else if s.char_at(0) == '-' {
+        err(&format!("crate name cannot start with a hyphen: {}", s));
     }
     for c in s.chars() {
         if c.is_alphanumeric() { continue }
         if c == '_' || c == '-' { continue }
-        err(&format!("invalid character `{}` in crate name: `{}`", c, s)[]);
+        err(&format!("invalid character `{}` in crate name: `{}`", c, s));
     }
     match sess {
         Some(sess) => sess.abort_if_errors(),
@@ -210,8 +212,8 @@ fn process_item(&mut self, i: &ast::Item) {
                 match self.extract_crate_info(i) {
                     Some(info) => {
                         let (cnum, _, _) = self.resolve_crate(&None,
-                                                              &info.ident[],
-                                                              &info.name[],
+                                                              &info.ident,
+                                                              &info.name,
                                                               None,
                                                               i.span,
                                                               PathKind::Crate);
@@ -268,7 +270,7 @@ fn process_item(&mut self, i: &ast::Item) {
                                     } else {
                                         self.sess.span_err(m.span,
                                             &format!("unknown kind: `{}`",
-                                                    k)[]);
+                                                    k));
                                         cstore::NativeUnknown
                                     }
                                 }
@@ -413,7 +415,7 @@ fn resolve_crate(&mut self,
                     hash: hash.map(|a| &*a),
                     filesearch: self.sess.target_filesearch(kind),
                     target: &self.sess.target.target,
-                    triple: &self.sess.opts.target_triple[],
+                    triple: &self.sess.opts.target_triple,
                     root: root,
                     rejected_via_hash: vec!(),
                     rejected_via_triple: vec!(),
@@ -440,8 +442,8 @@ fn resolve_crate_deps(&mut self,
         decoder::get_crate_deps(cdata).iter().map(|dep| {
             debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
             let (local_cnum, _, _) = self.resolve_crate(root,
-                                                   &dep.name[],
-                                                   &dep.name[],
+                                                   &dep.name,
+                                                   &dep.name,
                                                    Some(&dep.hash),
                                                    span,
                                                    PathKind::Dependency);
@@ -450,7 +452,7 @@ fn resolve_crate_deps(&mut self,
     }
 
     fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate {
-        let target_triple = &self.sess.opts.target_triple[];
+        let target_triple = &self.sess.opts.target_triple[..];
         let is_cross = target_triple != config::host_triple();
         let mut should_link = info.should_link && !is_cross;
         let mut target_only = false;
@@ -493,8 +495,8 @@ fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCra
                                                           PathKind::Crate).is_none();
         let metadata = if register {
             // Register crate now to avoid double-reading metadata
-            let (_, cmd, _) = self.register_crate(&None, &info.ident[],
-                                &info.name[], span, library);
+            let (_, cmd, _) = self.register_crate(&None, &info.ident,
+                                &info.name, span, library);
             PMDSource::Registered(cmd)
         } else {
             // Not registering the crate; just hold on to the metadata
index 7eeb0589118fbf8dbfd1cc47df80f92a576083b2..f5c4cce065955659fddcfcc17c6f0d4dee2d426e 100644 (file)
@@ -92,7 +92,7 @@ pub fn get_item_path(tcx: &ty::ctxt, def: ast::DefId) -> Vec<ast_map::PathElem>
 
     // FIXME #1920: This path is not always correct if the crate is not linked
     // into the root namespace.
-    let mut r = vec![ast_map::PathMod(token::intern(&cdata.name[]))];
+    let mut r = vec![ast_map::PathMod(token::intern(&cdata.name))];
     r.push_all(&path);
     r
 }
@@ -150,12 +150,9 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name {
                             def.node)
 }
 
-pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
-                                    -> (ast::Name, def::TraitItemKind) {
+pub fn is_static_method(cstore: &cstore::CStore, def: ast::DefId) -> bool {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
-                                          &*cdata,
-                                          def.node)
+    decoder::is_static_method(&*cdata, def.node)
 }
 
 pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
@@ -391,7 +388,7 @@ pub fn is_staged_api(cstore: &cstore::CStore, def: ast::DefId) -> bool {
     let cdata = cstore.get_crate_data(def.krate);
     let attrs = decoder::get_crate_attributes(cdata.data());
     for attr in &attrs {
-        if &attr.name()[] == "staged_api" {
+        if &attr.name()[..] == "staged_api" {
             match attr.node.value.node { ast::MetaWord(_) => return true, _ => (/*pass*/) }
         }
     }
@@ -410,3 +407,7 @@ pub fn is_associated_type(cstore: &cstore::CStore, def: ast::DefId) -> bool {
     decoder::is_associated_type(&*cdata, def.node)
 }
 
+pub fn is_default_trait(cstore: &cstore::CStore, def: ast::DefId) -> bool {
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::is_default_trait(&*cdata, def.node)
+}
index e5576de6e842442c0de92fc94f2b2c630b08eaca..0503045ac6e2d1673027bdf9bf1ede727c0c6f23 100644 (file)
@@ -119,13 +119,13 @@ enum Family {
     StaticMethod,          // F
     Method,                // h
     Type,                  // y
-    ForeignType,           // T
     Mod,                   // m
     ForeignMod,            // n
     Enum,                  // t
     TupleVariant,          // v
     StructVariant,         // V
     Impl,                  // i
+    DefaultImpl,              // d
     Trait,                 // I
     Struct,                // S
     PublicField,           // g
@@ -144,13 +144,13 @@ fn item_family(item: rbml::Doc) -> Family {
       'F' => StaticMethod,
       'h' => Method,
       'y' => Type,
-      'T' => ForeignType,
       'm' => Mod,
       'n' => ForeignMod,
       't' => Enum,
       'v' => TupleVariant,
       'V' => StructVariant,
       'i' => Impl,
+      'd' => DefaultImpl,
       'I' => Trait,
       'S' => Struct,
       'g' => PublicField,
@@ -172,16 +172,13 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
     }
 }
 
-fn item_sort(item: rbml::Doc) -> char {
+fn item_sort(item: rbml::Doc) -> Option<char> {
     let mut ret = None;
     reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
         ret = Some(doc.as_str_slice().as_bytes()[0] as char);
         false
     });
-    match ret {
-        Some(r) => r,
-        None => panic!("No item_sort found")
-    }
+    ret
 }
 
 fn item_symbol(item: rbml::Doc) -> String {
@@ -337,14 +334,16 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
                 def::FromImpl(item_reqd_and_translated_parent_item(cnum,
                                                                    item))
             };
-            match fam {
-                // We don't bother to get encode/decode the trait id, we don't need it.
-                Method => DlDef(def::DefMethod(did, None, provenance)),
-                StaticMethod => DlDef(def::DefStaticMethod(did, provenance)),
-                _ => panic!()
+            DlDef(def::DefMethod(did, provenance))
+        }
+        Type => {
+            if item_sort(item) == Some('t') {
+                let trait_did = item_reqd_and_translated_parent_item(cnum, item);
+                DlDef(def::DefAssociatedTy(trait_did, did))
+            } else {
+                DlDef(def::DefTy(did, false))
             }
         }
-        Type | ForeignType => DlDef(def::DefTy(did, false)),
         Mod => DlDef(def::DefMod(did)),
         ForeignMod => DlDef(def::DefForeignMod(did)),
         StructVariant => {
@@ -357,7 +356,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
         }
         Trait => DlDef(def::DefTrait(did)),
         Enum => DlDef(def::DefTy(did, true)),
-        Impl => DlImpl(did),
+        Impl | DefaultImpl => DlImpl(did),
         PublicField | InheritedField => DlField,
     }
 }
@@ -480,7 +479,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
     let item_doc = lookup_item(id, cdata.data());
     let fam = item_family(item_doc);
     match fam {
-        Family::Impl => {
+        Family::Impl | Family::DefaultImpl => {
             reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
                 doc_trait_ref(tp, tcx, cdata)
             })
@@ -829,8 +828,10 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
                         tag_item_impl_item, |doc| {
         let def_id = item_def_id(doc, cdata);
         match item_sort(doc) {
-            'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
-            't' => impl_items.push(ty::TypeTraitItemId(def_id)),
+            Some('r') | Some('p') => {
+                impl_items.push(ty::MethodTraitItemId(def_id))
+            }
+            Some('t') => impl_items.push(ty::TypeTraitItemId(def_id)),
             _ => panic!("unknown impl item sort"),
         }
         true
@@ -847,22 +848,13 @@ pub fn get_trait_name(intr: Rc<IdentInterner>,
     item_name(&*intr, doc)
 }
 
-pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
-                                    cdata: Cmd,
-                                    id: ast::NodeId)
-                                    -> (ast::Name, def::TraitItemKind) {
+pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
     let doc = lookup_item(id, cdata.data());
-    let name = item_name(&*intr, doc);
     match item_sort(doc) {
-        'r' | 'p' => {
-            let explicit_self = get_explicit_self(doc);
-            (name, def::TraitItemKind::from_explicit_self_category(explicit_self))
-        }
-        't' => (name, def::TypeTraitItemKind),
-        c => {
-            panic!("get_trait_item_name_and_kind(): unknown trait item kind \
-                   in metadata: `{}`", c)
+        Some('r') | Some('p') => {
+            get_explicit_self(doc) == ty::StaticExplicitSelfCategory
         }
+        _ => false
     }
 }
 
@@ -887,7 +879,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     let vis = item_visibility(method_doc);
 
     match item_sort(method_doc) {
-        'r' | 'p' => {
+        Some('r') | Some('p') => {
             let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
             let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
             let fty = doc_method_fty(method_doc, tcx, cdata);
@@ -904,7 +896,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                                         container,
                                                         provided_source)))
         }
-        't' => {
+        Some('t') => {
             ty::TypeTraitItem(Rc::new(ty::AssociatedType {
                 name: name,
                 vis: vis,
@@ -924,8 +916,10 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
     reader::tagged_docs(item, tag_item_trait_item, |mth| {
         let def_id = item_def_id(mth, cdata);
         match item_sort(mth) {
-            'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
-            't' => result.push(ty::TypeTraitItemId(def_id)),
+            Some('r') | Some('p') => {
+                result.push(ty::MethodTraitItemId(def_id));
+            }
+            Some('t') => result.push(ty::TypeTraitItemId(def_id)),
             _ => panic!("unknown trait item sort"),
         }
         true
@@ -954,7 +948,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
         let did = item_def_id(mth_id, cdata);
         let mth = lookup_item(did.node, data);
 
-        if item_sort(mth) == 'p' {
+        if item_sort(mth) == Some('p') {
             let trait_item = get_impl_or_trait_item(intr.clone(),
                                                     cdata,
                                                     did.node,
@@ -1225,7 +1219,7 @@ fn docstr(doc: rbml::Doc, tag_: uint) -> String {
     }
     reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| {
         let name = docstr(depdoc, tag_crate_dep_crate_name);
-        let hash = Svh::new(&docstr(depdoc, tag_crate_dep_hash)[]);
+        let hash = Svh::new(&docstr(depdoc, tag_crate_dep_hash));
         deps.push(CrateDep {
             cnum: crate_num,
             name: name,
@@ -1356,7 +1350,7 @@ pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
     let parent_item_doc = lookup_item(parent_item_id.node, cdata.data());
     match item_family(parent_item_doc) {
         Trait => Some(item_def_id(parent_item_doc, cdata)),
-        Impl => {
+        Impl | DefaultImpl => {
             reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref)
                 .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id)
         }
@@ -1558,6 +1552,15 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
     let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
     match maybe_find_item(id, items) {
         None => false,
-        Some(item) => item_sort(item) == 't',
+        Some(item) => item_sort(item) == Some('t'),
+    }
+}
+
+
+pub fn is_default_trait<'tcx>(cdata: Cmd, id: ast::NodeId) -> bool {
+    let item_doc = lookup_item(id, cdata.data());
+    match item_family(item_doc) {
+        Family::DefaultImpl => true,
+        _ => false
     }
 }
index 42a70cec5dfee08903c604b672a124e0e4aef4da..ee2745ca66bc59980a675bd7dd7da2f24129d447 100644 (file)
@@ -94,7 +94,7 @@ fn encode_impl_type_basename(rbml_w: &mut Encoder, name: ast::Ident) {
 }
 
 pub fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
-    rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id)[]);
+    rbml_w.wr_tagged_str(tag_def_id, &def_to_string(id));
 }
 
 #[derive(Clone)]
@@ -273,7 +273,7 @@ fn encode_symbol(ecx: &EncodeContext,
         }
         None => {
             ecx.diag.handler().bug(
-                &format!("encode_symbol: id not found {}", id)[]);
+                &format!("encode_symbol: id not found {}", id));
         }
     }
     rbml_w.end_tag();
@@ -341,8 +341,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         encode_name(rbml_w, variant.node.name.name);
         encode_parent_item(rbml_w, local_def(id));
         encode_visibility(rbml_w, variant.node.vis);
-        encode_attributes(rbml_w, &variant.node.attrs[]);
-        encode_repr_attrs(rbml_w, ecx, &variant.node.attrs[]);
+        encode_attributes(rbml_w, &variant.node.attrs);
+        encode_repr_attrs(rbml_w, ecx, &variant.node.attrs);
 
         let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
         encode_stability(rbml_w, stab);
@@ -394,12 +394,12 @@ fn encode_reexported_static_method(rbml_w: &mut Encoder,
             exp.name, token::get_name(method_name));
     rbml_w.start_tag(tag_items_data_item_reexport);
     rbml_w.start_tag(tag_items_data_item_reexport_def_id);
-    rbml_w.wr_str(&def_to_string(method_def_id)[]);
+    rbml_w.wr_str(&def_to_string(method_def_id));
     rbml_w.end_tag();
     rbml_w.start_tag(tag_items_data_item_reexport_name);
     rbml_w.wr_str(&format!("{}::{}",
                           exp.name,
-                          token::get_name(method_name))[]);
+                          token::get_name(method_name)));
     rbml_w.end_tag();
     rbml_w.end_tag();
 }
@@ -537,7 +537,7 @@ fn encode_reexports(ecx: &EncodeContext,
                        id);
                 rbml_w.start_tag(tag_items_data_item_reexport);
                 rbml_w.start_tag(tag_items_data_item_reexport_def_id);
-                rbml_w.wr_str(&def_to_string(exp.def_id)[]);
+                rbml_w.wr_str(&def_to_string(exp.def_id));
                 rbml_w.end_tag();
                 rbml_w.start_tag(tag_items_data_item_reexport_name);
                 rbml_w.wr_str(exp.name.as_str());
@@ -570,13 +570,13 @@ fn encode_info_for_mod(ecx: &EncodeContext,
     // Encode info about all the module children.
     for item in &md.items {
         rbml_w.start_tag(tag_mod_child);
-        rbml_w.wr_str(&def_to_string(local_def(item.id))[]);
+        rbml_w.wr_str(&def_to_string(local_def(item.id)));
         rbml_w.end_tag();
 
         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
             rbml_w.start_tag(tag_mod_child);
             rbml_w.wr_str(&def_to_string(local_def(
-                        auxiliary_node_id))[]);
+                        auxiliary_node_id)));
             rbml_w.end_tag();
             true
         });
@@ -588,7 +588,7 @@ fn encode_info_for_mod(ecx: &EncodeContext,
                    did, ecx.tcx.map.node_to_string(did));
 
             rbml_w.start_tag(tag_mod_impl);
-            rbml_w.wr_str(&def_to_string(local_def(did))[]);
+            rbml_w.wr_str(&def_to_string(local_def(did)));
             rbml_w.end_tag();
         }
     }
@@ -623,7 +623,7 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
         ast::Public => 'y',
         ast::Inherited => 'i',
     };
-    rbml_w.wr_str(&ch.to_string()[]);
+    rbml_w.wr_str(&ch.to_string());
     rbml_w.end_tag();
 }
 
@@ -783,7 +783,7 @@ fn encode_generics<'a, 'tcx>(rbml_w: &mut Encoder,
         rbml_w.end_tag();
 
         rbml_w.wr_tagged_str(tag_region_param_def_def_id,
-                             &def_to_string(param.def_id)[]);
+                             &def_to_string(param.def_id));
 
         rbml_w.wr_tagged_u64(tag_region_param_def_space,
                              param.space.to_uint() as u64);
@@ -858,10 +858,10 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
     match ast_item_opt {
         Some(&ast::MethodImplItem(ref ast_method)) => {
-            encode_attributes(rbml_w, &ast_method.attrs[]);
+            encode_attributes(rbml_w, &ast_method.attrs);
             let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
             let any_types = !scheme.generics.types.is_empty();
-            if any_types || is_default_impl || should_inline(&ast_method.attrs[]) {
+            if any_types || is_default_impl || attr::requests_inline(&ast_method.attrs) {
                 encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id),
                                                                ast_item_opt.unwrap()));
             }
@@ -906,7 +906,7 @@ fn encode_info_for_associated_type(ecx: &EncodeContext,
     match typedef_opt {
         None => {}
         Some(typedef) => {
-            encode_attributes(rbml_w, &typedef.attrs[]);
+            encode_attributes(rbml_w, &typedef.attrs);
             encode_type(ecx, rbml_w, ty::node_id_to_type(ecx.tcx,
                                                          typedef.id));
         }
@@ -954,14 +954,6 @@ fn encode_inlined_item(ecx: &EncodeContext,
 const STATIC_METHOD_FAMILY: char = 'F';
 const METHOD_FAMILY: char = 'h';
 
-fn should_inline(attrs: &[ast::Attribute]) -> bool {
-    use syntax::attr::*;
-    match find_inline_attr(attrs) {
-        InlineNone | InlineNever  => false,
-        InlineHint | InlineAlways => true
-    }
-}
-
 // Encodes the inherent implementations of a structure, enumeration, or trait.
 fn encode_inherent_implementations(ecx: &EncodeContext,
                                    rbml_w: &mut Encoder,
@@ -1040,7 +1032,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_path(rbml_w, path);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
-        encode_attributes(rbml_w, &item.attrs[]);
+        encode_attributes(rbml_w, &item.attrs);
         rbml_w.end_tag();
       }
       ast::ItemConst(_, _) => {
@@ -1066,8 +1058,8 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.ident.name);
         encode_path(rbml_w, path);
-        encode_attributes(rbml_w, &item.attrs[]);
-        if tps_len > 0 || should_inline(&item.attrs[]) {
+        encode_attributes(rbml_w, &item.attrs);
+        if tps_len > 0 || attr::requests_inline(&item.attrs) {
             encode_inlined_item(ecx, rbml_w, IIItemRef(item));
         }
         if tps_len == 0 {
@@ -1083,7 +1075,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_info_for_mod(ecx,
                             rbml_w,
                             m,
-                            &item.attrs[],
+                            &item.attrs,
                             item.id,
                             path,
                             item.ident,
@@ -1100,7 +1092,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         // Encode all the items in this module.
         for foreign_item in &fm.items {
             rbml_w.start_tag(tag_mod_child);
-            rbml_w.wr_str(&def_to_string(local_def(foreign_item.id))[]);
+            rbml_w.wr_str(&def_to_string(local_def(foreign_item.id)));
             rbml_w.end_tag();
         }
         encode_visibility(rbml_w, vis);
@@ -1128,8 +1120,8 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_item_variances(rbml_w, ecx, item.id);
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.ident.name);
-        encode_attributes(rbml_w, &item.attrs[]);
-        encode_repr_attrs(rbml_w, ecx, &item.attrs[]);
+        encode_attributes(rbml_w, &item.attrs);
+        encode_repr_attrs(rbml_w, ecx, &item.attrs);
         for v in &enum_definition.variants {
             encode_variant_id(rbml_w, local_def(v.node.id));
         }
@@ -1146,7 +1138,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_enum_variant_info(ecx,
                                  rbml_w,
                                  item.id,
-                                 &(*enum_definition).variants[],
+                                 &(*enum_definition).variants,
                                  index);
       }
       ast::ItemStruct(ref struct_def, _) => {
@@ -1172,11 +1164,11 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
 
         encode_item_variances(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.ident.name);
-        encode_attributes(rbml_w, &item.attrs[]);
+        encode_attributes(rbml_w, &item.attrs);
         encode_path(rbml_w, path.clone());
         encode_stability(rbml_w, stab);
         encode_visibility(rbml_w, vis);
-        encode_repr_attrs(rbml_w, ecx, &item.attrs[]);
+        encode_repr_attrs(rbml_w, ecx, &item.attrs);
 
         /* Encode def_ids for each field and method
          for methods, write all the stuff get_trait_method
@@ -1201,6 +1193,18 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             None => {}
         }
       }
+      ast::ItemDefaultImpl(unsafety, _) => {
+          add_to_index(item, rbml_w, index);
+          rbml_w.start_tag(tag_items_data_item);
+          encode_def_id(rbml_w, def_id);
+          encode_family(rbml_w, 'd');
+          encode_name(rbml_w, item.ident.name);
+          encode_unsafety(rbml_w, unsafety);
+
+          let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
+          encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
+          rbml_w.end_tag();
+      }
       ast::ItemImpl(unsafety, polarity, _, ref opt_trait, ref ty, ref ast_items) => {
         // We need to encode information about the default methods we
         // have inherited, so we drive this based on the impl structure.
@@ -1213,11 +1217,11 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_family(rbml_w, 'i');
         encode_bounds_and_type_for_item(rbml_w, ecx, item.id);
         encode_name(rbml_w, item.ident.name);
-        encode_attributes(rbml_w, &item.attrs[]);
+        encode_attributes(rbml_w, &item.attrs);
         encode_unsafety(rbml_w, unsafety);
         encode_polarity(rbml_w, polarity);
         match ty.node {
-            ast::TyPath(ref path, _) if path.segments.len() == 1 => {
+            ast::TyPath(None, ref path) if path.segments.len() == 1 => {
                 let ident = path.segments.last().unwrap().identifier;
                 encode_impl_type_basename(rbml_w, ident);
             }
@@ -1237,9 +1241,8 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             }
             rbml_w.end_tag();
         }
-        if let Some(ref ast_trait_ref) = *opt_trait {
-            let trait_ref = ty::node_id_to_trait_ref(
-                tcx, ast_trait_ref.ref_id);
+        if opt_trait.is_some() {
+            let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
             encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
         }
         encode_path(rbml_w, path.clone());
@@ -1319,7 +1322,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates, tag_item_generics);
         encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
         encode_name(rbml_w, item.ident.name);
-        encode_attributes(rbml_w, &item.attrs[]);
+        encode_attributes(rbml_w, &item.attrs);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
         for &method_def_id in &*ty::trait_item_def_ids(tcx, def_id) {
@@ -1337,7 +1340,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             rbml_w.end_tag();
 
             rbml_w.start_tag(tag_mod_child);
-            rbml_w.wr_str(&def_to_string(method_def_id.def_id())[]);
+            rbml_w.wr_str(&def_to_string(method_def_id.def_id()));
             rbml_w.end_tag();
         }
         encode_path(rbml_w, path.clone());
@@ -1426,14 +1429,14 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             };
             match trait_item {
                 &ast::RequiredMethod(ref m) => {
-                    encode_attributes(rbml_w, &m.attrs[]);
+                    encode_attributes(rbml_w, &m.attrs);
                     encode_trait_item(rbml_w);
                     encode_item_sort(rbml_w, 'r');
                     encode_method_argument_names(rbml_w, &*m.decl);
                 }
 
                 &ast::ProvidedMethod(ref m) => {
-                    encode_attributes(rbml_w, &m.attrs[]);
+                    encode_attributes(rbml_w, &m.attrs);
                     encode_trait_item(rbml_w);
                     encode_item_sort(rbml_w, 'p');
                     encode_inlined_item(ecx, rbml_w, IITraitItemRef(def_id, trait_item));
@@ -1442,7 +1445,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
 
                 &ast::TypeTraitItem(ref associated_type) => {
                     encode_attributes(rbml_w,
-                                      &associated_type.attrs[]);
+                                      &associated_type.attrs);
                     encode_item_sort(rbml_w, 't');
                 }
             }
@@ -1588,48 +1591,6 @@ fn encode_info_for_items(ecx: &EncodeContext,
 
 // Path and definition ID indexing
 
-#[cfg(stage0)]
-fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
-    F: FnMut(&mut SeekableMemWriter, &T),
-    T: Hash<SipHasher>,
-{
-    let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect();
-    for elt in index {
-        let mut s = SipHasher::new();
-        elt.val.hash(&mut s);
-        let h = s.finish() as uint;
-        (&mut buckets[h % 256]).push(elt);
-    }
-
-    rbml_w.start_tag(tag_index);
-    let mut bucket_locs = Vec::new();
-    rbml_w.start_tag(tag_index_buckets);
-    for bucket in &buckets {
-        bucket_locs.push(rbml_w.writer.tell().unwrap());
-        rbml_w.start_tag(tag_index_buckets_bucket);
-        for elt in bucket {
-            rbml_w.start_tag(tag_index_buckets_bucket_elt);
-            assert!(elt.pos < 0xffff_ffff);
-            {
-                let wr: &mut SeekableMemWriter = rbml_w.writer;
-                wr.write_be_u32(elt.pos as u32);
-            }
-            write_fn(rbml_w.writer, &elt.val);
-            rbml_w.end_tag();
-        }
-        rbml_w.end_tag();
-    }
-    rbml_w.end_tag();
-    rbml_w.start_tag(tag_index_table);
-    for pos in &bucket_locs {
-        assert!(*pos < 0xffff_ffff);
-        let wr: &mut SeekableMemWriter = rbml_w.writer;
-        wr.write_be_u32(*pos as u32);
-    }
-    rbml_w.end_tag();
-    rbml_w.end_tag();
-}
-#[cfg(not(stage0))]
 fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
     F: FnMut(&mut SeekableMemWriter, &T),
     T: Hash,
@@ -1867,10 +1828,10 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
         rbml_w.start_tag(tag_macro_def);
 
         encode_name(rbml_w, def.ident.name);
-        encode_attributes(rbml_w, &def.attrs[]);
+        encode_attributes(rbml_w, &def.attrs);
 
         rbml_w.start_tag(tag_macro_def_body);
-        rbml_w.wr_str(&pprust::tts_to_string(&def.body[])[]);
+        rbml_w.wr_str(&pprust::tts_to_string(&def.body));
         rbml_w.end_tag();
 
         rbml_w.end_tag();
@@ -1887,7 +1848,7 @@ impl<'a, 'b, 'v> Visitor<'v> for StructFieldVisitor<'a, 'b> {
         fn visit_struct_field(&mut self, field: &ast::StructField) {
             self.rbml_w.start_tag(tag_struct_field);
             self.rbml_w.wr_tagged_u32(tag_struct_field_id, field.node.id);
-            encode_attributes(self.rbml_w, &field.node.attrs[]);
+            encode_attributes(self.rbml_w, &field.node.attrs);
             self.rbml_w.end_tag();
         }
     }
@@ -1909,9 +1870,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
         if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
-            let def_map = &self.ecx.tcx.def_map;
-            let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
-            let def_id = trait_def.def_id();
+            let def_id = self.ecx.tcx.def_map.borrow()[trait_ref.ref_id].def_id();
 
             // Load eagerly if this is an implementation of the Drop trait
             // or if the trait is not defined in this crate.
@@ -1959,13 +1918,13 @@ fn encode_misc_info(ecx: &EncodeContext,
     rbml_w.start_tag(tag_misc_info_crate_items);
     for item in &krate.module.items {
         rbml_w.start_tag(tag_mod_child);
-        rbml_w.wr_str(&def_to_string(local_def(item.id))[]);
+        rbml_w.wr_str(&def_to_string(local_def(item.id)));
         rbml_w.end_tag();
 
         each_auxiliary_node_id(&**item, |auxiliary_node_id| {
             rbml_w.start_tag(tag_mod_child);
             rbml_w.wr_str(&def_to_string(local_def(
-                        auxiliary_node_id))[]);
+                        auxiliary_node_id)));
             rbml_w.end_tag();
             true
         });
@@ -2132,17 +2091,17 @@ struct Stats {
 
     let mut rbml_w = writer::Encoder::new(wr);
 
-    encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name[]);
+    encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
     encode_crate_triple(&mut rbml_w,
                         &tcx.sess
                            .opts
                            .target_triple
-                           []);
+                           );
     encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
     encode_dylib_dependency_formats(&mut rbml_w, &ecx);
 
     let mut i = rbml_w.writer.tell().unwrap();
-    encode_attributes(&mut rbml_w, &krate.attrs[]);
+    encode_attributes(&mut rbml_w, &krate.attrs);
     stats.attr_bytes = rbml_w.writer.tell().unwrap() - i;
 
     i = rbml_w.writer.tell().unwrap();
index 3caa0f5b4db4c97a13722cabc0a5ba1b6d280c3a..a8d39f95739326174f2f3714ef3085173ffcbfa4 100644 (file)
@@ -14,6 +14,7 @@
 
 use std::collections::HashSet;
 use std::env;
+use std::os;
 use std::old_io::fs::PathExtensions;
 use std::old_io::fs;
 
@@ -194,7 +195,7 @@ fn canonicalize(path: Option<Path>) -> Option<Path> {
             })
     }
 
-    match canonicalize(env::current_exe().ok()) {
+    match canonicalize(os::self_exe_name()) {
         Some(mut p) => { p.pop(); p.pop(); p }
         None => panic!("can't determine value for sysroot")
     }
@@ -219,12 +220,12 @@ pub fn rust_path() -> Vec<Path> {
     let mut env_rust_path: Vec<Path> = match get_rust_path() {
         Some(env_path) => {
             let env_path_components =
-                env_path.split_str(PATH_ENTRY_SEPARATOR);
+                env_path.split(PATH_ENTRY_SEPARATOR);
             env_path_components.map(|s| Path::new(s)).collect()
         }
         None => Vec::new()
     };
-    let mut cwd = env::current_dir().unwrap();
+    let mut cwd = os::getcwd().unwrap();
     // now add in default entries
     let cwd_dot_rust = cwd.join(".rust");
     if !env_rust_path.contains(&cwd_dot_rust) {
@@ -243,7 +244,7 @@ pub fn rust_path() -> Vec<Path> {
         }
         cwd.pop();
     }
-    if let Some(h) = env::home_dir() {
+    if let Some(h) = os::homedir() {
         let p = h.join(".rust");
         if !env_rust_path.contains(&p) && p.exists() {
             env_rust_path.push(p);
index 01d1f4e7011f8586c7196884fc851e35ee039d1c..07082d818769c44ba1d2cf25e5528b396fe1f346 100644 (file)
@@ -329,7 +329,7 @@ pub fn report_load_errs(&mut self) {
             for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
                 self.sess.fileline_note(self.span,
                     &format!("crate `{}`, path #{}, triple {}: {}",
-                            self.ident, i+1, got, path.display())[]);
+                            self.ident, i+1, got, path.display()));
             }
         }
         if self.rejected_via_hash.len() > 0 {
@@ -339,7 +339,7 @@ pub fn report_load_errs(&mut self) {
             for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
                 self.sess.fileline_note(self.span,
                     &format!("crate `{}` path #{}: {}",
-                            self.ident, i+1, path.display())[]);
+                            self.ident, i+1, path.display()));
             }
             match self.root {
                 &None => {}
@@ -347,7 +347,7 @@ pub fn report_load_errs(&mut self) {
                     for (i, path) in r.paths().iter().enumerate() {
                         self.sess.fileline_note(self.span,
                             &format!("crate `{}` path #{}: {}",
-                                    r.ident, i+1, path.display())[]);
+                                    r.ident, i+1, path.display()));
                     }
                 }
             }
@@ -359,7 +359,7 @@ pub fn report_load_errs(&mut self) {
             for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() {
                 self.sess.fileline_note(self.span,
                                         &format!("crate `{}` path #{}: {}",
-                                                 self.ident, i+1, path.display())[]);
+                                                 self.ident, i+1, path.display()));
             }
         }
         self.sess.abort_if_errors();
@@ -472,26 +472,26 @@ fn find_library_crate(&mut self) -> Option<Library> {
             _ => {
                 self.sess.span_err(self.span,
                     &format!("multiple matching crates for `{}`",
-                            self.crate_name)[]);
+                            self.crate_name));
                 self.sess.note("candidates:");
                 for lib in &libraries {
                     match lib.dylib {
                         Some((ref p, _)) => {
                             self.sess.note(&format!("path: {}",
-                                                   p.display())[]);
+                                                   p.display()));
                         }
                         None => {}
                     }
                     match lib.rlib {
                         Some((ref p, _)) => {
                             self.sess.note(&format!("path: {}",
-                                                    p.display())[]);
+                                                    p.display()));
                         }
                         None => {}
                     }
                     let data = lib.metadata.as_slice();
                     let name = decoder::get_crate_name(data);
-                    note_crate_name(self.sess.diagnostic(), &name[]);
+                    note_crate_name(self.sess.diagnostic(), &name);
                 }
                 None
             }
@@ -545,11 +545,11 @@ fn extract_one(&mut self, m: HashMap<Path, PathKind>, flavor: &str,
                                    &format!("multiple {} candidates for `{}` \
                                             found",
                                            flavor,
-                                           self.crate_name)[]);
+                                           self.crate_name));
                 self.sess.span_note(self.span,
                                     &format!(r"candidate #1: {}",
                                             ret.as_ref().unwrap().0
-                                               .display())[]);
+                                               .display()));
                 error = 1;
                 ret = None;
             }
@@ -557,7 +557,7 @@ fn extract_one(&mut self, m: HashMap<Path, PathKind>, flavor: &str,
                 error += 1;
                 self.sess.span_note(self.span,
                                     &format!(r"candidate #{}: {}", error,
-                                            lib.display())[]);
+                                            lib.display()));
                 continue
             }
             *slot = Some(metadata);
@@ -630,14 +630,14 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
             let locs = locs.iter().map(|l| Path::new(&l[..])).filter(|loc| {
                 if !loc.exists() {
                     sess.err(&format!("extern location for {} does not exist: {}",
-                                     self.crate_name, loc.display())[]);
+                                     self.crate_name, loc.display()));
                     return false;
                 }
                 let file = match loc.filename_str() {
                     Some(file) => file,
                     None => {
                         sess.err(&format!("extern location for {} is not a file: {}",
-                                         self.crate_name, loc.display())[]);
+                                         self.crate_name, loc.display()));
                         return false;
                     }
                 };
@@ -651,7 +651,7 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
                     }
                 }
                 sess.err(&format!("extern location for {} is of an unknown type: {}",
-                                 self.crate_name, loc.display())[]);
+                                 self.crate_name, loc.display()));
                 false
             });
 
@@ -686,7 +686,7 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
 }
 
 pub fn note_crate_name(diag: &SpanHandler, name: &str) {
-    diag.handler().note(&format!("crate name: {}", name)[]);
+    diag.handler().note(&format!("crate name: {}", name));
 }
 
 impl ArchiveMetadata {
@@ -736,12 +736,10 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
             }
         };
         return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
-            None => {
-                return Err((format!("failed to read rlib metadata: '{}'",
-                                    filename.display())))
-            }
-            Some(blob) => return Ok(blob)
-        }
+            None => Err(format!("failed to read rlib metadata: '{}'",
+                                filename.display())),
+            Some(blob) => Ok(blob)
+        };
     }
     unsafe {
         let buf = CString::new(filename.as_vec()).unwrap();
@@ -791,7 +789,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
             }
             llvm::LLVMMoveToNextSection(si.llsi);
         }
-        return Err(format!("metadata not found: '{}'", filename.display()));
+        Err(format!("metadata not found: '{}'", filename.display()))
     }
 }
 
index 28c98d455f046dc2e04601c1ce421275b52492af..d25dc4f58a5dfa6181472a12ff73c75237c69155 100644 (file)
@@ -78,7 +78,7 @@ fn visit_item(&mut self, item: &ast::Item) {
 
         for attr in &item.attrs {
             let mut used = true;
-            match &attr.name()[] {
+            match &attr.name()[..] {
                 "phase" => {
                     self.sess.span_err(attr.span, "#[phase] is deprecated");
                 }
@@ -86,7 +86,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                     self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated");
                     self.sess.span_help(attr.span, &format!("use a crate attribute instead, \
                                                             i.e. #![plugin({})]",
-                                                            item.ident.as_str())[]);
+                                                            item.ident.as_str()));
                 }
                 "macro_use" => {
                     let names = attr.meta_item_list();
index 5805725a8fc8b7cb6ad2f37651f437f33278182b..baecfb7eb22c5ec6cb95898ee8ca45f60e93f003 100644 (file)
@@ -305,7 +305,7 @@ fn parse_bound_region_<F>(st: &mut PState, conv: &mut F) -> ty::BoundRegion wher
         }
         '[' => {
             let def = parse_def_(st, RegionParameter, conv);
-            let ident = token::str_to_ident(&parse_str(st, ']')[]);
+            let ident = token::str_to_ident(&parse_str(st, ']'));
             ty::BrNamed(def, ident.name)
         }
         'f' => {
@@ -344,7 +344,7 @@ fn parse_region_<F>(st: &mut PState, conv: &mut F) -> ty::Region where
         assert_eq!(next(st), '|');
         let index = parse_u32(st);
         assert_eq!(next(st), '|');
-        let nm = token::str_to_ident(&parse_str(st, ']')[]);
+        let nm = token::str_to_ident(&parse_str(st, ']'));
         ty::ReEarlyBound(node_id, space, index, nm.name)
       }
       'f' => {
@@ -485,7 +485,7 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
         assert_eq!(next(st), '|');
         let space = parse_param_space(st);
         assert_eq!(next(st), '|');
-        let name = token::intern(&parse_str(st, ']')[]);
+        let name = token::intern(&parse_str(st, ']'));
         return ty::mk_param(tcx, space, index, name);
       }
       '~' => return ty::mk_uniq(tcx, parse_ty_(st, conv)),
@@ -822,7 +822,6 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
     assert_eq!(next(st), '|');
     let index = parse_u32(st);
     assert_eq!(next(st), '|');
-    let bounds = parse_bounds_(st, conv);
     let default = parse_opt(st, |st| parse_ty_(st, conv));
     let object_lifetime_default = parse_object_lifetime_default(st, conv);
 
@@ -831,7 +830,6 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
         def_id: def_id,
         space: space,
         index: index,
-        bounds: bounds,
         default: default,
         object_lifetime_default: object_lifetime_default,
     }
@@ -924,18 +922,18 @@ fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
 {
     let builtin_bounds = parse_builtin_bounds_(st, conv);
 
+    let region_bounds = parse_region_bounds_(st, conv);
+
     let mut param_bounds = ty::ParamBounds {
-        region_bounds: Vec::new(),
+        region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
         trait_bounds: Vec::new(),
         projection_bounds: Vec::new(),
     };
+
+
     loop {
         match next(st) {
-            'R' => {
-                param_bounds.region_bounds.push(
-                    parse_region_(st, conv));
-            }
             'I' => {
                 param_bounds.trait_bounds.push(
                     ty::Binder(parse_trait_ref_(st, conv)));
@@ -953,3 +951,18 @@ fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
         }
     }
 }
+
+fn parse_region_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
+                              -> Vec<ty::Region> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut region_bounds = Vec::new();
+    loop {
+        match next(st) {
+            'R' => { region_bounds.push(parse_region_(st, conv)); }
+            '.' => { return region_bounds; }
+            c => { panic!("parse_bounds: bad bounds ('{}')", c); }
+        }
+    }
+}
+
index e1e9d49dd05859d3df5e3ff67b98c2f6d17ef0cf..76a365259aa5713a3eb952a9a3eadfffeefb0bba 100644 (file)
@@ -153,9 +153,6 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
         ty::ty_err => {
             mywrite!(w, "e");
         }
-        ty::ty_open(_) => {
-            cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
-        }
     }
 
     let end = w.tell().unwrap();
@@ -389,10 +386,7 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
                             bs: &ty::ParamBounds<'tcx>) {
     enc_builtin_bounds(w, cx, &bs.builtin_bounds);
 
-    for &r in &bs.region_bounds {
-        mywrite!(w, "R");
-        enc_region(w, cx, r);
-    }
+    enc_region_bounds(w, cx, &bs.region_bounds);
 
     for tp in &bs.trait_bounds {
         mywrite!(w, "I");
@@ -407,12 +401,22 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
     mywrite!(w, ".");
 }
 
+pub fn enc_region_bounds<'a, 'tcx>(w: &mut SeekableMemWriter,
+                            cx: &ctxt<'a, 'tcx>,
+                            rs: &[ty::Region]) {
+    for &r in rs {
+        mywrite!(w, "R");
+        enc_region(w, cx, r);
+    }
+
+    mywrite!(w, ".");
+}
+
 pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
                                     v: &ty::TypeParameterDef<'tcx>) {
     mywrite!(w, "{}:{}|{}|{}|",
              token::get_name(v.name), (cx.ds)(v.def_id),
              v.space.to_uint(), v.index);
-    enc_bounds(w, cx, &v.bounds);
     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
     enc_object_lifetime_default(w, cx, v.object_lifetime_default);
 }
index 7143e3caac208f135dda9d44515bbcdd7dcee59c..17fd80ceaea428063654da274aef672114ca5b89 100644 (file)
 pub const NO_REGIONS: uint = 1;
 pub const NO_TPS: uint = 2;
 
-pub fn check_path_args(tcx: &ty::ctxt,
-                       path: &ast::Path,
-                       flags: uint) {
-    if (flags & NO_TPS) != 0 {
-        if path.segments.iter().any(|s| s.parameters.has_types()) {
-            span_err!(tcx.sess, path.span, E0109,
-                "type parameters are not allowed on this type");
+pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) {
+    for segment in segments {
+        if (flags & NO_TPS) != 0 {
+            for typ in segment.parameters.types() {
+                span_err!(tcx.sess, typ.span, E0109,
+                          "type parameters are not allowed on this type");
+                break;
+            }
         }
-    }
 
-    if (flags & NO_REGIONS) != 0 {
-        if path.segments.iter().any(|s| s.parameters.has_lifetimes()) {
-            span_err!(tcx.sess, path.span, E0110,
-                "region parameters are not allowed on this type");
+        if (flags & NO_REGIONS) != 0 {
+            for lifetime in segment.parameters.lifetimes() {
+                span_err!(tcx.sess, lifetime.span, E0110,
+                          "lifetime parameters are not allowed on this type");
+                break;
+            }
         }
     }
 }
 
+pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
+                           segments: &[ast::PathSegment],
+                           nty: ast::PrimTy)
+                           -> Ty<'tcx> {
+    check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
+    match nty {
+        ast::TyBool => tcx.types.bool,
+        ast::TyChar => tcx.types.char,
+        ast::TyInt(it) => ty::mk_mach_int(tcx, it),
+        ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit),
+        ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft),
+        ast::TyStr => ty::mk_str(tcx)
+    }
+}
+
 pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
                                -> Option<Ty<'tcx>> {
-    match ast_ty.node {
-        ast::TyPath(ref path, id) => {
-            let a_def = match tcx.def_map.borrow().get(&id) {
-                None => {
-                    tcx.sess.span_bug(ast_ty.span,
-                                      &format!("unbound path {}",
-                                              path.repr(tcx))[])
-                }
-                Some(&d) => d
-            };
-            match a_def {
-                def::DefPrimTy(nty) => {
-                    match nty {
-                        ast::TyBool => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(tcx.types.bool)
-                        }
-                        ast::TyChar => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(tcx.types.char)
-                        }
-                        ast::TyInt(it) => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_int(tcx, it))
-                        }
-                        ast::TyUint(uit) => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_uint(tcx, uit))
-                        }
-                        ast::TyFloat(ft) => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_float(tcx, ft))
-                        }
-                        ast::TyStr => {
-                            Some(ty::mk_str(tcx))
-                        }
-                    }
-                }
-                _ => None
+    if let ast::TyPath(None, ref path) = ast_ty.node {
+        let def = match tcx.def_map.borrow().get(&ast_ty.id) {
+            None => {
+                tcx.sess.span_bug(ast_ty.span,
+                                  &format!("unbound path {}", path.repr(tcx)))
             }
+            Some(d) => d.full_def()
+        };
+        if let def::DefPrimTy(nty) = def {
+            Some(prim_ty_to_ty(tcx, &path.segments[], nty))
+        } else {
+            None
         }
-        _ => None
+    } else {
+        None
     }
 }
 
index ae10eb686b010244ed71bcdf07de52c2d93616e6..5983829ed8fbef20e56b6124b2a1e868201aaf0d 100644 (file)
@@ -25,6 +25,7 @@
 use metadata::tyencode;
 use middle::check_const::ConstQualif;
 use middle::mem_categorization::Typer;
+use middle::privacy::{AllPublic, LastMod};
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
@@ -423,13 +424,8 @@ impl tr for def::Def {
     fn tr(&self, dcx: &DecodeContext) -> def::Def {
         match *self {
           def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
-          def::DefStaticMethod(did, p) => {
-            def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
-          }
-          def::DefMethod(did0, did1, p) => {
-            def::DefMethod(did0.tr(dcx),
-                           did1.map(|did1| did1.tr(dcx)),
-                           p.map(|did2| did2.tr(dcx)))
+          def::DefMethod(did, p) => {
+            def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
           }
           def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
           def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
@@ -442,11 +438,8 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
           },
           def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
           def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
-          def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
-          def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) =>
-              def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident),
-          def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) =>
-              def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident),
+          def::DefAssociatedTy(trait_did, did) =>
+              def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
           def::DefPrimTy(p) => def::DefPrimTy(p),
           def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
           def::DefUse(did) => def::DefUse(did.tr(dcx)),
@@ -455,9 +448,6 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
           }
           def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
           def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
-          def::DefTyParamBinder(nid) => {
-            def::DefTyParamBinder(dcx.tr_id(nid))
-          }
           def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
         }
     }
@@ -1159,10 +1149,10 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
 
     debug!("Encoding side tables for id {}", id);
 
-    if let Some(def) = tcx.def_map.borrow().get(&id) {
+    if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         rbml_w.tag(c::tag_table_def, |rbml_w| {
             rbml_w.id(id);
-            rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap());
+            rbml_w.tag(c::tag_table_val, |rbml_w| def.encode(rbml_w).unwrap());
         })
     }
 
@@ -1852,7 +1842,7 @@ fn decode_side_tables(dcx: &DecodeContext,
             None => {
                 dcx.tcx.sess.bug(
                     &format!("unknown tag found in side tables: {:x}",
-                            tag)[]);
+                            tag));
             }
             Some(value) => {
                 let val_doc = entry_doc.get(c::tag_table_val as uint);
@@ -1862,7 +1852,12 @@ fn decode_side_tables(dcx: &DecodeContext,
                 match value {
                     c::tag_table_def => {
                         let def = decode_def(dcx, val_doc);
-                        dcx.tcx.def_map.borrow_mut().insert(id, def);
+                        dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
+                            base_def: def,
+                            // This doesn't matter cross-crate.
+                            last_private: LastMod(AllPublic),
+                            depth: 0
+                        });
                     }
                     c::tag_table_node_type => {
                         let ty = val_dsr.read_ty(dcx);
@@ -1937,7 +1932,7 @@ fn decode_side_tables(dcx: &DecodeContext,
                     _ => {
                         dcx.tcx.sess.bug(
                             &format!("unknown tag found in side tables: {:x}",
-                                    tag)[]);
+                                    tag));
                     }
                 }
             }
index d39b94a202e4ae1ab12648d14fbbcfaf51928115..24c54b53590c04f57a4ff6eafe82f3179b9d3cfa 100644 (file)
 use middle::cfg::*;
 use middle::def;
 use middle::graph;
+use middle::pat_util;
 use middle::region::CodeExtent;
 use middle::ty;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::ptr::P;
-use util::nodemap::NodeMap;
 
 struct CFGBuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    exit_map: NodeMap<CFGIndex>,
     graph: CFGGraph,
     fn_exit: CFGIndex,
     loop_scopes: Vec<LoopScope>,
@@ -36,17 +35,16 @@ struct LoopScope {
 pub fn construct(tcx: &ty::ctxt,
                  blk: &ast::Block) -> CFG {
     let mut graph = graph::Graph::new();
-    let entry = add_initial_dummy_node(&mut graph);
+    let entry = graph.add_node(CFGNodeData::Entry);
 
     // `fn_exit` is target of return exprs, which lies somewhere
     // outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
     // also resolves chicken-and-egg problem that arises if you try to
     // have return exprs jump to `block_exit` during construction.)
-    let fn_exit = add_initial_dummy_node(&mut graph);
+    let fn_exit = graph.add_node(CFGNodeData::Exit);
     let block_exit;
 
     let mut cfg_builder = CFGBuilder {
-        exit_map: NodeMap(),
         graph: graph,
         fn_exit: fn_exit,
         tcx: tcx,
@@ -54,17 +52,12 @@ pub fn construct(tcx: &ty::ctxt,
     };
     block_exit = cfg_builder.block(blk, entry);
     cfg_builder.add_contained_edge(block_exit, fn_exit);
-    let CFGBuilder {exit_map, graph, ..} = cfg_builder;
-    CFG {exit_map: exit_map,
-         graph: graph,
+    let CFGBuilder {graph, ..} = cfg_builder;
+    CFG {graph: graph,
          entry: entry,
          exit: fn_exit}
 }
 
-fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex {
-    g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID })
-}
-
 impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
         let mut stmts_exit = pred;
@@ -74,19 +67,19 @@ fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
 
         let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
 
-        self.add_node(blk.id, &[expr_exit])
+        self.add_ast_node(blk.id, &[expr_exit])
     }
 
     fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex {
         match stmt.node {
             ast::StmtDecl(ref decl, id) => {
                 let exit = self.decl(&**decl, pred);
-                self.add_node(id, &[exit])
+                self.add_ast_node(id, &[exit])
             }
 
             ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => {
                 let exit = self.expr(&**expr, pred);
-                self.add_node(id, &[exit])
+                self.add_ast_node(id, &[exit])
             }
 
             ast::StmtMac(..) => {
@@ -115,33 +108,33 @@ fn pat(&mut self, pat: &ast::Pat, pred: CFGIndex) -> CFGIndex {
             ast::PatLit(..) |
             ast::PatRange(..) |
             ast::PatWild(_) => {
-                self.add_node(pat.id, &[pred])
+                self.add_ast_node(pat.id, &[pred])
             }
 
             ast::PatBox(ref subpat) |
             ast::PatRegion(ref subpat, _) |
             ast::PatIdent(_, _, Some(ref subpat)) => {
                 let subpat_exit = self.pat(&**subpat, pred);
-                self.add_node(pat.id, &[subpat_exit])
+                self.add_ast_node(pat.id, &[subpat_exit])
             }
 
             ast::PatEnum(_, Some(ref subpats)) |
             ast::PatTup(ref subpats) => {
                 let pats_exit = self.pats_all(subpats.iter(), pred);
-                self.add_node(pat.id, &[pats_exit])
+                self.add_ast_node(pat.id, &[pats_exit])
             }
 
             ast::PatStruct(_, ref subpats, _) => {
                 let pats_exit =
                     self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
-                self.add_node(pat.id, &[pats_exit])
+                self.add_ast_node(pat.id, &[pats_exit])
             }
 
             ast::PatVec(ref pre, ref vec, ref post) => {
                 let pre_exit = self.pats_all(pre.iter(), pred);
                 let vec_exit = self.pats_all(vec.iter(), pre_exit);
                 let post_exit = self.pats_all(post.iter(), vec_exit);
-                self.add_node(pat.id, &[post_exit])
+                self.add_ast_node(pat.id, &[post_exit])
             }
 
             ast::PatMac(_) => {
@@ -157,28 +150,11 @@ fn pats_all<'b, I: Iterator<Item=&'b P<ast::Pat>>>(&mut self,
         pats.fold(pred, |pred, pat| self.pat(&**pat, pred))
     }
 
-    fn pats_any(&mut self,
-                pats: &[P<ast::Pat>],
-                pred: CFGIndex) -> CFGIndex {
-        //! Handles case where just one of the patterns must match.
-
-        if pats.len() == 1 {
-            self.pat(&*pats[0], pred)
-        } else {
-            let collect = self.add_dummy_node(&[]);
-            for pat in pats {
-                let pat_exit = self.pat(&**pat, pred);
-                self.add_contained_edge(pat_exit, collect);
-            }
-            collect
-        }
-    }
-
     fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
         match expr.node {
             ast::ExprBlock(ref blk) => {
                 let blk_exit = self.block(&**blk, pred);
-                self.add_node(expr.id, &[blk_exit])
+                self.add_ast_node(expr.id, &[blk_exit])
             }
 
             ast::ExprIf(ref cond, ref then, None) => {
@@ -198,7 +174,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 //
                 let cond_exit = self.expr(&**cond, pred);                // 1
                 let then_exit = self.block(&**then, cond_exit);          // 2
-                self.add_node(expr.id, &[cond_exit, then_exit])          // 3,4
+                self.add_ast_node(expr.id, &[cond_exit, then_exit])      // 3,4
             }
 
             ast::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
@@ -219,7 +195,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 let cond_exit = self.expr(&**cond, pred);                // 1
                 let then_exit = self.block(&**then, cond_exit);          // 2
                 let else_exit = self.expr(&**otherwise, cond_exit);      // 3
-                self.add_node(expr.id, &[then_exit, else_exit])          // 4, 5
+                self.add_ast_node(expr.id, &[then_exit, else_exit])      // 4, 5
             }
 
             ast::ExprIfLet(..) => {
@@ -247,7 +223,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 // Is the condition considered part of the loop?
                 let loopback = self.add_dummy_node(&[pred]);              // 1
                 let cond_exit = self.expr(&**cond, loopback);             // 2
-                let expr_exit = self.add_node(expr.id, &[cond_exit]);     // 3
+                let expr_exit = self.add_ast_node(expr.id, &[cond_exit]); // 3
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.id,
                     continue_index: loopback,
@@ -283,7 +259,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 // may cause additional edges.
 
                 let loopback = self.add_dummy_node(&[pred]);              // 1
-                let expr_exit = self.add_node(expr.id, &[]);              // 2
+                let expr_exit = self.add_ast_node(expr.id, &[]);          // 2
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.id,
                     continue_index: loopback,
@@ -296,45 +272,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
             }
 
             ast::ExprMatch(ref discr, ref arms, _) => {
-                //
-                //     [pred]
-                //       |
-                //       v 1
-                //    [discr]
-                //       |
-                //       v 2
-                //    [cond1]
-                //      /  \
-                //     |    \
-                //     v 3   \
-                //  [pat1]    \
-                //     |       |
-                //     v 4     |
-                //  [guard1]   |
-                //     |       |
-                //     |       |
-                //     v 5     v
-                //  [body1]  [cond2]
-                //     |      /  \
-                //     |    ...  ...
-                //     |     |    |
-                //     v 6   v    v
-                //  [.....expr.....]
-                //
-                let discr_exit = self.expr(&**discr, pred);              // 1
-
-                let expr_exit = self.add_node(expr.id, &[]);
-                let mut cond_exit = discr_exit;
-                for arm in arms {
-                    cond_exit = self.add_dummy_node(&[cond_exit]);        // 2
-                    let pats_exit = self.pats_any(&arm.pats[],
-                                                  cond_exit);            // 3
-                    let guard_exit = self.opt_expr(&arm.guard,
-                                                   pats_exit);           // 4
-                    let body_exit = self.expr(&*arm.body, guard_exit);   // 5
-                    self.add_contained_edge(body_exit, expr_exit);       // 6
-                }
-                expr_exit
+                self.match_(expr.id, &discr, &arms, pred)
             }
 
             ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
@@ -354,30 +292,30 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 //
                 let l_exit = self.expr(&**l, pred);                      // 1
                 let r_exit = self.expr(&**r, l_exit);                    // 2
-                self.add_node(expr.id, &[l_exit, r_exit])                 // 3,4
+                self.add_ast_node(expr.id, &[l_exit, r_exit])            // 3,4
             }
 
             ast::ExprRet(ref v) => {
                 let v_exit = self.opt_expr(v, pred);
-                let b = self.add_node(expr.id, &[v_exit]);
+                let b = self.add_ast_node(expr.id, &[v_exit]);
                 self.add_returning_edge(expr, b);
-                self.add_node(ast::DUMMY_NODE_ID, &[])
+                self.add_unreachable_node()
             }
 
             ast::ExprBreak(label) => {
                 let loop_scope = self.find_scope(expr, label);
-                let b = self.add_node(expr.id, &[pred]);
+                let b = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, b,
                                       loop_scope, loop_scope.break_index);
-                self.add_node(ast::DUMMY_NODE_ID, &[])
+                self.add_unreachable_node()
             }
 
             ast::ExprAgain(label) => {
                 let loop_scope = self.find_scope(expr, label);
-                let a = self.add_node(expr.id, &[pred]);
+                let a = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, a,
                                       loop_scope, loop_scope.continue_index);
-                self.add_node(ast::DUMMY_NODE_ID, &[])
+                self.add_unreachable_node()
             }
 
             ast::ExprVec(ref elems) => {
@@ -454,14 +392,13 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                     let &(_, ref expr, _) = a;
                     &**expr
                 }), post_inputs);
-                self.add_node(expr.id, &[post_outputs])
+                self.add_ast_node(expr.id, &[post_outputs])
             }
 
             ast::ExprMac(..) |
             ast::ExprClosure(..) |
             ast::ExprLit(..) |
-            ast::ExprPath(..) |
-            ast::ExprQPath(..) => {
+            ast::ExprPath(..) => {
                 self.straightline(expr, pred, None::<ast::Expr>.iter())
             }
         }
@@ -481,7 +418,7 @@ fn call<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
         let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
         let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
         if return_ty.diverges() {
-            self.add_node(ast::DUMMY_NODE_ID, &[])
+            self.add_unreachable_node()
         } else {
             ret
         }
@@ -508,20 +445,126 @@ fn straightline<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
         //! Handles case of an expression that evaluates `subexprs` in order
 
         let subexprs_exit = self.exprs(subexprs, pred);
-        self.add_node(expr.id, &[subexprs_exit])
+        self.add_ast_node(expr.id, &[subexprs_exit])
+    }
+
+    fn match_(&mut self, id: ast::NodeId, discr: &ast::Expr,
+              arms: &[ast::Arm], pred: CFGIndex) -> CFGIndex {
+        // The CFG for match expression is quite complex, so no ASCII
+        // art for it (yet).
+        //
+        // The CFG generated below matches roughly what trans puts
+        // out. Each pattern and guard is visited in parallel, with
+        // arms containing multiple patterns generating multiple nodes
+        // for the same guard expression. The guard expressions chain
+        // into each other from top to bottom, with a specific
+        // exception to allow some additional valid programs
+        // (explained below). Trans differs slightly in that the
+        // pattern matching may continue after a guard but the visible
+        // behaviour should be the same.
+        //
+        // What is going on is explained in further comments.
+
+        // Visit the discriminant expression
+        let discr_exit = self.expr(discr, pred);
+
+        // Add a node for the exit of the match expression as a whole.
+        let expr_exit = self.add_ast_node(id, &[]);
+
+        // Keep track of the previous guard expressions
+        let mut prev_guards = Vec::new();
+        // Track if the previous pattern contained bindings or wildcards
+        let mut prev_has_bindings = false;
+
+        for arm in arms {
+            // Add an exit node for when we've visited all the
+            // patterns and the guard (if there is one) in the arm.
+            let arm_exit = self.add_dummy_node(&[]);
+
+            for pat in &arm.pats {
+                // Visit the pattern, coming from the discriminant exit
+                let mut pat_exit = self.pat(&**pat, discr_exit);
+
+                // If there is a guard expression, handle it here
+                if let Some(ref guard) = arm.guard {
+                    // Add a dummy node for the previous guard
+                    // expression to target
+                    let guard_start = self.add_dummy_node(&[pat_exit]);
+                    // Visit the guard expression
+                    let guard_exit = self.expr(&**guard, guard_start);
+
+                    let this_has_bindings = pat_util::pat_contains_bindings_or_wild(
+                        &self.tcx.def_map, &**pat);
+
+                    // If both this pattern and the previous pattern
+                    // were free of bindings, they must consist only
+                    // of "constant" patterns. Note we cannot match an
+                    // all-constant pattern, fail the guard, and then
+                    // match *another* all-constant pattern. This is
+                    // because if the previous pattern matches, then
+                    // we *cannot* match this one, unless all the
+                    // constants are the same (which is rejected by
+                    // `check_match`).
+                    //
+                    // We can use this to be smarter about the flow
+                    // along guards. If the previous pattern matched,
+                    // then we know we will not visit the guard in
+                    // this one (whether or not the guard succeeded),
+                    // if the previous pattern failed, then we know
+                    // the guard for that pattern will not have been
+                    // visited. Thus, it is not possible to visit both
+                    // the previous guard and the current one when
+                    // both patterns consist only of constant
+                    // sub-patterns.
+                    //
+                    // However, if the above does not hold, then all
+                    // previous guards need to be wired to visit the
+                    // current guard pattern.
+                    if prev_has_bindings || this_has_bindings {
+                        while let Some(prev) = prev_guards.pop() {
+                            self.add_contained_edge(prev, guard_start);
+                        }
+                    }
+
+                    prev_has_bindings = this_has_bindings;
+
+                    // Push the guard onto the list of previous guards
+                    prev_guards.push(guard_exit);
+
+                    // Update the exit node for the pattern
+                    pat_exit = guard_exit;
+                }
+
+                // Add an edge from the exit of this pattern to the
+                // exit of the arm
+                self.add_contained_edge(pat_exit, arm_exit);
+            }
+
+            // Visit the body of this arm
+            let body_exit = self.expr(&arm.body, arm_exit);
+
+            // Link the body to the exit of the expression
+            self.add_contained_edge(body_exit, expr_exit);
+        }
+
+        expr_exit
     }
 
     fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
-        self.add_node(ast::DUMMY_NODE_ID, preds)
+        self.add_node(CFGNodeData::Dummy, preds)
     }
 
-    fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
-        assert!(!self.exit_map.contains_key(&id));
-        let node = self.graph.add_node(CFGNodeData {id: id});
-        if id != ast::DUMMY_NODE_ID {
-            assert!(!self.exit_map.contains_key(&id));
-            self.exit_map.insert(id, node);
-        }
+    fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
+        assert!(id != ast::DUMMY_NODE_ID);
+        self.add_node(CFGNodeData::AST(id), preds)
+    }
+
+    fn add_unreachable_node(&mut self) -> CFGIndex {
+        self.add_node(CFGNodeData::Unreachable, &[])
+    }
+
+    fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex]) -> CFGIndex {
+        let node = self.graph.add_node(data);
         for &pred in preds {
             self.add_contained_edge(pred, node);
         }
@@ -566,32 +609,24 @@ fn add_returning_edge(&mut self,
     fn find_scope(&self,
                   expr: &ast::Expr,
                   label: Option<ast::Ident>) -> LoopScope {
-        match label {
-            None => {
-                return *self.loop_scopes.last().unwrap();
-            }
-
-            Some(_) => {
-                match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def::DefLabel(loop_id)) => {
-                        for l in &self.loop_scopes {
-                            if l.loop_id == loop_id {
-                                return *l;
-                            }
-                        }
-                        self.tcx.sess.span_bug(
-                            expr.span,
-                            &format!("no loop scope for id {}",
-                                    loop_id)[]);
-                    }
+        if label.is_none() {
+            return *self.loop_scopes.last().unwrap();
+        }
 
-                    r => {
-                        self.tcx.sess.span_bug(
-                            expr.span,
-                            &format!("bad entry `{:?}` in def_map for label",
-                                    r)[]);
+        match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
+            Some(def::DefLabel(loop_id)) => {
+                for l in &self.loop_scopes {
+                    if l.loop_id == loop_id {
+                        return *l;
                     }
                 }
+                self.tcx.sess.span_bug(expr.span,
+                    &format!("no loop scope for id {}", loop_id));
+            }
+
+            r => {
+                self.tcx.sess.span_bug(expr.span,
+                    &format!("bad entry `{:?}` in def_map for label", r));
             }
         }
     }
index 46b4a51c9d6fee7b00295727dbd71d600698cf47..0c5eca3c12968ee3b93d6b31371109271ef572c0 100644 (file)
@@ -54,7 +54,7 @@ fn replace_newline_with_backslash_l(s: String) -> String {
 }
 
 impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
-    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[]).ok().unwrap() }
+    fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(&self.name[..]).ok().unwrap() }
 
     fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
         dot::Id::new(format!("N{}", i.node_id())).ok().unwrap()
@@ -65,10 +65,10 @@ fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
             dot::LabelText::LabelStr("entry".into_cow())
         } else if i == self.cfg.exit {
             dot::LabelText::LabelStr("exit".into_cow())
-        } else if n.data.id == ast::DUMMY_NODE_ID {
+        } else if n.data.id() == ast::DUMMY_NODE_ID {
             dot::LabelText::LabelStr("(dummy_node)".into_cow())
         } else {
-            let s = self.ast_map.node_to_string(n.data.id);
+            let s = self.ast_map.node_to_string(n.data.id());
             // left-aligns the lines
             let s = replace_newline_with_backslash_l(s);
             dot::LabelText::EscStr(s.into_cow())
@@ -92,7 +92,7 @@ fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> {
             let s = replace_newline_with_backslash_l(s);
             label.push_str(&format!("exiting scope_{} {}",
                                    i,
-                                   &s[..])[]);
+                                   &s[..]));
         }
         dot::LabelText::EscStr(label.into_cow())
     }
index 0ca146a295e139a95712377578205699febcae97..e8a99f59b1e95b365c9c0e4184757608978b8638 100644 (file)
 use middle::graph;
 use middle::ty;
 use syntax::ast;
-use util::nodemap::NodeMap;
 
 mod construct;
 pub mod graphviz;
 
 pub struct CFG {
-    pub exit_map: NodeMap<CFGIndex>,
     pub graph: CFGGraph,
     pub entry: CFGIndex,
     pub exit: CFGIndex,
 }
 
-#[derive(Copy)]
-pub struct CFGNodeData {
-    pub id: ast::NodeId
+#[derive(Copy, PartialEq)]
+pub enum CFGNodeData {
+    AST(ast::NodeId),
+    Entry,
+    Exit,
+    Dummy,
+    Unreachable,
+}
+
+impl CFGNodeData {
+    pub fn id(&self) -> ast::NodeId {
+        if let CFGNodeData::AST(id) = *self {
+            id
+        } else {
+            ast::DUMMY_NODE_ID
+        }
+    }
 }
 
 pub struct CFGEdgeData {
@@ -50,6 +62,6 @@ pub fn new(tcx: &ty::ctxt,
     }
 
     pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
-        self.graph.depth_traverse(self.entry).any(|node| node.id == id)
+        self.graph.depth_traverse(self.entry).any(|node| node.id() == id)
     }
 }
index 41d425cd2f6652c54c579f30672dfb4dbf2b734a..8401d25024d3577e7fa4921445d7d03a0694393b 100644 (file)
@@ -176,7 +176,7 @@ fn check_static_mut_type(&self, e: &ast::Expr) {
         };
 
         self.tcx.sess.span_err(e.span, &format!("mutable statics are not allowed \
-                                                 to have {}", suffix)[]);
+                                                 to have {}", suffix));
     }
 
     fn check_static_type(&self, e: &ast::Expr) {
@@ -382,7 +382,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             if v.mode != Mode::Var {
                 v.tcx.sess.span_err(e.span,
                                     &format!("{}s are not allowed to have destructors",
-                                             v.msg())[]);
+                                             v.msg()));
             }
         }
         _ => {}
@@ -439,8 +439,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
             }
         }
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
-            let def = v.tcx.def_map.borrow().get(&e.id).cloned();
+        ast::ExprPath(..) => {
+            let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
             match def {
                 Some(def::DefVariant(_, _, _)) => {
                     // Count the discriminator or function pointer.
@@ -452,8 +452,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                         v.add_qualif(NON_ZERO_SIZED);
                     }
                 }
-                Some(def::DefFn(..)) |
-                Some(def::DefStaticMethod(..)) | Some(def::DefMethod(..)) => {
+                Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
                     // Count the function pointer.
                     v.add_qualif(NON_ZERO_SIZED);
                 }
@@ -500,7 +499,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                     _ => break
                 };
             }
-            let def = v.tcx.def_map.borrow().get(&callee.id).cloned();
+            let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
             match def {
                 Some(def::DefStruct(..)) => {}
                 Some(def::DefVariant(..)) => {
index 86c59b24e3e933663ed2100f3d5ede07fe3dc82a..c409c8fb13f14502437aa2d1c9813b1365624f9d 100644 (file)
@@ -163,7 +163,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
                 // First, check legality of move bindings.
                 check_legality_of_move_bindings(cx,
                                                 arm.guard.is_some(),
-                                                &arm.pats[]);
+                                                &arm.pats);
 
                 // Second, if there is a guard on each arm, make sure it isn't
                 // assigning or borrowing anything mutably.
@@ -242,7 +242,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
             ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
                 let pat_ty = ty::pat_ty(cx.tcx, p);
                 if let ty::ty_enum(def_id, _) = pat_ty.sty {
-                    let def = cx.tcx.def_map.borrow().get(&p.id).cloned();
+                    let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
                     if let Some(DefLocal(_)) = def {
                         if ty::enum_variants(cx.tcx, def_id).iter().any(|variant|
                             token::get_name(variant.name) == token::get_name(ident.node.name)
@@ -434,7 +434,7 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
     fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         return match pat.node {
             ast::PatIdent(..) | ast::PatEnum(..) => {
-                let def = self.tcx.def_map.borrow().get(&pat.id).cloned();
+                let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
                     Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
                         Some(const_expr) => {
@@ -733,28 +733,28 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     let pat = raw_pat(p);
     match pat.node {
         ast::PatIdent(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id) {
-                Some(&DefConst(..)) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(&DefStruct(_)) => vec!(Single),
-                Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(DefStruct(_)) => vec!(Single),
+                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!()
             },
         ast::PatEnum(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id) {
-                Some(&DefConst(..)) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         ast::PatStruct(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id) {
-                Some(&DefConst(..)) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         ast::PatLit(ref expr) =>
@@ -847,7 +847,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             Some(repeat(DUMMY_WILD_PAT).take(arity).collect()),
 
         ast::PatIdent(_, _, _) => {
-            let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned();
+            let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
                 Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@@ -862,7 +862,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         }
 
         ast::PatEnum(_, ref args) => {
-            let def = cx.tcx.def_map.borrow()[pat_id].clone();
+            let def = cx.tcx.def_map.borrow()[pat_id].full_def();
             match def {
                 DefConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@@ -880,7 +880,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
 
         ast::PatStruct(_, ref pattern_fields, _) => {
             // Is this a struct or an enum variant?
-            let def = cx.tcx.def_map.borrow()[pat_id].clone();
+            let def = cx.tcx.def_map.borrow()[pat_id].full_def();
             let class_id = match def {
                 DefConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@@ -1101,7 +1101,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                             &format!("binding pattern {} is not an \
                                      identifier: {:?}",
                                     p.id,
-                                    p.node)[]);
+                                    p.node));
                     }
                 }
             }
index 4280b7fe3f09649170a73dc7e37f90873a22fa9f..b97978fc03fff33ae23e04c0cb05595511f2d380 100644 (file)
@@ -93,10 +93,10 @@ fn visit_item(&mut self, it: &ast::Item) {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
-                match self.def_map.borrow().get(&e.id) {
-                    Some(&DefStatic(def_id, _)) |
-                    Some(&DefConst(def_id)) if
+            ast::ExprPath(..) => {
+                match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
+                    Some(DefStatic(def_id, _)) |
+                    Some(DefConst(def_id)) if
                             ast_util::is_local(def_id) => {
                         match self.ast_map.get(def_id.node) {
                           ast_map::NodeItem(item) =>
index 5bf7422dbc0d41ce7051d5a801238c4d4a28b12f..f793d3ce2fb4522c08aca64f0849c4022d18bf39 100644 (file)
@@ -31,7 +31,7 @@
 use std::rc::Rc;
 
 fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
-    let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
+    let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
     match opt_def {
         Some(def::DefConst(def_id)) => {
             lookup_const_by_id(tcx, def_id)
@@ -148,11 +148,11 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
 
         ast::ExprCall(ref callee, ref args) => {
-            let def = tcx.def_map.borrow()[callee.id].clone();
+            let def = tcx.def_map.borrow()[callee.id];
             if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
                entry.insert(def);
             }
-            let path = match def {
+            let path = match def.full_def() {
                 def::DefStruct(def_id) => def_to_path(tcx, def_id),
                 def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
                 _ => unreachable!()
@@ -178,8 +178,8 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             ast::PatVec(pats, None, vec![])
         }
 
-        ast::ExprPath(ref path) => {
-            let opt_def = tcx.def_map.borrow().get(&expr.id).cloned();
+        ast::ExprPath(_, ref path) => {
+            let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
             match opt_def {
                 Some(def::DefStruct(..)) =>
                     ast::PatStruct(path.clone(), vec![], false),
@@ -194,13 +194,6 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             }
         }
 
-        ast::ExprQPath(_) => {
-            match lookup_const(tcx, expr) {
-                Some(actual) => return const_expr_to_pat(tcx, actual, span),
-                _ => unreachable!()
-            }
-        }
-
         _ => ast::PatLit(P(expr.clone()))
     };
     P(ast::Pat { id: expr.id, node: pat, span: span })
@@ -388,8 +381,8 @@ fn fromb(b: bool) -> Result<const_val, String> { Ok(const_int(b as i64)) }
         let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
         cast_const(val, ety)
       }
-      ast::ExprPath(_) | ast::ExprQPath(_) => {
-          let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
+      ast::ExprPath(..) => {
+          let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
           let (const_expr, const_ty) = match opt_def {
               Some(def::DefConst(def_id)) => {
                   if ast_util::is_local(def_id) {
index 085d5cbc347e5b015801586b7756c1f2acce7b67..1718df702553f0f94886f0b365fd880ad55ad439 100644 (file)
@@ -53,7 +53,7 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> {
 
     // mapping from node to cfg node index
     // FIXME (#6298): Shouldn't this go with CFG?
-    nodeid_to_index: NodeMap<CFGIndex>,
+    nodeid_to_index: NodeMap<Vec<CFGIndex>>,
 
     // Bit sets per cfg node.  The following three fields (`gens`, `kills`,
     // and `on_entry`) all have the same structure. For each id in
@@ -88,11 +88,9 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> {
     changed: bool
 }
 
-fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
-    let opt_cfgindex = index.get(&id).cloned();
-    opt_cfgindex.unwrap_or_else(|| {
-        panic!("nodeid_to_index does not have entry for NodeId {}", id);
-    })
+fn get_cfg_indices<'a>(id: ast::NodeId, index: &'a NodeMap<Vec<CFGIndex>>) -> &'a [CFGIndex] {
+    let opt_indices = index.get(&id);
+    opt_indices.map(|v| &v[..]).unwrap_or(&[])
 }
 
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
@@ -114,9 +112,13 @@ fn pre(&self,
             pprust::NodePat(pat) => pat.id
         };
 
-        if self.has_bitset_for_nodeid(id) {
-            assert!(self.bits_per_id > 0);
-            let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
+        if !self.has_bitset_for_nodeid(id) {
+            return Ok(());
+        }
+
+        assert!(self.bits_per_id > 0);
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
             let (start, end) = self.compute_id_range(cfgidx);
             let on_entry = &self.on_entry[start.. end];
             let entry_str = bits_to_string(on_entry);
@@ -144,7 +146,7 @@ fn pre(&self,
 }
 
 fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
-                         cfg: &cfg::CFG) -> NodeMap<CFGIndex> {
+                         cfg: &cfg::CFG) -> NodeMap<Vec<CFGIndex>> {
     let mut index = NodeMap();
 
     // FIXME (#6298): Would it be better to fold formals from decl
@@ -157,28 +159,38 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
     }
 
     cfg.graph.each_node(|node_idx, node| {
-        if node.data.id != ast::DUMMY_NODE_ID {
-            index.insert(node.data.id, node_idx);
+        if let cfg::CFGNodeData::AST(id) = node.data {
+            match index.entry(id).get() {
+                Ok(v) => v.push(node_idx),
+                Err(e) => {
+                    e.insert(vec![node_idx]);
+                }
+            }
         }
         true
     });
 
     return index;
 
-    fn add_entries_from_fn_decl(index: &mut NodeMap<CFGIndex>,
+    fn add_entries_from_fn_decl(index: &mut NodeMap<Vec<CFGIndex>>,
                                 decl: &ast::FnDecl,
                                 entry: CFGIndex) {
         //! add mappings from the ast nodes for the formal bindings to
         //! the entry-node in the graph.
         struct Formals<'a> {
             entry: CFGIndex,
-            index: &'a mut NodeMap<CFGIndex>,
+            index: &'a mut NodeMap<Vec<CFGIndex>>,
         }
         let mut formals = Formals { entry: entry, index: index };
         visit::walk_fn_decl(&mut formals, decl);
         impl<'a, 'v> visit::Visitor<'v> for Formals<'a> {
             fn visit_pat(&mut self, p: &ast::Pat) {
-                self.index.insert(p.id, self.entry);
+                match self.index.entry(p.id).get() {
+                    Ok(v) => v.push(self.entry),
+                    Err(e) => {
+                        e.insert(vec![self.entry]);
+                    }
+                }
                 visit::walk_pat(self, p)
             }
         }
@@ -230,10 +242,12 @@ pub fn add_gen(&mut self, id: ast::NodeId, bit: uint) {
         assert!(self.nodeid_to_index.contains_key(&id));
         assert!(self.bits_per_id > 0);
 
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        let (start, end) = self.compute_id_range(cfgidx);
-        let gens = &mut self.gens[start.. end];
-        set_bit(gens, bit);
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let gens = &mut self.gens[start.. end];
+            set_bit(gens, bit);
+        }
     }
 
     pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) {
@@ -243,10 +257,12 @@ pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) {
         assert!(self.nodeid_to_index.contains_key(&id));
         assert!(self.bits_per_id > 0);
 
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        let (start, end) = self.compute_id_range(cfgidx);
-        let kills = &mut self.kills[start.. end];
-        set_bit(kills, bit);
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let kills = &mut self.kills[start.. end];
+            set_bit(kills, bit);
+        }
     }
 
     fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [uint]) {
@@ -279,7 +295,7 @@ fn compute_id_range(&self, cfgidx: CFGIndex) -> (uint, uint) {
     }
 
 
-    pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, f: F) -> bool where
+    pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, mut f: F) -> bool where
         F: FnMut(uint) -> bool,
     {
         //! Iterates through each bit that is set on entry to `id`.
@@ -287,8 +303,13 @@ pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, f: F) -> bool where
         if !self.has_bitset_for_nodeid(id) {
             return true;
         }
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        self.each_bit_for_node(Entry, cfgidx, f)
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            if !self.each_bit_for_node(Entry, cfgidx, |i| f(i)) {
+                return false;
+            }
+        }
+        return true;
     }
 
     pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where
@@ -320,7 +341,7 @@ pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bo
         self.each_bit(slice, f)
     }
 
-    pub fn each_gen_bit<F>(&self, id: ast::NodeId, f: F) -> bool where
+    pub fn each_gen_bit<F>(&self, id: ast::NodeId, mut f: F) -> bool where
         F: FnMut(uint) -> bool,
     {
         //! Iterates through each bit in the gen set for `id`.
@@ -334,12 +355,17 @@ pub fn each_gen_bit<F>(&self, id: ast::NodeId, f: F) -> bool where
             return true;
         }
 
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        let (start, end) = self.compute_id_range(cfgidx);
-        let gens = &self.gens[start.. end];
-        debug!("{} each_gen_bit(id={}, gens={})",
-               self.analysis_name, id, bits_to_string(gens));
-        self.each_bit(gens, f)
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let gens = &self.gens[start.. end];
+            debug!("{} each_gen_bit(id={}, gens={})",
+                   self.analysis_name, id, bits_to_string(gens));
+            if !self.each_bit(gens, |i| f(i)) {
+                return false;
+            }
+        }
+        return true;
     }
 
     fn each_bit<F>(&self, words: &[uint], mut f: F) -> bool where
@@ -400,13 +426,15 @@ pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) {
 
             let mut changed = false;
             for &node_id in &edge.data.exiting_scopes {
-                let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned();
+                let opt_cfg_idx = self.nodeid_to_index.get(&node_id);
                 match opt_cfg_idx {
-                    Some(cfg_idx) => {
-                        let (start, end) = self.compute_id_range(cfg_idx);
-                        let kills = &self.kills[start.. end];
-                        if bitwise(&mut orig_kills, kills, &Union) {
-                            changed = true;
+                    Some(indices) => {
+                        for &cfg_idx in indices {
+                            let (start, end) = self.compute_id_range(cfg_idx);
+                            let kills = &self.kills[start.. end];
+                            if bitwise(&mut orig_kills, kills, &Union) {
+                                changed = true;
+                            }
                         }
                     }
                     None => {
@@ -482,7 +510,7 @@ fn walk_cfg(&mut self,
 
         cfg.graph.each_node(|node_index, node| {
             debug!("DataFlowContext::walk_cfg idx={:?} id={} begin in_out={}",
-                   node_index, node.data.id, bits_to_string(in_out));
+                   node_index, node.data.id(), bits_to_string(in_out));
 
             let (start, end) = self.dfcx.compute_id_range(node_index);
 
@@ -554,7 +582,7 @@ fn bits_to_string(words: &[uint]) -> String {
         let mut v = word;
         for _ in 0..usize::BYTES {
             result.push(sep);
-            result.push_str(&format!("{:02x}", v & 0xFF)[]);
+            result.push_str(&format!("{:02x}", v & 0xFF));
             v >>= 8;
             sep = '-';
         }
index ff78deb8d12ea6ba945531b6c34f0762b38a2ee6..2d837ce52b56a4f9abcee7e973d8dc95d7a55d3f 100644 (file)
@@ -71,13 +71,13 @@ fn check_def_id(&mut self, def_id: ast::DefId) {
 
     fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
         self.tcx.def_map.borrow().get(id).map(|def| {
-            match def {
-                &def::DefConst(_) => {
+            match def.full_def() {
+                def::DefConst(_) => {
                     self.check_def_id(def.def_id())
                 }
                 _ if self.ignore_non_const_paths => (),
-                &def::DefPrimTy(_) => (),
-                &def::DefVariant(enum_id, variant_id, _) => {
+                def::DefPrimTy(_) => (),
+                def::DefVariant(enum_id, variant_id, _) => {
                     self.check_def_id(enum_id);
                     self.check_def_id(variant_id);
                 }
@@ -158,7 +158,7 @@ fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: uint) {
 
     fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
                                   pats: &[codemap::Spanned<ast::FieldPat>]) {
-        let id = match (*self.tcx.def_map.borrow())[lhs.id] {
+        let id = match self.tcx.def_map.borrow()[lhs.id].full_def() {
             def::DefVariant(_, id, _) => id,
             _ => {
                 match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
index 7857bcad8135d8dc6628c80aaf7e792221a07d84..1a054c0f464aac9afb5a91adb6f007490a8969da 100644 (file)
 
 pub use self::Def::*;
 pub use self::MethodProvenance::*;
-pub use self::TraitItemKind::*;
 
+use middle::privacy::LastPrivate;
 use middle::subst::ParamSpace;
-use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
 use util::nodemap::NodeMap;
 use syntax::ast;
 use syntax::ast_util::local_def;
@@ -23,7 +22,6 @@
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Def {
     DefFn(ast::DefId, bool /* is_ctor */),
-    DefStaticMethod(/* method */ ast::DefId, MethodProvenance),
     DefSelfTy(/* trait id */ ast::NodeId),
     DefMod(ast::DefId),
     DefForeignMod(ast::DefId),
@@ -32,12 +30,7 @@ pub enum Def {
     DefLocal(ast::NodeId),
     DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
     DefTy(ast::DefId, bool /* is_enum */),
-    DefAssociatedTy(ast::DefId),
-    // A partially resolved path to an associated type `T::U` where `T` is a concrete
-    // type (indicated by the DefId) which implements a trait which has an associated
-    // type `U` (indicated by the Ident).
-    // FIXME(#20301) -- should use Name
-    DefAssociatedPath(TyParamProvenance, ast::Ident),
+    DefAssociatedTy(ast::DefId /* trait */, ast::DefId),
     DefTrait(ast::DefId),
     DefPrimTy(ast::PrimTy),
     DefTyParam(ParamSpace, u32, ast::DefId, ast::Name),
@@ -54,14 +47,48 @@ pub enum Def {
     /// - If it's an ExprPath referring to some tuple struct, then DefMap maps
     ///   it to a def whose id is the StructDef.ctor_id.
     DefStruct(ast::DefId),
-    DefTyParamBinder(ast::NodeId), /* struct, impl or trait with ty params */
     DefRegion(ast::NodeId),
     DefLabel(ast::NodeId),
-    DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */, MethodProvenance),
+    DefMethod(ast::DefId /* method */, MethodProvenance),
+}
+
+/// The result of resolving a path.
+/// Before type checking completes, `depth` represents the number of
+/// trailing segments which are yet unresolved. Afterwards, if there
+/// were no errors, all paths should be fully resolved, with `depth`
+/// set to `0` and `base_def` representing the final resolution.
+///
+///     module::Type::AssocX::AssocY::MethodOrAssocType
+///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///     base_def      depth = 3
+///
+///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
+///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
+///           base_def        depth = 2
+#[derive(Copy, Debug)]
+pub struct PathResolution {
+    pub base_def: Def,
+    pub last_private: LastPrivate,
+    pub depth: usize
+}
+
+impl PathResolution {
+    /// Get the definition, if fully resolved, otherwise panic.
+    pub fn full_def(&self) -> Def {
+        if self.depth != 0 {
+            panic!("path not fully resolved: {:?}", self);
+        }
+        self.base_def
+    }
+
+    /// Get the DefId, if fully resolved, otherwise panic.
+    pub fn def_id(&self) -> ast::DefId {
+        self.full_def().def_id()
+    }
 }
 
 // Definition mapping
-pub type DefMap = RefCell<NodeMap<Def>>;
+pub type DefMap = RefCell<NodeMap<PathResolution>>;
 // This is the replacement export map. It maps a module to all of the exports
 // within.
 pub type ExportMap = NodeMap<Vec<Export>>;
@@ -78,12 +105,6 @@ pub enum MethodProvenance {
     FromImpl(ast::DefId),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TyParamProvenance {
-    FromSelf(ast::DefId),
-    FromParam(ast::DefId),
-}
-
 impl MethodProvenance {
     pub fn map<F>(self, f: F) -> MethodProvenance where
         F: FnOnce(ast::DefId) -> ast::DefId,
@@ -95,34 +116,6 @@ pub fn map<F>(self, f: F) -> MethodProvenance where
     }
 }
 
-impl TyParamProvenance {
-    pub fn def_id(&self) -> ast::DefId {
-        match *self {
-            TyParamProvenance::FromSelf(ref did) => did.clone(),
-            TyParamProvenance::FromParam(ref did) => did.clone(),
-        }
-    }
-}
-
-#[derive(Clone, Copy, Eq, PartialEq)]
-pub enum TraitItemKind {
-    NonstaticMethodTraitItemKind,
-    StaticMethodTraitItemKind,
-    TypeTraitItemKind,
-}
-
-impl TraitItemKind {
-    pub fn from_explicit_self_category(explicit_self_category:
-                                       ExplicitSelfCategory)
-                                       -> TraitItemKind {
-        if explicit_self_category == StaticExplicitSelfCategory {
-            StaticMethodTraitItemKind
-        } else {
-            NonstaticMethodTraitItemKind
-        }
-    }
-}
-
 impl Def {
     pub fn local_node_id(&self) -> ast::NodeId {
         let def_id = self.def_id();
@@ -132,25 +125,21 @@ pub fn local_node_id(&self) -> ast::NodeId {
 
     pub fn def_id(&self) -> ast::DefId {
         match *self {
-            DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) |
-            DefForeignMod(id) | DefStatic(id, _) |
-            DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) |
+            DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
+            DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
             DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
-            DefMethod(id, _, _) | DefConst(id) |
-            DefAssociatedPath(TyParamProvenance::FromSelf(id), _) |
-            DefAssociatedPath(TyParamProvenance::FromParam(id), _) => {
+            DefMethod(id, _) | DefConst(id) => {
                 id
             }
             DefLocal(id) |
             DefSelfTy(id) |
             DefUpvar(id, _) |
             DefRegion(id) |
-            DefTyParamBinder(id) |
             DefLabel(id) => {
                 local_def(id)
             }
 
-            DefPrimTy(_) => panic!()
+            DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy")
         }
     }
 
index ad9f4eade5c90d25538240080640f300aace049a..40e7610582f9c7454846a43c3bb06fec1aaebb54 100644 (file)
@@ -118,7 +118,7 @@ fn calculate_type(sess: &session::Session,
                 let src = sess.cstore.get_used_crate_source(cnum).unwrap();
                 if src.rlib.is_some() { return }
                 sess.err(&format!("dependency `{}` not found in rlib format",
-                                 data.name)[]);
+                                 data.name));
             });
             return Vec::new();
         }
@@ -197,7 +197,7 @@ fn calculate_type(sess: &session::Session,
                                  match kind {
                                      cstore::RequireStatic => "rlib",
                                      cstore::RequireDynamic => "dylib",
-                                 })[]);
+                                 }));
             }
         }
     }
@@ -222,7 +222,7 @@ fn add_library(sess: &session::Session,
                 let data = sess.cstore.get_crate_data(cnum);
                 sess.err(&format!("cannot satisfy dependencies so `{}` only \
                                   shows up once",
-                                 data.name)[]);
+                                 data.name));
                 sess.help("having upstream crates all available in one format \
                            will likely make this go away");
             }
index abb8f35f662b5e07604f03d873a7d0861a8b9c99..9c85b7748ab0c3449118daaf2502ea9ffbe44538 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 //! Enforces the Rust effect system. Currently there is just one effect,
-/// `unsafe`.
+//! `unsafe`.
 use self::UnsafeContext::*;
 
 use middle::def;
@@ -175,7 +175,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
             ast::ExprInlineAsm(..) => {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
+            ast::ExprPath(..) => {
                 if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
index e99d214742a0b668b40becf51bccafc8c387022b..a1e38a1c8bda795d4c35e304cb35bc4bc406fc32 100644 (file)
@@ -422,7 +422,7 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
                 self.walk_expr(&**subexpr)
             }
 
-            ast::ExprPath(_) | ast::ExprQPath(_) => { }
+            ast::ExprPath(..) => { }
 
             ast::ExprUnary(ast::UnDeref, ref base) => {      // *base
                 if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
@@ -841,7 +841,7 @@ fn walk_autoderefs(&mut self,
                         ty::ty_rptr(r, ref m) => (m.mutbl, r),
                         _ => self.tcx().sess.span_bug(expr.span,
                                 &format!("bad overloaded deref type {}",
-                                    method_ty.repr(self.tcx()))[])
+                                    method_ty.repr(self.tcx())))
                     };
                     let bk = ty::BorrowKind::from_mutbl(m);
                     self.delegate.borrow(expr.id, expr.span, cmt,
@@ -1017,7 +1017,7 @@ fn walk_pat(&mut self,
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
-                let def = def_map.borrow()[pat.id].clone();
+                let def = def_map.borrow()[pat.id].full_def();
                 match mc.cat_def(pat.id, pat.span, pat_ty, def) {
                     Ok(binding_cmt) => {
                         delegate.mutate(pat.id, pat.span, binding_cmt, Init);
@@ -1097,13 +1097,13 @@ fn walk_pat(&mut self,
 
             match pat.node {
                 ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
-                    match def_map.get(&pat.id) {
+                    match def_map.get(&pat.id).map(|d| d.full_def()) {
                         None => {
                             // no definition found: pat is not a
                             // struct or enum pattern.
                         }
 
-                        Some(&def::DefVariant(enum_did, variant_did, _is_struct)) => {
+                        Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
                             let downcast_cmt =
                                 if ty::enum_is_univariant(tcx, enum_did) {
                                     cmt_pat
@@ -1119,7 +1119,7 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, downcast_cmt, match_mode);
                         }
 
-                        Some(&def::DefStruct(..)) | Some(&def::DefTy(_, false)) => {
+                        Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => {
                             // A struct (in either the value or type
                             // namespace; we encounter the former on
                             // e.g. patterns for unit structs).
@@ -1131,14 +1131,14 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, cmt_pat, match_mode);
                         }
 
-                        Some(&def::DefConst(..)) |
-                        Some(&def::DefLocal(..)) => {
+                        Some(def::DefConst(..)) |
+                        Some(def::DefLocal(..)) => {
                             // This is a leaf (i.e. identifier binding
                             // or constant value to match); thus no
                             // `matched_pat` call.
                         }
 
-                        Some(def @ &def::DefTy(_, true)) => {
+                        Some(def @ def::DefTy(_, true)) => {
                             // An enum's type -- should never be in a
                             // pattern.
 
index b33e5a802f1582f6a639431938abaf3c026d8709..7584a2e44cc7c0b3316be2718c153705e530ec03 100644 (file)
@@ -93,7 +93,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
                 None
             }
         }
-        ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None,
+        ty::ty_infer(_) | ty::ty_err => None,
     }
 }
 
index 0eeafb767d8a625d2792a3c393f4888aec8cf68c..b782a655d89ff11155bf156793000776a9c6bbed 100644 (file)
@@ -228,11 +228,11 @@ fn fn_sigs(&self, a: &ty::FnSig<'tcx>, b: &ty::FnSig<'tcx>) -> cres<'tcx, ty::Fn
                              variadic: a.variadic});
 
 
-        fn argvecs<'tcx, C: Combine<'tcx>>(combiner: &C,
-                                           a_args: &[Ty<'tcx>],
-                                           b_args: &[Ty<'tcx>])
-                                           -> cres<'tcx, Vec<Ty<'tcx>>>
-        {
+        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()
@@ -265,13 +265,7 @@ fn projection_tys(&self,
             Err(ty::terr_projection_name_mismatched(
                 expected_found(self, a.item_name, b.item_name)))
         } else {
-            // Note that the trait refs for the projection must be
-            // *equal*. This is because there is no inherent
-            // relationship between `<T as Foo>::Bar` and `<U as
-            // Foo>::Bar` that we can derive based on how `T` relates
-            // to `U`. Issue #21726 contains further discussion and
-            // in-depth examples.
-            let trait_ref = try!(self.equate().trait_refs(&*a.trait_ref, &*b.trait_ref));
+            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 })
         }
     }
@@ -351,51 +345,51 @@ pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> {
 impl<'tcx,T> Combineable<'tcx> for Rc<T>
     where T : Combineable<'tcx>
 {
-    fn combine<C:Combine<'tcx>>(combiner: &C,
-                                a: &Rc<T>,
-                                b: &Rc<T>)
-                                -> cres<'tcx, Rc<T>>
-    {
+    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:Combine<'tcx>>(combiner: &C,
-                                a: &ty::TraitRef<'tcx>,
-                                b: &ty::TraitRef<'tcx>)
-                                -> cres<'tcx, 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:Combine<'tcx>>(combiner: &C,
-                                a: &Ty<'tcx>,
-                                b: &Ty<'tcx>)
-                                -> cres<'tcx, 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:Combine<'tcx>>(combiner: &C,
-                                a: &ty::ProjectionPredicate<'tcx>,
-                                b: &ty::ProjectionPredicate<'tcx>)
-                                -> cres<'tcx, 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:Combine<'tcx>>(combiner: &C,
-                                a: &ty::FnSig<'tcx>,
-                                b: &ty::FnSig<'tcx>)
-                                -> cres<'tcx, 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)
     }
 }
@@ -407,8 +401,11 @@ pub struct CombineFields<'a, 'tcx: 'a> {
     pub trace: TypeTrace<'tcx>,
 }
 
-pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
-        this: &C, a: T, b: T) -> ty::expected_found<T> {
+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 {
@@ -416,29 +413,26 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
     }
 }
 
-pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
-                                         a: Ty<'tcx>,
-                                         b: Ty<'tcx>)
-                                         -> cres<'tcx, Ty<'tcx>>
-{
+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)
-      }
+        // 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),
 
         // Relate integral variables to other types
         (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
@@ -475,68 +469,62 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
             unify_float_variable(this, !this.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_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)))
-      }
-
-      (&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 => {
+        (&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_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)))
+        }
+
+        (&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_region, a_substs),
-       &ty::ty_closure(b_id, b_region, 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 region = try!(this.equate().regions(*a_region, *b_region));
-          let substs = try!(this.substs_variances(None, a_substs, b_substs));
-          Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), 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)) => {
+        }
+
+        (&ty::ty_closure(a_id, a_region, a_substs),
+         &ty::ty_closure(b_id, b_region, 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 region = try!(this.equate().regions(*a_region, *b_region));
+            let substs = try!(this.substs_variances(None, a_substs, b_substs));
+            Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), 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));
 
             // FIXME(14985)  If we have mutable references to trait objects, we
@@ -551,45 +539,43 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
                 _ => 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, 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))
+        (&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_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 =>
@@ -598,33 +584,33 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
             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))
-      }
+        (&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)))
+        _ => Err(ty::terr_sorts(expected_found(this, a, b))),
     };
 
-    fn unify_integral_variable<'tcx, C: Combine<'tcx>>(
-        this: &C,
-        vid_is_expected: bool,
-        vid: ty::IntVid,
-        val: ty::IntVarValue) -> cres<'tcx, Ty<'tcx>>
-    {
+    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))
+            UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)),
         }
     }
 
-    fn unify_float_variable<'tcx, C: Combine<'tcx>>(
-        this: &C,
-        vid_is_expected: bool,
-        vid: ty::FloatVid,
-        val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>>
-    {
+    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))
     }
@@ -696,12 +682,8 @@ pub fn instantiate(&self,
                 None => {     // ...not yet instantiated:
                     // Generalize type if necessary.
                     let generalized_ty = try!(match dir {
-                        EqTo => {
-                            self.generalize(a_ty, b_vid, false)
-                        }
-                        BiTo | SupertypeOf | SubtypeOf => {
-                            self.generalize(a_ty, b_vid, true)
-                        }
+                        EqTo => self.generalize(a_ty, b_vid, false),
+                        BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
                     });
                     debug!("instantiate(a_ty={}, dir={:?}, \
                                         b_vid={}, generalized_ty={})",
@@ -723,22 +705,14 @@ pub fn instantiate(&self,
             // 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));
-                }
+                BiTo => try!(self.bivariate().tys(a_ty, b_ty)),
 
-                EqTo => {
-                    try!(self.equate().tys(a_ty, b_ty));
-                }
+                EqTo => try!(self.equate().tys(a_ty, b_ty)),
 
-                SubtypeOf => {
-                    try!(self.sub().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));
-                }
-            }
+                SupertypeOf => try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)),
+            };
         }
 
         Ok(())
@@ -754,11 +728,13 @@ fn generalize(&self,
                   make_region_vars: bool)
                   -> cres<'tcx, Ty<'tcx>>
     {
-        let mut generalize = Generalizer { infcx: self.infcx,
-                                           span: self.trace.origin.span(),
-                                           for_vid: for_vid,
-                                           make_region_vars: make_region_vars,
-                                           cycle_detected: false };
+        let mut generalize = Generalizer {
+            infcx: self.infcx,
+            span: self.trace.origin.span(),
+            for_vid: for_vid,
+            make_region_vars: make_region_vars,
+            cycle_detected: false
+        };
         let u = ty.fold_with(&mut generalize);
         if generalize.cycle_detected {
             Err(ty::terr_cyclic_ty)
@@ -818,7 +794,7 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
                 self.tcx().sess.span_bug(
                     self.span,
                     &format!("Encountered early bound region when generalizing: {}",
-                            r.repr(self.tcx()))[]);
+                            r.repr(self.tcx())));
             }
 
             // Always make a fresh region variable for skolemized regions;
index 53032f9b9ac64ac512d673d0faece23d2bee32a9..da4df813030c3ab504f228b24935a4f1d5b4a79f 100644 (file)
@@ -449,7 +449,7 @@ fn report_generic_bound_failure(&self,
                     &format!(
                         "consider adding an explicit lifetime bound `{}: {}`...",
                         bound_kind.user_string(self.tcx),
-                        sub.user_string(self.tcx))[]);
+                        sub.user_string(self.tcx)));
             }
 
             ty::ReStatic => {
@@ -460,7 +460,7 @@ fn report_generic_bound_failure(&self,
                     origin.span(),
                     &format!(
                         "consider adding an explicit lifetime bound `{}: 'static`...",
-                        bound_kind.user_string(self.tcx))[]);
+                        bound_kind.user_string(self.tcx)));
             }
 
             _ => {
@@ -472,10 +472,10 @@ fn report_generic_bound_failure(&self,
                     origin.span(),
                     &format!(
                         "consider adding an explicit lifetime bound for `{}`",
-                        bound_kind.user_string(self.tcx))[]);
+                        bound_kind.user_string(self.tcx)));
                 note_and_explain_region(
                     self.tcx,
-                    &format!("{} must be valid for ", labeled_user_string)[],
+                    &format!("{} must be valid for ", labeled_user_string),
                     sub,
                     "...");
             }
@@ -525,7 +525,7 @@ fn report_concrete_failure(&self,
                     &format!("...but `{}` is only valid for ",
                             ty::local_var_name_str(self.tcx,
                                                    upvar_id.var_id)
-                                .to_string())[],
+                                .to_string()),
                     sup,
                     "");
             }
@@ -568,7 +568,7 @@ fn report_concrete_failure(&self,
                     &format!("captured variable `{}` does not \
                             outlive the enclosing closure",
                             ty::local_var_name_str(self.tcx,
-                                                   id).to_string())[]);
+                                                   id).to_string()));
                 note_and_explain_region(
                     self.tcx,
                     "captured variable is valid for ",
@@ -610,7 +610,7 @@ fn report_concrete_failure(&self,
                     span,
                     &format!("the type `{}` does not fulfill the \
                              required lifetime",
-                            self.ty_to_string(ty))[]);
+                            self.ty_to_string(ty)));
                 note_and_explain_region(self.tcx,
                                         "type must outlive ",
                                         sub,
@@ -636,7 +636,7 @@ fn report_concrete_failure(&self,
                     span,
                     &format!("the type `{}` (provided as the value of \
                              a type parameter) is not valid at this point",
-                            self.ty_to_string(ty))[]);
+                            self.ty_to_string(ty)));
                 note_and_explain_region(self.tcx,
                                         "type must outlive ",
                                         sub,
@@ -713,7 +713,7 @@ fn report_concrete_failure(&self,
                     span,
                     &format!("type of expression contains references \
                              that are not valid during the expression: `{}`",
-                            self.ty_to_string(t))[]);
+                            self.ty_to_string(t)));
                 note_and_explain_region(
                     self.tcx,
                     "type is only valid for ",
@@ -752,7 +752,7 @@ fn report_concrete_failure(&self,
                     span,
                     &format!("in type `{}`, reference has a longer lifetime \
                              than the data it references",
-                            self.ty_to_string(ty))[]);
+                            self.ty_to_string(ty)));
                 note_and_explain_region(
                     self.tcx,
                     "the pointer is valid for ",
@@ -988,7 +988,7 @@ fn pick_lifetime(&self,
                 names.push(lt_name);
             }
             names.sort();
-            let name = token::str_to_ident(&names[0][]).name;
+            let name = token::str_to_ident(&names[0]).name;
             return (name_to_dummy_lifetime(name), Kept);
         }
         return (self.life_giver.give_lifetime(), Fresh);
@@ -1233,16 +1233,16 @@ fn rebuild_arg_ty_or_output(&self,
                     }
                     ty_queue.push(&*mut_ty.ty);
                 }
-                ast::TyPath(ref path, id) => {
-                    let a_def = match self.tcx.def_map.borrow().get(&id) {
+                ast::TyPath(ref maybe_qself, ref path) => {
+                    let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) {
                         None => {
                             self.tcx
                                 .sess
                                 .fatal(&format!(
                                         "unbound path {}",
-                                        pprust::path_to_string(path))[])
+                                        pprust::path_to_string(path)))
                         }
-                        Some(&d) => d
+                        Some(d) => d.full_def()
                     };
                     match a_def {
                         def::DefTy(did, _) | def::DefStruct(did) => {
@@ -1277,9 +1277,16 @@ fn rebuild_arg_ty_or_output(&self,
                                 region_names: region_names
                             };
                             let new_path = self.rebuild_path(rebuild_info, lifetime);
+                            let qself = maybe_qself.as_ref().map(|qself| {
+                                ast::QSelf {
+                                    ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
+                                                                      anon_nums, region_names),
+                                    position: qself.position
+                                }
+                            });
                             let to = ast::Ty {
                                 id: cur_ty.id,
-                                node: ast::TyPath(new_path, id),
+                                node: ast::TyPath(qself, new_path),
                                 span: cur_ty.span
                             };
                             new_ty = self.rebuild_ty(new_ty, P(to));
@@ -1479,7 +1486,7 @@ fn report_inference_failure(&self,
             var_origin.span(),
             &format!("cannot infer an appropriate lifetime{} \
                     due to conflicting requirements",
-                    var_description)[]);
+                    var_description));
     }
 
     fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
@@ -1527,7 +1534,7 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                         self.tcx.sess.span_note(
                             trace.origin.span(),
                             &format!("...so that {} ({})",
-                                    desc, values_str)[]);
+                                    desc, values_str));
                     }
                     None => {
                         // Really should avoid printing this error at
@@ -1536,7 +1543,7 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                         // doing right now. - nmatsakis
                         self.tcx.sess.span_note(
                             trace.origin.span(),
-                            &format!("...so that {}", desc)[]);
+                            &format!("...so that {}", desc));
                     }
                 }
             }
@@ -1552,7 +1559,7 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                     &format!(
                         "...so that closure can access `{}`",
                         ty::local_var_name_str(self.tcx, upvar_id.var_id)
-                            .to_string())[])
+                            .to_string()))
             }
             infer::InfStackClosure(span) => {
                 self.tcx.sess.span_note(
@@ -1577,7 +1584,7 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                             does not outlive the enclosing closure",
                             ty::local_var_name_str(
                                 self.tcx,
-                                id).to_string())[]);
+                                id).to_string()));
             }
             infer::IndexSlice(span) => {
                 self.tcx.sess.span_note(
@@ -1626,7 +1633,7 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                     span,
                     &format!("...so type `{}` of expression is valid during the \
                              expression",
-                            self.ty_to_string(t))[]);
+                            self.ty_to_string(t)));
             }
             infer::BindingTypeIsNotValidAtDecl(span) => {
                 self.tcx.sess.span_note(
@@ -1638,14 +1645,14 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                     span,
                     &format!("...so that the reference type `{}` \
                              does not outlive the data it points at",
-                            self.ty_to_string(ty))[]);
+                            self.ty_to_string(ty)));
             }
             infer::RelateParamBound(span, t) => {
                 self.tcx.sess.span_note(
                     span,
                     &format!("...so that the type `{}` \
                              will meet its required lifetime bounds",
-                            self.ty_to_string(t))[]);
+                            self.ty_to_string(t)));
             }
             infer::RelateDefaultParamBound(span, t) => {
                 self.tcx.sess.span_note(
@@ -1653,13 +1660,13 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
                     &format!("...so that type parameter \
                              instantiated with `{}`, \
                              will meet its declared lifetime bounds",
-                            self.ty_to_string(t))[]);
+                            self.ty_to_string(t)));
             }
             infer::RelateRegionParamBound(span) => {
                 self.tcx.sess.span_note(
                     span,
                     &format!("...so that the declared lifetime parameter bounds \
-                                are satisfied")[]);
+                                are satisfied"));
             }
             infer::SafeDestructor(span) => {
                 self.tcx.sess.span_note(
@@ -1717,7 +1724,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
         Some(node) => match node {
             ast_map::NodeItem(item) => match item.node {
                 ast::ItemFn(_, _, _, ref gen, _) => {
-                    taken.push_all(&gen.lifetimes[]);
+                    taken.push_all(&gen.lifetimes);
                     None
                 },
                 _ => None
@@ -1725,7 +1732,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
             ast_map::NodeImplItem(ii) => {
                 match *ii {
                     ast::MethodImplItem(ref m) => {
-                        taken.push_all(&m.pe_generics().lifetimes[]);
+                        taken.push_all(&m.pe_generics().lifetimes);
                         Some(m.id)
                     }
                     ast::TypeImplItem(_) => None,
@@ -1784,7 +1791,7 @@ fn give_lifetime(&self) -> ast::Lifetime {
         let mut lifetime;
         loop {
             let mut s = String::from_str("'");
-            s.push_str(&num_to_string(self.counter.get())[]);
+            s.push_str(&num_to_string(self.counter.get()));
             if !self.taken.contains(&s) {
                 lifetime = name_to_dummy_lifetime(
                                     token::str_to_ident(&s[..]).name);
index 1b7e6c33c0575f723d341ec8373005765a0c5147..e41b949d5df1d75cb98d80b57fccc83bb79a76eb 100644 (file)
@@ -135,7 +135,6 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 t
             }
 
-            ty::ty_open(..) |
             ty::ty_bool |
             ty::ty_char |
             ty::ty_int(..) |
index a729156c88b3588e3d85e442d6878b6c526fcd15..7d789bedc50b5c7f869ff943cda25c3315dfec65 100644 (file)
@@ -189,7 +189,7 @@ fn generalize_region(infcx: &InferCtxt,
                 span,
                 &format!("region {:?} is not associated with \
                          any bound region from A!",
-                        r0)[])
+                        r0))
         }
     }
 
@@ -322,7 +322,7 @@ fn rev_lookup(infcx: &InferCtxt,
             }
             infcx.tcx.sess.span_bug(
                 span,
-                &format!("could not find original bound region for {:?}", r)[]);
+                &format!("could not find original bound region for {:?}", r));
         }
 
         fn fresh_bound_variable(infcx: &InferCtxt, debruijn: ty::DebruijnIndex) -> ty::Region {
@@ -339,7 +339,7 @@ fn var_ids<'tcx, T: Combine<'tcx>>(combiner: &T,
             r => {
                 combiner.infcx().tcx.sess.span_bug(
                     combiner.trace().origin.span(),
-                    &format!("found non-region-vid: {:?}", r)[]);
+                    &format!("found non-region-vid: {:?}", r));
             }
         }).collect()
 }
@@ -465,7 +465,8 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
      * Replace all regions bound by `binder` with skolemized regions and
      * return a map indicating which bound-region was replaced with what
      * skolemized region. This is the first step of checking subtyping
-     * when higher-ranked things are involved. See `doc.rs` for more details.
+     * when higher-ranked things are involved. See `README.md` for more
+     * details.
      */
 
     let (result, map) = ty::replace_late_bound_regions(infcx.tcx, binder, |br| {
@@ -490,7 +491,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
      * and checks to determine whether any of the skolemized regions created
      * in `skol_map` would "escape" -- meaning that they are related to
      * other regions in some way. If so, the higher-ranked subtyping doesn't
-     * hold. See `doc.rs` for more details.
+     * hold. See `README.md` for more details.
      */
 
     debug!("leak_check: skol_map={}",
@@ -533,7 +534,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 /// passed; currently, it's used in the trait matching code to create
 /// a set of nested obligations frmo an impl that matches against
 /// something higher-ranked.  More details can be found in
-/// `middle::traits::doc.rs`.
+/// `librustc/middle/traits/README.md`.
 ///
 /// As a brief example, consider the obligation `for<'a> Fn(&'a int)
 /// -> &'a int`, and the impl:
index b0576ff55ff7390605b889c93df55b3b10aa6b2f..835964828d419c468785a2722902c113086febdb 100644 (file)
@@ -999,7 +999,7 @@ pub fn type_error_message_str_with_expected<M>(&self,
 
                 self.tcx.sess.span_err(sp, &format!("{}{}",
                     mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
-                    error_str)[]);
+                    error_str));
 
                 if let Some(err) = err {
                     ty::note_and_explain_type_err(self.tcx, err)
index 67875ae225224e030918f037980a9a72cac7e56a..43cd1fc8edbac83b87300390c0678087cb335dee 100644 (file)
@@ -90,7 +90,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
             tcx.sess.bug("empty string provided as RUST_REGION_GRAPH");
         }
 
-        if output_template.contains_char('%') {
+        if output_template.contains('%') {
             let mut new_str = String::new();
             for c in output_template.chars() {
                 if c == '%' {
index b4fd34f206fa728d258a40241a13fafa32a84a80..759d7357df1931d71b0843e61594c2dd4624cbcb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! See doc.rs
+//! See README.md
 
 pub use self::Constraint::*;
 pub use self::Verify::*;
@@ -473,7 +473,7 @@ pub fn make_subregion(&self,
                 origin.span(),
                 &format!("cannot relate bound region: {} <= {}",
                         sub.repr(self.tcx),
-                        sup.repr(self.tcx))[]);
+                        sup.repr(self.tcx)));
           }
           (_, ReStatic) => {
             // all regions are subregions of static, so we can ignore this
@@ -733,7 +733,7 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
             self.tcx.sess.bug(
                 &format!("cannot relate bound region: LUB({}, {})",
                         a.repr(self.tcx),
-                        b.repr(self.tcx))[]);
+                        b.repr(self.tcx)));
           }
 
           (ReStatic, _) | (_, ReStatic) => {
@@ -750,7 +750,7 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
                 &format!("lub_concrete_regions invoked with \
                          non-concrete regions: {:?}, {:?}",
                         a,
-                        b)[]);
+                        b));
           }
 
           (ReFree(ref fr), ReScope(s_id)) |
@@ -834,7 +834,7 @@ fn glb_concrete_regions(&self,
               self.tcx.sess.bug(
                   &format!("cannot relate bound region: GLB({}, {})",
                           a.repr(self.tcx),
-                          b.repr(self.tcx))[]);
+                          b.repr(self.tcx)));
             }
 
             (ReStatic, r) | (r, ReStatic) => {
@@ -854,7 +854,7 @@ fn glb_concrete_regions(&self,
                     &format!("glb_concrete_regions invoked with \
                              non-concrete regions: {:?}, {:?}",
                             a,
-                            b)[]);
+                            b));
             }
 
             (ReFree(ref fr), ReScope(s_id)) |
@@ -1133,18 +1133,12 @@ fn contract_node(&self,
                 true // changed
             }
 
-            ErrorValue => {
-                false // no change
-            }
+            ErrorValue => false, // no change
 
             Value(a_region) => {
                 match a_data.classification {
-                    Expanding => {
-                        check_node(self, a_vid, a_data, a_region, b_region)
-                    }
-                    Contracting => {
-                        adjust_node(self, a_vid, a_data, a_region, b_region)
-                    }
+                    Expanding => check_node(self, a_vid, a_data, a_region, b_region),
+                    Contracting => adjust_node(self, a_vid, a_data, a_region, b_region),
                 }
             }
         };
@@ -1154,7 +1148,7 @@ fn check_node(this: &RegionVarBindings,
                       a_data: &mut VarData,
                       a_region: Region,
                       b_region: Region)
-                   -> bool {
+                      -> bool {
             if !this.is_subregion_of(a_region, b_region) {
                 debug!("Setting {:?} to ErrorValue: {} not subregion of {}",
                        a_vid,
@@ -1170,7 +1164,7 @@ fn adjust_node(this: &RegionVarBindings,
                        a_data: &mut VarData,
                        a_region: Region,
                        b_region: Region)
-                    -> bool {
+                       -> bool {
             match this.glb_concrete_regions(a_region, b_region) {
                 Ok(glb) => {
                     if glb == a_region {
@@ -1417,7 +1411,7 @@ fn free_regions_first(a: &RegionAndOrigin,
                     for var {:?}, lower_bounds={}, upper_bounds={}",
                     node_idx,
                     lower_bounds.repr(self.tcx),
-                    upper_bounds.repr(self.tcx))[]);
+                    upper_bounds.repr(self.tcx)));
     }
 
     fn collect_error_for_contracting_node(
@@ -1461,7 +1455,7 @@ fn collect_error_for_contracting_node(
             &format!("collect_error_for_contracting_node() could not find error \
                      for var {:?}, upper_bounds={}",
                     node_idx,
-                    upper_bounds.repr(self.tcx))[]);
+                    upper_bounds.repr(self.tcx)));
     }
 
     fn collect_concrete_regions(&self,
index 7bb3106b0ba6ccfa3bfce9fccf199aff5c46e1a6..547696c0c4c2f243b409b6aecdb765b25226409a 100644 (file)
@@ -96,7 +96,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 ty::ty_infer(_) => {
                     self.infcx.tcx.sess.bug(
                         &format!("Unexpected type in full type resolver: {}",
-                                t.repr(self.infcx.tcx))[]);
+                                t.repr(self.infcx.tcx)));
                 }
                 _ => {
                     ty_fold::super_fold_ty(self, t)
index e58136fb3f4e454e18c6269b16ebd57f0dea5642..2ac019aa964dc6f1f0f15c9c4a17e917d8085a13 100644 (file)
@@ -325,7 +325,7 @@ fn variable(&self, node_id: NodeId, span: Span) -> Variable {
             self.tcx
                 .sess
                 .span_bug(span, &format!("no variable registered for id {}",
-                                        node_id)[]);
+                                        node_id));
           }
         }
     }
@@ -445,8 +445,8 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      ast::ExprPath(_) | ast::ExprQPath(_) => {
-        let def = ir.tcx.def_map.borrow()[expr.id].clone();
+      ast::ExprPath(..) => {
+        let def = ir.tcx.def_map.borrow()[expr.id].full_def();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let DefLocal(..) = def {
             ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@@ -585,7 +585,7 @@ fn live_node(&self, node_id: NodeId, span: Span) -> LiveNode {
             self.ir.tcx.sess.span_bug(
                 span,
                 &format!("no live node registered for node {}",
-                        node_id)[]);
+                        node_id));
           }
         }
     }
@@ -705,8 +705,8 @@ fn find_loop_scope(&self,
             Some(_) => {
                 // Refers to a labeled loop. Use the results of resolve
                 // to find with one
-                match self.ir.tcx.def_map.borrow().get(&id) {
-                    Some(&DefLabel(loop_id)) => loop_id,
+                match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
+                    Some(DefLabel(loop_id)) => loop_id,
                     _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
                                                         doesn't refer to a loop")
                 }
@@ -947,7 +947,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
+          ast::ExprPath(..) => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
@@ -1275,7 +1275,7 @@ fn propagate_through_lvalue_components(&mut self,
         // just ignore such cases and treat them as reads.
 
         match expr.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => succ,
+            ast::ExprPath(..) => succ,
             ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
             ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
             _ => self.propagate_through_expr(expr, succ)
@@ -1286,7 +1286,7 @@ fn propagate_through_lvalue_components(&mut self,
     fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                     -> LiveNode {
         match expr.node {
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
+          ast::ExprPath(..) => {
               self.access_path(expr, succ, acc)
           }
 
@@ -1300,7 +1300,7 @@ fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
 
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                    -> LiveNode {
-        match self.ir.tcx.def_map.borrow()[expr.id].clone() {
+        match self.ir.tcx.def_map.borrow()[expr.id].full_def() {
           DefLocal(nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0 {
@@ -1468,7 +1468,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
       ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
       ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
-      ast::ExprRange(..) | ast::ExprQPath(..) => {
+      ast::ExprRange(..) => {
         visit::walk_expr(this, expr);
       }
       ast::ExprIfLet(..) => {
@@ -1561,8 +1561,8 @@ fn check_ret(&self,
 
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
-                if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
+            ast::ExprPath(..) => {
+                if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
index 4be7bb9c365a16d57d846ac70a178dfda6f944ff..c4446b87855ca622d6a5ebd4fcca78f7ca0b9042 100644 (file)
@@ -529,8 +529,8 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
             }
           }
 
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
-            let def = (*self.tcx().def_map.borrow())[expr.id];
+          ast::ExprPath(..) => {
+            let def = self.tcx().def_map.borrow()[expr.id].full_def();
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
 
@@ -575,14 +575,14 @@ pub fn cat_def(&self,
 
         match def {
           def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
-          def::DefFn(..) | def::DefStaticMethod(..) |  def::DefMethod(..) => {
+          def::DefFn(..) | def::DefMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
           def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
-          def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
+          def::DefTyParam(..) | def::DefRegion(_) |
           def::DefLabel(_) | def::DefSelfTy(..) |
-          def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
+          def::DefAssociatedTy(..) => {
               Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
@@ -624,7 +624,7 @@ pub fn cat_def(&self,
                           span,
                           &format!("Upvar of non-closure {} - {}",
                                   fn_node_id,
-                                  ty.repr(self.tcx()))[]);
+                                  ty.repr(self.tcx())));
                   }
               }
           }
@@ -1199,14 +1199,13 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
 
         (*op)(self, cmt.clone(), pat);
 
-        let def_map = self.tcx().def_map.borrow();
-        let opt_def = def_map.get(&pat.id);
+        let opt_def = self.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
 
         // Note: This goes up here (rather than within the PatEnum arm
         // alone) because struct patterns can refer to struct types or
         // to struct variants within enums.
         let cmt = match opt_def {
-            Some(&def::DefVariant(enum_did, variant_did, _))
+            Some(def::DefVariant(enum_did, variant_did, _))
                 // univariant enums do not need downcasts
                 if !ty::enum_is_univariant(self.tcx(), enum_did) => {
                     self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
@@ -1224,7 +1223,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
           }
           ast::PatEnum(_, Some(ref subpats)) => {
             match opt_def {
-                Some(&def::DefVariant(..)) => {
+                Some(def::DefVariant(..)) => {
                     // variant(x, y, z)
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@@ -1237,7 +1236,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
                         try!(self.cat_pattern_(subcmt, &**subpat, op));
                     }
                 }
-                Some(&def::DefStruct(..)) => {
+                Some(def::DefStruct(..)) => {
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
                         let cmt_field =
@@ -1247,7 +1246,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
                         try!(self.cat_pattern_(cmt_field, &**subpat, op));
                     }
                 }
-                Some(&def::DefConst(..)) => {
+                Some(def::DefConst(..)) => {
                     for subpat in subpats {
                         try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
                     }
index 01dc55c3eeec0433b41fe45073e8231cb55cfcb8..c5abff3b96360bceaa9ca8b8d8124e02ad4fb08e 100644 (file)
@@ -34,8 +34,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
         ast::PatEnum(_, _) |
         ast::PatIdent(_, _, None) |
         ast::PatStruct(..) => {
-            match dm.borrow().get(&pat.id) {
-                Some(&DefVariant(..)) => true,
+            match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefVariant(..)) => true,
                 _ => false
             }
         }
@@ -49,8 +49,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
         ast::PatEnum(_, _) |
         ast::PatIdent(_, _, None) |
         ast::PatStruct(..) => {
-            match dm.borrow().get(&pat.id) {
-                Some(&DefVariant(..)) | Some(&DefStruct(..)) => true,
+            match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefVariant(..)) | Some(DefStruct(..)) => true,
                 _ => false
             }
         }
@@ -61,8 +61,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
 pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
     match pat.node {
         ast::PatIdent(_, _, None) | ast::PatEnum(..) => {
-            match dm.borrow().get(&pat.id) {
-                Some(&DefConst(..)) => true,
+            match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) => true,
                 _ => false
             }
         }
@@ -119,6 +119,21 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
     contains_bindings
 }
 
+/// Checks if the pattern contains any patterns that bind something to
+/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
+pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
+    let mut contains_bindings = false;
+    walk_pat(pat, |p| {
+        if pat_is_binding_or_wild(dm, p) {
+            contains_bindings = true;
+            false // there's at least one binding/wildcard, can short circuit now.
+        } else {
+            true
+        }
+    });
+    contains_bindings
+}
+
 pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> {
     match pat.node {
         ast::PatIdent(ast::BindByValue(_), ref path1, None) => {
index dd1e32d13a2be07d512d3d506f159b8387d13f51..3a253735f925b032e93390ce3618f6c4aa4aec87 100644 (file)
@@ -16,7 +16,7 @@
 pub use self::ImportUse::*;
 pub use self::LastPrivate::*;
 
-use util::nodemap::{DefIdSet, NodeMap, NodeSet};
+use util::nodemap::{DefIdSet, NodeSet};
 
 use syntax::ast;
 
@@ -32,9 +32,6 @@
 /// reexporting a public struct doesn't inline the doc).
 pub type PublicItems = NodeSet;
 
-// FIXME: dox
-pub type LastPrivateMap = NodeMap<LastPrivate>;
-
 #[derive(Copy, Debug)]
 pub enum LastPrivate {
     LastMod(PrivateDep),
index 0af226de251a182afe820b6c8ed4fe350b123d78..45d565ec693807f63e74e3887839602091372ecd 100644 (file)
 use syntax::ast;
 use syntax::ast_map;
 use syntax::ast_util::{is_local, PostExpansionMethod};
-use syntax::attr::{InlineAlways, InlineHint, InlineNever, InlineNone};
 use syntax::attr;
 use syntax::visit::Visitor;
 use syntax::visit;
 
-// Returns true if the given set of attributes contains the `#[inline]`
-// attribute.
-fn attributes_specify_inlining(attrs: &[ast::Attribute]) -> bool {
-    match attr::find_inline_attr(attrs) {
-        InlineNone | InlineNever => false,
-        InlineAlways | InlineHint => true,
-    }
-}
-
 // Returns true if the given set of generics implies that the item it's
 // associated with must be inlined.
 fn generics_require_inlining(generics: &ast::Generics) -> bool {
@@ -50,7 +40,7 @@ fn generics_require_inlining(generics: &ast::Generics) -> bool {
 // monomorphized or it was marked with `#[inline]`. This will only return
 // true for functions.
 fn item_might_be_inlined(item: &ast::Item) -> bool {
-    if attributes_specify_inlining(&item.attrs[]) {
+    if attr::requests_inline(&item.attrs) {
         return true
     }
 
@@ -65,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool {
 
 fn method_might_be_inlined(tcx: &ty::ctxt, method: &ast::Method,
                            impl_src: ast::DefId) -> bool {
-    if attributes_specify_inlining(&method.attrs[]) ||
+    if attr::requests_inline(&method.attrs) ||
         generics_require_inlining(method.pe_generics()) {
         return true
     }
@@ -104,9 +94,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &ast::Expr) {
 
         match expr.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
+            ast::ExprPath(..) => {
                 let def = match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def) => def,
+                    Some(d) => d.full_def(),
                     None => {
                         self.tcx.sess.span_bug(expr.span,
                                                "def ID not in def map?!")
@@ -201,8 +191,7 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
                 match *impl_item {
                     ast::MethodImplItem(ref method) => {
                         if generics_require_inlining(method.pe_generics()) ||
-                                attributes_specify_inlining(
-                                    &method.attrs[]) {
+                                attr::requests_inline(&method.attrs) {
                             true
                         } else {
                             let impl_did = self.tcx
@@ -249,7 +238,7 @@ fn propagate(&mut self) {
                 None => {
                     self.tcx.sess.bug(&format!("found unmapped ID in worklist: \
                                                {}",
-                                              search_item)[])
+                                              search_item))
                 }
             }
         }
@@ -301,7 +290,8 @@ fn propagate_node(&mut self, node: &ast_map::Node,
                     ast::ItemTy(..) | ast::ItemStatic(_, _, _) |
                     ast::ItemMod(..) | ast::ItemForeignMod(..) |
                     ast::ItemImpl(..) | ast::ItemTrait(..) |
-                    ast::ItemStruct(..) | ast::ItemEnum(..) => {}
+                    ast::ItemStruct(..) | ast::ItemEnum(..) |
+                    ast::ItemDefaultImpl(..) => {}
 
                     _ => {
                         self.tcx.sess.span_bug(item.span,
@@ -342,7 +332,7 @@ fn propagate_node(&mut self, node: &ast_map::Node,
                     .bug(&format!("found unexpected thingy in worklist: {}",
                                  self.tcx
                                      .map
-                                     .node_to_string(search_item))[])
+                                     .node_to_string(search_item)))
             }
         }
     }
index e539f6ae6cb9382898b2167093e91fe5b288e3db..7db1138ac72f6e58a168ce6ca3fb08719141208b 100644 (file)
@@ -852,7 +852,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &ast::Expr) {
                 // The idea is that call.callee_id represents *the time when
                 // the invoked function is actually running* and call.id
                 // represents *the time to prepare the arguments and make the
-                // call*.  See the section "Borrows in Calls" borrowck/doc.rs
+                // call*.  See the section "Borrows in Calls" borrowck/README.md
                 // for an extended explanation of why this distinction is
                 // important.
                 //
index 3ba08c1032031075224aaa0dddcd1ac67902f5d4..a8a2887644a9da40a237e472e9f0e5a66985f4e4 100644 (file)
@@ -115,6 +115,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                 ast::ItemUse(_) |
                 ast::ItemMod(..) |
                 ast::ItemMac(..) |
+                ast::ItemDefaultImpl(..) |
                 ast::ItemForeignMod(..) |
                 ast::ItemStatic(..) |
                 ast::ItemConst(..) => {
@@ -164,13 +165,13 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
                     visit::walk_ty(this, ty);
                 });
             }
-            ast::TyPath(ref path, id) => {
+            ast::TyPath(None, ref path) => {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
-                match self.def_map.borrow().get(&id) {
-                    Some(&def::DefTrait(..)) => {
+                match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) {
+                    Some((def::DefTrait(..), 0)) => {
                         self.with(LateScope(&Vec::new(), self.scope), |_, this| {
-                            this.visit_path(path, id);
+                            this.visit_path(path, ty.id);
                         });
                     }
                     _ => {
@@ -269,16 +270,12 @@ fn visit_poly_trait_ref(&mut self,
                 for lifetime in &trait_ref.bound_lifetimes {
                     this.visit_lifetime_def(lifetime);
                 }
-                this.visit_trait_ref(&trait_ref.trait_ref)
+                visit::walk_path(this, &trait_ref.trait_ref.path)
             })
         } else {
             self.visit_trait_ref(&trait_ref.trait_ref)
         }
     }
-
-    fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
-        self.visit_path(&trait_ref.path, trait_ref.ref_id);
-    }
 }
 
 impl<'a> LifetimeContext<'a> {
index 0a0f555f977698e7581c1435489bc5bd9dfa6781..f67e470ee54917a1a2f9105fca63a5c50c5a877a 100644 (file)
@@ -181,7 +181,7 @@ pub fn build(&mut self, sess: &Session, krate: &Crate, export_map: &PublicItems)
     pub fn new(krate: &Crate) -> Index {
         let mut staged_api = false;
         for attr in &krate.attrs {
-            if &attr.name()[] == "staged_api" {
+            if &attr.name()[..] == "staged_api" {
                 match attr.node.value.node {
                     ast::MetaWord(_) => {
                         attr::mark_used(attr);
@@ -393,12 +393,14 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
 
 pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
                   cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
-    let did = match tcx.def_map.borrow().get(&id) {
-        Some(&def::DefPrimTy(..)) => return,
-        Some(def) => def.def_id(),
-        None => return
-    };
-    maybe_do_stability_check(tcx, did, path.span, cb)
+    match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
+        Some(def::DefPrimTy(..)) => {}
+        Some(def) => {
+            maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
+        }
+        None => {}
+    }
+
 }
 
 fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
index 04fd03ab34224a3af51bfeed5ab69aad2c355bf4..684b28d03739e3fe28b84a524b120e4b48a32d3a 100644 (file)
@@ -639,7 +639,7 @@ fn fold_region(&mut self, r: ty::Region) -> ty::Region {
                                      (space={:?}, index={})",
                                     region_name.as_str(),
                                     self.root_ty.repr(self.tcx()),
-                                    space, i)[]);
+                                    space, i));
                             }
                         }
                 }
@@ -696,7 +696,7 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
                             p.space,
                             p.idx,
                             self.root_ty.repr(self.tcx()),
-                            self.substs.repr(self.tcx()))[]);
+                            self.substs.repr(self.tcx())));
             }
         };
 
index e199a60c370e30cf732f0dbb2d3a300f9276e3f8..62b81f0ebe7dba8b98e7d4368d755f4aba55da64 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! See `doc.rs` for high-level documentation
+//! See `README.md` for high-level documentation
 
 use super::Normalized;
 use super::SelectionContext;
@@ -52,9 +52,16 @@ fn overlap(selcx: &mut SelectionContext,
            b_def_id: ast::DefId)
            -> bool
 {
+    debug!("overlap(a_def_id={}, b_def_id={})",
+           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);
 
+    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.
     if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(),
                                                   true,
@@ -64,10 +71,20 @@ fn overlap(selcx: &mut SelectionContext,
         return false;
     }
 
+    debug!("overlap: subtraitref check succeeded");
+
     // Are any of the obligations unsatisfiable? If so, no overlap.
-    a_obligations.iter()
-                 .chain(b_obligations.iter())
-                 .all(|o| selcx.evaluate_obligation(o))
+    let opt_failing_obligation =
+        a_obligations.iter()
+                     .chain(b_obligations.iter())
+                     .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;
+    }
+
+    true
 }
 
 /// Instantiate fresh variables for all bound parameters of the impl
@@ -194,11 +211,10 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
 
         ty::ty_closure(..) |
         ty::ty_infer(..) |
-        ty::ty_open(..) |
         ty::ty_err => {
             tcx.sess.bug(
                 &format!("ty_is_local invoked on unexpected type: {}",
-                        ty.repr(tcx))[])
+                        ty.repr(tcx)))
         }
     }
 }
index 2197cbeb85db4afb7ead1629b4cc500a468ea140..d2b5b460d142002b174a88910a9972944f3f7316 100644 (file)
@@ -422,5 +422,5 @@ pub fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) {
         span,
         &format!(
             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
-            suggested_limit)[]);
+            suggested_limit));
 }
index a9cac4be3e368026e319a32b890df4a6f36263fb..c1066aa899eaea4fe4f7e34ea89b319a443c4e8f 100644 (file)
@@ -227,7 +227,7 @@ pub fn select_where_possible<'a>(&mut self,
     }
 
     pub fn pending_obligations(&self) -> &[PredicateObligation<'tcx>] {
-        &self.predicates[]
+        &self.predicates
     }
 
     /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
index a63dcfc24a10ec6d76314be312d3e0d81a671433..5a5639c701291f54716eba3b701e76f8bc825786 100644 (file)
@@ -18,7 +18,7 @@
 use middle::subst;
 use middle::ty::{self, HasProjectionTypes, Ty};
 use middle::ty_fold::TypeFoldable;
-use middle::infer::{self, InferCtxt};
+use middle::infer::{self, fixup_err_to_string, InferCtxt};
 use std::slice::Iter;
 use std::rc::Rc;
 use syntax::ast;
@@ -221,6 +221,12 @@ pub enum Vtable<'tcx, N> {
     /// Vtable identifying a particular impl.
     VtableImpl(VtableImplData<'tcx, N>),
 
+    /// Vtable for default trait implementations
+    /// This carries the information and nested obligations with regards
+    /// to a default implementation for a trait `Trait`. The nested obligations
+    /// ensure the trait implementation holds for all the constituent types.
+    VtableDefaultImpl(VtableDefaultImplData<N>),
+
     /// Successful resolution to an obligation provided by the caller
     /// for some type parameter. The `Vec<N>` represents the
     /// obligations incurred from normalizing the where-clause (if
@@ -259,6 +265,12 @@ pub struct VtableImplData<'tcx, N> {
     pub nested: subst::VecPerParamSpace<N>
 }
 
+#[derive(Debug,Clone)]
+pub struct VtableDefaultImplData<N> {
+    pub trait_def_id: ast::DefId,
+    pub nested: Vec<N>
+}
+
 #[derive(Debug,Clone)]
 pub struct VtableBuiltinData<N> {
     pub nested: subst::VecPerParamSpace<N>
@@ -383,53 +395,64 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     }
 }
 
+/// Normalizes the parameter environment, reporting errors if they occur.
 pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>,
                                              cause: ObligationCause<'tcx>)
                                              -> ty::ParameterEnvironment<'a,'tcx>
 {
-    match normalize_param_env(&unnormalized_env, cause) {
-        Ok(p) => p,
+    // I'm not wild about reporting errors here; I'd prefer to
+    // have the errors get reported at a defined place (e.g.,
+    // during typeck). Instead I have all parameter
+    // environments, in effect, going through this function
+    // and hence potentially reporting errors. This ensurse of
+    // course that we never forget to normalize (the
+    // alternative seemed like it would involve a lot of
+    // manual invocations of this fn -- and then we'd have to
+    // deal with the errors at each of those sites).
+    //
+    // In any case, in practice, typeck constructs all the
+    // parameter environments once for every fn as it goes,
+    // and errors will get reported then; so after typeck we
+    // can be sure that no errors should occur.
+
+    let tcx = unnormalized_env.tcx;
+    let span = cause.span;
+    let body_id = cause.body_id;
+
+    debug!("normalize_param_env_or_error(unnormalized_env={})",
+           unnormalized_env.repr(tcx));
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
+                                           &unnormalized_env.caller_bounds) {
+        Ok(predicates) => predicates,
         Err(errors) => {
-            // I'm not wild about reporting errors here; I'd prefer to
-            // have the errors get reported at a defined place (e.g.,
-            // during typeck). Instead I have all parameter
-            // environments, in effect, going through this function
-            // and hence potentially reporting errors. This ensurse of
-            // course that we never forget to normalize (the
-            // alternative seemed like it would involve a lot of
-            // manual invocations of this fn -- and then we'd have to
-            // deal with the errors at each of those sites).
-            //
-            // In any case, in practice, typeck constructs all the
-            // parameter environments once for every fn as it goes,
-            // and errors will get reported then; so after typeck we
-            // can be sure that no errors should occur.
-            let infcx = infer::new_infer_ctxt(unnormalized_env.tcx);
             report_fulfillment_errors(&infcx, &errors);
-
-            // Normalized failed? use what they gave us, it's better than nothing.
-            unnormalized_env
+            return unnormalized_env; // an unnormalized env is better than nothing
         }
-    }
-}
-
-pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
-                                    cause: ObligationCause<'tcx>)
-                                    -> Result<ty::ParameterEnvironment<'a,'tcx>,
-                                              Vec<FulfillmentError<'tcx>>>
-{
-    let tcx = param_env.tcx;
-
-    debug!("normalize_param_env(param_env={})",
-           param_env.repr(tcx));
+    };
 
-    let infcx = infer::new_infer_ctxt(tcx);
-    let predicates = try!(fully_normalize(&infcx, param_env, cause, &param_env.caller_bounds));
+    infcx.resolve_regions_and_report_errors(body_id);
+    let predicates = match infcx.fully_resolve(&predicates) {
+        Ok(predicates) => predicates,
+        Err(fixup_err) => {
+            // If we encounter a fixup error, it means that some type
+            // variable wound up unconstrained. I actually don't know
+            // if this can happen, and I certainly don't expect it to
+            // happen often, but if it did happen it probably
+            // represents a legitimate failure due to some kind of
+            // unconstrained variable, and it seems better not to ICE,
+            // all things considered.
+            let err_msg = fixup_err_to_string(fixup_err);
+            tcx.sess.span_err(span, &err_msg);
+            return unnormalized_env; // an unnormalized env is better than nothing
+        }
+    };
 
-    debug!("normalize_param_env: predicates={}",
+    debug!("normalize_param_env_or_error: predicates={}",
            predicates.repr(tcx));
 
-    Ok(param_env.with_caller_bounds(predicates))
+    unnormalized_env.with_caller_bounds(predicates)
 }
 
 pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
@@ -441,8 +464,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
 {
     let tcx = closure_typer.tcx();
 
-    debug!("normalize_param_env(value={})",
-           value.repr(tcx));
+    debug!("normalize_param_env(value={})", value.repr(tcx));
 
     let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
     let mut fulfill_cx = FulfillmentContext::new();
@@ -456,8 +478,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     }
     try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
     let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
-    debug!("normalize_param_env: resolved_value={}",
-           resolved_value.repr(tcx));
+    debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx));
     Ok(resolved_value)
 }
 
@@ -513,17 +534,18 @@ impl<'tcx, N> Vtable<'tcx, N> {
     pub fn iter_nested(&self) -> Iter<N> {
         match *self {
             VtableImpl(ref i) => i.iter_nested(),
-            VtableFnPointer(..) => (&[]).iter(),
-            VtableClosure(..) => (&[]).iter(),
             VtableParam(ref n) => n.iter(),
-            VtableObject(_) => (&[]).iter(),
             VtableBuiltin(ref i) => i.iter_nested(),
+            VtableObject(_) |
+            VtableDefaultImpl(..) | VtableFnPointer(..) |
+            VtableClosure(..) => (&[]).iter(),
         }
     }
 
     pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M {
         match *self {
             VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
+            VtableDefaultImpl(ref t) => VtableDefaultImpl(t.map_nested(op)),
             VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
             VtableClosure(d, ref s) => VtableClosure(d, s.clone()),
             VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
@@ -539,6 +561,7 @@ pub fn map_move_nested<M, F>(self, op: F) -> Vtable<'tcx, M> where
             VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
             VtableFnPointer(sig) => VtableFnPointer(sig),
             VtableClosure(d, s) => VtableClosure(d, s),
+            VtableDefaultImpl(t) => VtableDefaultImpl(t.map_move_nested(op)),
             VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
             VtableObject(p) => VtableObject(p),
             VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
@@ -573,6 +596,31 @@ pub fn map_move_nested<M, F>(self, op: F) -> VtableImplData<'tcx, M> where
     }
 }
 
+impl<N> VtableDefaultImplData<N> {
+    pub fn iter_nested(&self) -> Iter<N> {
+        self.nested.iter()
+    }
+
+    pub fn map_nested<M, F>(&self, op: F) -> VtableDefaultImplData<M> where
+        F: FnMut(&N) -> M,
+    {
+        VtableDefaultImplData {
+            trait_def_id: self.trait_def_id,
+            nested: self.nested.iter().map(op).collect()
+        }
+    }
+
+    pub fn map_move_nested<M, F>(self, op: F) -> VtableDefaultImplData<M> where
+        F: FnMut(N) -> M,
+    {
+        let VtableDefaultImplData { trait_def_id, nested } = self;
+        VtableDefaultImplData {
+            trait_def_id: trait_def_id,
+            nested: nested.into_iter().map(op).collect()
+        }
+    }
+}
+
 impl<N> VtableBuiltinData<N> {
     pub fn iter_nested(&self) -> Iter<N> {
         self.nested.iter()
index f10f7eb3951c7a0468a3a5e86367e9d4c024060f..64835a666faef46d6fe23c518d88108d5dbe7663 100644 (file)
@@ -42,9 +42,6 @@ pub enum ObjectSafetyViolation<'tcx> {
 /// Reasons a method might not be object-safe.
 #[derive(Copy,Clone,Debug)]
 pub enum MethodViolationCode {
-    /// e.g., `fn(self)`
-    ByValueSelf,
-
     /// e.g., `fn foo()`
     StaticMethod,
 
@@ -157,6 +154,16 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                               trait_def_id: ast::DefId)
                               -> bool
+{
+    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+    let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
+    generics_require_sized_self(tcx, &trait_def.generics, &trait_predicates)
+}
+
+fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                     generics: &ty::Generics<'tcx>,
+                                     predicates: &ty::GenericPredicates<'tcx>)
+                                     -> bool
 {
     let sized_def_id = match tcx.lang_items.sized_trait() {
         Some(def_id) => def_id,
@@ -164,12 +171,8 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
     };
 
     // Search for a predicate like `Self : Sized` amongst the trait bounds.
-    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
-    let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID);
-
-    let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
-    let predicates = trait_predicates.instantiate(tcx, &free_substs).predicates.into_vec();
-
+    let free_substs = ty::construct_free_substs(tcx, generics, ast::DUMMY_NODE_ID);
+    let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec();
     elaborate_predicates(tcx, predicates)
         .any(|predicate| {
             match predicate {
@@ -192,17 +195,21 @@ fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                              method: &ty::Method<'tcx>)
                                              -> Option<MethodViolationCode>
 {
-    // The method's first parameter must be something that derefs to
-    // `&self`. For now, we only accept `&self` and `Box<Self>`.
-    match method.explicit_self {
-        ty::ByValueExplicitSelfCategory => {
-            return Some(MethodViolationCode::ByValueSelf);
-        }
+    // Any method that has a `Self : Sized` requisite is otherwise
+    // exempt from the regulations.
+    if generics_require_sized_self(tcx, &method.generics, &method.predicates) {
+        return None;
+    }
 
+    // The method's first parameter must be something that derefs (or
+    // autorefs) to `&self`. For now, we only accept `self`, `&self`
+    // and `Box<Self>`.
+    match method.explicit_self {
         ty::StaticExplicitSelfCategory => {
             return Some(MethodViolationCode::StaticMethod);
         }
 
+        ty::ByValueExplicitSelfCategory |
         ty::ByReferenceExplicitSelfCategory(..) |
         ty::ByBoxExplicitSelfCategory => {
         }
index 13f309e129ac9c9a63bd613cd9a5235211323bec..7d4febb38e678186ff6b5380f55e53ec20bb1a2c 100644 (file)
@@ -709,6 +709,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
             // projection. And the projection where clause is handled
             // in `assemble_candidates_from_param_env`.
         }
+        super::VtableDefaultImpl(..) |
         super::VtableBuiltin(..) => {
             // These traits have no associated types.
             selcx.tcx().sess.span_bug(
index 0e29892084175d180047412a39c9a2e936c750a7..9ec89f55b8f329cd61ae5715580cb65aed420893 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! See `doc.rs` for high-level documentation
+//! See `README.md` for high-level documentation
 #![allow(dead_code)] // FIXME -- just temporarily
 
 pub use self::MethodMatchResult::*;
 use self::BuiltinBoundConditions::*;
 use self::EvaluationResult::*;
 
-use super::{DerivedObligationCause};
-use super::{project};
-use super::project::Normalized;
+use super::DerivedObligationCause;
+use super::project;
+use super::project::{normalize_with_depth, Normalized};
 use super::{PredicateObligation, TraitObligation, ObligationCause};
-use super::{ObligationCauseCode, BuiltinDerivedObligation};
+use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
 use super::{SelectionError, Unimplemented, Overflow, OutputTypeParameterMismatch};
 use super::{Selection};
 use super::{SelectionResult};
 use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
-            VtableFnPointer, VtableObject};
-use super::{VtableImplData, VtableObjectData, VtableBuiltinData};
+            VtableFnPointer, VtableObject, VtableDefaultImpl};
+use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableDefaultImplData};
 use super::object_safety;
 use super::{util};
 
@@ -136,6 +136,7 @@ enum SelectionCandidate<'tcx> {
     BuiltinCandidate(ty::BuiltinBound),
     ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(ast::DefId),
+    DefaultImplCandidate(ast::DefId),
 
     /// This is a trait matching with a projected type as `Self`, and
     /// we found an applicable bound in the trait definition.
@@ -151,6 +152,8 @@ enum SelectionCandidate<'tcx> {
 
     ObjectCandidate,
 
+    BuiltinObjectCandidate,
+
     ErrorCandidate,
 }
 
@@ -547,7 +550,8 @@ pub fn evaluate_impl(&mut self,
     //
     // The selection process begins by examining all in-scope impls,
     // caller obligations, and so forth and assembling a list of
-    // candidates. See `doc.rs` and the `Candidate` type for more details.
+    // candidates. See `README.md` and the `Candidate` type for more
+    // details.
 
     fn candidate_from_obligation<'o>(&mut self,
                                      stack: &TraitObligationStack<'o, 'tcx>)
@@ -817,31 +821,24 @@ fn assemble_candidates<'o>(&mut self,
                 debug!("obligation self ty is {}",
                        obligation.predicate.0.self_ty().repr(self.tcx()));
 
+                // User-defined copy impls are permitted, but only for
+                // structs and enums.
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
 
+                // For other types, we'll use the builtin rules.
                 try!(self.assemble_builtin_bound_candidates(ty::BoundCopy,
                                                             stack,
                                                             &mut candidates));
             }
-            Some(bound @ ty::BoundSend) |
-            Some(bound @ ty::BoundSync) => {
-                try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
-
-                // No explicit impls were declared for this type, consider the fallback rules.
-                if candidates.vec.is_empty() && !candidates.ambiguous {
-                    try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
-                }
-            }
-
             Some(bound @ ty::BoundSized) => {
-                // Sized and Copy are always automatically computed.
+                // Sized is never implementable by end-users, it is
+                // always automatically computed.
                 try!(self.assemble_builtin_bound_candidates(bound, stack, &mut candidates));
             }
 
+            Some(ty::BoundSend) |
+            Some(ty::BoundSync) |
             None => {
-                // For the time being, we ignore user-defined impls for builtin-bounds, other than
-                // `Copy`.
-                // (And unboxed candidates only apply to the Fn/FnMut/etc traits.)
                 try!(self.assemble_closure_candidates(obligation, &mut candidates));
                 try!(self.assemble_fn_pointer_candidates(obligation, &mut candidates));
                 try!(self.assemble_candidates_from_impls(obligation, &mut candidates));
@@ -851,6 +848,11 @@ fn assemble_candidates<'o>(&mut self,
 
         self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
         try!(self.assemble_candidates_from_caller_bounds(stack, &mut candidates));
+        // Default implementations have lower priority, so we only
+        // consider triggering a default if there is no other impl that can apply.
+        if candidates.vec.len() == 0 {
+            try!(self.assemble_candidates_from_default_impls(obligation, &mut candidates));
+        }
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
     }
@@ -1130,7 +1132,8 @@ fn assemble_candidates_from_impls(&mut self,
         let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
         debug!("assemble_candidates_from_impls(self_ty={})", self_ty.repr(self.tcx()));
 
-        let all_impls = self.all_impls(obligation.predicate.def_id());
+        let def_id = obligation.predicate.def_id();
+        let all_impls = self.all_impls(def_id);
         for &impl_def_id in &all_impls {
             self.infcx.probe(|snapshot| {
                 let (skol_obligation_trait_pred, skol_map) =
@@ -1144,6 +1147,65 @@ fn assemble_candidates_from_impls(&mut self,
                 }
             });
         }
+
+        Ok(())
+    }
+
+    fn assemble_candidates_from_default_impls(&mut self,
+                                              obligation: &TraitObligation<'tcx>,
+                                              candidates: &mut SelectionCandidateSet<'tcx>)
+                                              -> Result<(), SelectionError<'tcx>>
+    {
+
+        let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
+        debug!("assemble_candidates_from_default_impls(self_ty={})", self_ty.repr(self.tcx()));
+
+        let def_id = obligation.predicate.def_id();
+
+        if ty::trait_has_default_impl(self.tcx(), def_id) {
+            match self_ty.sty {
+                ty::ty_trait(..) |
+                ty::ty_param(..) |
+                ty::ty_projection(..) => {
+                    // In these cases, we don't know what the actual
+                    // type is.  Therefore, we cannot break it down
+                    // into its constituent types. So we don't
+                    // consider the `..` impl but instead just add no
+                    // candidates: this means that typeck will only
+                    // succeed if there is another reason to believe
+                    // that this obligation holds. That could be a
+                    // where-clause or, in the case of an object type,
+                    // it could be that the object type lists the
+                    // trait (e.g. `Foo+Send : Send`). See
+                    // `compile-fail/typeck-default-trait-impl-send-param.rs`
+                    // for an example of a test case that exercises
+                    // this path.
+                }
+                ty::ty_infer(ty::TyVar(_)) => {
+                    // the defaulted impl might apply, we don't know
+                    candidates.ambiguous = true;
+                }
+                _ => {
+                    if self.constituent_types_for_ty(self_ty).is_some() {
+                        candidates.vec.push(DefaultImplCandidate(def_id.clone()))
+                    } else {
+                        // We don't yet know what the constituent
+                        // types are. So call it ambiguous for now,
+                        // though this is a bit stronger than
+                        // necessary: that is, we know that the
+                        // defaulted impl applies, but we can't
+                        // process the confirmation step without
+                        // knowing the constituent types. (Anyway, in
+                        // the particular case of defaulted impls, it
+                        // doesn't really matter much either way,
+                        // since we won't be aiding inference by
+                        // processing the confirmation step.)
+                        candidates.ambiguous = true;
+                    }
+                }
+            }
+        }
+
         Ok(())
     }
 
@@ -1170,6 +1232,18 @@ fn assemble_candidates_from_object_ty(&mut self,
 
         let poly_trait_ref = match self_ty.sty {
             ty::ty_trait(ref data) => {
+                match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) {
+                    Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => {
+                        if data.bounds.builtin_bounds.contains(&bound) {
+                            debug!("assemble_candidates_from_object_ty: matched builtin bound, \
+                            pushing candidate");
+                            candidates.vec.push(BuiltinObjectCandidate);
+                            return;
+                        }
+                    }
+                    _ => {}
+                }
+
                 data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
             }
             ty::ty_infer(ty::TyVar(_)) => {
@@ -1257,6 +1331,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
             (&ImplCandidate(..), &ParamCandidate(..)) |
             (&ClosureCandidate(..), &ParamCandidate(..)) |
             (&FnPointerCandidate(..), &ParamCandidate(..)) |
+            (&BuiltinObjectCandidate(..), &ParamCandidate(_)) |
             (&BuiltinCandidate(..), &ParamCandidate(..)) => {
                 // We basically prefer always prefer to use a
                 // where-clause over another option. Where clauses
@@ -1266,6 +1341,12 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
                 // #18453.
                 true
             }
+            (&DefaultImplCandidate(_), _) => {
+                // Prefer other candidates over default implementations.
+                self.tcx().sess.bug(
+                    "default implementations shouldn't be recorded \
+                     when there are other valid candidates");
+            }
             (&ProjectionCandidate, &ParamCandidate(_)) => {
                 // FIXME(#20297) -- this gives where clauses precedent
                 // over projections. Really these are just two means
@@ -1328,56 +1409,44 @@ fn builtin_bound(&mut self,
 
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
         return match self_ty.sty {
-            ty::ty_infer(ty::IntVar(_)) |
-            ty::ty_infer(ty::FloatVar(_)) |
-            ty::ty_uint(_) |
-            ty::ty_int(_) |
-            ty::ty_bool |
-            ty::ty_float(_) |
-            ty::ty_bare_fn(..) |
-            ty::ty_char => {
+            ty::ty_infer(ty::IntVar(_))
+            | ty::ty_infer(ty::FloatVar(_))
+            | ty::ty_uint(_)
+            | ty::ty_int(_)
+            | ty::ty_bool
+            | ty::ty_float(_)
+            | ty::ty_bare_fn(..)
+            ty::ty_char => {
                 // safe for everything
                 Ok(If(Vec::new()))
             }
 
-            ty::ty_uniq(referent_ty) => {  // Box<T>
+            ty::ty_uniq(_) => {  // Box<T>
                 match bound {
-                    ty::BoundCopy => {
-                        Err(Unimplemented)
-                    }
+                    ty::BoundCopy => Err(Unimplemented),
 
-                    ty::BoundSized => {
-                        Ok(If(Vec::new()))
-                    }
+                    ty::BoundSized => Ok(If(Vec::new())),
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec![referent_ty]))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
 
             ty::ty_ptr(..) => {     // *const T, *mut T
                 match bound {
-                    ty::BoundCopy |
-                    ty::BoundSized => {
-                        Ok(If(Vec::new()))
-                    }
+                    ty::BoundCopy | ty::BoundSized => Ok(If(Vec::new())),
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        // sync and send are not implemented for *const, *mut
-                        Err(Unimplemented)
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
 
             ty::ty_trait(ref data) => {
                 match bound {
-                    ty::BoundSized => {
-                        Err(Unimplemented)
-                    }
-                    ty::BoundCopy | ty::BoundSync | ty::BoundSend => {
+                    ty::BoundSized => Err(Unimplemented),
+                    ty::BoundCopy => {
                         if data.bounds.builtin_bounds.contains(&bound) {
                             Ok(If(Vec::new()))
                         } else {
@@ -1396,33 +1465,29 @@ fn builtin_bound(&mut self,
                             Err(Unimplemented)
                         }
                     }
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                    }
                 }
             }
 
-            ty::ty_rptr(_, ty::mt { ty: referent_ty, mutbl }) => {
+            ty::ty_rptr(_, ty::mt { ty: _, mutbl }) => {
                 // &mut T or &T
                 match bound {
                     ty::BoundCopy => {
                         match mutbl {
                             // &mut T is affine and hence never `Copy`
-                            ast::MutMutable => {
-                                Err(Unimplemented)
-                            }
+                            ast::MutMutable => Err(Unimplemented),
 
                             // &T is always copyable
-                            ast::MutImmutable => {
-                                Ok(If(Vec::new()))
-                            }
+                            ast::MutImmutable => Ok(If(Vec::new())),
                         }
                     }
 
-                    ty::BoundSized => {
-                        Ok(If(Vec::new()))
-                    }
+                    ty::BoundSized => Ok(If(Vec::new())),
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec![referent_ty]))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1432,14 +1497,11 @@ fn builtin_bound(&mut self,
                 match bound {
                     ty::BoundCopy => {
                         match *len {
-                            Some(_) => {
-                                // [T, ..n] is copy iff T is copy
-                                Ok(If(vec![element_ty]))
-                            }
-                            None => {
-                                // [T] is unsized and hence affine
-                                Err(Unimplemented)
-                            }
+                            // [T, ..n] is copy iff T is copy
+                            Some(_) => Ok(If(vec![element_ty])),
+
+                            // [T] is unsized and hence affine
+                            None => Err(Unimplemented),
                         }
                     }
 
@@ -1451,9 +1513,8 @@ fn builtin_bound(&mut self,
                         }
                     }
 
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec![element_ty]))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1461,22 +1522,16 @@ fn builtin_bound(&mut self,
             ty::ty_str => {
                 // Equivalent to [u8]
                 match bound {
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(Vec::new()))
+                    ty::BoundSync | ty::BoundSend => {
+                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
 
-                    ty::BoundCopy |
-                    ty::BoundSized => {
-                        Err(Unimplemented)
-                    }
+                    ty::BoundCopy | ty::BoundSized => Err(Unimplemented),
                 }
             }
 
-            ty::ty_tup(ref tys) => {
-                // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-                Ok(If(tys.clone()))
-            }
+            // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
+            ty::ty_tup(ref tys) => Ok(If(tys.clone())),
 
             ty::ty_closure(def_id, _, substs) => {
                 // FIXME -- This case is tricky. In the case of by-ref
@@ -1505,9 +1560,7 @@ fn builtin_bound(&mut self,
                 }
 
                 match self.closure_typer.closure_upvars(def_id, substs) {
-                    Some(upvars) => {
-                        Ok(If(upvars.iter().map(|c| c.ty).collect()))
-                    }
+                    Some(upvars) => Ok(If(upvars.iter().map(|c| c.ty).collect())),
                     None => {
                         debug!("assemble_builtin_bound_candidates: no upvar types available yet");
                         Ok(AmbiguousBuiltin)
@@ -1520,7 +1573,7 @@ fn builtin_bound(&mut self,
                     ty::struct_fields(self.tcx(), def_id, substs).iter()
                                                                  .map(|f| f.mt.ty)
                                                                  .collect();
-                nominal(self, bound, def_id, types)
+                nominal(bound, types)
             }
 
             ty::ty_enum(def_id, substs) => {
@@ -1530,11 +1583,10 @@ fn builtin_bound(&mut self,
                     .flat_map(|variant| variant.args.iter())
                     .cloned()
                     .collect();
-                nominal(self, bound, def_id, types)
+                nominal(bound, types)
             }
 
-            ty::ty_projection(_) |
-            ty::ty_param(_) => {
+            ty::ty_projection(_) | ty::ty_param(_) => {
                 // Note: A type parameter is only considered to meet a
                 // particular bound if there is a where clause telling
                 // us that it does, and that case is handled by
@@ -1550,67 +1602,117 @@ fn builtin_bound(&mut self,
                 Ok(AmbiguousBuiltin)
             }
 
-            ty::ty_open(ty) => {
-                // these only crop up in trans, and represent an
-                // "opened" unsized/existential type (one that has
-                // been dereferenced)
-                match bound {
-                    ty::BoundCopy |
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        Ok(If(vec!(ty)))
-                    }
-
-                    ty::BoundSized => {
-                        Err(Unimplemented)
-                    }
-                }
-            }
-            ty::ty_err => {
-                Ok(If(Vec::new()))
-            }
+            ty::ty_err => Ok(If(Vec::new())),
 
-            ty::ty_infer(ty::FreshTy(_)) |
-            ty::ty_infer(ty::FreshIntTy(_)) => {
+            ty::ty_infer(ty::FreshTy(_))
+            ty::ty_infer(ty::FreshIntTy(_)) => {
                 self.tcx().sess.bug(
                     &format!(
                         "asked to assemble builtin bounds of unexpected type: {}",
-                        self_ty.repr(self.tcx()))[]);
+                        self_ty.repr(self.tcx())));
             }
         };
 
-        fn nominal<'cx, 'tcx>(this: &mut SelectionContext<'cx, 'tcx>,
-                              bound: ty::BuiltinBound,
-                              def_id: ast::DefId,
+        fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound,
                               types: Vec<Ty<'tcx>>)
-                              -> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
+                              -> Result<BuiltinBoundConditions<'tcx>, SelectionError<'tcx>>
         {
             // First check for markers and other nonsense.
-            let tcx = this.tcx();
             match bound {
-                ty::BoundSend => {
-                    if Some(def_id) == tcx.lang_items.managed_bound() {
-                        return Err(Unimplemented)
-                    }
-                }
+                // Fallback to whatever user-defined impls exist in this case.
+                ty::BoundCopy => Ok(ParameterBuiltin),
 
-                ty::BoundCopy => {
-                    return Ok(ParameterBuiltin)
-                }
+                // Sized if all the component types are sized.
+                ty::BoundSized => Ok(If(types)),
+
+                // Shouldn't be coming through here.
+                ty::BoundSend | ty::BoundSync => unreachable!(),
+            }
+        }
+    }
+
+    /// For default impls, we need to break apart a type into its
+    /// "constituent types" -- meaning, the types that it contains.
+    ///
+    /// Here are some (simple) examples:
+    ///
+    /// ```
+    /// (i32, u32) -> [i32, u32]
+    /// Foo where struct Foo { x: i32, y: u32 } -> [i32, u32]
+    /// Bar<i32> where struct Bar<T> { x: T, y: u32 } -> [i32, u32]
+    /// Zed<i32> where enum Zed { A(T), B(u32) } -> [i32, u32]
+    /// ```
+    fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
+        match t.sty {
+            ty::ty_uint(_) |
+            ty::ty_int(_) |
+            ty::ty_bool |
+            ty::ty_float(_) |
+            ty::ty_bare_fn(..) |
+            ty::ty_str |
+            ty::ty_err |
+            ty::ty_infer(ty::IntVar(_)) |
+            ty::ty_infer(ty::FloatVar(_)) |
+            ty::ty_char => {
+                Some(Vec::new())
+            }
+
+            ty::ty_trait(..) |
+            ty::ty_param(..) |
+            ty::ty_projection(..) |
+            ty::ty_infer(ty::TyVar(_)) |
+            ty::ty_infer(ty::FreshTy(_)) |
+            ty::ty_infer(ty::FreshIntTy(_)) => {
+                self.tcx().sess.bug(
+                    &format!(
+                        "asked to assemble constituent types of unexpected type: {}",
+                        t.repr(self.tcx())));
+            }
 
-                ty::BoundSync => {
-                    if
-                        Some(def_id) == tcx.lang_items.managed_bound() ||
-                        Some(def_id) == tcx.lang_items.unsafe_cell_type()
-                    {
-                        return Err(Unimplemented)
+            ty::ty_uniq(referent_ty) => {  // Box<T>
+                Some(vec![referent_ty])
+            }
+
+            ty::ty_ptr(ty::mt { ty: element_ty, ..}) |
+            ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => {
+                Some(vec![element_ty])
+            },
+
+            ty::ty_vec(element_ty, _) => {
+                Some(vec![element_ty])
+            }
+
+            ty::ty_tup(ref tys) => {
+                // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
+                Some(tys.clone())
+            }
+
+            ty::ty_closure(def_id, _, substs) => {
+                assert_eq!(def_id.krate, ast::LOCAL_CRATE);
+
+                match self.closure_typer.closure_upvars(def_id, substs) {
+                    Some(upvars) => {
+                        Some(upvars.iter().map(|c| c.ty).collect())
+                    }
+                    None => {
+                        None
                     }
                 }
+            }
 
-                ty::BoundSized => { }
+            ty::ty_struct(def_id, substs) => {
+                Some(ty::struct_fields(self.tcx(), def_id, substs).iter()
+                     .map(|f| f.mt.ty)
+                     .collect())
             }
 
-            Ok(If(types))
+            ty::ty_enum(def_id, substs) => {
+                Some(ty::substd_enum_variants(self.tcx(), def_id, substs)
+                     .iter()
+                     .flat_map(|variant| variant.args.iter())
+                     .map(|&ty| ty)
+                     .collect())
+            }
         }
     }
 
@@ -1619,7 +1721,7 @@ fn nominal<'cx, 'tcx>(this: &mut SelectionContext<'cx, 'tcx>,
     //
     // Confirmation unifies the output type parameters of the trait
     // with the values found in the obligation, possibly yielding a
-    // type error.  See `doc.rs` for more details.
+    // type error.  See `README.md` for more details.
 
     fn confirm_candidate(&mut self,
                          obligation: &TraitObligation<'tcx>,
@@ -1646,6 +1748,11 @@ fn confirm_candidate(&mut self,
                 Ok(VtableParam(obligations))
             }
 
+            DefaultImplCandidate(trait_def_id) => {
+                let data = try!(self.confirm_default_impl_candidate(obligation, trait_def_id));
+                Ok(VtableDefaultImpl(data))
+            }
+
             ImplCandidate(impl_def_id) => {
                 let vtable_impl =
                     try!(self.confirm_impl_candidate(obligation, impl_def_id));
@@ -1657,6 +1764,15 @@ fn confirm_candidate(&mut self,
                 Ok(VtableClosure(closure_def_id, substs))
             }
 
+            BuiltinObjectCandidate => {
+                // This indicates something like `(Trait+Send) :
+                // Send`. In this case, we know that this holds
+                // because that's what the object type is telling us,
+                // and there's really no additional obligations to
+                // prove and no types in particular to unify etc.
+                Ok(VtableParam(Vec::new()))
+            }
+
             ObjectCandidate => {
                 let data = self.confirm_object_candidate(obligation);
                 Ok(VtableObject(data))
@@ -1727,7 +1843,7 @@ fn confirm_builtin_candidate(&mut self,
                 self.tcx().sess.span_bug(
                     obligation.cause.span,
                     &format!("builtin bound for {} was ambig",
-                            obligation.repr(self.tcx()))[]);
+                            obligation.repr(self.tcx())));
             }
         }
     }
@@ -1767,7 +1883,7 @@ fn vtable_builtin_data(&mut self,
         }).collect::<Result<_, _>>();
         let obligations = match obligations {
             Ok(o) => o,
-            Err(ErrorReported) => Vec::new()
+            Err(ErrorReported) => Vec::new(),
         };
 
         let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
@@ -1778,6 +1894,97 @@ fn vtable_builtin_data(&mut self,
         VtableBuiltinData { nested: obligations }
     }
 
+    /// This handles the case where a `impl Foo for ..` impl is being used.
+    /// The idea is that the impl applies to `X : Foo` if the following conditions are met:
+    ///
+    /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
+    /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
+    fn confirm_default_impl_candidate(&mut self,
+                                      obligation: &TraitObligation<'tcx>,
+                                      impl_def_id: ast::DefId)
+                              -> Result<VtableDefaultImplData<PredicateObligation<'tcx>>,
+                                        SelectionError<'tcx>>
+    {
+        debug!("confirm_default_impl_candidate({}, {})",
+               obligation.repr(self.tcx()),
+               impl_def_id.repr(self.tcx()));
+
+        let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
+        match self.constituent_types_for_ty(self_ty) {
+            Some(types) => Ok(self.vtable_default_impl(obligation, impl_def_id, types)),
+            None => {
+                self.tcx().sess.bug(
+                    &format!(
+                        "asked to confirm default implementation for ambiguous type: {}",
+                        self_ty.repr(self.tcx())));
+            }
+        }
+    }
+
+    /// See `confirm_default_impl_candidate`
+    fn vtable_default_impl(&mut self,
+                           obligation: &TraitObligation<'tcx>,
+                           trait_def_id: ast::DefId,
+                           nested: Vec<Ty<'tcx>>)
+                           -> VtableDefaultImplData<PredicateObligation<'tcx>>
+    {
+        let derived_cause = self.derived_cause(obligation, ImplDerivedObligation);
+
+        let obligations = nested.iter().map(|&nested_ty| {
+            // the obligation might be higher-ranked, e.g. for<'a> &'a
+            // int : Copy. In that case, we will wind up with
+            // late-bound regions in the `nested` vector. So for each
+            // one we instantiate to a skolemized region, do our work
+            // to produce something like `&'0 int : Copy`, and then
+            // re-bind it. This is a bit of busy-work but preserves
+            // the invariant that we only manipulate free regions, not
+            // bound ones.
+            self.infcx.try(|snapshot| {
+                let (skol_ty, skol_map) =
+                    self.infcx().skolemize_late_bound_regions(&ty::Binder(nested_ty), snapshot);
+                let skol_predicate =
+                    util::predicate_for_default_trait_impl(
+                        self.tcx(),
+                        derived_cause.clone(),
+                        trait_def_id,
+                        obligation.recursion_depth + 1,
+                        skol_ty);
+                match skol_predicate {
+                    Ok(skol_predicate) => Ok(self.infcx().plug_leaks(skol_map, snapshot,
+                                                                     &skol_predicate)),
+                    Err(ErrorReported) => Err(ErrorReported)
+                }
+            })
+        }).collect::<Result<_, _>>();
+
+        let mut obligations = match obligations {
+            Ok(o) => o,
+            Err(ErrorReported) => Vec::new()
+        };
+
+        let _: Result<(),()> = self.infcx.try(|snapshot| {
+            let (_, skol_map) =
+                self.infcx().skolemize_late_bound_regions(&obligation.predicate, snapshot);
+
+            let substs = obligation.predicate.to_poly_trait_ref().substs();
+            let trait_obligations = self.impl_or_trait_obligations(obligation.cause.clone(),
+                                                                   obligation.recursion_depth + 1,
+                                                                   trait_def_id,
+                                                                   substs,
+                                                                   skol_map,
+                                                                   snapshot);
+            obligations.push_all(trait_obligations.as_slice());
+            Ok(())
+        });
+
+        debug!("vtable_default_impl_data: obligations={}", obligations.repr(self.tcx()));
+
+        VtableDefaultImplData {
+            trait_def_id: trait_def_id,
+            nested: obligations
+        }
+    }
+
     fn confirm_impl_candidate(&mut self,
                               obligation: &TraitObligation<'tcx>,
                               impl_def_id: ast::DefId)
@@ -1818,12 +2025,12 @@ fn vtable_impl(&mut self,
                skol_map.repr(self.tcx()));
 
         let mut impl_obligations =
-            self.impl_obligations(cause,
-                                 recursion_depth,
-                                 impl_def_id,
-                                 &substs.value,
-                                 skol_map,
-                                 snapshot);
+            self.impl_or_trait_obligations(cause,
+                                           recursion_depth,
+                                           impl_def_id,
+                                           &substs.value,
+                                           skol_map,
+                                           snapshot);
 
         debug!("vtable_impl: impl_def_id={} impl_obligations={}",
                impl_def_id.repr(self.tcx()),
@@ -1988,14 +2195,12 @@ fn rematch_impl(&mut self,
     {
         match self.match_impl(impl_def_id, obligation, snapshot,
                               skol_map, skol_obligation_trait_ref) {
-            Ok(substs) => {
-                substs
-            }
+            Ok(substs) => substs,
             Err(()) => {
                 self.tcx().sess.bug(
                     &format!("Impl {} was matchable against {} but now is not",
                             impl_def_id.repr(self.tcx()),
-                            obligation.repr(self.tcx()))[]);
+                            obligation.repr(self.tcx())));
             }
         }
     }
@@ -2038,30 +2243,26 @@ fn match_impl(&mut self,
                skol_obligation_trait_ref.repr(self.tcx()));
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
-        match self.infcx.sub_trait_refs(false,
-                                        origin,
-                                        impl_trait_ref.value.clone(),
-                                        skol_obligation_trait_ref) {
-            Ok(()) => { }
-            Err(e) => {
-                debug!("match_impl: failed sub_trait_refs due to `{}`",
-                       ty::type_err_to_str(self.tcx(), &e));
-                return Err(());
-            }
+        if let Err(e) = self.infcx.sub_trait_refs(false,
+                                                  origin,
+                                                  impl_trait_ref.value.clone(),
+                                                  skol_obligation_trait_ref) {
+            debug!("match_impl: failed sub_trait_refs due to `{}`",
+                   ty::type_err_to_str(self.tcx(), &e));
+            return Err(());
         }
 
-        match self.infcx.leak_check(skol_map, snapshot) {
-            Ok(()) => { }
-            Err(e) => {
-                debug!("match_impl: failed leak check due to `{}`",
-                       ty::type_err_to_str(self.tcx(), &e));
-                return Err(());
-            }
+        if let Err(e) = self.infcx.leak_check(skol_map, snapshot) {
+            debug!("match_impl: failed leak check due to `{}`",
+                   ty::type_err_to_str(self.tcx(), &e));
+            return Err(());
         }
 
         debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
-        Ok(Normalized { value: impl_substs,
-                        obligations: impl_trait_ref.obligations })
+        Ok(Normalized {
+            value: impl_substs,
+            obligations: impl_trait_ref.obligations
+        })
     }
 
     fn fast_reject_trait_refs(&mut self,
@@ -2097,9 +2298,7 @@ fn match_where_clause_trait_ref(&mut self,
                                     where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
                                     -> Result<Vec<PredicateObligation<'tcx>>,()>
     {
-        let () =
-            try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
-
+        try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
         Ok(Vec::new())
     }
 
@@ -2216,7 +2415,7 @@ fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
 
         match self.tcx().trait_impls.borrow().get(&trait_def_id) {
             None => Vec::new(),
-            Some(impls) => impls.borrow().clone()
+            Some(impls) => impls.borrow().clone(),
         }
     }
 
@@ -2243,28 +2442,30 @@ fn closure_trait_ref(&self,
         ty::Binder(trait_ref)
     }
 
-    fn impl_obligations(&mut self,
-                        cause: ObligationCause<'tcx>,
-                        recursion_depth: uint,
-                        impl_def_id: ast::DefId,
-                        impl_substs: &Substs<'tcx>,
-                        skol_map: infer::SkolemizationMap,
-                        snapshot: &infer::CombinedSnapshot)
-                        -> VecPerParamSpace<PredicateObligation<'tcx>>
+    /// Returns the obligations that are implied by instantiating an
+    /// impl or trait. The obligations are substituted and fully
+    /// normalized. This is used when confirming an impl or default
+    /// impl.
+    fn impl_or_trait_obligations(&mut self,
+                                 cause: ObligationCause<'tcx>,
+                                 recursion_depth: uint,
+                                 def_id: ast::DefId, // of impl or trait
+                                 substs: &Substs<'tcx>, // for impl or trait
+                                 skol_map: infer::SkolemizationMap,
+                                 snapshot: &infer::CombinedSnapshot)
+                                 -> VecPerParamSpace<PredicateObligation<'tcx>>
     {
-        let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id);
-        let bounds = impl_bounds.instantiate(self.tcx(), impl_substs);
-        let normalized_bounds =
-            project::normalize_with_depth(self, cause.clone(), recursion_depth, &bounds);
-        let normalized_bounds =
-            self.infcx().plug_leaks(skol_map, snapshot, &normalized_bounds);
-        let mut impl_obligations =
+        let predicates = ty::lookup_predicates(self.tcx(), def_id);
+        let predicates = predicates.instantiate(self.tcx(), substs);
+        let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates);
+        let predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates);
+        let mut obligations =
             util::predicates_for_generics(self.tcx(),
                                           cause,
                                           recursion_depth,
-                                          &normalized_bounds.value);
-        impl_obligations.extend(TypeSpace, normalized_bounds.obligations.into_iter());
-        impl_obligations
+                                          &predicates.value);
+        obligations.extend(TypeSpace, predicates.obligations.into_iter());
+        obligations
     }
 
     #[allow(unused_comparisons)]
@@ -2306,13 +2507,13 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
             PhantomFnCandidate => format!("PhantomFnCandidate"),
             ErrorCandidate => format!("ErrorCandidate"),
             BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
+            BuiltinObjectCandidate => format!("BuiltinObjectCandidate"),
             ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
             ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
+            DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
             ProjectionCandidate => format!("ProjectionCandidate"),
             FnPointerCandidate => format!("FnPointerCandidate"),
-            ObjectCandidate => {
-                format!("ObjectCandidate")
-            }
+            ObjectCandidate => format!("ObjectCandidate"),
             ClosureCandidate(c, ref s) => {
                 format!("ClosureCandidate({:?},{})", c, s.repr(tcx))
             }
@@ -2343,9 +2544,7 @@ fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
                 *self = o.previous;
                 Some(o)
             }
-            None => {
-                None
-            }
+            None => None
         }
     }
 }
@@ -2360,15 +2559,11 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 impl<'tcx> EvaluationResult<'tcx> {
     fn may_apply(&self) -> bool {
         match *self {
-            EvaluatedToOk |
-            EvaluatedToAmbig |
-            EvaluatedToErr(Overflow) |
-            EvaluatedToErr(OutputTypeParameterMismatch(..)) => {
-                true
-            }
-            EvaluatedToErr(Unimplemented) => {
-                false
-            }
+            EvaluatedToOk
+            | EvaluatedToAmbig
+            | EvaluatedToErr(Overflow)
+            | EvaluatedToErr(OutputTypeParameterMismatch(..)) => true,
+            EvaluatedToErr(Unimplemented) => false,
         }
     }
 }
index 6c54da1c134f5c63c01086e7090ecccab78c9806..9b462e6be60dd57bf2b80d46fd57a1ea120344a8 100644 (file)
@@ -20,7 +20,7 @@
 use util::ppaux::Repr;
 
 use super::{Obligation, ObligationCause, PredicateObligation,
-            VtableImpl, VtableParam, VtableImplData};
+            VtableImpl, VtableParam, VtableImplData, VtableDefaultImplData};
 
 struct PredicateSet<'a,'tcx:'a> {
     tcx: &'a ty::ctxt<'tcx>,
@@ -323,6 +323,35 @@ pub fn trait_ref_for_builtin_bound<'tcx>(
     }
 }
 
+
+pub fn predicate_for_trait_ref<'tcx>(
+    cause: ObligationCause<'tcx>,
+    trait_ref: Rc<ty::TraitRef<'tcx>>,
+    recursion_depth: uint)
+    -> Result<PredicateObligation<'tcx>, ErrorReported>
+{
+    Ok(Obligation {
+        cause: cause,
+        recursion_depth: recursion_depth,
+        predicate: trait_ref.as_predicate(),
+    })
+}
+
+pub fn predicate_for_default_trait_impl<'tcx>(
+    tcx: &ty::ctxt<'tcx>,
+    cause: ObligationCause<'tcx>,
+    trait_def_id: ast::DefId,
+    recursion_depth: uint,
+    param_ty: Ty<'tcx>)
+    -> Result<PredicateObligation<'tcx>, ErrorReported>
+{
+    let trait_ref = Rc::new(ty::TraitRef {
+        def_id: trait_def_id,
+        substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
+    });
+    predicate_for_trait_ref(cause, trait_ref, recursion_depth)
+}
+
 pub fn predicate_for_builtin_bound<'tcx>(
     tcx: &ty::ctxt<'tcx>,
     cause: ObligationCause<'tcx>,
@@ -332,11 +361,7 @@ pub fn predicate_for_builtin_bound<'tcx>(
     -> Result<PredicateObligation<'tcx>, ErrorReported>
 {
     let trait_ref = try!(trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty));
-    Ok(Obligation {
-        cause: cause,
-        recursion_depth: recursion_depth,
-        predicate: trait_ref.as_predicate(),
-    })
+    predicate_for_trait_ref(cause, trait_ref, recursion_depth)
 }
 
 /// Cast a trait reference into a reference to one of its super
@@ -444,6 +469,9 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
             super::VtableImpl(ref v) =>
                 v.repr(tcx),
 
+            super::VtableDefaultImpl(ref t) =>
+                t.repr(tcx),
+
             super::VtableClosure(ref d, ref s) =>
                 format!("VtableClosure({},{})",
                         d.repr(tcx),
@@ -483,6 +511,14 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
     }
 }
 
+impl<'tcx, N:Repr<'tcx>> Repr<'tcx> for super::VtableDefaultImplData<N> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
+        format!("VtableDefaultImplData(trait_def_id={}, nested={})",
+                self.trait_def_id.repr(tcx),
+                self.nested.repr(tcx))
+    }
+}
+
 impl<'tcx> Repr<'tcx> for super::VtableObjectData<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         format!("VtableObject(object_ty={})",
index e9908397f970387782fb097c4d478013d92c480a..78b8d4f7b1e28913ce747d166006804127f33c34 100644 (file)
@@ -55,7 +55,7 @@
 use middle::resolve_lifetime;
 use middle::infer;
 use middle::stability;
-use middle::subst::{self, Subst, Substs, VecPerParamSpace};
+use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
 use middle::ty;
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
@@ -73,7 +73,6 @@
 use std::cmp;
 use std::fmt;
 use std::hash::{Hash, SipHasher, Hasher};
-#[cfg(stage0)] use std::hash::Writer;
 use std::mem;
 use std::ops;
 use std::rc::Rc;
@@ -710,7 +709,7 @@ pub struct ctxt<'tcx> {
 
     pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
 
-    pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
+    pub impl_trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
 
     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
@@ -757,6 +756,9 @@ pub struct ctxt<'tcx> {
     /// Maps a trait onto a list of impls of that trait.
     pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
 
+    /// Maps a trait onto a list of *default* trait implementations
+    default_trait_impls: RefCell<DefIdMap<ast::DefId>>,
+
     /// Maps a DefId of a type to a list of its inherent impls.
     /// Contains implementations of methods that are inherent to a type.
     /// Methods in these implementations don't need to be exported.
@@ -928,7 +930,7 @@ pub fn print_debug_stats(&self) {
         sty_debug_print!(
             self,
             ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait,
-            ty_struct, ty_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection);
+            ty_struct, ty_closure, ty_tup, ty_param, ty_infer, ty_projection);
 
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@@ -959,13 +961,6 @@ fn eq(&self, other: &TyS<'tcx>) -> bool {
 }
 impl<'tcx> Eq for TyS<'tcx> {}
 
-#[cfg(stage0)]
-impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
-    fn hash(&self, s: &mut S) {
-        (self as *const _).hash(s)
-    }
-}
-#[cfg(not(stage0))]
 impl<'tcx> Hash for TyS<'tcx> {
     fn hash<H: Hasher>(&self, s: &mut H) {
         (self as *const _).hash(s)
@@ -988,13 +983,6 @@ fn eq(&self, other: &InternedTy<'tcx>) -> bool {
 
 impl<'tcx> Eq for InternedTy<'tcx> {}
 
-#[cfg(stage0)]
-impl<'tcx, S: Writer + Hasher> Hash<S> for InternedTy<'tcx> {
-    fn hash(&self, s: &mut S) {
-        self.ty.sty.hash(s)
-    }
-}
-#[cfg(not(stage0))]
 impl<'tcx> Hash for InternedTy<'tcx> {
     fn hash<H: Hasher>(&self, s: &mut H) {
         self.ty.sty.hash(s)
@@ -1386,12 +1374,6 @@ pub enum sty<'tcx> {
     ty_projection(ProjectionTy<'tcx>),
     ty_param(ParamTy), // type parameter
 
-    ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
-                       // and its size. Only ever used in trans. It is not necessary
-                       // earlier since we don't need to distinguish a DST with its
-                       // size (e.g., in a deref) vs a DST with the size elsewhere (
-                       // e.g., in a field).
-
     ty_infer(InferTy), // something used only during inference/typeck
     ty_err, // Also only used during inference/typeck, to represent
             // the type of an erroneous expression (helps cut down
@@ -1768,7 +1750,6 @@ pub struct TypeParameterDef<'tcx> {
     pub def_id: ast::DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
-    pub bounds: ParamBounds<'tcx>,
     pub default: Option<Ty<'tcx>>,
     pub object_lifetime_default: Option<ObjectLifetimeDefault>,
 }
@@ -2295,7 +2276,7 @@ pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx
             _ => {
                 cx.sess.bug(&format!("ParameterEnvironment::from_item(): \
                                      `{}` is not an item",
-                                    cx.map.node_to_string(id))[])
+                                    cx.map.node_to_string(id)))
             }
         }
     }
@@ -2441,7 +2422,7 @@ fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
 
 pub fn mk_ctxt<'tcx>(s: Session,
                      arenas: &'tcx CtxtArenas<'tcx>,
-                     dm: DefMap,
+                     def_map: DefMap,
                      named_region_map: resolve_lifetime::NamedRegionMap,
                      map: ast_map::Map<'tcx>,
                      freevars: RefCell<FreevarMap>,
@@ -2463,11 +2444,11 @@ pub fn mk_ctxt<'tcx>(s: Session,
         item_variance_map: RefCell::new(DefIdMap()),
         variance_computed: Cell::new(false),
         sess: s,
-        def_map: dm,
+        def_map: def_map,
         region_maps: region_maps,
         node_types: RefCell::new(FnvHashMap()),
         item_substs: RefCell::new(NodeMap()),
-        trait_refs: RefCell::new(NodeMap()),
+        impl_trait_refs: RefCell::new(NodeMap()),
         trait_defs: RefCell::new(DefIdMap()),
         predicates: RefCell::new(DefIdMap()),
         object_cast_map: RefCell::new(NodeMap()),
@@ -2493,6 +2474,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         destructor_for_type: RefCell::new(DefIdMap()),
         destructors: RefCell::new(DefIdSet()),
         trait_impls: RefCell::new(DefIdMap()),
+        default_trait_impls: RefCell::new(DefIdMap()),
         inherent_impls: RefCell::new(DefIdMap()),
         impl_items: RefCell::new(DefIdMap()),
         used_unsafe: RefCell::new(NodeSet()),
@@ -2563,6 +2545,13 @@ pub fn closure_type(&self,
     {
         self.closure_tys.borrow()[def_id].subst(self, substs)
     }
+
+    pub fn type_parameter_def(&self,
+                              node_id: ast::NodeId)
+                              -> TypeParameterDef<'tcx>
+    {
+        self.ty_param_defs.borrow()[node_id].clone()
+    }
 }
 
 // Interns a type/name combination, stores the resulting box in cx.interner,
@@ -2700,7 +2689,7 @@ fn add_sty(&mut self, st: &sty) {
                 self.add_bounds(bounds);
             }
 
-            &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
+            &ty_uniq(tt) | &ty_vec(tt, _) => {
                 self.add_ty(tt)
             }
 
@@ -2737,7 +2726,7 @@ fn add_tys(&mut self, tys: &[Ty]) {
     fn add_fn_sig(&mut self, fn_sig: &PolyFnSig) {
         let mut computation = FlagComputation::new();
 
-        computation.add_tys(&fn_sig.0.inputs[]);
+        computation.add_tys(&fn_sig.0.inputs);
 
         if let ty::FnConverging(output) = fn_sig.0.output {
             computation.add_ty(output);
@@ -2975,8 +2964,6 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t
     mk_param(cx, def.space, def.index, def.name)
 }
 
-pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
-
 impl<'tcx> TyS<'tcx> {
     /// Iterator that walks `self` and any types reachable from
     /// `self`, in depth-first order. Note that just walks the types
@@ -3015,6 +3002,13 @@ pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
             _ => None,
         }
     }
+
+    pub fn is_param(&self, space: ParamSpace, index: u32) -> bool {
+        match self.sty {
+            ty::ty_param(ref data) => data.space == space && data.idx == index,
+            _ => false,
+        }
+    }
 }
 
 pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
@@ -3175,9 +3169,8 @@ pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_vec(ty, _) => ty,
         ty_str => mk_mach_uint(cx, ast::TyU8),
-        ty_open(ty) => sequence_element_type(cx, ty),
         _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
-                                 ty_to_string(cx, ty))[]),
+                                 ty_to_string(cx, ty))),
     }
 }
 
@@ -3538,7 +3531,7 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                 let variants = substd_enum_variants(cx, did, substs);
                 let mut res =
                     TypeContents::union(&variants[..], |variant| {
-                        TypeContents::union(&variant.args[],
+                        TypeContents::union(&variant.args,
                                             |arg_ty| {
                             tc_ty(cx, *arg_ty, cache)
                         })
@@ -3594,12 +3587,6 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                 TC::All
             }
 
-            ty_open(ty) => {
-                let result = tc_ty(cx, ty, cache);
-                assert!(!result.is_sized(cx));
-                result.unsafe_pointer() | TC::Nonsized
-            }
-
             ty_infer(_) |
             ty_err => {
                 cx.sess.bug("asked to compute contents of error type");
@@ -3758,7 +3745,7 @@ fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
             ty_vec(_, None) => {
                 false
             }
-            ty_uniq(typ) | ty_open(typ) => {
+            ty_uniq(typ) => {
                 type_requires(cx, seen, r_ty, typ)
             }
             ty_rptr(_, ref mt) => {
@@ -4117,14 +4104,6 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
     }
 }
 
-pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        ty_open(ty) => mk_rptr(cx, cx.mk_region(ReStatic), mt {ty: ty, mutbl:ast::MutImmutable}),
-        _ => cx.sess.bug(&format!("Trying to close a non-open type {}",
-                                 ty_to_string(cx, ty))[])
-    }
-}
-
 pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_uniq(ty) => ty,
@@ -4133,14 +4112,6 @@ pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 }
 
-// Extract the unsized type in an open type (or just return ty if it is not open).
-pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        ty_open(ty) => ty,
-        _ => ty
-    }
-}
-
 // Returns the type of ty[i]
 pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     match ty.sty {
@@ -4216,13 +4187,13 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
     }
 }
 
-pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
+pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
                                   -> Rc<ty::TraitRef<'tcx>> {
-    match cx.trait_refs.borrow().get(&id) {
+    match cx.impl_trait_refs.borrow().get(&id) {
         Some(ty) => ty.clone(),
         None => cx.sess.bug(
-            &format!("node_id_to_trait_ref: no trait ref for node `{}`",
-                    cx.map.node_to_string(id))[])
+            &format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
+                    cx.map.node_to_string(id)))
     }
 }
 
@@ -4231,7 +4202,7 @@ pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
        Some(ty) => ty,
        None => cx.sess.bug(
            &format!("node_id_to_type: no type for node `{}`",
-                   cx.map.node_to_string(id))[])
+                   cx.map.node_to_string(id)))
     }
 }
 
@@ -4305,7 +4276,7 @@ pub fn ty_region(tcx: &ctxt,
             tcx.sess.span_bug(
                 span,
                 &format!("ty_region() invoked on an inappropriate ty: {:?}",
-                        s)[]);
+                        s));
         }
     }
 }
@@ -4370,11 +4341,11 @@ pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
         Some(f) => {
             cx.sess.bug(&format!("Node id {} is not an expr: {:?}",
                                 id,
-                                f)[]);
+                                f));
         }
         None => {
             cx.sess.bug(&format!("Node id {} is not present \
-                                in the node map", id)[]);
+                                in the node map", id));
         }
     }
 }
@@ -4390,14 +4361,14 @@ pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
                     cx.sess.bug(
                         &format!("Variable id {} maps to {:?}, not local",
                                 id,
-                                pat)[]);
+                                pat));
                 }
             }
         }
         r => {
             cx.sess.bug(&format!("Variable id {} maps to {:?}, not local",
                                 id,
-                                r)[]);
+                                r));
         }
     }
 }
@@ -4428,7 +4399,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                             cx.sess.bug(
                                 &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
                                          {:?}",
-                                        b)[]);
+                                        b));
                         }
                     }
                 }
@@ -4459,7 +4430,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
                                                 {}",
                                                 i,
                                                 ty_to_string(cx, adjusted_ty))
-                                        []);
+                                        );
                                 }
                             }
                         }
@@ -4522,7 +4493,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
             }
             _ => cx.sess.span_bug(span,
                                   &format!("UnsizeLength with bad sty: {:?}",
-                                          ty_to_string(cx, ty))[])
+                                          ty_to_string(cx, ty)))
         },
         &UnsizeStruct(box ref k, tp_index) => match ty.sty {
             ty_struct(did, substs) => {
@@ -4534,7 +4505,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
             }
             _ => cx.sess.span_bug(span,
                                   &format!("UnsizeStruct with bad sty: {:?}",
-                                          ty_to_string(cx, ty))[])
+                                          ty_to_string(cx, ty)))
         },
         &UnsizeVtable(TyTrait { ref principal, ref bounds }, _) => {
             mk_trait(cx, principal.clone(), bounds.clone())
@@ -4544,10 +4515,10 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
 
 pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
     match tcx.def_map.borrow().get(&expr.id) {
-        Some(&def) => def,
+        Some(def) => def.full_def(),
         None => {
             tcx.sess.span_bug(expr.span, &format!(
-                "no def-map entry for expr {}", expr.id)[]);
+                "no def-map entry for expr {}", expr.id));
         }
     }
 }
@@ -4592,7 +4563,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
     }
 
     match expr.node {
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             match resolve_expr(tcx, expr) {
                 def::DefVariant(tid, vid, _) => {
                     let variant_info = enum_variant_with_id(tcx, tid, vid);
@@ -4623,7 +4594,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                 def::DefFn(_, true) => RvalueDpsExpr,
 
                 // Fn pointers are just scalar values.
-                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr,
+                def::DefFn(..) | def::DefMethod(..) => RvalueDatumExpr,
 
                 // Note: there is actually a good case to be made that
                 // DefArg's, particularly those of immediate type, ought to
@@ -4639,7 +4610,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                         expr.span,
                         &format!("uncategorized def for expr {}: {:?}",
                                 expr.id,
-                                def)[]);
+                                def));
                 }
             }
         }
@@ -4727,11 +4698,10 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
 
         ast::ExprBox(Some(ref place), _) => {
             // Special case `Box<T>` for now:
-            let definition = match tcx.def_map.borrow().get(&place.id) {
-                Some(&def) => def,
+            let def_id = match tcx.def_map.borrow().get(&place.id) {
+                Some(def) => def.def_id(),
                 None => panic!("no def for place"),
             };
-            let def_id = definition.def_id();
             if tcx.lang_items.exchange_heap() == Some(def_id) {
                 RvalueDatumExpr
             } else {
@@ -4767,7 +4737,7 @@ pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
         token::get_name(name),
         fields.iter()
               .map(|f| token::get_name(f.name).to_string())
-              .collect::<Vec<String>>())[]);
+              .collect::<Vec<String>>()));
 }
 
 pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
@@ -4813,7 +4783,6 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
             }
         }
         ty_err => "type error".to_string(),
-        ty_open(_) => "opened DST".to_string(),
     }
 }
 
@@ -5019,14 +4988,14 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                     _ => {
                         cx.sess.bug(&format!("provided_trait_methods: `{:?}` is \
                                              not a trait",
-                                            id)[])
+                                            id))
                     }
                 }
             }
             _ => {
                 cx.sess.bug(&format!("provided_trait_methods: `{:?}` is not a \
                                      trait",
-                                    id)[])
+                                    id))
             }
         }
     } else {
@@ -5159,22 +5128,16 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
     memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
         if id.krate == ast::LOCAL_CRATE {
             debug!("(impl_trait_ref) searching for trait impl {:?}", id);
-            match cx.map.find(id.node) {
-                Some(ast_map::NodeItem(item)) => {
-                    match item.node {
-                        ast::ItemImpl(_, _, _, ref opt_trait, _, _) => {
-                            match opt_trait {
-                                &Some(ref t) => {
-                                    let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
-                                    Some(trait_ref)
-                                }
-                                &None => None
-                            }
-                        }
-                        _ => None
+            if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
+                match item.node {
+                    ast::ItemImpl(_, _, _, Some(_), _, _) |
+                    ast::ItemDefaultImpl(..) => {
+                        Some(ty::impl_id_to_trait_ref(cx, id.node))
                     }
+                    _ => None
                 }
-                _ => None
+            } else {
+                None
             }
         } else {
             csearch::get_impl_trait(cx, id)
@@ -5183,10 +5146,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
 }
 
 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
-    let def = *tcx.def_map.borrow()
-                     .get(&tr.ref_id)
-                     .expect("no def-map entry for trait");
-    def.def_id()
+    tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
 }
 
 pub fn try_add_builtin_trait(
@@ -5262,7 +5222,7 @@ pub fn from_ast_variant(cx: &ctxt<'tcx>,
                 };
             },
             ast::StructVariantKind(ref struct_def) => {
-                let fields: &[StructField] = &struct_def.fields[];
+                let fields: &[StructField] = &struct_def.fields;
 
                 assert!(fields.len() > 0);
 
@@ -5624,7 +5584,7 @@ pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId)
                        -> CowVec<'tcx, ast::Attribute> {
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
-        Cow::Borrowed(&item.attrs[])
+        Cow::Borrowed(&item.attrs)
     } else {
         Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did))
     }
@@ -5686,7 +5646,7 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
             _ => {
                 cx.sess.bug(
                     &format!("ID not mapped to struct fields: {}",
-                            cx.map.node_to_string(did.node))[]);
+                            cx.map.node_to_string(did.node)));
             }
         }
     } else {
@@ -5719,7 +5679,7 @@ pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tc
 pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
     v.iter().enumerate().map(|(i, &f)| {
        field {
-            name: token::intern(&i.to_string()[]),
+            name: token::intern(&i.to_string()),
             mt: mt {
                 ty: f,
                 mutbl: MutImmutable
@@ -5888,7 +5848,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
         }
         Err(_) => {
             let found = match count_expr.node {
-                ast::ExprPath(ast::Path {
+                ast::ExprPath(None, ast::Path {
                     global: false,
                     ref segments,
                     ..
@@ -5992,6 +5952,32 @@ pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
         || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
 }
 
+pub fn trait_default_impl(tcx: &ctxt, trait_def_id: DefId) -> Option<ast::DefId> {
+    match tcx.default_trait_impls.borrow().get(&trait_def_id) {
+        Some(id) => Some(*id),
+        None => None
+    }
+}
+
+pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool {
+    match tcx.lang_items.to_builtin_kind(trait_def_id) {
+        Some(BoundSend) | Some(BoundSync) => true,
+        _ => tcx.default_trait_impls.borrow().contains_key(&trait_def_id)
+    }
+}
+
+/// Records a trait-to-implementation mapping.
+pub fn record_default_trait_implementation(tcx: &ctxt,
+                                           trait_def_id: DefId,
+                                           impl_def_id: DefId) {
+
+    // We're using the latest implementation found as the reference one.
+    // Duplicated implementations are caught and reported in the coherence
+    // step.
+    tcx.default_trait_impls.borrow_mut().insert(trait_def_id, impl_def_id);
+}
+
+
 /// Records a trait-to-implementation mapping.
 pub fn record_trait_implementation(tcx: &ctxt,
                                    trait_def_id: DefId,
@@ -6074,11 +6060,22 @@ pub fn populate_implementations_for_trait_if_necessary(
     }
 
     csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
-            |implementation_def_id| {
+            |implementation_def_id|{
         let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
 
-        // Record the trait->implementation mapping.
-        record_trait_implementation(tcx, trait_id, implementation_def_id);
+        if csearch::is_default_trait(&tcx.sess.cstore, implementation_def_id) {
+            record_default_trait_implementation(tcx, trait_id,
+                                                implementation_def_id);
+            tcx.populated_external_traits.borrow_mut().insert(trait_id);
+
+            // Nothing else to do for default trait implementations since
+            // they are not allowed to have type parameters, methods, or any
+            // other item that could be associated to a trait implementation.
+            return;
+        } else {
+            // Record the trait->implementation mapping.
+            record_trait_implementation(tcx, trait_id, implementation_def_id);
+        }
 
         // For any methods that use a default implementation, add them to
         // the map. This is a bit unfortunate.
@@ -6299,16 +6296,15 @@ macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
                     hash!(p.idx);
                     hash!(token::get_name(p.name));
                 }
-                ty_open(_) => byte!(22),
                 ty_infer(_) => unreachable!(),
-                ty_err => byte!(23),
+                ty_err => byte!(21),
                 ty_closure(d, r, _) => {
-                    byte!(24);
+                    byte!(22);
                     did(state, d);
                     region(state, *r);
                 }
                 ty_projection(ref data) => {
-                    byte!(25);
+                    byte!(23);
                     did(state, data.trait_ref.def_id);
                     hash!(token::get_name(data.item_name));
                 }
@@ -6637,7 +6633,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
             ty_projection(_) |
             ty_param(_) |
             ty_infer(_) |
-            ty_open(_) |
             ty_err => {
             }
         }
index 5e46ce08e4f7605b57fd458e383a85ad4241342e..4bf47c3a75f8003761a99ca641a540b8ae4a7f96 100644 (file)
@@ -377,7 +377,6 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef
             def_id: self.def_id,
             space: self.space,
             index: self.index,
-            bounds: self.bounds.fold_with(folder),
             default: self.default.fold_with(folder),
             object_lifetime_default: self.object_lifetime_default.fold_with(folder),
         }
@@ -507,6 +506,15 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableImplDat
     }
 }
 
+impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableDefaultImplData<N> {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableDefaultImplData<N> {
+        traits::VtableDefaultImplData {
+            trait_def_id: self.trait_def_id,
+            nested: self.nested.fold_with(folder),
+        }
+    }
+}
+
 impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
         traits::VtableBuiltinData {
@@ -519,6 +527,7 @@ impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N>
     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
         match *self {
             traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
+            traits::VtableDefaultImpl(ref t) => traits::VtableDefaultImpl(t.fold_with(folder)),
             traits::VtableClosure(d, ref s) => {
                 traits::VtableClosure(d, s.fold_with(folder))
             }
@@ -616,9 +625,6 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
         ty::ty_vec(typ, sz) => {
             ty::ty_vec(typ.fold_with(this), sz)
         }
-        ty::ty_open(typ) => {
-            ty::ty_open(typ.fold_with(this))
-        }
         ty::ty_enum(tid, ref substs) => {
             let substs = substs.fold_with(this);
             ty::ty_enum(tid, this.tcx().mk_substs(substs))
index 40dfd479364a6c18c76f960518bef48a3e87777b..3336e7ee8bf71e6186107a989782913d8dd13f2f 100644 (file)
@@ -28,7 +28,7 @@ fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) {
             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, _) | ty::ty_open(ty) => {
+            ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
                 self.stack.push(ty);
             }
             ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
index b3bc898748fdc00ba3637c5efde0d0bc473255cd..a419d4134b40e4677faba9b0355848ccc5e1b98a 100644 (file)
@@ -15,7 +15,7 @@
 use plugin::registry::Registry;
 
 use std::mem;
-use std::env;
+use std::os;
 use std::dynamic_lib::DynamicLibrary;
 use std::borrow::ToOwned;
 use syntax::ast;
@@ -103,7 +103,7 @@ fn dylink_registrar(&mut self,
                         path: Path,
                         symbol: String) -> PluginRegistrarFun {
         // Make sure the path contains a / or the linker will search for it.
-        let path = env::current_dir().unwrap().join(&path);
+        let path = os::getcwd().unwrap().join(&path);
 
         let lib = match DynamicLibrary::open(Some(&path)) {
             Ok(lib) => lib,
index 93a25de0491fe018ab8fef7d7e11435c80c211e4..efcde8b2fa1ac94cb00bb44c1dbc19616da14561 100644 (file)
@@ -99,6 +99,7 @@ pub struct Options {
     pub test: bool,
     pub parse_only: bool,
     pub no_trans: bool,
+    pub treat_err_as_bug: bool,
     pub no_analysis: bool,
     pub debugging_opts: DebuggingOptions,
     /// Whether to write dependency files. It's (enabled, optional filename).
@@ -223,6 +224,7 @@ pub fn basic_options() -> Options {
         test: false,
         parse_only: false,
         no_trans: false,
+        treat_err_as_bug: false,
         no_analysis: false,
         debugging_opts: basic_debugging_options(),
         write_dependency_info: (false, None),
@@ -311,19 +313,19 @@ pub fn $buildfn(matches: &getopts::Matches) -> $struct_name
                     match (value, opt_type_desc) {
                         (Some(..), None) => {
                             early_error(&format!("{} option `{}` takes no \
-                                                 value", $outputname, key)[])
+                                                 value", $outputname, key))
                         }
                         (None, Some(type_desc)) => {
                             early_error(&format!("{0} option `{1}` requires \
                                                  {2} ({3} {1}=<value>)",
                                                 $outputname, key,
-                                                type_desc, $prefix)[])
+                                                type_desc, $prefix))
                         }
                         (Some(value), Some(type_desc)) => {
                             early_error(&format!("incorrect value `{}` for {} \
                                                  option `{}` - {} was expected",
                                                  value, $outputname,
-                                                 key, type_desc)[])
+                                                 key, type_desc))
                         }
                         (None, None) => unreachable!()
                     }
@@ -333,7 +335,7 @@ pub fn $buildfn(matches: &getopts::Matches) -> $struct_name
             }
             if !found {
                 early_error(&format!("unknown {} option: `{}`",
-                                    $outputname, key)[]);
+                                    $outputname, key));
             }
         }
         return op;
@@ -573,6 +575,8 @@ fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
           "Parse only; do not compile, assemble, or link"),
     no_trans: bool = (false, parse_bool,
           "Run all passes except translation; no output"),
+    treat_err_as_bug: bool = (false, parse_bool,
+          "Treat all errors that occur as bugs"),
     no_analysis: bool = (false, parse_bool,
           "Parse and expand the source, but run no analysis"),
     extra_plugins: Vec<String> = (Vec::new(), parse_list,
@@ -590,10 +594,10 @@ pub fn default_lib_output() -> CrateType {
 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     use syntax::parse::token::intern_and_get_ident as intern;
 
-    let end = &sess.target.target.target_endian[];
-    let arch = &sess.target.target.arch[];
-    let wordsz = &sess.target.target.target_pointer_width[];
-    let os = &sess.target.target.target_os[];
+    let end = &sess.target.target.target_endian;
+    let arch = &sess.target.target.arch;
+    let wordsz = &sess.target.target.target_pointer_width;
+    let os = &sess.target.target.target_os;
 
     let fam = match sess.target.target.options.is_like_windows {
         true  => InternedString::new("windows"),
@@ -634,18 +638,18 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
 }
 
 pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
-    let target = match Target::search(&opts.target_triple[]) {
+    let target = match Target::search(&opts.target_triple) {
         Ok(t) => t,
         Err(e) => {
             sp.handler().fatal(&format!("Error loading target specification: {}", e));
     }
     };
 
-    let (int_type, uint_type) = match &target.target_pointer_width[] {
+    let (int_type, uint_type) = match &target.target_pointer_width[..] {
         "32" => (ast::TyI32, ast::TyU32),
         "64" => (ast::TyI64, ast::TyU64),
         w    => sp.handler().fatal(&format!("target specification was invalid: unrecognized \
-                                             target-pointer-width {}", w)[])
+                                             target-pointer-width {}", w))
     };
 
     Config {
@@ -843,6 +847,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let parse_only = debugging_opts.parse_only;
     let no_trans = debugging_opts.no_trans;
+    let treat_err_as_bug = debugging_opts.treat_err_as_bug;
     let no_analysis = debugging_opts.no_analysis;
 
     if debugging_opts.debug_llvm {
@@ -863,7 +868,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
                     "dep-info" => OutputTypeDepInfo,
                     _ => {
                         early_error(&format!("unknown emission type: `{}`",
-                                            part)[])
+                                            part))
                     }
                 };
                 output_types.push(output_type)
@@ -955,7 +960,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
             (_, s) => {
                 early_error(&format!("unknown library kind `{}`, expected \
                                      one of dylib, framework, or static",
-                                    s)[]);
+                                    s));
             }
         };
         (name.to_string(), kind)
@@ -991,7 +996,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         Some(arg) => {
             early_error(&format!("argument for --color must be auto, always \
                                  or never (instead was `{}`)",
-                                arg)[])
+                                arg))
         }
     };
 
@@ -1030,6 +1035,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         test: test,
         parse_only: parse_only,
         no_trans: no_trans,
+        treat_err_as_bug: treat_err_as_bug,
         no_analysis: no_analysis,
         debugging_opts: debugging_opts,
         write_dependency_info: write_dependency_info,
@@ -1111,7 +1117,7 @@ mod test {
     #[test]
     fn test_switch_implies_cfg_test() {
         let matches =
-            &match getopts(&["--test".to_string()], &optgroups()[]) {
+            &match getopts(&["--test".to_string()], &optgroups()) {
               Ok(m) => m,
               Err(f) => panic!("test_switch_implies_cfg_test: {}", f)
             };
@@ -1128,7 +1134,7 @@ fn test_switch_implies_cfg_test() {
     fn test_switch_implies_cfg_test_unless_cfg_test() {
         let matches =
             &match getopts(&["--test".to_string(), "--cfg=test".to_string()],
-                           &optgroups()[]) {
+                           &optgroups()) {
               Ok(m) => m,
               Err(f) => {
                 panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
@@ -1148,7 +1154,7 @@ fn test_can_print_warnings() {
         {
             let matches = getopts(&[
                 "-Awarnings".to_string()
-            ], &optgroups()[]).unwrap();
+            ], &optgroups()).unwrap();
             let registry = diagnostics::registry::Registry::new(&[]);
             let sessopts = build_session_options(&matches);
             let sess = build_session(sessopts, None, registry);
@@ -1159,7 +1165,7 @@ fn test_can_print_warnings() {
             let matches = getopts(&[
                 "-Awarnings".to_string(),
                 "-Dwarnings".to_string()
-            ], &optgroups()[]).unwrap();
+            ], &optgroups()).unwrap();
             let registry = diagnostics::registry::Registry::new(&[]);
             let sessopts = build_session_options(&matches);
             let sess = build_session(sessopts, None, registry);
@@ -1169,7 +1175,7 @@ fn test_can_print_warnings() {
         {
             let matches = getopts(&[
                 "-Adead_code".to_string()
-            ], &optgroups()[]).unwrap();
+            ], &optgroups()).unwrap();
             let registry = diagnostics::registry::Registry::new(&[]);
             let sessopts = build_session_options(&matches);
             let sess = build_session(sessopts, None, registry);
index c1c5518887577d83462db5a07e032c48012f497e..99b2fce0607686193070e53e859611f6f4efd639 100644 (file)
@@ -27,8 +27,8 @@
 
 use rustc_back::target::Target;
 
-use std::env;
 use std::cell::{Cell, RefCell};
+use std::os;
 
 pub mod config;
 pub mod search_paths;
@@ -74,18 +74,27 @@ pub fn fatal(&self, msg: &str) -> ! {
         self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
+        if self.opts.treat_err_as_bug {
+            self.span_bug(sp, msg);
+        }
         match split_msg_into_multilines(msg) {
             Some(msg) => self.diagnostic().span_err(sp, &msg[..]),
             None => self.diagnostic().span_err(sp, msg)
         }
     }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
+        if self.opts.treat_err_as_bug {
+            self.span_bug(sp, msg);
+        }
         match split_msg_into_multilines(msg) {
             Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
             None => self.diagnostic().span_err_with_code(sp, msg, code)
         }
     }
     pub fn err(&self, msg: &str) {
+        if self.opts.treat_err_as_bug {
+            self.bug(msg);
+        }
         self.diagnostic().handler().err(msg)
     }
     pub fn err_count(&self) -> uint {
@@ -186,7 +195,7 @@ pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
     // cases later on
     pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
         self.span_bug(sp,
-                      &format!("impossible case reached: {}", msg)[]);
+                      &format!("impossible case reached: {}", msg));
     }
     pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
     pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
@@ -228,7 +237,7 @@ pub fn sysroot<'a>(&'a self) -> &'a Path {
     }
     pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
         filesearch::FileSearch::new(self.sysroot(),
-                                    &self.opts.target_triple[],
+                                    &self.opts.target_triple,
                                     &self.opts.search_paths,
                                     kind)
     }
@@ -280,9 +289,9 @@ fn split_msg_into_multilines(msg: &str) -> Option<String> {
     }
 
     let mut tail = &msg[head..];
-    let third = tail.find_str("(values differ")
-                   .or(tail.find_str("(lifetime"))
-                   .or(tail.find_str("(cyclic type of infinite size"));
+    let third = tail.find("(values differ")
+                   .or(tail.find("(lifetime"))
+                   .or(tail.find("(cyclic type of infinite size"));
     // Insert `\n` before any remaining messages which match.
     if let Some(pos) = third {
         // The end of the message may just be wrapped in `()` without
@@ -347,7 +356,7 @@ pub fn build_session_(sopts: config::Options,
         if path.is_absolute() {
             path.clone()
         } else {
-            env::current_dir().unwrap().join(&path)
+            os::getcwd().unwrap().join(&path)
         }
     );
 
@@ -370,7 +379,7 @@ pub fn build_session_(sopts: config::Options,
         plugin_registrar_fn: Cell::new(None),
         default_sysroot: default_sysroot,
         local_crate_source_file: local_crate_source_file,
-        working_dir: env::current_dir().unwrap(),
+        working_dir: os::getcwd().unwrap(),
         lint_store: RefCell::new(lint::LintStore::new()),
         lints: RefCell::new(NodeMap()),
         crate_types: RefCell::new(Vec::new()),
index c9d50b9cecf84ff005f033b439c589b5202a61fa..ca740f53782192de205ca915ea630785cd62bc1d 100644 (file)
@@ -14,7 +14,6 @@
 use std::collections::HashMap;
 use std::fmt::Debug;
 use std::hash::Hash;
-#[cfg(stage0)] use std::hash::Hasher;
 use std::iter::repeat;
 use std::time::Duration;
 use std::collections::hash_state::HashState;
@@ -139,57 +138,13 @@ pub fn block_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) -
 
 /// K: Eq + Hash<S>, V, S, H: Hasher<S>
 ///
-/// Determines whether there exists a path from `source` to `destination`.  The graph is defined by
-/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`.
+/// Determines whether there exists a path from `source` to `destination`.  The
+/// graph is defined by the `edges_map`, which maps from a node `S` to a list of
+/// its adjacent nodes `T`.
 ///
-/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
-/// very small graphs. If the graphs become larger, a more efficient graph representation and
-/// algorithm would probably be advised.
-#[cfg(stage0)]
-pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
-                       destination: T) -> bool
-    where S: HashState,
-          <S as HashState>::Hasher: Hasher<Output=u64>,
-          T: Hash<<S as HashState>::Hasher> + Eq + Clone,
-{
-    if source == destination {
-        return true;
-    }
-
-    // Do a little breadth-first-search here.  The `queue` list
-    // doubles as a way to detect if we've seen a particular FR
-    // before.  Note that we expect this graph to be an *extremely
-    // shallow* tree.
-    let mut queue = vec!(source);
-    let mut i = 0;
-    while i < queue.len() {
-        match edges_map.get(&queue[i]) {
-            Some(edges) => {
-                for target in edges {
-                    if *target == destination {
-                        return true;
-                    }
-
-                    if !queue.iter().any(|x| x == target) {
-                        queue.push((*target).clone());
-                    }
-                }
-            }
-            None => {}
-        }
-        i += 1;
-    }
-    return false;
-}
-/// K: Eq + Hash<S>, V, S, H: Hasher<S>
-///
-/// Determines whether there exists a path from `source` to `destination`.  The graph is defined by
-/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`.
-///
-/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
-/// very small graphs. If the graphs become larger, a more efficient graph representation and
-/// algorithm would probably be advised.
-#[cfg(not(stage0))]
+/// Efficiency note: This is implemented in an inefficient way because it is
+/// typically invoked on very small graphs. If the graphs become larger, a more
+/// efficient graph representation and algorithm would probably be advised.
 pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
                        destination: T) -> bool
     where S: HashState, T: Hash + Eq + Clone,
@@ -250,52 +205,6 @@ pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
 /// }
 /// ```
 #[inline(always)]
-#[cfg(stage0)]
-pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
-    where T: Clone + Hash<<S as HashState>::Hasher> + Eq,
-          U: Clone,
-          S: HashState,
-          <S as HashState>::Hasher: Hasher<Output=u64>,
-          F: FnOnce(T) -> U,
-{
-    let key = arg.clone();
-    let result = cache.borrow().get(&key).cloned();
-    match result {
-        Some(result) => result,
-        None => {
-            let result = f(arg);
-            cache.borrow_mut().insert(key, result.clone());
-            result
-        }
-    }
-}
-/// Memoizes a one-argument closure using the given RefCell containing
-/// a type implementing MutableMap to serve as a cache.
-///
-/// In the future the signature of this function is expected to be:
-/// ```
-/// pub fn memoized<T: Clone, U: Clone, M: MutableMap<T, U>>(
-///    cache: &RefCell<M>,
-///    f: &|T| -> U
-/// ) -> impl |T| -> U {
-/// ```
-/// but currently it is not possible.
-///
-/// # Example
-/// ```
-/// struct Context {
-///    cache: RefCell<HashMap<uint, uint>>
-/// }
-///
-/// fn factorial(ctxt: &Context, n: uint) -> uint {
-///     memoized(&ctxt.cache, n, |n| match n {
-///         0 | 1 => n,
-///         _ => factorial(ctxt, n - 2) + factorial(ctxt, n - 1)
-///     })
-/// }
-/// ```
-#[inline(always)]
-#[cfg(not(stage0))]
 pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
     where T: Clone + Hash + Eq,
           U: Clone,
@@ -303,7 +212,7 @@ pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) ->
           F: FnOnce(T) -> U,
 {
     let key = arg.clone();
-    let result = cache.borrow().get(&key).map(|result| result.clone());
+    let result = cache.borrow().get(&key).cloned();
     match result {
         Some(result) => result,
         None => {
index 1b07ce789e77c8e7713c3ff2f2831fde021fc818..b15da7dab3ee606627f78d4d53618fa47e55dfd8 100644 (file)
@@ -16,7 +16,6 @@
 use std::collections::{HashMap, HashSet};
 use std::default::Default;
 use std::hash::{Hasher, Hash};
-#[cfg(stage0)] use std::hash::Writer;
 use syntax::ast;
 
 pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
 pub type NodeSet = FnvHashSet<ast::NodeId>;
 pub type DefIdSet = FnvHashSet<ast::DefId>;
 
-#[cfg(stage0)]
-pub fn FnvHashMap<K: Hash<FnvHasher> + Eq, V>() -> FnvHashMap<K, V> {
-    Default::default()
-}
-#[cfg(stage0)]
-pub fn FnvHashSet<V: Hash<FnvHasher> + Eq>() -> FnvHashSet<V> {
-    Default::default()
-}
-#[cfg(not(stage0))]
 pub fn FnvHashMap<K: Hash + Eq, V>() -> FnvHashMap<K, V> {
     Default::default()
 }
-#[cfg(not(stage0))]
 pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
     Default::default()
 }
@@ -63,26 +52,6 @@ impl Default for FnvHasher {
     fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
 }
 
-#[cfg(stage0)]
-impl Hasher for FnvHasher {
-    type Output = u64;
-    fn reset(&mut self) { *self = Default::default(); }
-    fn finish(&self) -> u64 { self.0 }
-}
-
-#[cfg(stage0)]
-impl Writer for FnvHasher {
-    fn write(&mut self, bytes: &[u8]) {
-        let FnvHasher(mut hash) = *self;
-        for byte in bytes {
-            hash = hash ^ (*byte as u64);
-            hash = hash * 0x100000001b3;
-        }
-        *self = FnvHasher(hash);
-    }
-}
-
-#[cfg(not(stage0))]
 impl Hasher for FnvHasher {
     fn write(&mut self, bytes: &[u8]) {
         let FnvHasher(mut hash) = *self;
index 1d46c011bb32e7298334fa4a1ea5318b1565feb4..15b3c6d9d0602c7ed65a0ce39c560de1e99f4414 100644 (file)
@@ -20,7 +20,7 @@
 use middle::ty::{mt, Ty, ParamTy};
 use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn};
-use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
+use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup};
 use middle::ty::{ty_closure};
 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
@@ -29,7 +29,6 @@
 use std::collections::HashMap;
 use std::collections::hash_state::HashState;
 use std::hash::Hash;
-#[cfg(stage0)] use std::hash::Hasher;
 use std::rc::Rc;
 use syntax::abi;
 use syntax::ast_map;
@@ -58,12 +57,12 @@ pub fn note_and_explain_region(cx: &ctxt,
       (ref str, Some(span)) => {
         cx.sess.span_note(
             span,
-            &format!("{}{}{}", prefix, *str, suffix)[]);
+            &format!("{}{}{}", prefix, *str, suffix));
         Some(span)
       }
       (ref str, None) => {
         cx.sess.note(
-            &format!("{}{}{}", prefix, *str, suffix)[]);
+            &format!("{}{}{}", prefix, *str, suffix));
         None
       }
     }
@@ -274,7 +273,7 @@ fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>,
         };
 
         if abi != abi::Rust {
-            s.push_str(&format!("extern {} ", abi.to_string())[]);
+            s.push_str(&format!("extern {} ", abi.to_string()));
         };
 
         s.push_str("fn");
@@ -330,7 +329,7 @@ fn push_sig_to_string<'tcx>(cx: &ctxt<'tcx>,
             ty::FnConverging(t) => {
                 if !ty::type_is_nil(t) {
                    s.push_str(" -> ");
-                   s.push_str(&ty_to_string(cx, t)[]);
+                   s.push_str(&ty_to_string(cx, t));
                 }
             }
             ty::FnDiverging => {
@@ -367,11 +366,9 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
         }
         ty_rptr(r, ref tm) => {
             let mut buf = region_ptr_to_string(cx, *r);
-            buf.push_str(&mt_to_string(cx, tm)[]);
+            buf.push_str(&mt_to_string(cx, tm));
             buf
         }
-        ty_open(typ) =>
-            format!("opened<{}>", ty_to_string(cx, typ)),
         ty_tup(ref elems) => {
             let strs = elems
                 .iter()
@@ -561,7 +558,7 @@ pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
                 } else if strs[0].starts_with("(") && strs[0].ends_with(")") {
                     &strs[0][1 .. strs[0].len() - 1] // Remove '(' and ')'
                 } else {
-                    &strs[0][]
+                    &strs[0][..]
                 },
                 tail)
     } else if strs.len() > 0 {
@@ -1434,23 +1431,6 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
     }
 }
 
-#[cfg(stage0)]
-impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
-    where K: Hash<<S as HashState>::Hasher> + Eq + Repr<'tcx>,
-          V: Repr<'tcx>,
-          S: HashState,
-          <S as HashState>::Hasher: Hasher<Output=u64>,
-{
-    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("HashMap({})",
-                self.iter()
-                    .map(|(k,v)| format!("{} => {}", k.repr(tcx), v.repr(tcx)))
-                    .collect::<Vec<String>>()
-                    .connect(", "))
-    }
-}
-
-#[cfg(not(stage0))]
 impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
     where K: Hash + Eq + Repr<'tcx>,
           V: Repr<'tcx>,
index c45ee258342ec1be9c24a8f83d03f2bdae694488..3fcae6a8034c207ac3408c2beb3ea76bdf2f97cb 100644 (file)
@@ -14,7 +14,7 @@
 use std::old_io::process::{Command, ProcessOutput};
 use std::old_io::{fs, TempDir};
 use std::old_io;
-use std::env;
+use std::os;
 use std::str;
 use syntax::diagnostic::Handler as ErrorHandler;
 
@@ -73,19 +73,19 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
         Ok(prog) => {
             let o = prog.wait_with_output().unwrap();
             if !o.status.success() {
-                handler.err(&format!("{:?} failed with: {}", cmd, o.status)[]);
+                handler.err(&format!("{:?} failed with: {}", cmd, o.status));
                 handler.note(&format!("stdout ---\n{}",
-                                  str::from_utf8(&o.output[]).unwrap())[]);
+                                  str::from_utf8(&o.output).unwrap()));
                 handler.note(&format!("stderr ---\n{}",
-                                  str::from_utf8(&o.error[]).unwrap())
-                             []);
+                                  str::from_utf8(&o.error).unwrap())
+                             );
                 handler.abort_if_errors();
             }
             o
         },
         Err(e) => {
             handler.err(&format!("could not exec `{}`: {}", &ar[..],
-                             e)[]);
+                             e));
             handler.abort_if_errors();
             panic!("rustc::back::archive::run_ar() should not reach this point");
         }
@@ -110,7 +110,7 @@ pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
     }
     handler.fatal(&format!("could not find native static library `{}`, \
                            perhaps an -L flag is missing?",
-                          name)[]);
+                          name));
 }
 
 impl<'a> Archive<'a> {
@@ -142,7 +142,7 @@ pub fn remove_file(&mut self, file: &str) {
     /// Lists all files in an archive
     pub fn files(&self) -> Vec<String> {
         let output = run_ar(self.handler, &self.maybe_ar_prog, "t", None, &[&self.dst]);
-        let output = str::from_utf8(&output.output[]).unwrap();
+        let output = str::from_utf8(&output.output).unwrap();
         // use lines_any because windows delimits output with `\r\n` instead of
         // just `\n`
         output.lines_any().map(|s| s.to_string()).collect()
@@ -174,9 +174,9 @@ pub fn create(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> {
     /// search in the relevant locations for a library named `name`.
     pub fn add_native_library(&mut self, name: &str) -> old_io::IoResult<()> {
         let location = find_library(name,
-                                    &self.archive.slib_prefix[],
-                                    &self.archive.slib_suffix[],
-                                    &self.archive.lib_search_paths[],
+                                    &self.archive.slib_prefix,
+                                    &self.archive.slib_suffix,
+                                    &self.archive.lib_search_paths,
                                     self.archive.handler);
         self.add_archive(&location, name, |_| false)
     }
@@ -224,7 +224,7 @@ pub fn update_symbols(&mut self) {
     pub fn build(self) -> Archive<'a> {
         // Get an absolute path to the destination, so `ar` will work even
         // though we run it from `self.work_dir`.
-        let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
+        let abs_dst = os::getcwd().unwrap().join(&self.archive.dst);
         assert!(!abs_dst.is_relative());
         let mut args = vec![&abs_dst];
         let mut total_len = abs_dst.as_vec().len();
@@ -283,7 +283,7 @@ fn add_archive<F>(&mut self, archive: &Path, name: &str,
         // First, extract the contents of the archive to a temporary directory.
         // We don't unpack directly into `self.work_dir` due to the possibility
         // of filename collisions.
-        let archive = env::current_dir().unwrap().join(archive);
+        let archive = os::getcwd().unwrap().join(archive);
         run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
                "x", Some(loc.path()), &[&archive]);
 
index a4417b49f1c41e771fd65a0e18dbc692183597dd..7325e4e7a2ece9aa4a15bee6e35c2820e4159a0c 100644 (file)
@@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index acf49d1ca46e3b6d7a3c55cc44a607d48aea0681..99a1df95a80cddf398549aa2226f3d48fb2be119 100644 (file)
 
 use std::old_io;
 use std::old_io::fs;
-use std::env;
+use std::os;
 
 /// Returns an absolute path in the filesystem that `path` points to. The
 /// returned path does not contain any symlinks in its hierarchy.
 pub fn realpath(original: &Path) -> old_io::IoResult<Path> {
     static MAX_LINKS_FOLLOWED: uint = 256;
-    let original = try!(env::current_dir()).join(original);
+    let original = try!(os::getcwd()).join(original);
 
     // Right now lstat on windows doesn't work quite well
     if cfg!(windows) {
index d589b063204c7d2d0fa903d6ff2848cd2de84454..711f937d2f355991e5cc6ac1f97b6d47ffb93734 100644 (file)
@@ -41,6 +41,7 @@
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(env)]
+#![feature(path)]
 
 extern crate syntax;
 extern crate serialize;
index cb44fe117f54645d7740dd287e0355f2b3fb40d1..b46150f75d084516102e96252fc7017489955254 100644 (file)
@@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
             "E-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index 7ee357fb1eaf35d7a28c8e4ea5c1559872535119..c7fa7aa879ac272c440982fe5ece76fadd3a70c0 100644 (file)
@@ -56,7 +56,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 -a:0:64-n32".to_string()
           }
 
-          abi::OsFreebsd | abi::OsDragonfly | abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
             "e-p:32:32:32\
                 -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
                 -f32:32:32-f64:64:64\
index e7419d4bec30747717d0bf68c88a3a26db383d7b..943ff52925a244545de15c4856f252db57bf7991 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use std::collections::HashSet;
 use std::env;
 use std::old_io::IoError;
+use std::os;
 use syntax::ast;
 
 pub struct RPathConfig<F, G> where
@@ -49,7 +49,7 @@ pub fn get_rpath_flags<F, G>(config: RPathConfig<F, G>) -> Vec<String> where
 fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
     let mut ret = Vec::new();
     for rpath in rpaths {
-        ret.push(format!("-Wl,-rpath,{}", &(*rpath)[]));
+        ret.push(format!("-Wl,-rpath,{}", &(*rpath)));
     }
     return ret;
 }
@@ -109,7 +109,7 @@ fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path
         "$ORIGIN"
     };
 
-    let cwd = env::current_dir().unwrap();
+    let cwd = os::getcwd().unwrap();
     let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
     lib.pop();
     let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
@@ -129,7 +129,7 @@ fn get_install_prefix_rpath<F, G>(config: RPathConfig<F, G>) -> String where
     let path = (config.get_install_prefix_lib_path)();
     let path = env::current_dir().unwrap().join(&path);
     // FIXME (#9639): This needs to handle non-utf8 paths
-    path.as_str().expect("non-utf8 component in rpath").to_string()
+    path.to_str().expect("non-utf8 component in rpath").to_string()
 }
 
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
@@ -212,6 +212,7 @@ fn test_rpath_relative() {
     #[test]
     #[cfg(any(target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     fn test_rpath_relative() {
         let config = &mut RPathConfig {
index c33d10bfbab39aaef7a08149d03304f76cfe0230..e16df61c25c47a9e83c97746f13b61ab3c13f41c 100644 (file)
@@ -64,7 +64,7 @@ pub fn new(hash: &str) -> Svh {
     }
 
     pub fn as_str<'a>(&'a self) -> &'a str {
-        &self.hash[]
+        &self.hash
     }
 
     pub fn calculate(metadata: &Vec<String>, krate: &ast::Crate) -> Svh {
@@ -244,8 +244,7 @@ pub enum SawExprComponent<'a> {
         SawExprAssignOp(ast::BinOp_),
         SawExprIndex,
         SawExprRange,
-        SawExprPath,
-        SawExprQPath,
+        SawExprPath(Option<usize>),
         SawExprAddrOf(ast::Mutability),
         SawExprRet,
         SawExprInlineAsm(&'a ast::InlineAsm),
@@ -277,8 +276,7 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
             ExprTupField(_, id)      => SawExprTupField(id.node),
             ExprIndex(..)            => SawExprIndex,
             ExprRange(..)            => SawExprRange,
-            ExprPath(..)             => SawExprPath,
-            ExprQPath(..)            => SawExprQPath,
+            ExprPath(ref qself, _)   => SawExprPath(qself.as_ref().map(|q| q.position)),
             ExprAddrOf(m, _)         => SawExprAddrOf(m),
             ExprBreak(id)            => SawExprBreak(id.map(content)),
             ExprAgain(id)            => SawExprAgain(id.map(content)),
@@ -329,7 +327,7 @@ fn visit_mac(&mut self, mac: &Mac) {
             // macro invocations, namely macro_rules definitions,
             // *can* appear as items, even in the expanded crate AST.
 
-            if &macro_name(mac)[] == "macro_rules" {
+            if &macro_name(mac)[..] == "macro_rules" {
                 // Pretty-printing definition to a string strips out
                 // surface artifacts (currently), such as the span
                 // information, yielding a content-based hash.
@@ -356,7 +354,7 @@ fn visit_mac(&mut self, mac: &Mac) {
             fn macro_name(mac: &Mac) -> token::InternedString {
                 match &mac.node {
                     &MacInvocTT(ref path, ref _tts, ref _stx_ctxt) => {
-                        let s = &path.segments[];
+                        let s = &path.segments;
                         assert_eq!(s.len(), 1);
                         content(s[0].identifier)
                     }
diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_back/target/bitrig_base.rs
new file mode 100644 (file)
index 0000000..6e5a48c
--- /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.
+
+use target::TargetOptions;
+use std::default::Default;
+
+pub fn opts() -> TargetOptions {
+    TargetOptions {
+        linker: "cc".to_string(),
+        dynamic_linking: true,
+        executables: true,
+        morestack: false,
+        linker_is_gnu: true,
+        has_rpath: true,
+        position_independent_executables: true,
+        pre_link_args: vec!(
+        ),
+
+        .. Default::default()
+    }
+}
index 01a5f0d6e20f881c481ad0e62f8153fdc21d3ece..d09a7c355d3e3c32ef00aa2d1f819f1d9d39ff26 100644 (file)
@@ -56,6 +56,7 @@
 mod apple_ios_base;
 mod freebsd_base;
 mod dragonfly_base;
+mod bitrig_base;
 mod openbsd_base;
 
 mod armv7_apple_ios;
@@ -80,6 +81,7 @@
 mod x86_64_pc_windows_gnu;
 mod x86_64_unknown_freebsd;
 mod x86_64_unknown_dragonfly;
+mod x86_64_unknown_bitrig;
 mod x86_64_unknown_linux_gnu;
 mod x86_64_unknown_openbsd;
 
@@ -237,7 +239,7 @@ pub fn from_json(obj: Json) -> Target {
                      .and_then(|os| os.map(|s| s.to_string())) {
                 Some(val) => val,
                 None =>
-                    handler.fatal(&format!("Field {} in target specification is required", name)[])
+                    handler.fatal(&format!("Field {} in target specification is required", name))
             }
         };
 
@@ -308,6 +310,7 @@ macro_rules! key {
     /// JSON decoding.
     pub fn search(target: &str) -> Result<Target, String> {
         use std::env;
+        use std::os;
         use std::ffi::OsString;
         use std::old_io::File;
         use std::old_path::Path;
@@ -361,6 +364,7 @@ macro_rules! load_specific {
             i686_unknown_dragonfly,
             x86_64_unknown_dragonfly,
 
+            x86_64_unknown_bitrig,
             x86_64_unknown_openbsd,
 
             x86_64_apple_darwin,
@@ -393,7 +397,7 @@ macro_rules! load_specific {
 
         // FIXME 16351: add a sane default search path?
 
-        for dir in env::split_paths(&target_path) {
+        for dir in os::split_paths(target_path.to_str().unwrap()).iter() {
             let p =  dir.join(path.clone());
             if p.is_file() {
                 return load_file(&p);
index 42220a87bd414891ea17830790cdfcdeefeaeb9d..759147b939cb850a5f84279de7d8859e850c9c9d 100644 (file)
@@ -20,6 +20,11 @@ pub fn opts() -> TargetOptions {
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec!(
+            // GNU-style linkers will use this to omit linking to libraries
+            // which don't actually fulfill any relocations, but only for
+            // libraries which follow this flag.  Thus, use it before
+            // specifying libraries to link to.
+            "-Wl,--as-needed".to_string(),
         ),
         position_independent_executables: true,
         .. Default::default()
diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_back/target/x86_64_unknown_bitrig.rs
new file mode 100644 (file)
index 0000000..7b7877c
--- /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.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::bitrig_base::opts();
+    base.pre_link_args.push("-m64".to_string());
+
+    Target {
+        data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                     f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
+                     s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
+        llvm_target: "x86_64-unknown-bitrig".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "bitrig".to_string(),
+        options: base,
+    }
+}
index 9d1b7347d0651039a799e10bccfd7e3a1113fd21..1c6eacc355947850044b035fb5d6db4f8690a1c9 100644 (file)
@@ -45,13 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
             "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
           }
 
-          abi::OsFreebsd => {
-            "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
-          }
-          abi::OsDragonfly => {
-            "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
-          }
-          abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
             "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string()
           }
 
index 2f13bb3158119ad6e8a8f1661bd36b2014f431f7..d016bd12c698fdd5646cafbf4f5c7e298ba10c7a 100644 (file)
@@ -47,17 +47,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
           }
 
-          abi::OsFreebsd => {
-            "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
-                s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
-          }
-          abi::OsDragonfly => {
-            "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
-                f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
-                s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
-          }
-          abi::OsOpenbsd => {
+          abi::OsFreebsd | abi::OsDragonfly | abi::OsBitrig | abi::OsOpenbsd => {
             "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
                 f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
                 s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
index c5a304289227117c4840801cc637928790e4f769..08f0897e7617e918e320dedd16d3ae3201cdd45b 100644 (file)
@@ -53,8 +53,8 @@ Here `x` represents some variable, `LV.f` is a field reference,
 and `*LV` is a pointer dereference. There is no auto-deref or other
 niceties. This means that if you have a type like:
 
-```text
-struct S { f: uint }
+```rust
+struct S { f: i32 }
 ```
 
 and a variable `a: Box<S>`, then the rust expression `a.f` would correspond
@@ -63,8 +63,8 @@ to an `LV` of `(*a).f`.
 Here is the formal grammar for the types we'll consider:
 
 ```text
-TY = () | S<'LT...> | Box<TY> | & 'LT MQ TY
-MQ = mut | imm | const
+TY = i32 | bool | S<'LT...> | Box<TY> | & 'LT MQ TY
+MQ = mut | imm
 ```
 
 Most of these types should be pretty self explanatory. Here `S` is a
@@ -82,13 +82,13 @@ SD = struct S<'LT...> { (f: TY)... }
 
 Now, imagine we had a program like this:
 
-```text
-struct Foo { f: uint, g: uint }
+```rust
+struct Foo { f: i32, g: i32 }
 ...
 'a: {
-  let mut x: Box<Foo> = ...;
-  let y = &mut (*x).f;
-  x = ...;
+    let mut x: Box<Foo> = ...;
+    let y = &mut (*x).f;
+    x = ...;
 }
 ```
 
@@ -198,7 +198,7 @@ The kinds of expressions which in-scope loans can render illegal are:
 
 Now that we hopefully have some kind of intuitive feeling for how the
 borrow checker works, let's look a bit more closely now at the precise
-conditions that it uses. For simplicity I will ignore const loans.
+conditions that it uses.
 
 I will present the rules in a modified form of standard inference
 rules, which looks as follows:
@@ -261,12 +261,11 @@ that will go into the final loan. We'll discuss in more detail below.
 ## Checking mutability
 
 Checking mutability is fairly straightforward. We just want to prevent
-immutable data from being borrowed as mutable. Note that it is ok to
-borrow mutable data as immutable, since that is simply a
-freeze. Formally we define a predicate `MUTABLE(LV, MQ)` which, if
-defined, means that "borrowing `LV` with mutability `MQ` is ok. The
-Rust code corresponding to this predicate is the function
-`check_mutability` in `middle::borrowck::gather_loans`.
+immutable data from being borrowed as mutable. Note that it is ok to borrow
+mutable data as immutable, since that is simply a freeze. The judgement
+`MUTABILITY(LV, MQ)` means the mutability of `LV` is compatible with a borrow
+of mutability `MQ`. The Rust code corresponding to this predicate is the
+function `check_mutability` in `middle::borrowck::gather_loans`.
 
 ### Checking mutability of variables
 
@@ -275,15 +274,14 @@ but also the code in `mem_categorization`.
 
 Let's begin with the rules for variables, which state that if a
 variable is declared as mutable, it may be borrowed any which way, but
-otherwise the variable must be borrowed as immutable or const:
+otherwise the variable must be borrowed as immutable:
 
 ```text
 MUTABILITY(X, MQ)                   // M-Var-Mut
   DECL(X) = mut
 
-MUTABILITY(X, MQ)                   // M-Var-Imm
+MUTABILITY(X, imm)                  // M-Var-Imm
   DECL(X) = imm
-  MQ = imm | const
 ```
 
 ### Checking mutability of owned content
@@ -304,12 +302,11 @@ MUTABILITY(*LV, MQ)                 // M-Deref-Unique
 ### Checking mutability of immutable pointer types
 
 Immutable pointer types like `&T` can only
-be borrowed if MQ is immutable or const:
+be borrowed if MQ is immutable:
 
 ```text
-MUTABILITY(*LV, MQ)                // M-Deref-Borrowed-Imm
+MUTABILITY(*LV, imm)               // M-Deref-Borrowed-Imm
   TYPE(LV) = &Ty
-  MQ == imm | const
 ```
 
 ### Checking mutability of mutable pointer types
@@ -323,12 +320,11 @@ MUTABILITY(*LV, MQ)                 // M-Deref-Borrowed-Mut
 
 ## Checking aliasability
 
-The goal of the aliasability check is to ensure that we never permit
-`&mut` borrows of aliasable data. Formally we define a predicate
-`ALIASABLE(LV, MQ)` which if defined means that
-"borrowing `LV` with mutability `MQ` is ok". The
-Rust code corresponding to this predicate is the function
-`check_aliasability()` in `middle::borrowck::gather_loans`.
+The goal of the aliasability check is to ensure that we never permit `&mut`
+borrows of aliasable data. The judgement `ALIASABLE(LV, MQ)` means the
+aliasability of `LV` is compatible with a borrow of mutability `MQ`. The Rust
+code corresponding to this predicate is the function `check_aliasability()` in
+`middle::borrowck::gather_loans`.
 
 ### Checking aliasability of variables
 
@@ -379,40 +375,6 @@ Formally, we define a predicate `LIFETIME(LV, LT, MQ)`, which states that
 `MQ`". The Rust code corresponding to this predicate is the module
 `middle::borrowck::gather_loans::lifetime`.
 
-### The Scope function
-
-Several of the rules refer to a helper function `SCOPE(LV)=LT`.  The
-`SCOPE(LV)` yields the lifetime `LT` for which the lvalue `LV` is
-guaranteed to exist, presuming that no mutations occur.
-
-The scope of a local variable is the block where it is declared:
-
-```text
-  SCOPE(X) = block where X is declared
-```
-
-The scope of a field is the scope of the struct:
-
-```text
-  SCOPE(LV.f) = SCOPE(LV)
-```
-
-The scope of a unique referent is the scope of the pointer, since
-(barring mutation or moves) the pointer will not be freed until
-the pointer itself `LV` goes out of scope:
-
-```text
-  SCOPE(*LV) = SCOPE(LV) if LV has type Box<T>
-```
-
-The scope of a borrowed referent is the scope associated with the
-pointer.  This is a conservative approximation, since the data that
-the pointer points at may actually live longer:
-
-```text
-  SCOPE(*LV) = LT if LV has type &'LT T or &'LT mut T
-```
-
 ### Checking lifetime of variables
 
 The rule for variables states that a variable can only be borrowed a
@@ -420,7 +382,7 @@ lifetime `LT` that is a subregion of the variable's scope:
 
 ```text
 LIFETIME(X, LT, MQ)                 // L-Local
-  LT <= SCOPE(X)
+  LT <= block where X is declared
 ```
 
 ### Checking lifetime for owned content
@@ -466,15 +428,12 @@ are computed based on the kind of borrow:
 ```text
 &mut LV =>   RESTRICTIONS(LV, LT, MUTATE|CLAIM|FREEZE)
 &LV =>       RESTRICTIONS(LV, LT, MUTATE|CLAIM)
-&const LV => RESTRICTIONS(LV, LT, [])
 ```
 
 The reasoning here is that a mutable borrow must be the only writer,
 therefore it prevents other writes (`MUTATE`), mutable borrows
 (`CLAIM`), and immutable borrows (`FREEZE`). An immutable borrow
 permits other immutable borrows but forbids writes and mutable borrows.
-Finally, a const borrow just wants to be sure that the value is not
-moved out from under it, so no actions are forbidden.
 
 ### Restrictions for loans of a local variable
 
@@ -548,8 +507,8 @@ specify that the lifetime of the loan must be less than the lifetime
 of the `&Ty` pointer. In simple cases, this clause is redundant, since
 the `LIFETIME()` function will already enforce the required rule:
 
-```
-fn foo(point: &'a Point) -> &'static f32 {
+```rust
+fn foo(point: &'a Point) -> &'static i32 {
     &point.x // Error
 }
 ```
@@ -558,8 +517,8 @@ The above example fails to compile both because of clause (1) above
 but also by the basic `LIFETIME()` check. However, in more advanced
 examples involving multiple nested pointers, clause (1) is needed:
 
-```
-fn foo(point: &'a &'b mut Point) -> &'b f32 {
+```rust
+fn foo(point: &'a &'b mut Point) -> &'b i32 {
     &point.x // Error
 }
 ```
@@ -577,8 +536,8 @@ which is only `'a`, not `'b`. Hence this example yields an error.
 As a final twist, consider the case of two nested *immutable*
 pointers, rather than a mutable pointer within an immutable one:
 
-```
-fn foo(point: &'a &'b Point) -> &'b f32 {
+```rust
+fn foo(point: &'a &'b Point) -> &'b i32 {
     &point.x // OK
 }
 ```
@@ -599,8 +558,8 @@ The rules pertaining to `LIFETIME` exist to ensure that we don't
 create a borrowed pointer that outlives the memory it points at. So
 `LIFETIME` prevents a function like this:
 
-```
-fn get_1<'a>() -> &'a int {
+```rust
+fn get_1<'a>() -> &'a i32 {
     let x = 1;
     &x
 }
@@ -619,8 +578,8 @@ after we return and hence the remaining code in `'a` cannot possibly
 mutate it. This distinction is important for type checking functions
 like this one:
 
-```
-fn inc_and_get<'a>(p: &'a mut Point) -> &'a int {
+```rust
+fn inc_and_get<'a>(p: &'a mut Point) -> &'a i32 {
     p.x += 1;
     &p.x
 }
@@ -641,19 +600,6 @@ in terms of capability, the caller passed in the ability to mutate
 `*p` is borrowed since that would be a move of `p`, as `&mut` pointers
 are affine.)
 
-### Restrictions for loans of const aliasable referents
-
-Freeze pointers are read-only. There may be `&mut` or `&` aliases, and
-we can not prevent *anything* but moves in that case. So the
-`RESTRICTIONS` function is only defined if `ACTIONS` is the empty set.
-Because moves from a `&const` lvalue are never legal, it is not
-necessary to add any restrictions at all to the final result.
-
-```text
-    RESTRICTIONS(*LV, LT, []) = []                // R-Deref-Freeze-Borrowed
-      TYPE(LV) = &const Ty
-```
-
 ### Restrictions for loans of mutable borrowed referents
 
 Mutable borrowed pointers are guaranteed to be the only way to mutate
@@ -685,7 +631,7 @@ maximum of `LT'`.
 
 Here is a concrete example of a bug this rule prevents:
 
-```
+```rust
 // Test region-reborrow-from-shorter-mut-ref.rs:
 fn copy_pointer<'a,'b,T>(x: &'a mut &'b mut T) -> &'b mut T {
     &mut **p // ERROR due to clause (1)
@@ -713,10 +659,10 @@ ways to violate the rules is to move the base pointer to a new name
 and access it via that new name, thus bypassing the restrictions on
 the old name. Here is an example:
 
-```
+```rust
 // src/test/compile-fail/borrowck-move-mut-base-ptr.rs
-fn foo(t0: &mut int) {
-    let p: &int = &*t0; // Freezes `*t0`
+fn foo(t0: &mut i32) {
+    let p: &i32 = &*t0; // Freezes `*t0`
     let t1 = t0;        //~ ERROR cannot move out of `t0`
     *t1 = 22;           // OK, not a write through `*t0`
 }
@@ -733,11 +679,11 @@ danger is to mutably borrow the base path. This can lead to two bad
 scenarios. The most obvious is that the mutable borrow itself becomes
 another path to access the same data, as shown here:
 
-```
+```rust
 // src/test/compile-fail/borrowck-mut-borrow-of-mut-base-ptr.rs
-fn foo<'a>(mut t0: &'a mut int,
-           mut t1: &'a mut int) {
-    let p: &int = &*t0;     // Freezes `*t0`
+fn foo<'a>(mut t0: &'a mut i32,
+           mut t1: &'a mut i32) {
+    let p: &i32 = &*t0;     // Freezes `*t0`
     let mut t2 = &mut t0;   //~ ERROR cannot borrow `t0`
     **t2 += 1;              // Mutates `*t0`
 }
@@ -754,11 +700,11 @@ of `t0`. Hence the claim `&mut t0` is illegal.
 Another danger with an `&mut` pointer is that we could swap the `t0`
 value away to create a new path:
 
-```
+```rust
 // src/test/compile-fail/borrowck-swap-mut-base-ptr.rs
-fn foo<'a>(mut t0: &'a mut int,
-           mut t1: &'a mut int) {
-    let p: &int = &*t0;     // Freezes `*t0`
+fn foo<'a>(mut t0: &'a mut i32,
+           mut t1: &'a mut i32) {
+    let p: &i32 = &*t0;     // Freezes `*t0`
     swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0`
     *t1 = 22;
 }
@@ -772,37 +718,37 @@ careful to ensure this example is still illegal.
 referent is claimed, even freezing the base pointer can be dangerous,
 as shown in the following example:
 
-```
+```rust
 // src/test/compile-fail/borrowck-borrow-of-mut-base-ptr.rs
-fn foo<'a>(mut t0: &'a mut int,
-           mut t1: &'a mut int) {
-    let p: &mut int = &mut *t0; // Claims `*t0`
+fn foo<'a>(mut t0: &'a mut i32,
+           mut t1: &'a mut i32) {
+    let p: &mut i32 = &mut *t0; // Claims `*t0`
     let mut t2 = &t0;           //~ ERROR cannot borrow `t0`
-    let q: &int = &*t2;         // Freezes `*t0` but not through `*p`
+    let q: &i32 = &*t2;         // Freezes `*t0` but not through `*p`
     *p += 1;                    // violates type of `*q`
 }
 ```
 
 Here the problem is that `*t0` is claimed by `p`, and hence `p` wants
 to be the controlling pointer through which mutation or freezes occur.
-But `t2` would -- if it were legal -- have the type `& &mut int`, and
+But `t2` would -- if it were legal -- have the type `& &mut i32`, and
 hence would be a mutable pointer in an aliasable location, which is
 considered frozen (since no one can write to `**t2` as it is not a
-unique path). Therefore, we could reasonably create a frozen `&int`
+unique path). Therefore, we could reasonably create a frozen `&i32`
 pointer pointing at `*t0` that coexists with the mutable pointer `p`,
 which is clearly unsound.
 
 However, it is not always unsafe to freeze the base pointer. In
 particular, if the referent is frozen, there is no harm in it:
 
-```
+```rust
 // src/test/run-pass/borrowck-borrow-of-mut-base-ptr-safe.rs
-fn foo<'a>(mut t0: &'a mut int,
-           mut t1: &'a mut int) {
-    let p: &int = &*t0; // Freezes `*t0`
+fn foo<'a>(mut t0: &'a mut i32,
+           mut t1: &'a mut i32) {
+    let p: &i32 = &*t0; // Freezes `*t0`
     let mut t2 = &t0;
-    let q: &int = &*t2; // Freezes `*t0`, but that's ok...
-    let r: &int = &*t0; // ...after all, could do same thing directly.
+    let q: &i32 = &*t2; // Freezes `*t0`, but that's ok...
+    let r: &i32 = &*t0; // ...after all, could do same thing directly.
 }
 ```
 
@@ -811,11 +757,11 @@ thing `t2` can be used for is to further freeze `*t0`, which is
 already frozen. In particular, we cannot assign to `*t0` through the
 new alias `t2`, as demonstrated in this test case:
 
-```
+```rust
 // src/test/run-pass/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs
-fn foo(t0: & &mut int) {
+fn foo(t0: & &mut i32) {
     let t1 = t0;
-    let p: &int = &**t0;
+    let p: &i32 = &**t0;
     **t1 = 22; //~ ERROR cannot assign
 }
 ```
@@ -855,6 +801,9 @@ prohibited from both freezes and claims. This would avoid the need to
 prevent `const` borrows of the base pointer when the referent is
 borrowed.
 
+[ Previous revisions of this document discussed `&const` in more detail.
+See the revision history. ]
+
 # Moves and initialization
 
 The borrow checker is also in charge of ensuring that:
@@ -881,9 +830,9 @@ moves/uninitializations of the variable that is being used.
 
 Let's look at a simple example:
 
-```
-fn foo(a: Box<int>) {
-    let b: Box<int>;   // Gen bit 0.
+```rust
+fn foo(a: Box<i32>) {
+    let b: Box<i32>;   // Gen bit 0.
 
     if cond {          // Bits: 0
         use(&*a);
@@ -897,7 +846,7 @@ fn foo(a: Box<int>) {
     use(&*b);          // Error.
 }
 
-fn use(a: &int) { }
+fn use(a: &i32) { }
 ```
 
 In this example, the variable `b` is created uninitialized. In one
@@ -1028,8 +977,8 @@ not) the destructor invocation for that path.
 A simple example of this is the following:
 
 ```rust
-struct D { p: int }
-impl D { fn new(x: int) -> D { ... }
+struct D { p: i32 }
+impl D { fn new(x: i32) -> D { ... }
 impl Drop for D { ... }
 
 fn foo(a: D, b: D, t: || -> bool) {
@@ -1142,7 +1091,7 @@ the elements of an array that has been passed by value, such as
 the following:
 
 ```rust
-fn foo(a: [D; 10], i: uint) -> D {
+fn foo(a: [D; 10], i: i32) -> D {
     a[i]
 }
 ```
@@ -1158,7 +1107,7 @@ all-but-one element of the array.  A place where that distinction
 would arise is the following:
 
 ```rust
-fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D {
+fn foo(a: [D; 10], b: [D; 10], i: i32, t: bool) -> D {
     if t {
         a[i]
     } else {
@@ -1173,7 +1122,7 @@ fn foo(a: [D; 10], b: [D; 10], i: uint, t: bool) -> D {
 
 There are a number of ways that the trans backend could choose to
 compile this (e.g. a `[bool; 10]` array for each such moved array;
-or an `Option<uint>` for each moved array).  From the viewpoint of the
+or an `Option<usize>` for each moved array).  From the viewpoint of the
 borrow-checker, the important thing is to record what kind of fragment
 is implied by the relevant moves.
 
index abe01d193b4929b308f04dc3051b7cff761ccec5..23ca5b636815b0ae8512de888a10f3bd1a25947f 100644 (file)
@@ -466,7 +466,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                         new_loan.span,
                         &format!("cannot borrow `{}`{} as mutable \
                                 more than once at a time",
-                                nl, new_loan_msg)[])
+                                nl, new_loan_msg))
                 }
 
                 (ty::UniqueImmBorrow, _) => {
@@ -474,7 +474,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                         new_loan.span,
                         &format!("closure requires unique access to `{}` \
                                 but {} is already borrowed{}",
-                                nl, ol_pronoun, old_loan_msg)[]);
+                                nl, ol_pronoun, old_loan_msg));
                 }
 
                 (_, ty::UniqueImmBorrow) => {
@@ -482,7 +482,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                         new_loan.span,
                         &format!("cannot borrow `{}`{} as {} because \
                                 previous closure requires unique access",
-                                nl, new_loan_msg, new_loan.kind.to_user_str())[]);
+                                nl, new_loan_msg, new_loan.kind.to_user_str()));
                 }
 
                 (_, _) => {
@@ -495,7 +495,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                                 new_loan.kind.to_user_str(),
                                 ol_pronoun,
                                 old_loan.kind.to_user_str(),
-                                old_loan_msg)[]);
+                                old_loan_msg));
                 }
             }
 
@@ -504,7 +504,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
                     self.bccx.span_note(
                         span,
                         &format!("borrow occurs due to use of `{}` in closure",
-                                nl)[]);
+                                nl));
                 }
                 _ => { }
             }
@@ -553,7 +553,7 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
 
             self.bccx.span_note(
                 old_loan.span,
-                &format!("{}; {}", borrow_summary, rule_summary)[]);
+                &format!("{}; {}", borrow_summary, rule_summary));
 
             let old_loan_span = self.tcx().map.span(old_loan.kill_scope.node_id());
             self.bccx.span_end_note(old_loan_span,
@@ -623,13 +623,13 @@ fn check_for_copy_of_frozen_path(&self,
                 self.bccx.span_err(
                     span,
                     &format!("cannot use `{}` because it was mutably borrowed",
-                            &self.bccx.loan_path_to_string(copy_path)[])
-                    []);
+                            &self.bccx.loan_path_to_string(copy_path))
+                    );
                 self.bccx.span_note(
                     loan_span,
                     &format!("borrow of `{}` occurs here",
-                            &self.bccx.loan_path_to_string(&*loan_path)[])
-                    []);
+                            &self.bccx.loan_path_to_string(&*loan_path))
+                    );
             }
         }
     }
@@ -648,20 +648,20 @@ fn check_for_move_of_borrowed_path(&self,
                 let err_message = match move_kind {
                     move_data::Captured =>
                         format!("cannot move `{}` into closure because it is borrowed",
-                                &self.bccx.loan_path_to_string(move_path)[]),
+                                &self.bccx.loan_path_to_string(move_path)),
                     move_data::Declared |
                     move_data::MoveExpr |
                     move_data::MovePat =>
                         format!("cannot move out of `{}` because it is borrowed",
-                                &self.bccx.loan_path_to_string(move_path)[])
+                                &self.bccx.loan_path_to_string(move_path))
                 };
 
                 self.bccx.span_err(span, &err_message[..]);
                 self.bccx.span_note(
                     loan_span,
                     &format!("borrow of `{}` occurs here",
-                            &self.bccx.loan_path_to_string(&*loan_path)[])
-                    []);
+                            &self.bccx.loan_path_to_string(&*loan_path))
+                    );
             }
         }
     }
@@ -842,7 +842,7 @@ fn check_assignment(&self,
                     self.bccx.span_err(
                         assignment_span,
                         &format!("cannot assign to {}",
-                                self.bccx.cmt_to_string(&*assignee_cmt))[]);
+                                self.bccx.cmt_to_string(&*assignee_cmt)));
                     self.bccx.span_help(
                         self.tcx().map.span(upvar_id.closure_expr_id),
                         "consider changing this closure to take self by mutable reference");
@@ -851,7 +851,7 @@ fn check_assignment(&self,
                         assignment_span,
                         &format!("cannot assign to {} {}",
                                 assignee_cmt.mutbl.to_user_str(),
-                                self.bccx.cmt_to_string(&*assignee_cmt))[]);
+                                self.bccx.cmt_to_string(&*assignee_cmt)));
                 }
             }
             _ => match opt_loan_path(&assignee_cmt) {
@@ -861,14 +861,14 @@ fn check_assignment(&self,
                         &format!("cannot assign to {} {} `{}`",
                                 assignee_cmt.mutbl.to_user_str(),
                                 self.bccx.cmt_to_string(&*assignee_cmt),
-                                self.bccx.loan_path_to_string(&*lp))[]);
+                                self.bccx.loan_path_to_string(&*lp)));
                 }
                 None => {
                     self.bccx.span_err(
                         assignment_span,
                         &format!("cannot assign to {} {}",
                                 assignee_cmt.mutbl.to_user_str(),
-                                self.bccx.cmt_to_string(&*assignee_cmt))[]);
+                                self.bccx.cmt_to_string(&*assignee_cmt)));
                 }
             }
         }
@@ -988,10 +988,10 @@ pub fn report_illegal_mutation(&self,
         self.bccx.span_err(
             span,
             &format!("cannot assign to `{}` because it is borrowed",
-                    self.bccx.loan_path_to_string(loan_path))[]);
+                    self.bccx.loan_path_to_string(loan_path)));
         self.bccx.span_note(
             loan.span,
             &format!("borrow of `{}` occurs here",
-                    self.bccx.loan_path_to_string(loan_path))[]);
+                    self.bccx.loan_path_to_string(loan_path)));
     }
 }
index c873831cb0f657b6faa3fb81a16641b55211ce5c..8cb4090bf39290ed2330f78d21527e05790d449f 100644 (file)
@@ -10,7 +10,7 @@
 
 //! Helper routines used for fragmenting structural paths due to moves for
 //! tracking drop obligations. Please see the extensive comments in the
-//! section "Structural fragments" in `doc.rs`.
+//! section "Structural fragments" in `README.md`.
 
 use self::Fragment::*;
 
@@ -123,12 +123,12 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
         let attrs : &[ast::Attribute];
         attrs = match tcx.map.find(id) {
             Some(ast_map::NodeItem(ref item)) =>
-                &item.attrs[],
+                &item.attrs,
             Some(ast_map::NodeImplItem(&ast::MethodImplItem(ref m))) =>
-                &m.attrs[],
+                &m.attrs,
             Some(ast_map::NodeTraitItem(&ast::ProvidedMethod(ref m))) =>
-                &m.attrs[],
-            _ => &[][],
+                &m.attrs,
+            _ => &[],
         };
 
         let span_err =
@@ -144,7 +144,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
         for (i, mpi) in vec_rc.iter().enumerate() {
             let render = || this.path_loan_path(*mpi).user_string(tcx);
             if span_err {
-                tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render())[]);
+                tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render()));
             }
             if print {
                 println!("id:{} {}[{}] `{}`", id, kind, i, render());
@@ -156,7 +156,7 @@ pub fn instrument_move_fragments<'tcx>(this: &MoveData<'tcx>,
         for (i, f) in vec_rc.iter().enumerate() {
             let render = || f.loan_path_user_string(this, tcx);
             if span_err {
-                tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render())[]);
+                tcx.sess.span_err(sp, &format!("{}: `{}`", kind, render()));
             }
             if print {
                 println!("id:{} {}[{}] `{}`", id, kind, i, render());
index 1c57097ae26339a9c70626cc96617836836521a1..9f7b4cf26e1c47fa60dabc40b6bdc37abb10c293 100644 (file)
@@ -106,8 +106,6 @@ fn scope(&self, cmt: &mc::cmt) -> ty::Region {
         //! lvalue `cmt` is guaranteed to be valid without any
         //! rooting etc, and presuming `cmt` is not mutated.
 
-        // See the SCOPE(LV) function in doc.rs
-
         match cmt.cat {
             mc::cat_rvalue(temp_scope) => {
                 temp_scope
index 4e308c5809f45ba96657628d891ba0b2fe36ea52..d51ad6e0c97b5f3b9a44b73454add2b96f471eae 100644 (file)
@@ -173,7 +173,7 @@ fn decl_without_init(&mut self, id: ast::NodeId, span: Span) {
     }
 }
 
-/// Implements the A-* rules in doc.rs.
+/// Implements the A-* rules in README.md.
 fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                 borrow_span: Span,
                                 loan_cause: euv::LoanCause,
@@ -307,7 +307,7 @@ fn guarantee_valid(&mut self,
                         self.tcx().sess.span_bug(
                             cmt.span,
                             &format!("invalid borrow lifetime: {:?}",
-                                    loan_region)[]);
+                                    loan_region));
                     }
                 };
                 debug!("loan_scope = {:?}", loan_scope);
@@ -375,7 +375,7 @@ fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                       cmt: mc::cmt<'tcx>,
                                       req_kind: ty::BorrowKind)
                                       -> Result<(),()> {
-            //! Implements the M-* rules in doc.rs.
+            //! Implements the M-* rules in README.md.
 
             match req_kind {
                 ty::UniqueImmBorrow | ty::ImmBorrow => {
index da5c847a04607e7cc79fc8e3de8e01726906d578..53761eb14713def82f45a671a5a2dc45a3f6daab 100644 (file)
@@ -121,7 +121,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         mc::cat_static_item => {
             bccx.span_err(move_from.span,
                           &format!("cannot move out of {}",
-                                  move_from.descriptive_string(bccx.tcx))[]);
+                                  move_from.descriptive_string(bccx.tcx)));
         }
 
         mc::cat_interior(ref b, mc::InteriorElement(Kind::Index, _)) => {
@@ -130,7 +130,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                 bccx.span_err(move_from.span,
                               &format!("cannot move out of type `{}`, \
                                         a non-copy fixed-size array",
-                                       b.ty.user_string(bccx.tcx))[]);
+                                       b.ty.user_string(bccx.tcx)));
             }
         }
 
@@ -143,7 +143,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                         move_from.span,
                         &format!("cannot move out of type `{}`, \
                                  which defines the `Drop` trait",
-                                b.ty.user_string(bccx.tcx))[]);
+                                b.ty.user_string(bccx.tcx)));
                 },
                 _ => {
                     bccx.span_bug(move_from.span, "this path should not cause illegal move")
@@ -170,10 +170,10 @@ fn note_move_destination(bccx: &BorrowckCtxt,
             &format!("to prevent the move, \
                      use `ref {0}` or `ref mut {0}` to capture value by \
                      reference",
-                    pat_name)[]);
+                    pat_name));
     } else {
         bccx.span_note(move_to_span,
                        &format!("and here (use `ref {0}` or `ref mut {0}`)",
-                               pat_name)[]);
+                               pat_name));
     }
 }
index 518e4bc472ca4aa6c117c8db26f9e0796ad5ce93..67462ab01003e29ec33f3f21e3a1cd1998ee3bfa 100644 (file)
@@ -105,10 +105,10 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
         ast::ItemConst(_, ref ex) => {
             gather_loans::gather_loans_in_static_initializer(this, &**ex);
         }
-        _ => {
-            visit::walk_item(this, item);
-        }
+        _ => { }
     }
+
+    visit::walk_item(this, item);
 }
 
 /// Collection of conclusions determined via borrow checker analyses.
@@ -295,7 +295,7 @@ fn eq(&self, that: &LoanPath<'tcx>) -> bool {
 
 #[derive(PartialEq, Eq, Hash, Debug)]
 pub enum LoanPathKind<'tcx> {
-    LpVar(ast::NodeId),                         // `x` in doc.rs
+    LpVar(ast::NodeId),                         // `x` in README.md
     LpUpvar(ty::UpvarId),                       // `x` captured by-value into closure
     LpDowncast(Rc<LoanPath<'tcx>>, ast::DefId), // `x` downcast to particular enum variant
     LpExtend(Rc<LoanPath<'tcx>>, mc::MutabilityCategory, LoanPathElem)
@@ -336,8 +336,8 @@ fn cleaned(self) -> InteriorKind {
 
 #[derive(Copy, PartialEq, Eq, Hash, Debug)]
 pub enum LoanPathElem {
-    LpDeref(mc::PointerKind),    // `*LV` in doc.rs
-    LpInterior(InteriorKind),    // `LV.f` in doc.rs
+    LpDeref(mc::PointerKind),    // `*LV` in README.md
+    LpInterior(InteriorKind),    // `LV.f` in README.md
 }
 
 pub fn closure_to_block(closure_id: ast::NodeId,
@@ -524,7 +524,7 @@ pub fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region)
     pub fn report(&self, err: BckError<'tcx>) {
         self.span_err(
             err.span,
-            &self.bckerr_to_string(&err)[]);
+            &self.bckerr_to_string(&err));
         self.note_and_explain_bckerr(err);
     }
 
@@ -546,7 +546,7 @@ pub fn report_use_of_moved_value<'b>(&self,
                     use_span,
                     &format!("{} of possibly uninitialized variable: `{}`",
                             verb,
-                            self.loan_path_to_string(lp))[]);
+                            self.loan_path_to_string(lp)));
                 (self.loan_path_to_string(moved_lp),
                  String::new())
             }
@@ -588,7 +588,7 @@ pub fn report_use_of_moved_value<'b>(&self,
                     &format!("{} of {}moved value: `{}`",
                             verb,
                             msg,
-                            nl)[]);
+                            nl));
                 (ol, moved_lp_msg)
             }
         };
@@ -607,18 +607,31 @@ pub fn report_use_of_moved_value<'b>(&self,
                         self.tcx.sess.bug(&format!("MoveExpr({}) maps to \
                                                    {:?}, not Expr",
                                                   the_move.id,
-                                                  r)[])
+                                                  r))
                     }
                 };
                 let (suggestion, _) =
                     move_suggestion(param_env, expr_span, expr_ty, ("moved by default", ""));
-                self.tcx.sess.span_note(
-                    expr_span,
-                    &format!("`{}` moved here{} because it has type `{}`, which is {}",
-                            ol,
-                            moved_lp_msg,
-                            expr_ty.user_string(self.tcx),
-                            suggestion)[]);
+                // If the two spans are the same, it's because the expression will be evaluated
+                // multiple times. Avoid printing the same span and adjust the wording so it makes
+                // more sense that it's from multiple evalutations.
+                if expr_span == use_span {
+                    self.tcx.sess.note(
+                        &format!("`{}` was previously moved here{} because it has type `{}`, \
+                                  which is {}",
+                                 ol,
+                                 moved_lp_msg,
+                                 expr_ty.user_string(self.tcx),
+                                 suggestion));
+                } else {
+                    self.tcx.sess.span_note(
+                        expr_span,
+                        &format!("`{}` moved here{} because it has type `{}`, which is {}",
+                                 ol,
+                                 moved_lp_msg,
+                                 expr_ty.user_string(self.tcx),
+                                 suggestion));
+                }
             }
 
             move_data::MovePat => {
@@ -629,7 +642,7 @@ pub fn report_use_of_moved_value<'b>(&self,
                              which is moved by default",
                             ol,
                             moved_lp_msg,
-                            pat_ty.user_string(self.tcx))[]);
+                            pat_ty.user_string(self.tcx)));
                 self.tcx.sess.span_help(span,
                     "use `ref` to override");
             }
@@ -645,7 +658,7 @@ pub fn report_use_of_moved_value<'b>(&self,
                         self.tcx.sess.bug(&format!("Captured({}) maps to \
                                                    {:?}, not Expr",
                                                   the_move.id,
-                                                  r)[])
+                                                  r))
                     }
                 };
                 let (suggestion, help) =
@@ -661,7 +674,7 @@ pub fn report_use_of_moved_value<'b>(&self,
                             ol,
                             moved_lp_msg,
                             expr_ty.user_string(self.tcx),
-                            suggestion)[]);
+                            suggestion));
                 self.tcx.sess.span_help(expr_span, help);
             }
         }
@@ -704,7 +717,7 @@ pub fn report_reassigned_immutable_variable(&self,
         self.tcx.sess.span_err(
             span,
             &format!("re-assignment of immutable variable `{}`",
-                    self.loan_path_to_string(lp))[]);
+                    self.loan_path_to_string(lp)));
         self.tcx.sess.span_note(assign.span, "prior assignment occurs here");
     }
 
@@ -825,7 +838,7 @@ pub fn report_aliasability_violation(&self,
                 self.tcx.sess.span_err(
                     span,
                     &format!("{} in an aliasable location",
-                             prefix)[]);
+                             prefix));
             }
             mc::AliasableClosure(id) => {
                 self.tcx.sess.span_err(span,
@@ -847,12 +860,12 @@ pub fn report_aliasability_violation(&self,
             mc::AliasableStaticMut(..) => {
                 self.tcx.sess.span_err(
                     span,
-                    &format!("{} in a static location", prefix)[]);
+                    &format!("{} in a static location", prefix));
             }
             mc::AliasableBorrowed => {
                 self.tcx.sess.span_err(
                     span,
-                    &format!("{} in a `&` reference", prefix)[]);
+                    &format!("{} in a `&` reference", prefix));
             }
         }
 
@@ -920,12 +933,12 @@ pub fn note_and_explain_bckerr(&self, err: BckError<'tcx>) {
                 note_and_explain_region(
                     self.tcx,
                     &format!("{} would have to be valid for ",
-                            descr)[],
+                            descr),
                     loan_scope,
                     "...");
                 note_and_explain_region(
                     self.tcx,
-                    &format!("...but {} is only valid for ", descr)[],
+                    &format!("...but {} is only valid for ", descr),
                     ptr_scope,
                     "");
             }
@@ -945,7 +958,7 @@ pub fn append_loan_path_to_string(&self,
                 out.push('(');
                 self.append_loan_path_to_string(&**lp_base, out);
                 out.push_str(DOWNCAST_PRINTED_OPERATOR);
-                out.push_str(&ty::item_path_str(self.tcx, variant_def_id)[]);
+                out.push_str(&ty::item_path_str(self.tcx, variant_def_id));
                 out.push(')');
             }
 
@@ -959,7 +972,7 @@ pub fn append_loan_path_to_string(&self,
                     }
                     mc::PositionalField(idx) => {
                         out.push('.');
-                        out.push_str(&idx.to_string()[]);
+                        out.push_str(&idx.to_string());
                     }
                 }
             }
@@ -991,7 +1004,7 @@ pub fn append_autoderefd_loan_path_to_string(&self,
                 out.push('(');
                 self.append_autoderefd_loan_path_to_string(&**lp_base, out);
                 out.push(':');
-                out.push_str(&ty::item_path_str(self.tcx, variant_def_id)[]);
+                out.push_str(&ty::item_path_str(self.tcx, variant_def_id));
                 out.push(')');
             }
 
index 9c5ddc06519b97208e523379170d84609ef430b4..0f7f8e61e37e0a1788c2a20ae0d79a48fd14ff22 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 //! Data structures used for tracking moves. Please see the extensive
-//! comments in the section "Moves and initialization" in `doc.rs`.
+//! comments in the section "Moves and initialization" in `README.md`.
 
 pub use self::MoveKind::*;
 
@@ -33,7 +33,7 @@
 pub mod fragments;
 
 pub struct MoveData<'tcx> {
-    /// Move paths. See section "Move paths" in `doc.rs`.
+    /// Move paths. See section "Move paths" in `README.md`.
     pub paths: RefCell<Vec<MovePath<'tcx>>>,
 
     /// Cache of loan path to move path index, for easy lookup.
@@ -464,7 +464,7 @@ fn fixup_fragment_sets(&self, tcx: &ty::ctxt<'tcx>) {
     /// assignments into the provided data flow contexts.
     /// Moves are generated by moves and killed by assignments and
     /// scoping. Assignments are generated by assignment to variables and
-    /// killed by scoping. See `doc.rs` for more details.
+    /// killed by scoping. See `README.md` for more details.
     fn add_gen_kills(&self,
                      tcx: &ty::ctxt<'tcx>,
                      dfcx_moves: &mut MoveDataFlow,
index 39c9d9ba6ad24ae5f067b893c66627c6d4e209a8..a2c9930c0ed2fdc36f4469af01af05eb292f4c28 100644 (file)
@@ -52,7 +52,7 @@ pub struct DataflowLabeller<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
     fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
-        let id = n.1.data.id;
+        let id = n.1.data.id();
         debug!("dataflow_for({:?}, id={}) {:?}", e, id, self.variants);
         let mut sets = "".to_string();
         let mut seen_one = false;
@@ -60,7 +60,7 @@ fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
             if seen_one { sets.push_str(" "); } else { seen_one = true; }
             sets.push_str(variant.short_name());
             sets.push_str(": ");
-            sets.push_str(&self.dataflow_for_variant(e, n, variant)[]);
+            sets.push_str(&self.dataflow_for_variant(e, n, variant));
         }
         sets
     }
index a260997f605940da7ac8d8fd6b83c9e93232af1b..425ec7ec452eecd4b2347c36a5d32257f7accf01 100644 (file)
@@ -32,6 +32,7 @@
 use serialize::json;
 
 use std::env;
+use std::os;
 use std::ffi::OsString;
 use std::old_io::fs;
 use std::old_io;
@@ -77,10 +78,10 @@ macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({
             let outputs = build_output_filenames(input,
                                                  outdir,
                                                  output,
-                                                 &krate.attrs[],
+                                                 &krate.attrs,
                                                  &sess);
             let id = link::find_crate_name(Some(&sess),
-                                           &krate.attrs[],
+                                           &krate.attrs,
                                            input);
             let expanded_crate
                 = match phase_2_configure_and_expand(&sess,
@@ -112,6 +113,7 @@ macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({
                                                                      &sess,
                                                                      outdir,
                                                                      &ast_map,
+                                                                     &ast_map.krate(),
                                                                      &id[..]));
 
         let analysis = phase_3_run_analysis_passes(sess,
@@ -287,11 +289,13 @@ fn state_after_write_deps(input: &'a Input,
                               session: &'a Session,
                               out_dir: &'a Option<Path>,
                               ast_map: &'a ast_map::Map<'ast>,
+                              expanded_crate: &'a ast::Crate,
                               crate_name: &'a str)
                               -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             crate_name: Some(crate_name),
             ast_map: Some(ast_map),
+            expanded_crate: Some(expanded_crate),
             .. CompileState::empty(input, session, out_dir)
         }
     }
@@ -299,14 +303,14 @@ fn state_after_write_deps(input: &'a Input,
     fn state_after_analysis(input: &'a Input,
                             session: &'a Session,
                             out_dir: &'a Option<Path>,
-                            krate: &'a ast::Crate,
+                            expanded_crate: &'a ast::Crate,
                             analysis: &'a ty::CrateAnalysis<'tcx>,
                             tcx: &'a ty::ctxt<'tcx>)
                             -> CompileState<'a, 'ast, 'tcx> {
         CompileState {
             analysis: Some(analysis),
             tcx: Some(tcx),
-            krate: Some(krate),
+            expanded_crate: Some(expanded_crate),
             .. CompileState::empty(input, session, out_dir)
         }
     }
@@ -375,9 +379,9 @@ pub fn phase_2_configure_and_expand(sess: &Session,
     let time_passes = sess.time_passes();
 
     *sess.crate_types.borrow_mut() =
-        collect_crate_types(sess, &krate.attrs[]);
+        collect_crate_types(sess, &krate.attrs);
     *sess.crate_metadata.borrow_mut() =
-        collect_crate_metadata(sess, &krate.attrs[]);
+        collect_crate_metadata(sess, &krate.attrs);
 
     time(time_passes, "recursion limit", (), |_| {
         middle::recursion_limit::update_recursion_limit(sess, &krate);
@@ -468,7 +472,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
             if cfg!(windows) {
                 _old_path = env::var_os("PATH").unwrap_or(_old_path);
                 let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
-                new_path.extend(env::split_paths(&_old_path));
+                new_path.extend(os::split_paths(_old_path.to_str().unwrap()).into_iter());
                 env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
             }
             let features = sess.features.borrow();
@@ -568,7 +572,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
         export_map,
         trait_map,
         external_exports,
-        last_private_map,
         glob_map,
     } =
         time(time_passes, "resolution", (),
@@ -617,10 +620,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     time(time_passes, "const checking", (), |_|
          middle::check_const::check_crate(&ty_cx));
 
-    let maps = (external_exports, last_private_map);
     let (exported_items, public_items) =
-            time(time_passes, "privacy checking", maps, |(a, b)|
-                 rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
+            time(time_passes, "privacy checking", (), |_|
+                 rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));
 
     // Do not move this check past lint
     time(time_passes, "stability index", (), |_|
@@ -721,7 +723,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
         time(sess.time_passes(), "LLVM passes", (), |_|
             write::run_passes(sess,
                               trans,
-                              &sess.opts.output_types[],
+                              &sess.opts.output_types,
                               outputs));
     }
 
@@ -735,14 +737,14 @@ pub fn phase_6_link_output(sess: &Session,
                            outputs: &OutputFilenames) {
     let old_path = env::var_os("PATH").unwrap_or(OsString::from_str(""));
     let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
-    new_path.extend(env::split_paths(&old_path));
+    new_path.extend(os::split_paths(old_path.to_str().unwrap()).into_iter());
     env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
 
     time(sess.time_passes(), "linking", (), |_|
          link::link_binary(sess,
                            trans,
                            outputs,
-                           &trans.link.crate_name[]));
+                           &trans.link.crate_name));
 
     env::set_var("PATH", &old_path);
 }
@@ -796,7 +798,7 @@ fn write_out_deps(sess: &Session,
         // write Makefile-compatible dependency rules
         let files: Vec<String> = sess.codemap().files.borrow()
                                    .iter().filter(|fmap| fmap.is_real_file())
-                                   .map(|fmap| escape_dep_filename(&fmap.name[]))
+                                   .map(|fmap| escape_dep_filename(&fmap.name))
                                    .collect();
         let mut file = try!(old_io::File::create(&deps_filename));
         for path in &out_filenames {
@@ -810,7 +812,7 @@ fn write_out_deps(sess: &Session,
         Ok(()) => {}
         Err(e) => {
             sess.fatal(&format!("error writing dependencies to `{}`: {}",
-                               deps_filename.display(), e)[]);
+                               deps_filename.display(), e));
         }
     }
 }
@@ -881,7 +883,7 @@ pub fn collect_crate_types(session: &Session,
         if !res {
             session.warn(&format!("dropping unsupported crate type `{}` \
                                    for target `{}`",
-                                 *crate_type, session.opts.target_triple)[]);
+                                 *crate_type, session.opts.target_triple));
         }
 
         res
index 2550432c8101adde411a3828936cb1a031eecaa0..0fbfeb831850f2d7dc9e4e37cb081899ac5c4029 100644 (file)
@@ -124,7 +124,7 @@ macro_rules! do_or_return {($expr: expr) => {
     let sopts = config::build_session_options(&matches);
 
     let (odir, ofile) = make_output(&matches);
-    let (input, input_file_path) = match make_input(&matches.free[]) {
+    let (input, input_file_path) = match make_input(&matches.free) {
         Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
         None => match callbacks.no_input(&matches, &sopts, &odir, &ofile, &descriptions) {
             Some((input, input_file_path)) => (input, input_file_path),
@@ -166,7 +166,7 @@ fn make_output(matches: &getopts::Matches) -> (Option<Path>, Option<Path>) {
 // Extract input (string or file and optional path) from matches.
 fn make_input(free_matches: &[String]) -> Option<(Input, Option<Path>)> {
     if free_matches.len() == 1 {
-        let ifile = &free_matches[0][];
+        let ifile = &free_matches[0][..];
         if ifile == "-" {
             let contents = old_io::stdin().read_to_end().unwrap();
             let src = String::from_utf8(contents).unwrap();
@@ -277,7 +277,7 @@ fn early_callback(&mut self,
                         println!("{}", description);
                     }
                     None => {
-                        early_error(&format!("no extended information for {}", code)[]);
+                        early_error(&format!("no extended information for {}", code));
                     }
                 }
                 return Compilation::Stop;
@@ -373,11 +373,13 @@ fn build_controller(&mut self, sess: &Session) -> CompileController<'a> {
 
         if sess.opts.debugging_opts.save_analysis {
             control.after_analysis.callback = box |state| {
-                time(state.session.time_passes(), "save analysis", state.krate.unwrap(), |krate|
-                     save::process_crate(state.session,
-                                         krate,
-                                         state.analysis.unwrap(),
-                                         state.out_dir));
+                time(state.session.time_passes(),
+                     "save analysis",
+                     state.expanded_crate.unwrap(),
+                     |krate| save::process_crate(state.session,
+                                                 krate,
+                                                 state.analysis.unwrap(),
+                                                 state.out_dir));
             };
             control.make_glob_map = resolve::MakeGlobMap::Yes;
         }
@@ -678,7 +680,7 @@ pub fn handle_options(mut args: Vec<String>) -> Option<getopts::Matches> {
     }
 
     let matches =
-        match getopts::getopts(&args[..], &config::optgroups()[]) {
+        match getopts::getopts(&args[..], &config::optgroups()) {
             Ok(m) => m,
             Err(f_stable_attempt) => {
                 // redo option parsing, including unstable options this time,
@@ -811,7 +813,7 @@ pub fn monitor<F:FnOnce()+Send+'static>(f: F) {
                     Err(e) => {
                         emitter.emit(None,
                                      &format!("failed to read internal \
-                                              stderr: {}", e)[],
+                                              stderr: {}", e),
                                      None,
                                      diagnostic::Error)
                     }
index 0fbfa5fd89dd7f3fdc1216ccb271332640b6fff2..22473099baf60311fbe59b6e505a56a84e4ad35d 100644 (file)
@@ -312,7 +312,7 @@ fn post(&self,
                 try!(pp::word(&mut s.s,
                               &ppaux::ty_to_string(
                                   tcx,
-                                  ty::expr_ty(tcx, expr))[]));
+                                  ty::expr_ty(tcx, expr))));
                 s.pclose()
             }
             _ => Ok(())
@@ -348,7 +348,7 @@ impl FromStr for UserIdentifiedItem {
     type Err = ();
     fn from_str(s: &str) -> Result<UserIdentifiedItem, ()> {
         Ok(s.parse().map(ItemViaNode).unwrap_or_else(|_| {
-            ItemViaPath(s.split_str("::").map(|s| s.to_string()).collect())
+            ItemViaPath(s.split("::").map(|s| s.to_string()).collect())
         }))
     }
 }
@@ -602,7 +602,7 @@ pub fn pretty_print_input(sess: Session,
             debug!("pretty printing flow graph for {:?}", opt_uii);
             let uii = opt_uii.unwrap_or_else(|| {
                 sess.fatal(&format!("`pretty flowgraph=..` needs NodeId (int) or
-                                     unique path suffix (b::c::d)")[])
+                                     unique path suffix (b::c::d)"))
 
             });
             let ast_map = ast_map.expect("--pretty flowgraph missing ast_map");
@@ -610,7 +610,7 @@ pub fn pretty_print_input(sess: Session,
 
             let node = ast_map.find(nodeid).unwrap_or_else(|| {
                 sess.fatal(&format!("--pretty flowgraph couldn't find id: {}",
-                                   nodeid)[])
+                                   nodeid))
             });
 
             let code = blocks::Code::from_node(node);
index fbbd72e2c76be6efd75fe6182759d3d578997c0a..d9cedc482985155e84445cc947292d222e412359 100644 (file)
@@ -206,7 +206,7 @@ fn search(this: &Env,
 
                 ast::ItemEnum(..) | ast::ItemStruct(..) |
                 ast::ItemTrait(..) | ast::ItemImpl(..) |
-                ast::ItemMac(..) => {
+                ast::ItemMac(..) | ast::ItemDefaultImpl(..) => {
                     None
                 }
 
@@ -806,11 +806,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!(vec!(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),
+        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);
     })
 }
index 5662a74a53d34d087f06eae47370427c8e01d1e0..436a826687e1368616c83aee88ebda2e6bf06166 100644 (file)
@@ -17,7 +17,6 @@
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
-#![feature(core)]
 #![feature(int_uint)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
@@ -38,8 +37,7 @@
 use rustc::middle::privacy::ImportUse::*;
 use rustc::middle::privacy::LastPrivate::*;
 use rustc::middle::privacy::PrivateDep::*;
-use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
-use rustc::middle::privacy::{ExternalExports};
+use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
 use rustc::middle::ty::{MethodTypeParam, MethodStatic};
 use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
 use rustc::middle::ty::{MethodStaticClosure, MethodObject};
@@ -209,7 +207,7 @@ fn visit_item(&mut self, item: &ast::Item) {
         match item.node {
             // impls/extern blocks do not break the "public chain" because they
             // cannot have visibility qualifiers on them anyway
-            ast::ItemImpl(..) | ast::ItemForeignMod(..) => {}
+            ast::ItemImpl(..) | ast::ItemDefaultImpl(..) | ast::ItemForeignMod(..) => {}
 
             // Traits are a little special in that even if they themselves are
             // not public they may still be exported.
@@ -259,8 +257,8 @@ fn visit_item(&mut self, item: &ast::Item) {
             // * Private trait impls for private types can be completely ignored
             ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
-                    ast::TyPath(_, id) => {
-                        match self.tcx.def_map.borrow()[id].clone() {
+                    ast::TyPath(..) => {
+                        match self.tcx.def_map.borrow()[ty.id].full_def() {
                             def::DefPrimTy(..) => true,
                             def => {
                                 let did = def.def_id();
@@ -326,8 +324,8 @@ fn visit_item(&mut self, item: &ast::Item) {
             }
 
             ast::ItemTy(ref ty, _) if public_first => {
-                if let ast::TyPath(_, id) = ty.node {
-                    match self.tcx.def_map.borrow()[id].clone() {
+                if let ast::TyPath(..) = ty.node {
+                    match self.tcx.def_map.borrow()[ty.id].full_def() {
                         def::DefPrimTy(..) | def::DefTyParam(..) => {},
                         def => {
                             let did = def.def_id();
@@ -379,7 +377,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
     in_foreign: bool,
     parents: NodeMap<ast::NodeId>,
     external_exports: ExternalExports,
-    last_private_map: LastPrivateMap,
 }
 
 enum PrivacyResult {
@@ -628,11 +625,11 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId,
                     // back up the chains to find the relevant struct/enum that
                     // was private.
                     ast::ItemImpl(_, _, _, _, ref ty, _) => {
-                        let id = match ty.node {
-                            ast::TyPath(_, id) => id,
+                        match ty.node {
+                            ast::TyPath(..) => {}
                             _ => return Some((err_span, err_msg, None)),
                         };
-                        let def = self.tcx.def_map.borrow()[id].clone();
+                        let def = self.tcx.def_map.borrow()[ty.id].full_def();
                         let did = def.def_id();
                         assert!(is_local(did));
                         match self.tcx.map.get(did.node) {
@@ -712,25 +709,25 @@ fn check_static_method(&mut self,
                                              method_id,
                                              None,
                                              &format!("method `{}`",
-                                                     string)[]));
+                                                     string)));
     }
 
     // Checks that a path is in scope.
-    fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
+    fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) {
         debug!("privacy - path {}", self.nodestr(path_id));
-        let orig_def = self.tcx.def_map.borrow()[path_id].clone();
+        let path_res = self.tcx.def_map.borrow()[path_id];
         let ck = |tyname: &str| {
             let ck_public = |def: ast::DefId| {
                 debug!("privacy - ck_public {:?}", def);
-                let name = token::get_ident(path.segments.last().unwrap().identifier);
-                let origdid = orig_def.def_id();
+                let name = token::get_ident(last);
+                let origdid = path_res.def_id();
                 self.ensure_public(span,
                                    def,
                                    Some(origdid),
-                                   &format!("{} `{}`", tyname, name)[])
+                                   &format!("{} `{}`", tyname, name))
             };
 
-            match self.last_private_map[path_id] {
+            match path_res.last_private {
                 LastMod(AllPublic) => {},
                 LastMod(DependsOn(def)) => {
                     self.report_error(ck_public(def));
@@ -794,8 +791,7 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
         // def map is not. Therefore the names we work out below will not always
         // be accurate and we can get slightly wonky error messages (but type
         // checking is always correct).
-        match self.tcx.def_map.borrow()[path_id].clone() {
-            def::DefStaticMethod(..) => ck("static method"),
+        match path_res.full_def() {
             def::DefFn(..) => ck("function"),
             def::DefStatic(..) => ck("static"),
             def::DefConst(..) => ck("const"),
@@ -804,7 +800,6 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
             def::DefTy(_, true) => ck("enum"),
             def::DefTrait(..) => ck("trait"),
             def::DefStruct(..) => ck("struct"),
-            def::DefMethod(_, Some(..), _) => ck("trait method"),
             def::DefMethod(..) => ck("method"),
             def::DefMod(..) => ck("module"),
             _ => {}
@@ -832,37 +827,22 @@ fn check_method(&mut self, span: Span, origin: &MethodOrigin,
 
 impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
-        match item.node {
-            ast::ItemUse(ref vpath) => {
-                match vpath.node {
-                    ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
-                    ast::ViewPathList(ref prefix, ref list) => {
-                        for pid in list {
-                            match pid.node {
-                                ast::PathListIdent { id, name } => {
-                                    debug!("privacy - ident item {}", id);
-                                    let seg = ast::PathSegment {
-                                        identifier: name,
-                                        parameters: ast::PathParameters::none(),
-                                    };
-                                    let segs = vec![seg];
-                                    let path = ast::Path {
-                                        global: false,
-                                        span: pid.span,
-                                        segments: segs,
-                                    };
-                                    self.check_path(pid.span, id, &path);
-                                }
-                                ast::PathListMod { id } => {
-                                    debug!("privacy - mod item {}", id);
-                                    self.check_path(pid.span, id, prefix);
-                                }
-                            }
+        if let ast::ItemUse(ref vpath) = item.node {
+            if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
+                for pid in list {
+                    match pid.node {
+                        ast::PathListIdent { id, name } => {
+                            debug!("privacy - ident item {}", id);
+                            self.check_path(pid.span, id, name);
+                        }
+                        ast::PathListMod { id } => {
+                            debug!("privacy - mod item {}", id);
+                            let name = prefix.segments.last().unwrap().identifier;
+                            self.check_path(pid.span, id, name);
                         }
                     }
                 }
             }
-            _ => {}
         }
         let orig_curitem = replace(&mut self.curitem, item.id);
         visit::walk_item(self, item);
@@ -908,7 +888,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                         }
                     }
                     ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow()[expr.id].clone() {
+                        match self.tcx.def_map.borrow()[expr.id].full_def() {
                             def::DefVariant(_, variant_id, _) => {
                                 for field in fields {
                                     self.check_field(expr.span, variant_id,
@@ -927,7 +907,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                                                             struct type?!"),
                 }
             }
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
+            ast::ExprPath(..) => {
                 let guard = |did: ast::DefId| {
                     let fields = ty::lookup_struct_fields(self.tcx, did);
                     let any_priv = fields.iter().any(|f| {
@@ -941,8 +921,8 @@ struct type?!"),
                              with private fields");
                     }
                 };
-                match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def::DefStruct(did)) => {
+                match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
+                    Some(def::DefStruct(did)) => {
                         guard(if is_local(did) {
                             local_def(self.tcx.map.get_parent(did.node))
                         } else {
@@ -981,8 +961,8 @@ fn visit_pat(&mut self, pattern: &ast::Pat) {
                         }
                     }
                     ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow().get(&pattern.id) {
-                            Some(&def::DefVariant(_, variant_id, _)) => {
+                        match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) {
+                            Some(def::DefVariant(_, variant_id, _)) => {
                                 for field in fields {
                                     self.check_field(pattern.span, variant_id,
                                                      NamedField(field.node.ident.name));
@@ -1033,7 +1013,7 @@ fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
     }
 
     fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
-        self.check_path(path.span, id, path);
+        self.check_path(path.span, id, path.segments.last().unwrap().identifier);
         visit::walk_path(self, path);
     }
 }
@@ -1145,6 +1125,7 @@ fn check_sane_privacy(&self, item: &ast::Item) {
                 }
             }
 
+            ast::ItemDefaultImpl(..) |
             ast::ItemConst(..) | ast::ItemStatic(..) | ast::ItemStruct(..) |
             ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
             ast::ItemExternCrate(_) | ast::ItemUse(_) | ast::ItemMac(..) => {}
@@ -1204,7 +1185,7 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
                 }
             }
 
-            ast::ItemExternCrate(_) | ast::ItemUse(_) |
+            ast::ItemDefaultImpl(..) | ast::ItemExternCrate(_) | ast::ItemUse(_) |
             ast::ItemStatic(..) | ast::ItemConst(..) |
             ast::ItemFn(..) | ast::ItemMod(..) | ast::ItemTy(..) |
             ast::ItemMac(..) => {}
@@ -1232,7 +1213,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
 
 impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
-        let did = match self.tcx.def_map.borrow().get(&path_id).cloned() {
+        let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
             // `int` etc. (None doesn't seem to occur.)
             None | Some(def::DefPrimTy(..)) => return false,
             Some(def) => def.def_id()
@@ -1272,8 +1253,8 @@ fn check_ty_param_bound(&self,
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
     fn visit_ty(&mut self, ty: &ast::Ty) {
-        if let ast::TyPath(_, path_id) = ty.node {
-            if self.inner.path_is_private_type(path_id) {
+        if let ast::TyPath(..) = ty.node {
+            if self.inner.path_is_private_type(ty.id) {
                 self.contains_private = true;
                 // found what we're looking for so let's stop
                 // working.
@@ -1397,7 +1378,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                             //
                             // Those in 2. are warned via walk_generics and this
                             // call here.
-                            self.visit_trait_ref(tr)
+                            visit::walk_path(self, &tr.path);
                         }
                     }
                 } else if trait_ref.is_none() && self_is_public_path {
@@ -1478,9 +1459,9 @@ fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
     }
 
     fn visit_ty(&mut self, t: &ast::Ty) {
-        if let ast::TyPath(ref p, path_id) = t.node {
+        if let ast::TyPath(_, ref p) = t.node {
             if !self.tcx.sess.features.borrow().visible_private_types &&
-                self.path_is_private_type(path_id) {
+                self.path_is_private_type(t.id) {
                 self.tcx.sess.span_err(p.span,
                                        "private type in exported type signature");
             }
@@ -1516,8 +1497,7 @@ fn visit_expr(&mut self, _: &ast::Expr) {}
 
 pub fn check_crate(tcx: &ty::ctxt,
                    export_map: &def::ExportMap,
-                   external_exports: ExternalExports,
-                   last_private_map: LastPrivateMap)
+                   external_exports: ExternalExports)
                    -> (ExportedItems, PublicItems) {
     let krate = tcx.map.krate();
 
@@ -1535,7 +1515,6 @@ pub fn check_crate(tcx: &ty::ctxt,
         tcx: tcx,
         parents: visitor.parents,
         external_exports: external_exports,
-        last_private_map: last_private_map,
     };
     visit::walk_crate(&mut visitor, krate);
 
index 2f25f34a92ad07434340f8a6ab5b5fdaa85a910e..67e2b409c8e2213d8dfd8613d68d803972992dd5 100644 (file)
 use NameBindings;
 use ParentLink::{self, ModuleParentLink, BlockParentLink};
 use Resolver;
-use RibKind::*;
 use Shadowable;
 use TypeNsDef;
-use TypeParameters::HasTypeParameters;
 
 use self::DuplicateCheckingMode::*;
 use self::NamespaceError::*;
 use rustc::metadata::csearch;
 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
-use rustc::middle::subst::FnSpace;
 
 use syntax::ast::{Block, Crate};
 use syntax::ast::{DeclItem, DefId};
 use syntax::ast::{ForeignItem, ForeignItemFn, ForeignItemStatic};
 use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
-use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
+use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
 use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
-use syntax::ast::{PathListIdent, PathListMod};
-use syntax::ast::{Public, SelfStatic};
+use syntax::ast::{Name, NamedField, NodeId};
+use syntax::ast::{PathListIdent, PathListMod, Public};
 use syntax::ast::StmtDecl;
 use syntax::ast::StructVariantKind;
 use syntax::ast::TupleVariantKind;
-use syntax::ast::TyObjectSum;
-use syntax::ast::{TypeImplItem, UnnamedField};
+use syntax::ast::UnnamedField;
 use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::ast::{Visibility};
-use syntax::ast::TyPath;
 use syntax::ast;
-use syntax::ast_util::{self, PostExpansionMethod, local_def};
+use syntax::ast_util::{self, local_def};
 use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::{self, special_idents};
 use syntax::codemap::{Span, DUMMY_SP};
@@ -181,12 +175,8 @@ fn add_child(&self,
                         Some(TypeNS)
                     }
                     ForbidDuplicateTypesAndModules => {
-                        match child.def_for_namespace(TypeNS) {
-                            None => {}
-                            Some(_) if child.get_module_if_available()
-                                            .map(|m| m.kind.get()) ==
-                                       Some(ImplModuleKind) => {}
-                            Some(_) => duplicate_type = TypeError
+                        if child.defined_in_namespace(TypeNS) {
+                            duplicate_type = TypeError;
                         }
                         Some(TypeNS)
                     }
@@ -220,14 +210,14 @@ fn add_child(&self,
                     self.resolve_error(sp,
                         &format!("duplicate definition of {} `{}`",
                              namespace_error_to_string(duplicate_type),
-                             token::get_name(name))[]);
+                             token::get_name(name)));
                     {
                         let r = child.span_for_namespace(ns);
                         if let Some(sp) = r {
                             self.session.span_note(sp,
                                  &format!("first definition of {} `{}` here",
                                       namespace_error_to_string(duplicate_type),
-                                      token::get_name(name))[]);
+                                      token::get_name(name)));
                         }
                     }
                 }
@@ -307,8 +297,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                     ViewPathSimple(binding, ref full_path) => {
                         let source_name =
                             full_path.segments.last().unwrap().identifier.name;
-                        if &token::get_name(source_name)[] == "mod" ||
-                           &token::get_name(source_name)[] == "self" {
+                        if &token::get_name(source_name)[..] == "mod" ||
+                           &token::get_name(source_name)[..] == "self" {
                             self.resolve_error(view_path.span,
                                 "`self` imports are only allowed within a { } list");
                         }
@@ -465,9 +455,6 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
 
                 let parent_link = self.get_parent_link(parent, name);
-                // We want to make sure the module type is EnumModuleKind
-                // even if there's already an ImplModuleKind module defined,
-                // since that's how we prevent duplicate enum definitions
                 name_bindings.set_module_kind(parent_link,
                                               Some(local_def(item.id)),
                                               EnumModuleKind,
@@ -517,146 +504,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 parent.clone()
             }
 
-            ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
-                // If this implements an anonymous trait, then add all the
-                // methods within to a new module, if the type was defined
-                // within this module.
-
-                let mod_name = match ty.node {
-                    TyPath(ref path, _) if path.segments.len() == 1 => {
-                        // FIXME(18446) we should distinguish between the name of
-                        // a trait and the name of an impl of that trait.
-                        Some(path.segments.last().unwrap().identifier.name)
-                    }
-                    TyObjectSum(ref lhs_ty, _) => {
-                        match lhs_ty.node {
-                            TyPath(ref path, _) if path.segments.len() == 1 => {
-                                Some(path.segments.last().unwrap().identifier.name)
-                            }
-                            _ => {
-                                None
-                            }
-                        }
-                    }
-                    _ => {
-                        None
-                    }
-                };
-
-                let mod_name = match mod_name {
-                    Some(mod_name) => mod_name,
-                    None => {
-                        self.resolve_error(ty.span,
-                                           "inherent implementations may \
-                                            only be implemented in the same \
-                                            module as the type they are \
-                                            implemented for");
-                        return parent.clone();
-                    }
-                };
-                // Create the module and add all methods.
-                let child_opt = parent.children.borrow().get(&mod_name)
-                                       .and_then(|m| m.get_module_if_available());
-                let new_parent = match child_opt {
-                    // It already exists
-                    Some(ref child) if (child.kind.get() == ImplModuleKind ||
-                                        child.kind.get() == TraitModuleKind) => {
-                        child.clone()
-                    }
-                    Some(ref child) if child.kind.get() == EnumModuleKind ||
-                                       child.kind.get() == TypeModuleKind => {
-                        child.clone()
-                    }
-                    // Create the module
-                    _ => {
-                        let name_bindings =
-                            self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
-
-                        let parent_link = self.get_parent_link(parent, name);
-                        let def_id = local_def(item.id);
-                        let ns = TypeNS;
-                        let is_public =
-                            !name_bindings.defined_in_namespace(ns) ||
-                            name_bindings.defined_in_public_namespace(ns);
-
-                        name_bindings.define_module(parent_link,
-                                                    Some(def_id),
-                                                    ImplModuleKind,
-                                                    false,
-                                                    is_public,
-                                                    sp);
-
-                        name_bindings.get_module()
-                    }
-                };
-
-                // For each implementation item...
-                for impl_item in impl_items {
-                    match *impl_item {
-                        MethodImplItem(ref method) => {
-                            // Add the method to the module.
-                            let name = method.pe_ident().name;
-                            let method_name_bindings =
-                                self.add_child(name,
-                                               &new_parent,
-                                               ForbidDuplicateValues,
-                                               method.span);
-                            let def = match method.pe_explicit_self()
-                                .node {
-                                    SelfStatic => {
-                                        // Static methods become
-                                        // `DefStaticMethod`s.
-                                        DefStaticMethod(local_def(method.id),
-                                                        FromImpl(local_def(item.id)))
-                                    }
-                                    _ => {
-                                        // Non-static methods become
-                                        // `DefMethod`s.
-                                        DefMethod(local_def(method.id),
-                                                  None,
-                                                  FromImpl(local_def(item.id)))
-                                    }
-                                };
-
-                            // NB: not IMPORTABLE
-                            let modifiers = if method.pe_vis() == ast::Public {
-                                PUBLIC
-                            } else {
-                                DefModifiers::empty()
-                            };
-                            method_name_bindings.define_value(
-                                def,
-                                method.span,
-                                modifiers);
-                        }
-                        TypeImplItem(ref typedef) => {
-                            // Add the typedef to the module.
-                            let name = typedef.ident.name;
-                            let typedef_name_bindings =
-                                self.add_child(
-                                    name,
-                                    &new_parent,
-                                    ForbidDuplicateTypesAndModules,
-                                    typedef.span);
-                            let def = DefAssociatedTy(local_def(
-                                typedef.id));
-                            // NB: not IMPORTABLE
-                            let modifiers = if typedef.vis == ast::Public {
-                                PUBLIC
-                            } else {
-                                DefModifiers::empty()
-                            };
-                            typedef_name_bindings.define_type(
-                                def,
-                                typedef.span,
-                                modifiers);
-                        }
-                    }
-                }
-                parent.clone()
-            }
-
-            ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
+            ItemDefaultImpl(_, _) |
+            ItemImpl(..) => parent.clone(),
 
             ItemTrait(_, _, _, ref items) => {
                 let name_bindings =
@@ -676,7 +525,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
 
                 // Add the names of all the items to the trait info.
                 for trait_item in items {
-                    let (name, kind) = match *trait_item {
+                    let (name, trait_item_id) = match *trait_item {
                         ast::RequiredMethod(_) |
                         ast::ProvidedMethod(_) => {
                             let ty_m = ast_util::trait_item_to_ty_method(trait_item);
@@ -684,23 +533,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                             let name = ty_m.ident.name;
 
                             // Add it as a name in the trait module.
-                            let (def, static_flag) = match ty_m.explicit_self
-                                                               .node {
-                                SelfStatic => {
-                                    // Static methods become `DefStaticMethod`s.
-                                    (DefStaticMethod(
-                                            local_def(ty_m.id),
-                                            FromTrait(local_def(item.id))),
-                                     StaticMethodTraitItemKind)
-                                }
-                                _ => {
-                                    // Non-static methods become `DefMethod`s.
-                                    (DefMethod(local_def(ty_m.id),
-                                               Some(local_def(item.id)),
-                                               FromTrait(local_def(item.id))),
-                                     NonstaticMethodTraitItemKind)
-                                }
-                            };
+                            let def = DefMethod(local_def(ty_m.id),
+                                                FromTrait(local_def(item.id)));
 
                             let method_name_bindings =
                                 self.add_child(name,
@@ -712,11 +546,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                               ty_m.span,
                                                               PUBLIC);
 
-                            (name, static_flag)
+                            (name, local_def(ty_m.id))
                         }
                         ast::TypeTraitItem(ref associated_type) => {
-                            let def = DefAssociatedTy(local_def(
-                                    associated_type.ty_param.id));
+                            let def = DefAssociatedTy(local_def(item.id),
+                                                      local_def(associated_type.ty_param.id));
 
                             let name_bindings =
                                 self.add_child(associated_type.ty_param.ident.name,
@@ -728,11 +562,12 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                       associated_type.ty_param.span,
                                                       PUBLIC);
 
-                            (associated_type.ty_param.ident.name, TypeTraitItemKind)
+                            (associated_type.ty_param.ident.name,
+                             local_def(associated_type.ty_param.id))
                         }
                     };
 
-                    self.trait_item_map.insert((name, def_id), kind);
+                    self.trait_item_map.insert((name, def_id), trait_item_id);
                 }
 
                 name_bindings.define_type(DefTrait(def_id), sp, modifiers);
@@ -772,12 +607,9 @@ fn build_reduced_graph_for_variant(&mut self,
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item<F>(&mut self,
-                                               foreign_item: &ForeignItem,
-                                               parent: &Rc<Module>,
-                                               f: F) where
-        F: FnOnce(&mut Resolver),
-    {
+    fn build_reduced_graph_for_foreign_item(&mut self,
+                                            foreign_item: &ForeignItem,
+                                            parent: &Rc<Module>) {
         let name = foreign_item.ident.name;
         let is_public = foreign_item.vis == ast::Public;
         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
@@ -785,25 +617,15 @@ fn build_reduced_graph_for_foreign_item<F>(&mut self,
             self.add_child(name, parent, ForbidDuplicateValues,
                            foreign_item.span);
 
-        match foreign_item.node {
-            ForeignItemFn(_, ref generics) => {
-                let def = DefFn(local_def(foreign_item.id), false);
-                name_bindings.define_value(def, foreign_item.span, modifiers);
-
-                self.with_type_parameter_rib(
-                    HasTypeParameters(generics,
-                                      FnSpace,
-                                      foreign_item.id,
-                                      NormalRibKind),
-                    f);
+        let def = match foreign_item.node {
+            ForeignItemFn(..) => {
+                DefFn(local_def(foreign_item.id), false)
             }
             ForeignItemStatic(_, m) => {
-                let def = DefStatic(local_def(foreign_item.id), m);
-                name_bindings.define_value(def, foreign_item.span, modifiers);
-
-                f(self.resolver)
+                DefStatic(local_def(foreign_item.id), m)
             }
-        }
+        };
+        name_bindings.define_value(def, foreign_item.span, modifiers);
     }
 
     fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
@@ -849,8 +671,7 @@ fn handle_external_def(&mut self,
 
         let kind = match def {
             DefTy(_, true) => EnumModuleKind,
-            DefTy(_, false) => TypeModuleKind,
-            DefStruct(..) => ImplModuleKind,
+            DefTy(_, false) | DefStruct(..) => TypeModuleKind,
             _ => NormalModuleKind
         };
 
@@ -904,7 +725,7 @@ fn handle_external_def(&mut self,
                 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
                     .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
           }
-          DefFn(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
+          DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
             debug!("(building reduced graph for external \
                     crate) building value (fn/static) {}", final_ident);
             // impl methods have already been defined with the correct importability modifier
@@ -926,21 +747,19 @@ fn handle_external_def(&mut self,
 
               let trait_item_def_ids =
                 csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
-              for trait_item_def_id in &trait_item_def_ids {
-                  let (trait_item_name, trait_item_kind) =
-                      csearch::get_trait_item_name_and_kind(
-                          &self.session.cstore,
-                          trait_item_def_id.def_id());
+              for trait_item_def in &trait_item_def_ids {
+                  let trait_item_name = csearch::get_trait_name(&self.session.cstore,
+                                                                trait_item_def.def_id());
 
                   debug!("(building reduced graph for external crate) ... \
                           adding trait item '{}'",
                          token::get_name(trait_item_name));
 
-                  self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
+                  self.trait_item_map.insert((trait_item_name, def_id),
+                                             trait_item_def.def_id());
 
                   if is_exported {
-                      self.external_exports
-                          .insert(trait_item_def_id.def_id());
+                      self.external_exports.insert(trait_item_def.def_id());
                   }
               }
 
@@ -955,7 +774,7 @@ fn handle_external_def(&mut self,
                                                   is_public,
                                                   DUMMY_SP)
           }
-          DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
+          DefTy(..) | DefAssociatedTy(..) => {
               debug!("(building reduced graph for external \
                       crate) building type {}", final_ident);
 
@@ -979,7 +798,7 @@ fn handle_external_def(&mut self,
           }
           DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
           DefUse(..) | DefUpvar(..) | DefRegion(..) |
-          DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
+          DefLabel(..) | DefSelfTy(..) => {
             panic!("didn't expect `{:?}`", def);
           }
         }
@@ -1026,92 +845,9 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
                     }
                 }
             }
-            DlImpl(def) => {
-                match csearch::get_type_name_if_impl(&self.session.cstore, def) {
-                    None => {}
-                    Some(final_name) => {
-                        let methods_opt =
-                            csearch::get_methods_if_impl(&self.session.cstore, def);
-                        match methods_opt {
-                            Some(ref methods) if
-                                methods.len() >= 1 => {
-                                debug!("(building reduced graph for \
-                                        external crate) processing \
-                                        static methods for type name {}",
-                                        token::get_name(final_name));
-
-                                let child_name_bindings =
-                                    self.add_child(
-                                        final_name,
-                                        root,
-                                        OverwriteDuplicates,
-                                        DUMMY_SP);
-
-                                // Process the static methods. First,
-                                // create the module.
-                                let type_module;
-                                let type_def = child_name_bindings.type_def.borrow().clone();
-                                match type_def {
-                                    Some(TypeNsDef {
-                                        module_def: Some(module_def),
-                                        ..
-                                    }) => {
-                                        // We already have a module. This
-                                        // is OK.
-                                        type_module = module_def;
-
-                                        // Mark it as an impl module if
-                                        // necessary.
-                                        type_module.kind.set(ImplModuleKind);
-                                    }
-                                    Some(_) | None => {
-                                        let parent_link =
-                                            self.get_parent_link(root, final_name);
-                                        child_name_bindings.define_module(
-                                            parent_link,
-                                            Some(def),
-                                            ImplModuleKind,
-                                            true,
-                                            true,
-                                            DUMMY_SP);
-                                        type_module =
-                                            child_name_bindings.
-                                                get_module();
-                                    }
-                                }
-
-                                // Add each static method to the module.
-                                let new_parent = type_module;
-                                for method_info in methods {
-                                    let name = method_info.name;
-                                    debug!("(building reduced graph for \
-                                             external crate) creating \
-                                             static method '{}'",
-                                           token::get_name(name));
-
-                                    let method_name_bindings =
-                                        self.add_child(name,
-                                                       &new_parent,
-                                                       OverwriteDuplicates,
-                                                       DUMMY_SP);
-                                    let def = DefFn(method_info.def_id, false);
-
-                                    // NB: not IMPORTABLE
-                                    let modifiers = if method_info.vis == ast::Public {
-                                        PUBLIC
-                                    } else {
-                                        DefModifiers::empty()
-                                    };
-                                    method_name_bindings.define_value(
-                                        def, DUMMY_SP, modifiers);
-                                }
-                            }
-
-                            // Otherwise, do nothing.
-                            Some(_) | None => {}
-                        }
-                    }
-                }
+            DlImpl(_) => {
+                debug!("(building reduced graph for external crate) \
+                        ignoring impl");
             }
             DlField => {
                 debug!("(building reduced graph for external crate) \
@@ -1192,7 +928,7 @@ fn build_import_directive(&mut self,
                 debug!("(building import directive) building import \
                         directive: {}::{}",
                        self.names_to_string(&module_.imports.borrow().last().unwrap().
-                                                             module_path[]),
+                                                             module_path),
                        token::get_name(target));
 
                 let mut import_resolutions = module_.import_resolutions
@@ -1240,16 +976,7 @@ fn visit_item(&mut self, item: &Item) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        let parent = &self.parent;
-        self.builder.build_reduced_graph_for_foreign_item(foreign_item,
-                                                          parent,
-                                                          |r| {
-            let mut v = BuildReducedGraphVisitor {
-                builder: GraphBuilder { resolver: r },
-                parent: parent.clone()
-            };
-            visit::walk_foreign_item(&mut v, foreign_item);
-        })
+        self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
     }
 
     fn visit_block(&mut self, block: &Block) {
index a239c73c110dbd67e96353ad8efca3f20b6b82b5..aebbe14407380336174b9c85f82bd693b5084dbd 100644 (file)
@@ -68,17 +68,17 @@ fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
                                   "unused import".to_string());
         }
 
-        let (v_priv, t_priv) = match self.last_private.get(&id) {
-            Some(&LastImport {
-                value_priv: v,
-                value_used: _,
-                type_priv: t,
-                type_used: _
-            }) => (v, t),
-            Some(_) => {
+        let mut def_map = self.def_map.borrow_mut();
+        let path_res = if let Some(r) = def_map.get_mut(&id) {
+            r
+        } else {
+            return;
+        };
+        let (v_priv, t_priv) = match path_res.last_private {
+            LastImport { value_priv, type_priv, .. } => (value_priv, type_priv),
+            _ => {
                 panic!("we should only have LastImport for `use` directives")
             }
-            _ => return,
         };
 
         let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
@@ -100,10 +100,12 @@ fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
             _ => {},
         }
 
-        self.last_private.insert(id, LastImport{value_priv: v_priv,
-                                                value_used: v_used,
-                                                type_priv: t_priv,
-                                                type_used: t_used});
+        path_res.last_private = LastImport {
+            value_priv: v_priv,
+            value_used: v_used,
+            type_priv: t_priv,
+            type_used: t_used
+        };
     }
 }
 
index 333d32d76b6d5fc85c8f63ea874eec047c5a46e5..95523be68c3bf9ffa3ec594ca0c3202db98e267f 100644 (file)
 use self::FallbackSuggestion::*;
 use self::TypeParameters::*;
 use self::RibKind::*;
-use self::MethodSort::*;
 use self::UseLexicalScopeFlag::*;
 use self::ModulePrefixResult::*;
 use self::NameSearchType::*;
 use self::BareIdentifierPatternResolution::*;
 use self::ParentLink::*;
 use self::ModuleKind::*;
-use self::TraitReferenceType::*;
 use self::FallbackChecks::*;
 
 use rustc::session::Session;
 
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
 use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
-use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall};
-use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
+use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall};
+use syntax::ast::{ExprPath, ExprStruct, FnDecl};
 use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
-use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
+use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
 use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId};
+use syntax::ast::{Local, MethodImplItem, Name, NodeId};
 use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
-use syntax::ast::{PatRange, PatStruct, Path};
-use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit};
-use syntax::ast::{RegionTyParamBound, StructField};
-use syntax::ast::{TraitRef, TraitTyParamBound};
-use syntax::ast::{Ty, TyBool, TyChar, TyF32};
-use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum};
-use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath};
+use syntax::ast::{PatRange, PatStruct, Path, PrimTy};
+use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32};
+use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt};
+use syntax::ast::{TyPath, TyPtr};
 use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint};
 use syntax::ast::{TypeImplItem};
 use syntax::ast;
@@ -89,8 +84,7 @@
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
 use syntax::parse::token::{self, special_names, special_idents};
-use syntax::codemap::{Span, Pos};
-use syntax::owned_slice::OwnedSlice;
+use syntax::codemap::{self, Span, Pos};
 use syntax::visit::{self, Visitor};
 
 use std::collections::{HashMap, HashSet};
@@ -188,6 +182,72 @@ fn visit_local(&mut self, local: &Local) {
     fn visit_ty(&mut self, ty: &Ty) {
         self.resolve_type(ty);
     }
+    fn visit_generics(&mut self, generics: &Generics) {
+        self.resolve_generics(generics);
+    }
+    fn visit_poly_trait_ref(&mut self,
+                            tref: &ast::PolyTraitRef,
+                            m: &ast::TraitBoundModifier) {
+        match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
+            Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
+            Err(_) => { /* error already reported */ }
+        }
+        visit::walk_poly_trait_ref(self, tref, m);
+    }
+    fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) {
+        if let Some(ref dis_expr) = variant.node.disr_expr {
+            // resolve the discriminator expr as a constant
+            self.with_constant_rib(|this| {
+                this.visit_expr(&**dis_expr);
+            });
+        }
+
+        // `visit::walk_variant` without the discriminant expression.
+        match variant.node.kind {
+            ast::TupleVariantKind(ref variant_arguments) => {
+                for variant_argument in variant_arguments.iter() {
+                    self.visit_ty(&*variant_argument.ty);
+                }
+            }
+            ast::StructVariantKind(ref struct_definition) => {
+                self.visit_struct_def(&**struct_definition,
+                                      variant.node.name,
+                                      generics,
+                                      variant.node.id);
+            }
+        }
+    }
+    fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) {
+        let type_parameters = match foreign_item.node {
+            ForeignItemFn(_, ref generics) => {
+                HasTypeParameters(generics, FnSpace, ItemRibKind)
+            }
+            ForeignItemStatic(..) => NoTypeParameters
+        };
+        self.with_type_parameter_rib(type_parameters, |this| {
+            visit::walk_foreign_item(this, foreign_item);
+        });
+    }
+    fn visit_fn(&mut self,
+                function_kind: visit::FnKind<'v>,
+                declaration: &'v FnDecl,
+                block: &'v Block,
+                _: Span,
+                node_id: NodeId) {
+        let rib_kind = match function_kind {
+            visit::FkItemFn(_, generics, _, _) => {
+                self.visit_generics(generics);
+                ItemRibKind
+            }
+            visit::FkMethod(_, generics, method) => {
+                self.visit_generics(generics);
+                self.visit_explicit_self(method.pe_explicit_self());
+                MethodRibKind
+            }
+            visit::FkFnBlock(..) => ClosureRibKind(node_id)
+        };
+        self.resolve_function(rib_kind, declaration, block);
+    }
 }
 
 /// Contains data for specific types of import directives.
@@ -231,9 +291,6 @@ enum TypeParameters<'a> {
         // were declared on (type, fn, etc)
         ParamSpace,
 
-        // ID of the enclosing item.
-        NodeId,
-
         // The kind of the rib used for type parameters.
         RibKind)
 }
@@ -253,8 +310,7 @@ enum RibKind {
     // methods. Allow references to ty params that impl or trait
     // binds. Disallow any other upvars (including other ty params that are
     // upvars).
-              // parent;   method itself
-    MethodRibKind(NodeId, MethodSort),
+    MethodRibKind,
 
     // We passed through an item scope. Disallow upvars.
     ItemRibKind,
@@ -263,13 +319,6 @@ enum RibKind {
     ConstantItemRibKind
 }
 
-// Methods can be required or provided. RequiredMethod methods only occur in traits.
-#[derive(Copy, Debug)]
-enum MethodSort {
-    RequiredMethod,
-    ProvidedMethod(NodeId)
-}
-
 #[derive(Copy)]
 enum UseLexicalScopeFlag {
     DontUseLexicalScope,
@@ -465,7 +514,6 @@ enum ParentLink {
 enum ModuleKind {
     NormalModuleKind,
     TraitModuleKind,
-    ImplModuleKind,
     EnumModuleKind,
     TypeModuleKind,
     AnonymousModuleKind,
@@ -586,16 +634,6 @@ struct NameBindings {
     value_def: RefCell<Option<ValueNsDef>>, //< Meaning in value namespace.
 }
 
-/// Ways in which a trait can be referenced
-#[derive(Copy)]
-enum TraitReferenceType {
-    TraitImplementation,             // impl SomeTrait for T { ... }
-    TraitDerivation,                 // trait T : SomeTrait { ... }
-    TraitBoundingTypeParameter,      // fn f<T:SomeTrait>() { ... }
-    TraitObject,                     // Box<for<'a> SomeTrait>
-    TraitQPath,                      // <T as SomeTrait>::
-}
-
 impl NameBindings {
     fn new() -> NameBindings {
         NameBindings {
@@ -861,7 +899,7 @@ struct Resolver<'a, 'tcx:'a> {
 
     graph_root: NameBindings,
 
-    trait_item_map: FnvHashMap<(Name, DefId), TraitItemKind>,
+    trait_item_map: FnvHashMap<(Name, DefId), DefId>,
 
     structs: FnvHashMap<DefId, Vec<Name>>,
 
@@ -901,7 +939,6 @@ struct Resolver<'a, 'tcx:'a> {
     export_map: ExportMap,
     trait_map: TraitMap,
     external_exports: ExternalExports,
-    last_private: LastPrivateMap,
 
     // Whether or not to print error messages. Can be set to true
     // when getting additional info for error message suggestions,
@@ -976,7 +1013,6 @@ fn new(session: &'a Session,
             used_imports: HashSet::new(),
             used_crates: HashSet::new(),
             external_exports: DefIdSet(),
-            last_private: NodeMap(),
 
             emit_errors: true,
             make_glob_map: make_glob_map == MakeGlobMap::Yes,
@@ -1068,7 +1104,7 @@ fn resolve_imports_for_module(&mut self, module: Rc<Module>) {
                     };
                     let msg = format!("unresolved import `{}`{}",
                                       self.import_path_to_string(
-                                          &import_directive.module_path[],
+                                          &import_directive.module_path,
                                           import_directive.subclass),
                                       help);
                     self.resolve_error(span, &msg[..]);
@@ -1096,8 +1132,8 @@ fn names_to_string(&self, names: &[Name]) -> String {
         result
     }
 
-    fn path_names_to_string(&self, path: &Path) -> String {
-        let names: Vec<ast::Name> = path.segments
+    fn path_names_to_string(&self, path: &Path, depth: usize) -> String {
+        let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth]
                                         .iter()
                                         .map(|seg| seg.identifier.name)
                                         .collect();
@@ -1534,31 +1570,36 @@ fn get_binding(this: &mut Resolver,
         // record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
-        let value_private = match import_resolution.value_target {
-            Some(ref target) => {
-                let def = target.bindings.def_for_namespace(ValueNS).unwrap();
-                self.def_map.borrow_mut().insert(directive.id, def);
-                let did = def.def_id();
-                if value_used_public {Some(lp)} else {Some(DependsOn(did))}
-            },
-            // AllPublic here and below is a dummy value, it should never be used because
-            // _exists is false.
-            None => None,
-        };
-        let type_private = match import_resolution.type_target {
-            Some(ref target) => {
-                let def = target.bindings.def_for_namespace(TypeNS).unwrap();
-                self.def_map.borrow_mut().insert(directive.id, def);
-                let did = def.def_id();
-                if type_used_public {Some(lp)} else {Some(DependsOn(did))}
-            },
-            None => None,
+        let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| {
+            let def = target.bindings.def_for_namespace(ValueNS).unwrap();
+            (def, if value_used_public { lp } else { DependsOn(def.def_id()) })
+        });
+        let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| {
+            let def = target.bindings.def_for_namespace(TypeNS).unwrap();
+            (def, if type_used_public { lp } else { DependsOn(def.def_id()) })
+        });
+
+        let import_lp = LastImport {
+            value_priv: value_def_and_priv.map(|(_, p)| p),
+            value_used: Used,
+            type_priv: type_def_and_priv.map(|(_, p)| p),
+            type_used: Used
         };
 
-        self.last_private.insert(directive.id, LastImport{value_priv: value_private,
-                                                          value_used: Used,
-                                                          type_priv: type_private,
-                                                          type_used: Used});
+        if let Some((def, _)) = value_def_and_priv {
+            self.def_map.borrow_mut().insert(directive.id, PathResolution {
+                base_def: def,
+                last_private: import_lp,
+                depth: 0
+            });
+        }
+        if let Some((def, _)) = type_def_and_priv {
+            self.def_map.borrow_mut().insert(directive.id, PathResolution {
+                base_def: def,
+                last_private: import_lp,
+                depth: 0
+            });
+        }
 
         debug!("(resolving single import) successfully resolved import");
         return Success(());
@@ -1676,12 +1717,12 @@ fn resolve_glob_import(&mut self,
         }
 
         // Record the destination of this import
-        match containing_module.def_id.get() {
-            Some(did) => {
-                self.def_map.borrow_mut().insert(id, DefMod(did));
-                self.last_private.insert(id, lp);
-            }
-            None => {}
+        if let Some(did) = containing_module.def_id.get() {
+            self.def_map.borrow_mut().insert(id, PathResolution {
+                base_def: DefMod(did),
+                last_private: lp,
+                depth: 0
+            });
         }
 
         debug!("(resolving glob import) successfully resolved import");
@@ -1822,13 +1863,11 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
         match import_resolution.value_target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref value) = *name_bindings.value_def.borrow() {
-                    let msg = format!("import `{}` conflicts with value \
-                                       in this module",
-                                      &token::get_name(name));
-                    span_err!(self.session, import_span, E0255, "{}", &msg[..]);
+                    span_err!(self.session, import_span, E0255,
+                              "import `{}` conflicts with value in this module",
+                              &token::get_name(name));
                     if let Some(span) = value.value_span {
-                        self.session.span_note(span,
-                                               "conflicting value here");
+                        self.session.span_note(span, "conflicting value here");
                     }
                 }
             }
@@ -1838,41 +1877,16 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
         match import_resolution.type_target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref ty) = *name_bindings.type_def.borrow() {
-                    match ty.module_def {
-                        None => {
-                            let msg = format!("import `{}` conflicts with type in \
-                                               this module",
-                                              &token::get_name(name));
-                            span_err!(self.session, import_span, E0256, "{}", &msg[..]);
-                            if let Some(span) = ty.type_span {
-                                self.session.span_note(span,
-                                                       "note conflicting type here")
-                            }
-                        }
-                        Some(ref module_def) => {
-                            match module_def.kind.get() {
-                                ImplModuleKind => {
-                                    if let Some(span) = ty.type_span {
-                                        let msg = format!("inherent implementations \
-                                                           are only allowed on types \
-                                                           defined in the current module");
-                                        span_err!(self.session, span, E0257, "{}", &msg[..]);
-                                        self.session.span_note(import_span,
-                                                               "import from other module here")
-                                    }
-                                }
-                                _ => {
-                                    let msg = format!("import `{}` conflicts with existing \
-                                                       submodule",
-                                                      &token::get_name(name));
-                                    span_err!(self.session, import_span, E0258, "{}", &msg[..]);
-                                    if let Some(span) = ty.type_span {
-                                        self.session.span_note(span,
-                                                               "note conflicting module here")
-                                    }
-                                }
-                            }
-                        }
+                    let (what, note) = if ty.module_def.is_some() {
+                        ("existing submodule", "note conflicting module here")
+                    } else {
+                        ("type in this module", "note conflicting type here")
+                    };
+                    span_err!(self.session, import_span, E0256,
+                              "import `{}` conflicts with {}",
+                              &token::get_name(name), what);
+                    if let Some(span) = ty.type_span {
+                        self.session.span_note(span, note);
                     }
                 }
             }
@@ -2226,7 +2240,6 @@ fn resolve_item_in_lexical_scope(&mut self,
                             return Failed(None);
                         }
                         TraitModuleKind |
-                        ImplModuleKind |
                         EnumModuleKind |
                         TypeModuleKind |
                         AnonymousModuleKind => {
@@ -2247,7 +2260,7 @@ fn resolve_item_in_lexical_scope(&mut self,
                                               true) {
                 Failed(Some((span, msg))) =>
                     self.resolve_error(span, &format!("failed to resolve. {}",
-                                                     msg)[]),
+                                                     msg)),
                 Failed(None) => (), // Continue up the search chain.
                 Indeterminate => {
                     // We couldn't see through the higher scope because of an
@@ -2324,7 +2337,6 @@ fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>)
                     match new_module.kind.get() {
                         NormalModuleKind => return Some(new_module),
                         TraitModuleKind |
-                        ImplModuleKind |
                         EnumModuleKind |
                         TypeModuleKind |
                         AnonymousModuleKind => module_ = new_module,
@@ -2341,7 +2353,6 @@ fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>)
         match module_.kind.get() {
             NormalModuleKind => return module_,
             TraitModuleKind |
-            ImplModuleKind |
             EnumModuleKind |
             TypeModuleKind |
             AnonymousModuleKind => {
@@ -2600,14 +2611,16 @@ fn upvarify(&self,
                 def_like: DefLike,
                 span: Span)
                 -> Option<DefLike> {
-        match def_like {
-            DlDef(d @ DefUpvar(..)) => {
+        let mut def = match def_like {
+            DlDef(def) => def,
+            _ => return Some(def_like)
+        };
+        match def {
+            DefUpvar(..) => {
                 self.session.span_bug(span,
-                    &format!("unexpected {:?} in bindings", d)[])
+                    &format!("unexpected {:?} in bindings", def))
             }
-            DlDef(d @ DefLocal(_)) => {
-                let node_id = d.def_id().node;
-                let mut def = d;
+            DefLocal(node_id) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind => {
@@ -2631,39 +2644,14 @@ fn upvarify(&self,
                             }.push(Freevar { def: prev_def, span: span });
                             seen.insert(node_id);
                         }
-                        MethodRibKind(item_id, _) => {
-                            // If the def is a ty param, and came from the parent
-                            // item, it's ok
-                            match def {
-                                DefTyParam(_, _, did, _) if {
-                                    self.def_map.borrow().get(&did.node).cloned()
-                                        == Some(DefTyParamBinder(item_id))
-                                } => {} // ok
-                                DefSelfTy(did) if did == item_id => {} // ok
-                                _ => {
-                                    // This was an attempt to access an upvar inside a
-                                    // named function item. This is not allowed, so we
-                                    // report an error.
-
-                                    self.resolve_error(
-                                        span,
-                                        "can't capture dynamic environment in a fn item; \
-                                        use the || { ... } closure form instead");
-
-                                    return None;
-                                }
-                            }
-                        }
-                        ItemRibKind => {
+                        ItemRibKind | MethodRibKind => {
                             // This was an attempt to access an upvar inside a
                             // named function item. This is not allowed, so we
                             // report an error.
 
-                            self.resolve_error(
-                                span,
+                            self.resolve_error(span,
                                 "can't capture dynamic environment in a fn item; \
-                                use the || { ... } closure form instead");
-
+                                 use the || { ... } closure form instead");
                             return None;
                         }
                         ConstantItemRibKind => {
@@ -2671,42 +2659,17 @@ fn upvarify(&self,
                             self.resolve_error(span,
                                                "attempt to use a non-constant \
                                                 value in a constant");
-
+                            return None;
                         }
                     }
                 }
-                Some(DlDef(def))
             }
-            DlDef(def @ DefTyParam(..)) |
-            DlDef(def @ DefSelfTy(..)) => {
+            DefTyParam(..) | DefSelfTy(_) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind | ClosureRibKind(..) => {
+                        NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
                             // Nothing to do. Continue.
                         }
-                        MethodRibKind(item_id, _) => {
-                            // If the def is a ty param, and came from the parent
-                            // item, it's ok
-                            match def {
-                                DefTyParam(_, _, did, _) if {
-                                    self.def_map.borrow().get(&did.node).cloned()
-                                        == Some(DefTyParamBinder(item_id))
-                                } => {} // ok
-                                DefSelfTy(did) if did == item_id => {} // ok
-
-                                _ => {
-                                    // This was an attempt to use a type parameter outside
-                                    // its scope.
-
-                                    self.resolve_error(span,
-                                                        "can't use type parameters from \
-                                                        outer function; try using a local \
-                                                        type parameter instead");
-
-                                    return None;
-                                }
-                            }
-                        }
                         ItemRibKind => {
                             // This was an attempt to use a type parameter outside
                             // its scope.
@@ -2715,7 +2678,6 @@ fn upvarify(&self,
                                                "can't use type parameters from \
                                                 outer function; try using a local \
                                                 type parameter instead");
-
                             return None;
                         }
                         ConstantItemRibKind => {
@@ -2723,14 +2685,14 @@ fn upvarify(&self,
                             self.resolve_error(span,
                                                "cannot use an outer type \
                                                 parameter in this context");
-
+                            return None;
                         }
                     }
                 }
-                Some(DlDef(def))
             }
-            _ => Some(def_like)
+            _ => {}
         }
+        Some(DlDef(def))
     }
 
     /// Searches the current set of local scopes and
@@ -2743,13 +2705,8 @@ fn search_ribs(&self,
         // FIXME #4950: Try caching?
 
         for (i, rib) in ribs.iter().enumerate().rev() {
-            match rib.bindings.get(&name).cloned() {
-                Some(def_like) => {
-                    return self.upvarify(&ribs[i + 1..], def_like, span);
-                }
-                None => {
-                    // Continue.
-                }
+            if let Some(def_like) = rib.bindings.get(&name).cloned() {
+                return self.upvarify(&ribs[i + 1..], def_like, span);
             }
         }
 
@@ -2797,56 +2754,32 @@ fn resolve_item(&mut self, item: &Item) {
                token::get_name(name));
 
         match item.node {
-
-            // enum item: resolve all the variants' discrs,
-            // then resolve the ty params
-            ItemEnum(ref enum_def, ref generics) => {
+            ItemEnum(_, ref generics) |
+            ItemTy(_, ref generics) |
+            ItemStruct(_, ref generics) => {
                 self.check_if_primitive_type_name(name, item.span);
 
-                for variant in &(*enum_def).variants {
-                    if let Some(ref dis_expr) = variant.node.disr_expr {
-                        // resolve the discriminator expr
-                        // as a constant
-                        self.with_constant_rib(|this| {
-                            this.resolve_expr(&**dis_expr);
-                        });
-                    }
-                }
-
-                // n.b. the discr expr gets visited twice.
-                // but maybe it's okay since the first time will signal an
-                // error if there is one? -- tjc
                 self.with_type_parameter_rib(HasTypeParameters(generics,
                                                                TypeSpace,
-                                                               item.id,
                                                                ItemRibKind),
-                                             |this| {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    this.resolve_where_clause(&generics.where_clause);
-                    visit::walk_item(this, item);
-                });
+                                             |this| visit::walk_item(this, item));
             }
-
-            ItemTy(_, ref generics) => {
-                self.check_if_primitive_type_name(name, item.span);
-
+            ItemFn(_, _, _, ref generics, _) => {
                 self.with_type_parameter_rib(HasTypeParameters(generics,
-                                                               TypeSpace,
-                                                               item.id,
+                                                               FnSpace,
                                                                ItemRibKind),
-                                             |this| {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    visit::walk_item(this, item);
-                });
+                                             |this| visit::walk_item(this, item));
             }
 
+            ItemDefaultImpl(_, ref trait_ref) => {
+                self.with_optional_trait_ref(Some(trait_ref), |_| {});
+            }
             ItemImpl(_, _,
                      ref generics,
                      ref implemented_traits,
                      ref self_type,
                      ref impl_items) => {
-                self.resolve_implementation(item.id,
-                                            generics,
+                self.resolve_implementation(generics,
                                             implemented_traits,
                                             &**self_type,
                                             &impl_items[..]);
@@ -2866,14 +2799,10 @@ fn resolve_item(&mut self, item: &Item) {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics,
                                                                TypeSpace,
-                                                               item.id,
                                                                NormalRibKind),
                                              |this| {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    this.resolve_where_clause(&generics.where_clause);
-
-                    this.resolve_type_parameter_bounds(item.id, bounds,
-                                                       TraitDerivation);
+                    this.visit_generics(generics);
+                    visit::walk_ty_param_bounds_helper(this, bounds);
 
                     for trait_item in &(*trait_items) {
                         // Create a new rib for the trait_item-specific type
@@ -2881,101 +2810,39 @@ fn resolve_item(&mut self, item: &Item) {
                         //
                         // FIXME #4951: Do we need a node ID here?
 
-                        match *trait_item {
-                          ast::RequiredMethod(ref ty_m) => {
-                            this.with_type_parameter_rib
-                                (HasTypeParameters(&ty_m.generics,
-                                                   FnSpace,
-                                                   item.id,
-                                        MethodRibKind(item.id, RequiredMethod)),
-                                 |this| {
-
-                                // Resolve the method-specific type
-                                // parameters.
-                                this.resolve_type_parameters(
-                                    &ty_m.generics.ty_params);
-                                this.resolve_where_clause(&ty_m.generics
-                                                               .where_clause);
-
-                                for argument in &ty_m.decl.inputs {
-                                    this.resolve_type(&*argument.ty);
-                                }
-
-                                if let SelfExplicit(ref typ, _) = ty_m.explicit_self.node {
-                                    this.resolve_type(&**typ)
-                                }
-
-                                if let ast::Return(ref ret_ty) = ty_m.decl.output {
-                                    this.resolve_type(&**ret_ty);
-                                }
-                            });
-                          }
-                          ast::ProvidedMethod(ref m) => {
-                              this.resolve_method(MethodRibKind(item.id,
-                                                                ProvidedMethod(m.id)),
-                                                  &**m)
-                          }
-                          ast::TypeTraitItem(ref data) => {
-                              this.resolve_type_parameter(&data.ty_param);
-                              visit::walk_trait_item(this, trait_item);
-                          }
-                        }
+                        let type_parameters = match *trait_item {
+                            ast::RequiredMethod(ref ty_m) => {
+                                HasTypeParameters(&ty_m.generics,
+                                                  FnSpace,
+                                                  MethodRibKind)
+                            }
+                            ast::ProvidedMethod(ref m) => {
+                                HasTypeParameters(m.pe_generics(),
+                                                  FnSpace,
+                                                  MethodRibKind)
+                            }
+                            ast::TypeTraitItem(ref assoc_ty) => {
+                                let ty_param = &assoc_ty.ty_param;
+                                this.check_if_primitive_type_name(ty_param.ident.name,
+                                                                  ty_param.span);
+                                NoTypeParameters
+                            }
+                        };
+                        this.with_type_parameter_rib(type_parameters, |this| {
+                            visit::walk_trait_item(this, trait_item)
+                        });
                     }
                 });
 
                 self.type_ribs.pop();
             }
 
-            ItemStruct(ref struct_def, ref generics) => {
-                self.check_if_primitive_type_name(name, item.span);
-
-                self.resolve_struct(item.id,
-                                    generics,
-                                    &struct_def.fields[]);
-            }
-
-            ItemMod(ref module_) => {
+            ItemMod(_) | ItemForeignMod(_) => {
                 self.with_scope(Some(name), |this| {
-                    this.resolve_module(module_, item.span, name,
-                                        item.id);
-                });
-            }
-
-            ItemForeignMod(ref foreign_module) => {
-                self.with_scope(Some(name), |this| {
-                    for foreign_item in &foreign_module.items {
-                        match foreign_item.node {
-                            ForeignItemFn(_, ref generics) => {
-                                this.with_type_parameter_rib(
-                                    HasTypeParameters(
-                                        generics, FnSpace, foreign_item.id,
-                                        ItemRibKind),
-                                    |this| {
-                                        this.resolve_type_parameters(&generics.ty_params);
-                                        this.resolve_where_clause(&generics.where_clause);
-                                        visit::walk_foreign_item(this, &**foreign_item)
-                                    });
-                            }
-                            ForeignItemStatic(..) => {
-                                visit::walk_foreign_item(this,
-                                                         &**foreign_item);
-                            }
-                        }
-                    }
+                    visit::walk_item(this, item);
                 });
             }
 
-            ItemFn(ref fn_decl, _, _, ref generics, ref block) => {
-                self.resolve_function(ItemRibKind,
-                                      Some(&**fn_decl),
-                                      HasTypeParameters
-                                        (generics,
-                                         FnSpace,
-                                         item.id,
-                                         ItemRibKind),
-                                      &**block);
-            }
-
             ItemConst(..) | ItemStatic(..) => {
                 self.with_constant_rib(|this| {
                     visit::walk_item(this, item);
@@ -2985,8 +2852,8 @@ fn resolve_item(&mut self, item: &Item) {
             ItemUse(ref view_path) => {
                 // check for imports shadowing primitive types
                 if let ast::ViewPathSimple(ident, _) = view_path.node {
-                    match self.def_map.borrow().get(&item.id) {
-                        Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefTrait(..)) | None => {
+                    match self.def_map.borrow().get(&item.id).map(|d| d.full_def()) {
+                        Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
                             self.check_if_primitive_type_name(ident.name, item.span);
                         }
                         _ => {}
@@ -3004,35 +2871,29 @@ fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F)
         F: FnOnce(&mut Resolver),
     {
         match type_parameters {
-            HasTypeParameters(generics, space, node_id, rib_kind) => {
+            HasTypeParameters(generics, space, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = HashSet::new();
                 for (index, type_parameter) in generics.ty_params.iter().enumerate() {
                     let name = type_parameter.ident.name;
-                    debug!("with_type_parameter_rib: {} {}", node_id,
-                           type_parameter.id);
+                    debug!("with_type_parameter_rib: {}", type_parameter.id);
 
                     if seen_bindings.contains(&name) {
                         self.resolve_error(type_parameter.span,
                                            &format!("the name `{}` is already \
-                                                    used for a type \
-                                                    parameter in this type \
-                                                    parameter list",
-                                                   token::get_name(
-                                                       name))[])
+                                                     used for a type \
+                                                     parameter in this type \
+                                                     parameter list",
+                                                    token::get_name(name)))
                     }
                     seen_bindings.insert(name);
 
-                    let def_like = DlDef(DefTyParam(space,
-                                                    index as u32,
-                                                    local_def(type_parameter.id),
-                                                    name));
-                    // Associate this type parameter with
-                    // the item that bound it
-                    self.record_def(type_parameter.id,
-                                    (DefTyParamBinder(node_id), LastMod(AllPublic)));
                     // plain insert (no renaming)
-                    function_type_rib.bindings.insert(name, def_like);
+                    function_type_rib.bindings.insert(name,
+                        DlDef(DefTyParam(space,
+                                         index as u32,
+                                         local_def(type_parameter.id),
+                                         name)));
                 }
                 self.type_ribs.push(function_type_rib);
             }
@@ -3070,224 +2931,84 @@ fn with_constant_rib<F>(&mut self, f: F) where
 
     fn resolve_function(&mut self,
                         rib_kind: RibKind,
-                        optional_declaration: Option<&FnDecl>,
-                        type_parameters: TypeParameters,
+                        declaration: &FnDecl,
                         block: &Block) {
         // Create a value rib for the function.
-        let function_value_rib = Rib::new(rib_kind);
-        self.value_ribs.push(function_value_rib);
+        self.value_ribs.push(Rib::new(rib_kind));
 
         // Create a label rib for the function.
-        let function_label_rib = Rib::new(rib_kind);
-        self.label_ribs.push(function_label_rib);
+        self.label_ribs.push(Rib::new(rib_kind));
 
-        // If this function has type parameters, add them now.
-        self.with_type_parameter_rib(type_parameters, |this| {
-            // Resolve the type parameters.
-            match type_parameters {
-                NoTypeParameters => {
-                    // Continue.
-                }
-                HasTypeParameters(ref generics, _, _, _) => {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    this.resolve_where_clause(&generics.where_clause);
-                }
-            }
-
-            // Add each argument to the rib.
-            match optional_declaration {
-                None => {
-                    // Nothing to do.
-                }
-                Some(declaration) => {
-                    let mut bindings_list = HashMap::new();
-                    for argument in &declaration.inputs {
-                        this.resolve_pattern(&*argument.pat,
-                                             ArgumentIrrefutableMode,
-                                             &mut bindings_list);
-
-                        this.resolve_type(&*argument.ty);
+        // Add each argument to the rib.
+        let mut bindings_list = HashMap::new();
+        for argument in &declaration.inputs {
+            self.resolve_pattern(&*argument.pat,
+                                 ArgumentIrrefutableMode,
+                                 &mut bindings_list);
 
-                        debug!("(resolving function) recorded argument");
-                    }
+            self.visit_ty(&*argument.ty);
 
-                    if let ast::Return(ref ret_ty) = declaration.output {
-                        this.resolve_type(&**ret_ty);
-                    }
-                }
-            }
+            debug!("(resolving function) recorded argument");
+        }
+        visit::walk_fn_ret_ty(self, &declaration.output);
 
-            // Resolve the function body.
-            this.resolve_block(&*block);
+        // Resolve the function body.
+        self.visit_block(&*block);
 
-            debug!("(resolving function) leaving function");
-        });
+        debug!("(resolving function) leaving function");
 
         self.label_ribs.pop();
         self.value_ribs.pop();
     }
 
-    fn resolve_type_parameters(&mut self,
-                               type_parameters: &OwnedSlice<TyParam>) {
-        for type_parameter in &**type_parameters {
-            self.resolve_type_parameter(type_parameter);
-        }
-    }
-
-    fn resolve_type_parameter(&mut self,
-                              type_parameter: &TyParam) {
-        self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
-        for bound in &*type_parameter.bounds {
-            self.resolve_type_parameter_bound(type_parameter.id, bound,
-                                              TraitBoundingTypeParameter);
-        }
-        match type_parameter.default {
-            Some(ref ty) => self.resolve_type(&**ty),
-            None => {}
-        }
-    }
-
-    fn resolve_type_parameter_bounds(&mut self,
-                                     id: NodeId,
-                                     type_parameter_bounds: &OwnedSlice<TyParamBound>,
-                                     reference_type: TraitReferenceType) {
-        for type_parameter_bound in &**type_parameter_bounds {
-            self.resolve_type_parameter_bound(id, type_parameter_bound,
-                                              reference_type);
-        }
-    }
-
-    fn resolve_type_parameter_bound(&mut self,
-                                    id: NodeId,
-                                    type_parameter_bound: &TyParamBound,
-                                    reference_type: TraitReferenceType) {
-        match *type_parameter_bound {
-            TraitTyParamBound(ref tref, _) => {
-                self.resolve_poly_trait_reference(id, tref, reference_type)
-            }
-            RegionTyParamBound(..) => {}
-        }
-    }
-
-    fn resolve_poly_trait_reference(&mut self,
-                                    id: NodeId,
-                                    poly_trait_reference: &PolyTraitRef,
-                                    reference_type: TraitReferenceType) {
-        self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type)
-    }
-
     fn resolve_trait_reference(&mut self,
                                id: NodeId,
-                               trait_reference: &TraitRef,
-                               reference_type: TraitReferenceType) {
-        match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
-            None => {
-                let path_str = self.path_names_to_string(&trait_reference.path);
-                let usage_str = match reference_type {
-                    TraitBoundingTypeParameter => "bound type parameter with",
-                    TraitImplementation        => "implement",
-                    TraitDerivation            => "derive",
-                    TraitObject                => "reference",
-                    TraitQPath                 => "extract an associated item from",
-                };
-
-                let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
-                self.resolve_error(trait_reference.path.span, &msg[..]);
-            }
-            Some(def) => {
-                match def {
-                    (DefTrait(_), _) => {
-                        debug!("(resolving trait) found trait def: {:?}", def);
-                        self.record_def(trait_reference.ref_id, def);
-                    }
-                    (def, _) => {
-                        self.resolve_error(trait_reference.path.span,
-                                           &format!("`{}` is not a trait",
-                                                   self.path_names_to_string(
-                                                       &trait_reference.path))[]);
-
-                        // If it's a typedef, give a note
-                        if let DefTy(..) = def {
-                            self.session.span_note(
-                                trait_reference.path.span,
-                                &format!("`type` aliases cannot be used for traits")
-                                []);
-                        }
-                    }
+                               trait_path: &Path,
+                               path_depth: usize)
+                               -> Result<PathResolution, ()> {
+        if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
+            if let DefTrait(_) = path_res.base_def {
+                debug!("(resolving trait) found trait def: {:?}", path_res);
+                Ok(path_res)
+            } else {
+                self.resolve_error(trait_path.span,
+                    &format!("`{}` is not a trait",
+                             self.path_names_to_string(trait_path, path_depth)));
+
+                // If it's a typedef, give a note
+                if let DefTy(..) = path_res.base_def {
+                    self.session.span_note(trait_path.span,
+                                           "`type` aliases cannot be used for traits");
                 }
+                Err(())
             }
+        } else {
+            let msg = format!("use of undeclared trait name `{}`",
+                              self.path_names_to_string(trait_path, path_depth));
+            self.resolve_error(trait_path.span, &msg[]);
+            Err(())
         }
     }
 
-    fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
-        for predicate in &where_clause.predicates {
+    fn resolve_generics(&mut self, generics: &Generics) {
+        for type_parameter in &*generics.ty_params {
+            self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
+        }
+        for predicate in &generics.where_clause.predicates {
             match predicate {
-                &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                    self.resolve_type(&*bound_pred.bounded_ty);
-
-                    for bound in &*bound_pred.bounds {
-                        self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound,
-                                                          TraitBoundingTypeParameter);
-                    }
-                }
+                &ast::WherePredicate::BoundPredicate(_) |
                 &ast::WherePredicate::RegionPredicate(_) => {}
                 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
-                    match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
-                        Some((def @ DefTyParam(..), last_private)) => {
-                            self.record_def(eq_pred.id, (def, last_private));
-                        }
-                        _ => {
-                            self.resolve_error(eq_pred.path.span,
-                                               "undeclared associated type");
-                        }
+                    let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
+                    if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
+                        self.record_def(eq_pred.id, path_res.unwrap());
+                    } else {
+                        self.resolve_error(eq_pred.path.span, "undeclared associated type");
                     }
-
-                    self.resolve_type(&*eq_pred.ty);
                 }
             }
         }
-    }
-
-    fn resolve_struct(&mut self,
-                      id: NodeId,
-                      generics: &Generics,
-                      fields: &[StructField]) {
-        // If applicable, create a rib for the type parameters.
-        self.with_type_parameter_rib(HasTypeParameters(generics,
-                                                       TypeSpace,
-                                                       id,
-                                                       ItemRibKind),
-                                     |this| {
-            // Resolve the type parameters.
-            this.resolve_type_parameters(&generics.ty_params);
-            this.resolve_where_clause(&generics.where_clause);
-
-            // Resolve fields.
-            for field in fields {
-                this.resolve_type(&*field.node.ty);
-            }
-        });
-    }
-
-    // Does this really need to take a RibKind or is it always going
-    // to be NormalRibKind?
-    fn resolve_method(&mut self,
-                      rib_kind: RibKind,
-                      method: &ast::Method) {
-        let method_generics = method.pe_generics();
-        let type_parameters = HasTypeParameters(method_generics,
-                                                FnSpace,
-                                                method.id,
-                                                rib_kind);
-
-        if let SelfExplicit(ref typ, _) = method.pe_explicit_self().node {
-            self.resolve_type(&**typ);
-        }
-
-        self.resolve_function(rib_kind,
-                              Some(method.pe_fn_decl()),
-                              type_parameters,
-                              method.pe_body());
+        visit::walk_generics(self, generics);
     }
 
     fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
@@ -3300,25 +3021,22 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
         result
     }
 
-    fn with_optional_trait_ref<T, F>(&mut self, id: NodeId,
-                                     opt_trait_ref: &Option<TraitRef>,
+    fn with_optional_trait_ref<T, F>(&mut self,
+                                     opt_trait_ref: Option<&TraitRef>,
                                      f: F) -> T where
         F: FnOnce(&mut Resolver) -> T,
     {
-        let new_val = match *opt_trait_ref {
-            Some(ref trait_ref) => {
-                self.resolve_trait_reference(id, trait_ref, TraitImplementation);
-
-                match self.def_map.borrow().get(&trait_ref.ref_id) {
-                    Some(def) => {
-                        let did = def.def_id();
-                        Some((did, trait_ref.clone()))
-                    }
-                    None => None
+        let mut new_val = None;
+        if let Some(trait_ref) = opt_trait_ref {
+            match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) {
+                Ok(path_res) => {
+                    self.record_def(trait_ref.ref_id, path_res);
+                    new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
                 }
+                Err(_) => { /* error was already reported */ }
             }
-            None => None
-        };
+            visit::walk_trait_ref(self, trait_ref);
+        }
         let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
         let result = f(self);
         self.current_trait_ref = original_trait_ref;
@@ -3326,7 +3044,6 @@ fn with_optional_trait_ref<T, F>(&mut self, id: NodeId,
     }
 
     fn resolve_implementation(&mut self,
-                              id: NodeId,
                               generics: &Generics,
                               opt_trait_reference: &Option<TraitRef>,
                               self_type: &Ty,
@@ -3334,17 +3051,15 @@ fn resolve_implementation(&mut self,
         // If applicable, create a rib for the type parameters.
         self.with_type_parameter_rib(HasTypeParameters(generics,
                                                        TypeSpace,
-                                                       id,
-                                                       NormalRibKind),
+                                                       ItemRibKind),
                                      |this| {
             // Resolve the type parameters.
-            this.resolve_type_parameters(&generics.ty_params);
-            this.resolve_where_clause(&generics.where_clause);
+            this.visit_generics(generics);
 
             // Resolve the trait reference, if necessary.
-            this.with_optional_trait_ref(id, opt_trait_reference, |this| {
+            this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this| {
                 // Resolve the self type.
-                this.resolve_type(self_type);
+                this.visit_ty(self_type);
 
                 this.with_current_self_type(self_type, |this| {
                     for impl_item in impl_items {
@@ -3357,9 +3072,13 @@ fn resolve_implementation(&mut self,
 
                                 // We also need a new scope for the method-
                                 // specific type parameters.
-                                this.resolve_method(
-                                    MethodRibKind(id, ProvidedMethod(method.id)),
-                                    &**method);
+                                let type_parameters =
+                                    HasTypeParameters(method.pe_generics(),
+                                                      FnSpace,
+                                                      MethodRibKind);
+                                this.with_type_parameter_rib(type_parameters, |this| {
+                                    visit::walk_method_helper(this, &**method);
+                                });
                             }
                             TypeImplItem(ref typedef) => {
                                 // If this is a trait impl, ensure the method
@@ -3367,80 +3086,39 @@ fn resolve_implementation(&mut self,
                                 this.check_trait_item(typedef.ident.name,
                                                       typedef.span);
 
-                                this.resolve_type(&*typedef.typ);
+                                this.visit_ty(&*typedef.typ);
                             }
                         }
                     }
                 });
             });
         });
-
-        // Check that the current type is indeed a type, if we have an anonymous impl
-        if opt_trait_reference.is_none() {
-            match self_type.node {
-                // TyPath is the only thing that we handled in `build_reduced_graph_for_item`,
-                // where we created a module with the name of the type in order to implement
-                // an anonymous trait. In the case that the path does not resolve to an actual
-                // type, the result will be that the type name resolves to a module but not
-                // a type (shadowing any imported modules or types with this name), leading
-                // to weird user-visible bugs. So we ward this off here. See #15060.
-                TyPath(ref path, path_id) => {
-                    match self.def_map.borrow().get(&path_id) {
-                        // FIXME: should we catch other options and give more precise errors?
-                        Some(&DefMod(_)) => {
-                            self.resolve_error(path.span, "inherent implementations are not \
-                                                           allowed for types not defined in \
-                                                           the current module");
-                        }
-                        _ => {}
-                    }
-                }
-                _ => { }
-            }
-        }
     }
 
     fn check_trait_item(&self, name: Name, span: Span) {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         if let Some((did, ref trait_ref)) = self.current_trait_ref {
-            if self.trait_item_map.get(&(name, did)).is_none() {
-                let path_str = self.path_names_to_string(&trait_ref.path);
+            if !self.trait_item_map.contains_key(&(name, did)) {
+                let path_str = self.path_names_to_string(&trait_ref.path, 0);
                 self.resolve_error(span,
                                     &format!("method `{}` is not a member of trait `{}`",
                                             token::get_name(name),
-                                            path_str)[]);
+                                            path_str));
             }
         }
     }
 
-    fn resolve_module(&mut self, module: &Mod, _span: Span,
-                      _name: Name, id: NodeId) {
-        // Write the implementations in scope into the module metadata.
-        debug!("(resolving module) resolving module ID {}", id);
-        visit::walk_mod(self, module);
-    }
-
     fn resolve_local(&mut self, local: &Local) {
         // Resolve the type.
-        if let Some(ref ty) = local.ty {
-            self.resolve_type(&**ty);
-        }
+        visit::walk_ty_opt(self, &local.ty);
 
-        // Resolve the initializer, if necessary.
-        match local.init {
-            None => {
-                // Nothing to do.
-            }
-            Some(ref initializer) => {
-                self.resolve_expr(&**initializer);
-            }
-        }
+        // Resolve the initializer.
+        visit::walk_expr_opt(self, &local.init);
 
         // Resolve the pattern.
-        let mut bindings_list = HashMap::new();
         self.resolve_pattern(&*local.pat,
                              LocalIrrefutableMode,
-                             &mut bindings_list);
+                             &mut HashMap::new());
     }
 
     // build a map from pattern identifiers to binding-info's.
@@ -3477,7 +3155,7 @@ fn check_consistent_bindings(&mut self, arm: &Arm) {
                         &format!("variable `{}` from pattern #1 is \
                                   not bound in pattern #{}",
                                 token::get_name(key),
-                                i + 1)[]);
+                                i + 1));
                   }
                   Some(binding_i) => {
                     if binding_0.binding_mode != binding_i.binding_mode {
@@ -3486,7 +3164,7 @@ fn check_consistent_bindings(&mut self, arm: &Arm) {
                             &format!("variable `{}` is bound with different \
                                       mode in pattern #{} than in pattern #1",
                                     token::get_name(key),
-                                    i + 1)[]);
+                                    i + 1));
                     }
                   }
                 }
@@ -3499,7 +3177,7 @@ fn check_consistent_bindings(&mut self, arm: &Arm) {
                         &format!("variable `{}` from pattern {}{} is \
                                   not bound in pattern {}1",
                                 token::get_name(key),
-                                "#", i + 1, "#")[]);
+                                "#", i + 1, "#"));
                 }
             }
         }
@@ -3518,7 +3196,7 @@ fn resolve_arm(&mut self, arm: &Arm) {
         self.check_consistent_bindings(arm);
 
         visit::walk_expr_opt(self, &arm.guard);
-        self.resolve_expr(&*arm.body);
+        self.visit_expr(&*arm.body);
 
         self.value_ribs.pop();
     }
@@ -3570,90 +3248,63 @@ fn resolve_block(&mut self, block: &Block) {
 
     fn resolve_type(&mut self, ty: &Ty) {
         match ty.node {
-            // Like path expressions, the interpretation of path types depends
-            // on whether the path has multiple elements in it or not.
+            // `<T>::a::b::c` is resolved by typeck alone.
+            TyPath(Some(ast::QSelf { position: 0, .. }), _) => {}
+
+            TyPath(ref maybe_qself, ref path) => {
+                let max_assoc_types = if let Some(ref qself) = *maybe_qself {
+                    // Make sure the trait is valid.
+                    let _ = self.resolve_trait_reference(ty.id, path, 1);
+                    path.segments.len() - qself.position
+                } else {
+                    path.segments.len()
+                };
 
-            TyPath(ref path, path_id) => {
-                // This is a path in the type namespace. Walk through scopes
-                // looking for it.
-                let mut result_def = None;
-
-                // First, check to see whether the name is a primitive type.
-                if path.segments.len() == 1 {
-                    let id = path.segments.last().unwrap().identifier;
-
-                    match self.primitive_type_table
-                            .primitive_types
-                            .get(&id.name) {
-
-                        Some(&primitive_type) => {
-                            result_def =
-                                Some((DefPrimTy(primitive_type), LastMod(AllPublic)));
-
-                            if path.segments[0].parameters.has_lifetimes() {
-                                span_err!(self.session, path.span, E0157,
-                                    "lifetime parameters are not allowed on this type");
-                            } else if !path.segments[0].parameters.is_empty() {
-                                span_err!(self.session, path.span, E0153,
-                                    "type parameters are not allowed on this type");
-                            }
-                        }
-                        None => {
-                            // Continue.
-                        }
+                let mut resolution = None;
+                for depth in 0..max_assoc_types {
+                    self.with_no_errors(|this| {
+                        resolution = this.resolve_path(ty.id, path, depth, TypeNS, true);
+                    });
+                    if resolution.is_some() {
+                        break;
                     }
                 }
-
-                if let None = result_def {
-                    result_def = self.resolve_path(ty.id, path, TypeNS, true);
+                if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
+                    // A module is not a valid type.
+                    resolution = None;
                 }
 
-                match result_def {
+                // This is a path in the type namespace. Walk through scopes
+                // looking for it.
+                match resolution {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving type) writing resolution for `{}` \
                                 (id {}) = {:?}",
-                               self.path_names_to_string(path),
-                               path_id, def);
-                        self.record_def(path_id, def);
+                               self.path_names_to_string(path, 0),
+                               ty.id, def);
+                        self.record_def(ty.id, def);
                     }
                     None => {
-                        let msg = format!("use of undeclared type name `{}`",
-                                          self.path_names_to_string(path));
-                        self.resolve_error(ty.span, &msg[..]);
-                    }
-                }
-            }
+                        // Keep reporting some errors even if they're ignored above.
+                        self.resolve_path(ty.id, path, 0, TypeNS, true);
 
-            TyObjectSum(ref ty, ref bound_vec) => {
-                self.resolve_type(&**ty);
-                self.resolve_type_parameter_bounds(ty.id, bound_vec,
-                                                       TraitBoundingTypeParameter);
-            }
+                        let kind = if maybe_qself.is_some() {
+                            "associated type"
+                        } else {
+                            "type name"
+                        };
 
-            TyQPath(ref qpath) => {
-                self.resolve_type(&*qpath.self_type);
-                self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
-                for ty in qpath.item_path.parameters.types() {
-                    self.resolve_type(&**ty);
-                }
-                for binding in qpath.item_path.parameters.bindings() {
-                    self.resolve_type(&*binding.ty);
+                        let msg = format!("use of undeclared {} `{}`", kind,
+                                          self.path_names_to_string(path, 0));
+                        self.resolve_error(ty.span, &msg[..]);
+                    }
                 }
             }
-
-            TyPolyTraitRef(ref bounds) => {
-                self.resolve_type_parameter_bounds(
-                    ty.id,
-                    bounds,
-                    TraitObject);
-                visit::walk_ty(self, ty);
-            }
-            _ => {
-                // Just resolve embedded types.
-                visit::walk_ty(self, ty);
-            }
+            _ => {}
         }
+        // Resolve embedded types.
+        visit::walk_ty(self, ty);
     }
 
     fn resolve_pattern(&mut self,
@@ -3680,7 +3331,7 @@ fn resolve_pattern(&mut self,
                     let renamed = mtwt::resolve(ident);
 
                     match self.resolve_bare_identifier_pattern(ident.name, pattern.span) {
-                        FoundStructOrEnumVariant(ref def, lp)
+                        FoundStructOrEnumVariant(def, lp)
                                 if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
                                     struct or enum variant",
@@ -3690,7 +3341,11 @@ struct or enum variant",
                                 pattern,
                                 binding_mode,
                                 "an enum variant");
-                            self.record_def(pattern.id, (def.clone(), lp));
+                            self.record_def(pattern.id, PathResolution {
+                                base_def: def,
+                                last_private: lp,
+                                depth: 0
+                            });
                         }
                         FoundStructOrEnumVariant(..) => {
                             self.resolve_error(
@@ -3698,9 +3353,9 @@ struct or enum variant",
                                 &format!("declaration of `{}` shadows an enum \
                                          variant or unit-like struct in \
                                          scope",
-                                        token::get_name(renamed))[]);
+                                        token::get_name(renamed)));
                         }
-                        FoundConst(ref def, lp) if mode == RefutableMode => {
+                        FoundConst(def, lp) if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
                                     constant",
                                    token::get_name(renamed));
@@ -3709,7 +3364,11 @@ struct or enum variant",
                                 pattern,
                                 binding_mode,
                                 "a constant");
-                            self.record_def(pattern.id, (def.clone(), lp));
+                            self.record_def(pattern.id, PathResolution {
+                                base_def: def,
+                                last_private: lp,
+                                depth: 0
+                            });
                         }
                         FoundConst(..) => {
                             self.resolve_error(pattern.span,
@@ -3726,7 +3385,11 @@ struct or enum variant",
                             // will be able to distinguish variants from
                             // locals in patterns.
 
-                            self.record_def(pattern.id, (def, LastMod(AllPublic)));
+                            self.record_def(pattern.id, PathResolution {
+                                base_def: def,
+                                last_private: LastMod(AllPublic),
+                                depth: 0
+                            });
 
                             // Add the binding to the local ribs, if it
                             // doesn't already exist in the bindings list. (We
@@ -3750,7 +3413,7 @@ struct or enum variant",
                                                             list",
                                                            token::get_ident(
                                                                ident))
-                                                   [])
+                                                   )
                             } else if bindings_list.get(&renamed) ==
                                     Some(&pat_id) {
                                 // Then this is a duplicate variable in the
@@ -3759,7 +3422,7 @@ struct or enum variant",
                                     &format!("identifier `{}` is bound \
                                              more than once in the same \
                                              pattern",
-                                            token::get_ident(ident))[]);
+                                            token::get_ident(ident)));
                             }
                             // Else, not bound in the same pattern: do
                             // nothing.
@@ -3769,50 +3432,34 @@ struct or enum variant",
 
                 PatEnum(ref path, _) => {
                     // This must be an enum variant, struct or const.
-                    match self.resolve_path(pat_id, path, ValueNS, false) {
-                        Some(def @ (DefVariant(..), _)) |
-                        Some(def @ (DefStruct(..), _))  |
-                        Some(def @ (DefConst(..), _)) => {
-                            self.record_def(pattern.id, def);
-                        }
-                        Some((DefStatic(..), _)) => {
-                            self.resolve_error(path.span,
-                                               "static variables cannot be \
-                                                referenced in a pattern, \
-                                                use a `const` instead");
-                        }
-                        Some(_) => {
-                            self.resolve_error(path.span,
-                                &format!("`{}` is not an enum variant, struct or const",
-                                    token::get_ident(
-                                        path.segments.last().unwrap().identifier)));
-                        }
-                        None => {
-                            self.resolve_error(path.span,
-                                &format!("unresolved enum variant, struct or const `{}`",
-                                    token::get_ident(path.segments.last().unwrap().identifier)));
+                    if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) {
+                        match path_res.base_def {
+                            DefVariant(..) | DefStruct(..) | DefConst(..) => {
+                                self.record_def(pattern.id, path_res);
+                            }
+                            DefStatic(..) => {
+                                self.resolve_error(path.span,
+                                                   "static variables cannot be \
+                                                    referenced in a pattern, \
+                                                    use a `const` instead");
+                            }
+                            _ => {
+                                self.resolve_error(path.span,
+                                    &format!("`{}` is not an enum variant, struct or const",
+                                        token::get_ident(
+                                            path.segments.last().unwrap().identifier)));
+                            }
                         }
+                    } else {
+                        self.resolve_error(path.span,
+                            &format!("unresolved enum variant, struct or const `{}`",
+                                token::get_ident(path.segments.last().unwrap().identifier)));
                     }
-
-                    // Check the types in the path pattern.
-                    for ty in path.segments
-                                  .iter()
-                                  .flat_map(|s| s.parameters.types().into_iter()) {
-                        self.resolve_type(&**ty);
-                    }
-                }
-
-                PatLit(ref expr) => {
-                    self.resolve_expr(&**expr);
-                }
-
-                PatRange(ref first_expr, ref last_expr) => {
-                    self.resolve_expr(&**first_expr);
-                    self.resolve_expr(&**last_expr);
+                    visit::walk_path(self, path);
                 }
 
                 PatStruct(ref path, _, _) => {
-                    match self.resolve_path(pat_id, path, TypeNS, false) {
+                    match self.resolve_path(pat_id, path, 0, TypeNS, false) {
                         Some(definition) => {
                             self.record_def(pattern.id, definition);
                         }
@@ -3820,10 +3467,15 @@ struct or enum variant",
                             debug!("(resolving pattern) didn't find struct \
                                     def: {:?}", result);
                             let msg = format!("`{}` does not name a structure",
-                                              self.path_names_to_string(path));
+                                              self.path_names_to_string(path, 0));
                             self.resolve_error(path.span, &msg[..]);
                         }
                     }
+                    visit::walk_path(self, path);
+                }
+
+                PatLit(_) | PatRange(..) => {
+                    visit::walk_pat(self, pattern);
                 }
 
                 _ => {
@@ -3883,7 +3535,7 @@ fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span)
                 match err {
                     Some((span, msg)) => {
                         self.resolve_error(span, &format!("failed to resolve: {}",
-                                                         msg)[]);
+                                                         msg));
                     }
                     None => ()
                 }
@@ -3897,75 +3549,51 @@ fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span)
 
     /// If `check_ribs` is true, checks the local definitions first; i.e.
     /// doesn't skip straight to the containing module.
+    /// Skips `path_depth` trailing segments, which is also reflected in the
+    /// returned value. See `middle::def::PathResolution` for more info.
     fn resolve_path(&mut self,
                     id: NodeId,
                     path: &Path,
+                    path_depth: usize,
                     namespace: Namespace,
-                    check_ribs: bool) -> Option<(Def, LastPrivate)> {
-        // First, resolve the types and associated type bindings.
-        for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
-            self.resolve_type(&**ty);
-        }
-        for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
-            self.resolve_type(&*binding.ty);
-        }
-
-        // A special case for sugared associated type paths `T::A` where `T` is
-        // a type parameter and `A` is an associated type on some bound of `T`.
-        if namespace == TypeNS && path.segments.len() == 2 {
-            match self.resolve_identifier(path.segments[0].identifier,
-                                          TypeNS,
-                                          true,
-                                          path.span) {
-                Some((def, last_private)) => {
-                    match def {
-                        DefTyParam(_, _, did, _) => {
-                            let def = DefAssociatedPath(TyParamProvenance::FromParam(did),
-                                                        path.segments.last()
-                                                            .unwrap().identifier);
-                            return Some((def, last_private));
-                        }
-                        DefSelfTy(nid) => {
-                            let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)),
-                                                        path.segments.last()
-                                                            .unwrap().identifier);
-                            return Some((def, last_private));
-                        }
-                        _ => {}
-                    }
-                }
-                _ => {}
-            }
-        }
+                    check_ribs: bool) -> Option<PathResolution> {
+        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
+        };
 
         if path.global {
-            return self.resolve_crate_relative_path(path, namespace);
+            let def = self.resolve_crate_relative_path(span, segments, namespace);
+            return def.map(mk_res);
         }
 
         // Try to find a path to an item in a module.
         let unqualified_def =
-                self.resolve_identifier(path.segments.last().unwrap().identifier,
+                self.resolve_identifier(segments.last().unwrap().identifier,
                                         namespace,
                                         check_ribs,
-                                        path.span);
+                                        span);
 
-        if path.segments.len() > 1 {
-            let def = self.resolve_module_relative_path(path, namespace);
+        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,
-                                  path.span,
+                                  id, span,
                                   "unnecessary qualification".to_string());
                 }
                 _ => ()
             }
 
-            return def;
+            def.map(mk_res)
+        } else {
+            unqualified_def.map(mk_res)
         }
-
-        return unqualified_def;
     }
 
     // resolve a single identifier (used as a varref)
@@ -3975,20 +3603,24 @@ fn resolve_identifier(&mut self,
                           check_ribs: bool,
                           span: Span)
                           -> Option<(Def, LastPrivate)> {
+        // First, check to see whether the name is a primitive type.
+        if namespace == TypeNS {
+            if let Some(&prim_ty) = self.primitive_type_table
+                                        .primitive_types
+                                        .get(&identifier.name) {
+                return Some((DefPrimTy(prim_ty), LastMod(AllPublic)));
+            }
+        }
+
         if check_ribs {
-            match self.resolve_identifier_in_local_ribs(identifier,
-                                                        namespace,
-                                                        span) {
-                Some(def) => {
-                    return Some((def, LastMod(AllPublic)));
-                }
-                None => {
-                    // Continue.
-                }
+            if let Some(def) = self.resolve_identifier_in_local_ribs(identifier,
+                                                                     namespace,
+                                                                     span) {
+                return Some((def, LastMod(AllPublic)));
             }
         }
 
-        return self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace);
+        self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace)
     }
 
     // FIXME #4952: Merge me with resolve_name_in_module?
@@ -4067,12 +3699,13 @@ fn resolve_definition_of_name_in_module(&mut self,
 
     // resolve a "module-relative" path, e.g. a::b::c
     fn resolve_module_relative_path(&mut self,
-                                    path: &Path,
+                                    span: Span,
+                                    segments: &[ast::PathSegment],
                                     namespace: Namespace)
                                     -> Option<(Def, LastPrivate)> {
-        let module_path = path.segments.init().iter()
-                                              .map(|ps| ps.identifier.name)
-                                              .collect::<Vec<_>>();
+        let module_path = segments.init().iter()
+                                         .map(|ps| ps.identifier.name)
+                                         .collect::<Vec<_>>();
 
         let containing_module;
         let last_private;
@@ -4080,7 +3713,7 @@ fn resolve_module_relative_path(&mut self,
         match self.resolve_module_path(module,
                                        &module_path[..],
                                        UseLexicalScope,
-                                       path.span,
+                                       span,
                                        PathSearch) {
             Failed(err) => {
                 let (span, msg) = match err {
@@ -4088,12 +3721,12 @@ fn resolve_module_relative_path(&mut self,
                     None => {
                         let msg = format!("Use of undeclared type or module `{}`",
                                           self.names_to_string(&module_path));
-                        (path.span, msg)
+                        (span, msg)
                     }
                 };
 
                 self.resolve_error(span, &format!("failed to resolve. {}",
-                                                 msg)[]);
+                                                 msg));
                 return None;
             }
             Indeterminate => panic!("indeterminate unexpected"),
@@ -4103,7 +3736,7 @@ fn resolve_module_relative_path(&mut self,
             }
         }
 
-        let name = path.segments.last().unwrap().identifier.name;
+        let name = segments.last().unwrap().identifier.name;
         let def = match self.resolve_definition_of_name_in_module(containing_module.clone(),
                                                                   name,
                                                                   namespace) {
@@ -4124,12 +3757,13 @@ fn resolve_module_relative_path(&mut self,
     /// Invariant: This must be called only during main resolution, not during
     /// import resolution.
     fn resolve_crate_relative_path(&mut self,
-                                   path: &Path,
+                                   span: Span,
+                                   segments: &[ast::PathSegment],
                                    namespace: Namespace)
                                        -> Option<(Def, LastPrivate)> {
-        let module_path = path.segments.init().iter()
-                                              .map(|ps| ps.identifier.name)
-                                              .collect::<Vec<_>>();
+        let module_path = segments.init().iter()
+                                         .map(|ps| ps.identifier.name)
+                                         .collect::<Vec<_>>();
 
         let root_module = self.graph_root.get_module();
 
@@ -4138,7 +3772,7 @@ fn resolve_crate_relative_path(&mut self,
         match self.resolve_module_path_from_root(root_module,
                                                  &module_path[..],
                                                  0,
-                                                 path.span,
+                                                 span,
                                                  PathSearch,
                                                  LastMod(AllPublic)) {
             Failed(err) => {
@@ -4147,12 +3781,12 @@ fn resolve_crate_relative_path(&mut self,
                     None => {
                         let msg = format!("Use of undeclared module `::{}`",
                                           self.names_to_string(&module_path[..]));
-                        (path.span, msg)
+                        (span, msg)
                     }
                 };
 
                 self.resolve_error(span, &format!("failed to resolve. {}",
-                                                 msg)[]);
+                                                 msg));
                 return None;
             }
 
@@ -4166,7 +3800,7 @@ fn resolve_crate_relative_path(&mut self,
             }
         }
 
-        let name = path.segments.last().unwrap().identifier.name;
+        let name = segments.last().unwrap().identifier.name;
         match self.resolve_definition_of_name_in_module(containing_module,
                                                         name,
                                                         namespace) {
@@ -4193,7 +3827,7 @@ fn resolve_identifier_in_local_ribs(&mut self,
             }
             TypeNS => {
                 let name = ident.name;
-                self.search_ribs(&self.type_ribs[], name, span)
+                self.search_ribs(&self.type_ribs, name, span)
             }
         };
 
@@ -4203,10 +3837,10 @@ fn resolve_identifier_in_local_ribs(&mut self,
                         local: {:?}",
                        token::get_ident(ident),
                        def);
-                return Some(def);
+                Some(def)
             }
             Some(DlField) | Some(DlImpl(_)) | None => {
-                return None;
+                None
             }
         }
     }
@@ -4248,7 +3882,7 @@ fn resolve_item_by_name_in_lexical_scope(&mut self,
                 match err {
                     Some((span, msg)) =>
                         self.resolve_error(span, &format!("failed to resolve. {}",
-                                                         msg)[]),
+                                                         msg)),
                     None => ()
                 }
 
@@ -4278,7 +3912,7 @@ fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
         fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
                                                     -> Option<(Path, NodeId, FallbackChecks)> {
             match t.node {
-                TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)),
+                TyPath(None, ref path) => Some((path.clone(), t.id, allow)),
                 TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
                 TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
                 // This doesn't handle the remaining `Ty` variants as they are not
@@ -4315,6 +3949,26 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
             }
         }
 
+        fn is_static_method(this: &Resolver, did: DefId) -> bool {
+            if did.krate == ast::LOCAL_CRATE {
+                let explicit_self = match this.ast_map.get(did.node) {
+                    ast_map::NodeTraitItem(m) => match *m {
+                        ast::RequiredMethod(ref m) => &m.explicit_self,
+                        ast::ProvidedMethod(ref m) => m.pe_explicit_self(),
+                        _ => return false
+                    },
+                    ast_map::NodeImplItem(m) => match *m {
+                        ast::MethodImplItem(ref m) => m.pe_explicit_self(),
+                        _ => return false
+                    },
+                    _ => return false
+                };
+                explicit_self.node == ast::SelfStatic
+            } else {
+                csearch::is_static_method(&this.session.cstore, did)
+            }
+        }
+
         let (path, node_id, allowed) = match self.current_self_type {
             Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
                 Some(x) => x,
@@ -4325,10 +3979,10 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
 
         if allowed == Everything {
             // Look for a field with the same name in the current self_type.
-            match self.def_map.borrow().get(&node_id) {
-                 Some(&DefTy(did, _))
-                | Some(&DefStruct(did))
-                | Some(&DefVariant(_, did, _)) => match self.structs.get(&did) {
+            match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
+                Some(DefTy(did, _)) |
+                Some(DefStruct(did)) |
+                Some(DefVariant(_, did, _)) => match self.structs.get(&did) {
                     None => {}
                     Some(fields) => {
                         if fields.iter().any(|&field_name| name == field_name) {
@@ -4343,41 +3997,30 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
         let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();
 
         // Look for a method in the current self type's impl module.
-        match get_module(self, path.span, &name_path[..]) {
-            Some(module) => match module.children.borrow().get(&name) {
-                Some(binding) => {
-                    let p_str = self.path_names_to_string(&path);
-                    match binding.def_for_namespace(ValueNS) {
-                        Some(DefStaticMethod(_, provenance)) => {
-                            match provenance {
-                                FromImpl(_) => return StaticMethod(p_str),
-                                FromTrait(_) => unreachable!()
-                            }
-                        }
-                        Some(DefMethod(_, None, _)) if allowed == Everything => return Method,
-                        Some(DefMethod(_, Some(_), _)) => return TraitItem,
-                        _ => ()
+        if let Some(module) = get_module(self, path.span, &name_path) {
+            if let Some(binding) = module.children.borrow().get(&name) {
+                if let Some(DefMethod(did, _)) = binding.def_for_namespace(ValueNS) {
+                    if is_static_method(self, did) {
+                        return StaticMethod(self.path_names_to_string(&path, 0))
+                    }
+                    if self.current_trait_ref.is_some() {
+                        return TraitItem;
+                    } else if allowed == Everything {
+                        return Method;
                     }
                 }
-                None => {}
-            },
-            None => {}
+            }
         }
 
         // Look for a method in the current trait.
-        match self.current_trait_ref {
-            Some((did, ref trait_ref)) => {
-                let path_str = self.path_names_to_string(&trait_ref.path);
-
-                match self.trait_item_map.get(&(name, did)) {
-                    Some(&StaticMethodTraitItemKind) => {
-                        return TraitMethod(path_str)
-                    }
-                    Some(_) => return TraitItem,
-                    None => {}
+        if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
+            if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) {
+                if is_static_method(self, did) {
+                    return TraitMethod(self.path_names_to_string(&trait_ref.path, 0));
+                } else {
+                    return TraitItem;
                 }
             }
-            None => {}
         }
 
         NoSuggestion
@@ -4410,7 +4053,7 @@ fn find_best_match_for_name(&mut self, name: &str, max_distance: uint)
             values[smallest] != usize::MAX &&
             values[smallest] < name.len() + 2 &&
             values[smallest] <= max_distance &&
-            name != &maybes[smallest][] {
+            name != &maybes[smallest][..] {
 
             Some(maybes[smallest].to_string())
 
@@ -4427,28 +4070,45 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
         // Next, resolve the node.
         match expr.node {
-            // The interpretation of paths depends on whether the path has
-            // multiple elements in it or not.
-
-            ExprPath(_) | ExprQPath(_) => {
-                let mut path_from_qpath;
-                let path = match expr.node {
-                    ExprPath(ref path) => path,
-                    ExprQPath(ref qpath) => {
-                        self.resolve_type(&*qpath.self_type);
-                        self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
-                        path_from_qpath = qpath.trait_ref.path.clone();
-                        path_from_qpath.segments.push(qpath.item_path.clone());
-                        &path_from_qpath
-                    }
-                    _ => unreachable!()
+            // `<T>::a::b::c` is resolved by typeck alone.
+            ExprPath(Some(ast::QSelf { position: 0, .. }), ref path) => {
+                let method_name = path.segments.last().unwrap().identifier.name;
+                let traits = self.search_for_traits_containing_method(method_name);
+                self.trait_map.insert(expr.id, traits);
+                visit::walk_expr(self, expr);
+            }
+
+            ExprPath(ref maybe_qself, ref path) => {
+                let max_assoc_types = if let Some(ref qself) = *maybe_qself {
+                    // Make sure the trait is valid.
+                    let _ = self.resolve_trait_reference(expr.id, path, 1);
+                    path.segments.len() - qself.position
+                } else {
+                    path.segments.len()
                 };
+
+                let mut resolution = self.with_no_errors(|this| {
+                    this.resolve_path(expr.id, path, 0, ValueNS, true)
+                });
+                for depth in 1..max_assoc_types {
+                    if resolution.is_some() {
+                        break;
+                    }
+                    self.with_no_errors(|this| {
+                        resolution = this.resolve_path(expr.id, path, depth, TypeNS, true);
+                    });
+                }
+                if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
+                    // A module is not a valid type or value.
+                    resolution = None;
+                }
+
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
-                match self.resolve_path(expr.id, path, ValueNS, true) {
+                if let Some(path_res) = resolution {
                     // Check if struct variant
-                    Some((DefVariant(_, _, true), _)) => {
-                        let path_name = self.path_names_to_string(path);
+                    if let DefVariant(_, _, true) = path_res.base_def {
+                        let path_name = self.path_names_to_string(path, 0);
                         self.resolve_error(expr.span,
                                 &format!("`{}` is a struct variant name, but \
                                           this expression \
@@ -4459,86 +4119,93 @@ fn resolve_expr(&mut self, expr: &Expr) {
                             &format!("Did you mean to write: \
                                      `{} {{ /* fields */ }}`?",
                                      path_name));
-                    }
-                    Some(def) => {
+                    } else {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `{}`",
-                               self.path_names_to_string(path));
+                               self.path_names_to_string(path, 0));
+
+                        // Partial resolutions will need the set of traits in scope,
+                        // so they can be completed during typeck.
+                        if path_res.depth != 0 {
+                            let method_name = path.segments.last().unwrap().identifier.name;
+                            let traits = self.search_for_traits_containing_method(method_name);
+                            self.trait_map.insert(expr.id, traits);
+                        }
 
-                        self.record_def(expr.id, def);
+                        self.record_def(expr.id, path_res);
                     }
-                    None => {
-                        // Be helpful if the name refers to a struct
-                        // (The pattern matching def_tys where the id is in self.structs
-                        // matches on regular structs while excluding tuple- and enum-like
-                        // structs, which wouldn't result in this error.)
-                        let path_name = self.path_names_to_string(path);
-                        match self.with_no_errors(|this|
-                            this.resolve_path(expr.id, path, TypeNS, false)) {
-                            Some((DefTy(struct_id, _), _))
-                              if self.structs.contains_key(&struct_id) => {
-                                self.resolve_error(expr.span,
-                                        &format!("`{}` is a structure name, but \
-                                                  this expression \
-                                                  uses it like a function name",
-                                                 path_name));
-
-                                self.session.span_help(expr.span,
-                                    &format!("Did you mean to write: \
-                                             `{} {{ /* fields */ }}`?",
-                                             path_name));
-
-                            }
-                            _ => {
-                                let mut method_scope = false;
-                                self.value_ribs.iter().rev().all(|rib| {
-                                    let res = match *rib {
-                                        Rib { bindings: _, kind: MethodRibKind(_, _) } => true,
-                                        Rib { bindings: _, kind: ItemRibKind } => false,
-                                        _ => return true, // Keep advancing
-                                    };
-
-                                    method_scope = res;
-                                    false // Stop advancing
-                                });
+                } else {
+                    // Be helpful if the name refers to a struct
+                    // (The pattern matching def_tys where the id is in self.structs
+                    // matches on regular structs while excluding tuple- and enum-like
+                    // structs, which wouldn't result in this error.)
+                    let path_name = self.path_names_to_string(path, 0);
+                    let type_res = self.with_no_errors(|this| {
+                        this.resolve_path(expr.id, path, 0, TypeNS, false)
+                    });
+                    match type_res.map(|r| r.base_def) {
+                        Some(DefTy(struct_id, _))
+                            if self.structs.contains_key(&struct_id) => {
+                            self.resolve_error(expr.span,
+                                    &format!("`{}` is a structure name, but \
+                                                this expression \
+                                                uses it like a function name",
+                                                path_name));
+
+                            self.session.span_help(expr.span,
+                                &format!("Did you mean to write: \
+                                            `{} {{ /* fields */ }}`?",
+                                            path_name));
 
-                                if method_scope && &token::get_name(self.self_name)[]
-                                                                   == path_name {
-                                        self.resolve_error(
-                                            expr.span,
-                                            "`self` is not available \
-                                             in a static method. Maybe a \
-                                             `self` argument is missing?");
-                                } else {
-                                    let last_name = path.segments.last().unwrap().identifier.name;
-                                    let mut msg = match self.find_fallback_in_self_type(last_name) {
-                                        NoSuggestion => {
-                                            // limit search to 5 to reduce the number
-                                            // of stupid suggestions
-                                            self.find_best_match_for_name(&path_name, 5)
-                                                                .map_or("".to_string(),
-                                                                        |x| format!("`{}`", x))
-                                        }
-                                        Field =>
-                                            format!("`self.{}`", path_name),
-                                        Method
-                                        | TraitItem =>
-                                            format!("to call `self.{}`", path_name),
-                                        TraitMethod(path_str)
-                                        | StaticMethod(path_str) =>
-                                            format!("to call `{}::{}`", path_str, path_name)
-                                    };
-
-                                    if msg.len() > 0 {
-                                        msg = format!(". Did you mean {}?", msg)
-                                    }
+                        }
+                        _ => {
+                            // Keep reporting some errors even if they're ignored above.
+                            self.resolve_path(expr.id, path, 0, ValueNS, true);
+
+                            let mut method_scope = false;
+                            self.value_ribs.iter().rev().all(|rib| {
+                                method_scope = match rib.kind {
+                                    MethodRibKind => true,
+                                    ItemRibKind | ConstantItemRibKind => false,
+                                    _ => return true, // Keep advancing
+                                };
+                                false // Stop advancing
+                            });
 
+                            if method_scope && &token::get_name(self.self_name)[..]
+                                                                == path_name {
                                     self.resolve_error(
                                         expr.span,
-                                        &format!("unresolved name `{}`{}",
-                                                 path_name,
-                                                 msg));
+                                        "`self` is not available \
+                                         in a static method. Maybe a \
+                                         `self` argument is missing?");
+                            } else {
+                                let last_name = path.segments.last().unwrap().identifier.name;
+                                let mut msg = match self.find_fallback_in_self_type(last_name) {
+                                    NoSuggestion => {
+                                        // limit search to 5 to reduce the number
+                                        // of stupid suggestions
+                                        self.find_best_match_for_name(&path_name, 5)
+                                                            .map_or("".to_string(),
+                                                                    |x| format!("`{}`", x))
+                                    }
+                                    Field => format!("`self.{}`", path_name),
+                                    Method |
+                                    TraitItem =>
+                                        format!("to call `self.{}`", path_name),
+                                    TraitMethod(path_str) |
+                                    StaticMethod(path_str) =>
+                                        format!("to call `{}::{}`", path_str, path_name)
+                                };
+
+                                if msg.len() > 0 {
+                                    msg = format!(". Did you mean {}?", msg)
                                 }
+
+                                self.resolve_error(
+                                    expr.span,
+                                    &format!("unresolved name `{}`{}",
+                                             path_name, msg));
                             }
                         }
                     }
@@ -4547,23 +4214,16 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 visit::walk_expr(self, expr);
             }
 
-            ExprClosure(_, ref fn_decl, ref block) => {
-                self.resolve_function(ClosureRibKind(expr.id),
-                                      Some(&**fn_decl), NoTypeParameters,
-                                      &**block);
-            }
-
             ExprStruct(ref path, _, _) => {
                 // Resolve the path to the structure it goes to. We don't
                 // check to ensure that the path is actually a structure; that
                 // is checked later during typeck.
-                match self.resolve_path(expr.id, path, TypeNS, false) {
+                match self.resolve_path(expr.id, path, 0, TypeNS, false) {
                     Some(definition) => self.record_def(expr.id, definition),
-                    result => {
-                        debug!("(resolving expression) didn't find struct \
-                                def: {:?}", result);
+                    None => {
+                        debug!("(resolving expression) didn't find struct def",);
                         let msg = format!("`{}` does not name a structure",
-                                          self.path_names_to_string(path));
+                                          self.path_names_to_string(path, 0));
                         self.resolve_error(path.span, &msg[..]);
                     }
                 }
@@ -4592,11 +4252,15 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         self.resolve_error(
                             expr.span,
                             &format!("use of undeclared label `{}`",
-                                    token::get_ident(label))[])
+                                    token::get_ident(label)))
                     }
                     Some(DlDef(def @ DefLabel(_))) => {
                         // Since this def is a label, it is never read.
-                        self.record_def(expr.id, (def, LastMod(AllPublic)))
+                        self.record_def(expr.id, PathResolution {
+                            base_def: def,
+                            last_private: LastMod(AllPublic),
+                            depth: 0
+                        })
                     }
                     Some(_) => {
                         self.session.span_bug(expr.span,
@@ -4714,26 +4378,16 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
         found_traits
     }
 
-    fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
-        debug!("(recording def) recording {:?} for {}, last private {:?}",
-                def, node_id, lp);
-        assert!(match lp {LastImport{..} => false, _ => true},
+    fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
+        debug!("(recording def) recording {:?} for {}", resolution, node_id);
+        assert!(match resolution.last_private {LastImport{..} => false, _ => true},
                 "Import should only be used for `use` directives");
-        self.last_private.insert(node_id, lp);
 
-        match self.def_map.borrow_mut().entry(node_id) {
-            // Resolve appears to "resolve" the same ID multiple
-            // times, so here is a sanity check it at least comes to
-            // the same conclusion! - nmatsakis
-            Occupied(entry) => if def != *entry.get() {
-                self.session
-                    .bug(&format!("node_id {} resolved first to {:?} and \
-                                  then {:?}",
-                                 node_id,
-                                 *entry.get(),
-                                 def)[]);
-            },
-            Vacant(entry) => { entry.insert(def); },
+        if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
+            let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
+            self.session.span_bug(span, &format!("path resolved multiple times \
+                                                  ({:?} before, {:?} now)",
+                                                 prev_res, resolution));
         }
     }
 
@@ -4747,7 +4401,7 @@ fn enforce_default_binding_mode(&mut self,
                 self.resolve_error(pat.span,
                                    &format!("cannot use `ref` binding mode \
                                             with {}",
-                                           descr)[]);
+                                           descr));
             }
         }
     }
@@ -4783,7 +4437,7 @@ fn collect_mod(names: &mut Vec<ast::Name>, module: &Module) {
             return "???".to_string();
         }
         self.names_to_string(&names.into_iter().rev()
-                                  .collect::<Vec<ast::Name>>()[])
+                                  .collect::<Vec<ast::Name>>())
     }
 
     #[allow(dead_code)]   // useful for debugging
@@ -4828,7 +4482,6 @@ pub struct CrateMap {
     pub export_map: ExportMap,
     pub trait_map: TraitMap,
     pub external_exports: ExternalExports,
-    pub last_private_map: LastPrivateMap,
     pub glob_map: Option<GlobMap>
 }
 
@@ -4867,7 +4520,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
         export_map: resolver.export_map,
         trait_map: resolver.trait_map,
         external_exports: resolver.external_exports,
-        last_private_map: resolver.last_private,
         glob_map: if resolver.make_glob_map {
                         Some(resolver.glob_map)
                     } else {
index ef849bb3dca056348147adbf6a0a154e5c9d2dd4..ea5001aa814b49ab5dab7f8be7c047e8f6456498 100644 (file)
@@ -191,17 +191,17 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>,
     // to be independent of one another in the crate.
 
     symbol_hasher.reset();
-    symbol_hasher.input_str(&link_meta.crate_name[]);
+    symbol_hasher.input_str(&link_meta.crate_name);
     symbol_hasher.input_str("-");
     symbol_hasher.input_str(link_meta.crate_hash.as_str());
     for meta in &*tcx.sess.crate_metadata.borrow() {
         symbol_hasher.input_str(&meta[..]);
     }
     symbol_hasher.input_str("-");
-    symbol_hasher.input_str(&encoder::encoded_ty(tcx, t)[]);
+    symbol_hasher.input_str(&encoder::encoded_ty(tcx, t));
     // Prefix with 'h' so that it never blends into adjacent digits
     let mut hash = String::from_str("h");
-    hash.push_str(&truncated_hash_result(symbol_hasher)[]);
+    hash.push_str(&truncated_hash_result(symbol_hasher));
     hash
 }
 
@@ -288,7 +288,7 @@ pub fn mangle<PI: Iterator<Item=PathElem>>(path: PI,
 
     fn push(n: &mut String, s: &str) {
         let sani = sanitize(s);
-        n.push_str(&format!("{}{}", sani.len(), sani)[]);
+        n.push_str(&format!("{}{}", sani.len(), sani));
     }
 
     // First, connect each component with <len, name> pairs.
@@ -361,7 +361,7 @@ pub fn remove(sess: &Session, path: &Path) {
         Err(e) => {
             sess.err(&format!("failed to remove {}: {}",
                              path.display(),
-                             e)[]);
+                             e));
         }
     }
 }
@@ -376,7 +376,7 @@ pub fn link_binary(sess: &Session,
     for &crate_type in &*sess.crate_types.borrow() {
         if invalid_output_for_target(sess, crate_type) {
             sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
-                             crate_type, sess.opts.target_triple)[]);
+                             crate_type, sess.opts.target_triple));
         }
         let out_file = link_binary_output(sess, trans, crate_type, outputs,
                                           crate_name);
@@ -441,8 +441,8 @@ pub fn filename_for_input(sess: &Session,
             out_filename.with_filename(format!("lib{}.rlib", libname))
         }
         config::CrateTypeDylib => {
-            let (prefix, suffix) = (&sess.target.target.options.dll_prefix[],
-                                    &sess.target.target.options.dll_suffix[]);
+            let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
+                                    &sess.target.target.options.dll_suffix);
             out_filename.with_filename(format!("{}{}{}",
                                                prefix,
                                                libname,
@@ -452,7 +452,7 @@ pub fn filename_for_input(sess: &Session,
             out_filename.with_filename(format!("lib{}.a", libname))
         }
         config::CrateTypeExecutable => {
-            let suffix = &sess.target.target.options.exe_suffix[];
+            let suffix = &sess.target.target.options.exe_suffix;
             out_filename.with_filename(format!("{}{}", libname, suffix))
         }
     }
@@ -481,12 +481,12 @@ fn link_binary_output(sess: &Session,
     if !out_is_writeable {
         sess.fatal(&format!("output file {} is not writeable -- check its \
                             permissions.",
-                           out_filename.display())[]);
+                           out_filename.display()));
     }
     else if !obj_is_writeable {
         sess.fatal(&format!("object file {} is not writeable -- check its \
                             permissions.",
-                           obj_filename.display())[]);
+                           obj_filename.display()));
     }
 
     match crate_type {
@@ -588,12 +588,12 @@ fn link_rlib<'a>(sess: &'a Session,
             // the same filename for metadata (stomping over one another)
             let tmpdir = TempDir::new("rustc").ok().expect("needs a temp dir");
             let metadata = tmpdir.path().join(METADATA_FILENAME);
-            match fs::File::create(&metadata).write_all(&trans.metadata[]) {
+            match fs::File::create(&metadata).write_all(&trans.metadata) {
                 Ok(..) => {}
                 Err(e) => {
                     sess.err(&format!("failed to write {}: {}",
                                      metadata.display(),
-                                     e)[]);
+                                     e));
                     sess.abort_if_errors();
                 }
             }
@@ -611,25 +611,25 @@ fn link_rlib<'a>(sess: &'a Session,
                 // was exactly 16 bytes.
                 let bc_filename = obj_filename.with_extension(&format!("{}.bc", i));
                 let bc_deflated_filename = obj_filename.with_extension(
-                    &format!("{}.bytecode.deflate", i)[]);
+                    &format!("{}.bytecode.deflate", i));
 
                 let bc_data = match fs::File::open(&bc_filename).read_to_end() {
                     Ok(buffer) => buffer,
                     Err(e) => sess.fatal(&format!("failed to read bytecode: {}",
-                                                 e)[])
+                                                 e))
                 };
 
                 let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) {
                     Some(compressed) => compressed,
                     None => sess.fatal(&format!("failed to compress bytecode from {}",
-                                               bc_filename.display())[])
+                                               bc_filename.display()))
                 };
 
                 let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
                     Ok(file) => file,
                     Err(e) => {
                         sess.fatal(&format!("failed to create compressed bytecode \
-                                            file: {}", e)[])
+                                            file: {}", e))
                     }
                 };
 
@@ -638,7 +638,7 @@ fn link_rlib<'a>(sess: &'a Session,
                     Ok(()) => {}
                     Err(e) => {
                         sess.err(&format!("failed to write compressed bytecode: \
-                                          {}", e)[]);
+                                          {}", e));
                         sess.abort_if_errors()
                     }
                 };
@@ -729,7 +729,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
         let p = match *path {
             Some(ref p) => p.clone(), None => {
                 sess.err(&format!("could not find rlib for: `{}`",
-                                 name)[]);
+                                 name));
                 continue
             }
         };
@@ -755,7 +755,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
             cstore::NativeUnknown => "library",
             cstore::NativeFramework => "framework",
         };
-        sess.note(&format!("{}: {}", name, *lib)[]);
+        sess.note(&format!("{}: {}", name, *lib));
     }
 }
 
@@ -771,10 +771,10 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
     let pname = get_cc_prog(sess);
     let mut cmd = Command::new(&pname[..]);
 
-    cmd.args(&sess.target.target.options.pre_link_args[]);
+    cmd.args(&sess.target.target.options.pre_link_args);
     link_args(&mut cmd, sess, dylib, tmpdir.path(),
               trans, obj_filename, out_filename);
-    cmd.args(&sess.target.target.options.post_link_args[]);
+    cmd.args(&sess.target.target.options.post_link_args);
     if !sess.target.target.options.no_compiler_rt {
         cmd.arg("-lcompiler-rt");
     }
@@ -794,10 +794,10 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
             if !prog.status.success() {
                 sess.err(&format!("linking with `{}` failed: {}",
                                  pname,
-                                 prog.status)[]);
-                sess.note(&format!("{:?}", &cmd)[]);
+                                 prog.status));
+                sess.note(&format!("{:?}", &cmd));
                 let mut output = prog.error.clone();
-                output.push_all(&prog.output[]);
+                output.push_all(&prog.output);
                 sess.note(str::from_utf8(&output[..]).unwrap());
                 sess.abort_if_errors();
             }
@@ -807,7 +807,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
         Err(e) => {
             sess.err(&format!("could not exec the linker `{}`: {}",
                              pname,
-                             e)[]);
+                             e));
             sess.abort_if_errors();
         }
     }
@@ -819,7 +819,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
         match Command::new("dsymutil").arg(out_filename).output() {
             Ok(..) => {}
             Err(e) => {
-                sess.err(&format!("failed to run dsymutil: {}", e)[]);
+                sess.err(&format!("failed to run dsymutil: {}", e));
                 sess.abort_if_errors();
             }
         }
@@ -1005,7 +1005,7 @@ fn link_args(cmd: &mut Command,
     // addl_lib_search_paths
     if sess.opts.cg.rpath {
         let sysroot = sess.sysroot();
-        let target_triple = &sess.opts.target_triple[];
+        let target_triple = &sess.opts.target_triple;
         let get_install_prefix_lib_path = || {
             let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
             let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
@@ -1022,13 +1022,13 @@ fn link_args(cmd: &mut Command,
             get_install_prefix_lib_path: get_install_prefix_lib_path,
             realpath: ::util::fs::realpath
         };
-        cmd.args(&rpath::get_rpath_flags(rpath_config)[]);
+        cmd.args(&rpath::get_rpath_flags(rpath_config));
     }
 
     // Finally add all the linker arguments provided on the command line along
     // with any #[link_args] attributes found inside the crate
     let empty = Vec::new();
-    cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty)[]);
+    cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty));
     cmd.args(&used_link_args[..]);
 }
 
@@ -1189,7 +1189,7 @@ fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
             let name = cratepath.filename_str().unwrap();
             let name = &name[3..name.len() - 5]; // chop off lib/.rlib
             time(sess.time_passes(),
-                 &format!("altering {}.rlib", name)[],
+                 &format!("altering {}.rlib", name),
                  (), |()| {
                 let dst = tmpdir.join(cratepath.filename().unwrap());
                 match fs::copy(&cratepath, &dst) {
@@ -1198,7 +1198,7 @@ fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
                         sess.err(&format!("failed to copy {} to {}: {}",
                                          cratepath.display(),
                                          dst.display(),
-                                         e)[]);
+                                         e));
                         sess.abort_if_errors();
                     }
                 }
@@ -1210,7 +1210,7 @@ fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
                     Err(e) => {
                         sess.err(&format!("failed to chmod {} when preparing \
                                           for LTO: {}", dst.display(),
-                                         e)[]);
+                                         e));
                         sess.abort_if_errors();
                     }
                 }
@@ -1224,9 +1224,9 @@ fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
                     maybe_ar_prog: sess.opts.cg.ar.clone()
                 };
                 let mut archive = Archive::open(config);
-                archive.remove_file(&format!("{}.o", name)[]);
+                archive.remove_file(&format!("{}.o", name));
                 let files = archive.files();
-                if files.iter().any(|s| s[].ends_with(".o")) {
+                if files.iter().any(|s| s.ends_with(".o")) {
                     cmd.arg(dst);
                 }
             });
index 0a0f2a9c18627adeb821ca15e03c7f21b881119d..d8a296bf0410cdde29e5c64362037ecc5b009937 100644 (file)
@@ -54,7 +54,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
             Some(p) => p,
             None => {
                 sess.fatal(&format!("could not find rlib for: `{}`",
-                                   name)[]);
+                                   name));
             }
         };
 
@@ -68,7 +68,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
                                   (),
                                   |_| {
                                       archive.read(&format!("{}.{}.bytecode.deflate",
-                                                           file, i)[])
+                                                           file, i))
                                   });
             let bc_encoded = match bc_encoded {
                 Some(data) => data,
@@ -76,7 +76,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
                     if i == 0 {
                         // No bitcode was found at all.
                         sess.fatal(&format!("missing compressed bytecode in {}",
-                                           path.display())[]);
+                                           path.display()));
                     }
                     // No more bitcode files to read.
                     break;
@@ -99,12 +99,12 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
                             Some(inflated) => inflated,
                             None => {
                                 sess.fatal(&format!("failed to decompress bc of `{}`",
-                                                   name)[])
+                                                   name))
                             }
                         }
                     } else {
                         sess.fatal(&format!("Unsupported bytecode format version {}",
-                                           version)[])
+                                           version))
                     }
                 })
             } else {
@@ -115,7 +115,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
                         Some(bc) => bc,
                         None => {
                             sess.fatal(&format!("failed to decompress bc of `{}`",
-                                               name)[])
+                                               name))
                         }
                     }
                 })
@@ -124,7 +124,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
             let ptr = bc_decoded.as_ptr();
             debug!("linking {}, part {}", name, i);
             time(sess.time_passes(),
-                 &format!("ll link {}.{}", name, i)[],
+                 &format!("ll link {}.{}", name, i),
                  (),
                  |()| unsafe {
                 if !llvm::LLVMRustLinkInExternalBitcode(llmod,
@@ -167,7 +167,12 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
         llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
         llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
-        let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint;
+        let opt = match sess.opts.optimize {
+            config::No => 0,
+            config::Less => 1,
+            config::Default => 2,
+            config::Aggressive => 3,
+        };
 
         let builder = llvm::LLVMPassManagerBuilderCreate();
         llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt);
index 86b720d3fc171191f451bb9bc31a32e4eedef4ef..a1fc63778ce8af858a5bda6b5a935b2c7fa81571 100644 (file)
@@ -54,7 +54,7 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
             libc::free(cstr as *mut _);
             handler.fatal(&format!("{}: {}",
                                   &msg[..],
-                                  &err[..])[]);
+                                  &err[..]));
         }
     }
 }
@@ -104,13 +104,13 @@ fn dump(&mut self, handler: &Handler) {
             match diag.code {
                 Some(ref code) => {
                     handler.emit_with_code(None,
-                                           &diag.msg[],
+                                           &diag.msg,
                                            &code[..],
                                            diag.lvl);
                 },
                 None => {
                     handler.emit(None,
-                                 &diag.msg[],
+                                 &diag.msg,
                                  diag.lvl);
                 },
             }
@@ -166,7 +166,7 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
 fn create_target_machine(sess: &Session) -> TargetMachineRef {
     let reloc_model_arg = match sess.opts.cg.relocation_model {
         Some(ref s) => &s[..],
-        None => &sess.target.target.options.relocation_model[]
+        None => &sess.target.target.options.relocation_model[..],
     };
     let reloc_model = match reloc_model_arg {
         "pic" => llvm::RelocPIC,
@@ -177,7 +177,7 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
             sess.err(&format!("{:?} is not a valid relocation mode",
                              sess.opts
                                  .cg
-                                 .relocation_model)[]);
+                                 .relocation_model));
             sess.abort_if_errors();
             unreachable!();
         }
@@ -199,7 +199,7 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
 
     let code_model_arg = match sess.opts.cg.code_model {
         Some(ref s) => &s[..],
-        None => &sess.target.target.options.code_model[]
+        None => &sess.target.target.options.code_model[..],
     };
 
     let code_model = match code_model_arg {
@@ -212,13 +212,13 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
             sess.err(&format!("{:?} is not a valid code model",
                              sess.opts
                                  .cg
-                                 .code_model)[]);
+                                 .code_model));
             sess.abort_if_errors();
             unreachable!();
         }
     };
 
-    let triple = &sess.target.target.llvm_target[];
+    let triple = &sess.target.target.llvm_target;
 
     let tm = unsafe {
         let triple = CString::new(triple.as_bytes()).unwrap();
@@ -526,14 +526,14 @@ unsafe fn with_codegen<F>(tm: TargetMachineRef,
         }
 
         if config.emit_asm {
-            let path = output_names.with_extension(&format!("{}.s", name_extra)[]);
+            let path = output_names.with_extension(&format!("{}.s", name_extra));
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::AssemblyFileType);
             });
         }
 
         if config.emit_obj {
-            let path = output_names.with_extension(&format!("{}.o", name_extra)[]);
+            let path = output_names.with_extension(&format!("{}.o", name_extra));
             with_codegen(tm, llmod, config.no_builtins, |cpm| {
                 write_output_file(cgcx.handler, tm, cpm, llmod, &path, llvm::ObjectFileType);
             });
@@ -647,7 +647,7 @@ pub fn run_passes(sess: &Session,
 
     // Process the work items, optionally using worker threads.
     if sess.opts.cg.codegen_units == 1 {
-        run_work_singlethreaded(sess, &trans.reachable[], work_items);
+        run_work_singlethreaded(sess, &trans.reachable, work_items);
     } else {
         run_work_multithreaded(sess, work_items, sess.opts.cg.codegen_units);
     }
@@ -679,7 +679,7 @@ pub fn run_passes(sess: &Session,
                 // 2) Multiple codegen units, with `-o some_name`.  We have
                 //    no good solution for this case, so warn the user.
                 sess.warn(&format!("ignoring -o because multiple .{} files were produced",
-                                  ext)[]);
+                                  ext));
             } else {
                 // 3) Multiple codegen units, but no `-o some_name`.  We
                 //    just leave the `foo.0.x` files in place.
@@ -713,18 +713,18 @@ pub fn run_passes(sess: &Session,
         let pname = get_cc_prog(sess);
         let mut cmd = Command::new(&pname[..]);
 
-        cmd.args(&sess.target.target.options.pre_link_args[]);
+        cmd.args(&sess.target.target.options.pre_link_args);
         cmd.arg("-nostdlib");
 
         for index in 0..trans.modules.len() {
-            cmd.arg(crate_output.with_extension(&format!("{}.o", index)[]));
+            cmd.arg(crate_output.with_extension(&format!("{}.o", index)));
         }
 
         cmd.arg("-r")
            .arg("-o")
            .arg(windows_output_path.as_ref().unwrap_or(output_path));
 
-        cmd.args(&sess.target.target.options.post_link_args[]);
+        cmd.args(&sess.target.target.options.post_link_args);
 
         if sess.opts.debugging_opts.print_link_args {
             println!("{:?}", &cmd);
@@ -737,14 +737,14 @@ pub fn run_passes(sess: &Session,
             Ok(status) => {
                 if !status.success() {
                     sess.err(&format!("linking of {} with `{:?}` failed",
-                                     output_path.display(), cmd)[]);
+                                     output_path.display(), cmd));
                     sess.abort_if_errors();
                 }
             },
             Err(e) => {
                 sess.err(&format!("could not exec the linker `{}`: {}",
                                  pname,
-                                 e)[]);
+                                 e));
                 sess.abort_if_errors();
             },
         }
@@ -971,10 +971,10 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
             if !prog.status.success() {
                 sess.err(&format!("linking with `{}` failed: {}",
                                  pname,
-                                 prog.status)[]);
-                sess.note(&format!("{:?}", &cmd)[]);
+                                 prog.status));
+                sess.note(&format!("{:?}", &cmd));
                 let mut note = prog.error.clone();
-                note.push_all(&prog.output[]);
+                note.push_all(&prog.output);
                 sess.note(str::from_utf8(&note[..]).unwrap());
                 sess.abort_if_errors();
             }
@@ -982,7 +982,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
         Err(e) => {
             sess.err(&format!("could not exec the linker `{}`: {}",
                              pname,
-                             e)[]);
+                             e));
             sess.abort_if_errors();
         }
     }
@@ -1018,7 +1018,7 @@ unsafe fn configure_llvm(sess: &Session) {
         if sess.target.target.arch == "aarch64" { add("-fast-isel=0"); }
 
         for arg in &sess.opts.cg.llvm_args {
-            add(&(*arg)[]);
+            add(&(*arg));
         }
     }
 
index 8d2a2d51ee42366b6f78d8262abf701d8966481a..371b9268fba0de800de32544ce97f95de7f9b707 100644 (file)
@@ -94,7 +94,7 @@ fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
 
         // dump info about all the external crates referenced from this crate
         self.sess.cstore.iter_crate_data(|n, cmd| {
-            self.fmt.external_crate_str(krate.span, &cmd.name[], n);
+            self.fmt.external_crate_str(krate.span, &cmd.name, n);
         });
         self.fmt.recorder.record("end_external_crates\n");
     }
@@ -216,9 +216,9 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
     fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
         if !self.analysis.ty_cx.def_map.borrow().contains_key(&ref_id) {
             self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
-                                  ref_id)[]);
+                                  ref_id));
         }
-        let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id];
+        let def = self.analysis.ty_cx.def_map.borrow()[ref_id].full_def();
         match def {
             def::DefPrimTy(_) => None,
             _ => Some(def.def_id()),
@@ -229,16 +229,15 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
         let def_map = self.analysis.ty_cx.def_map.borrow();
         if !def_map.contains_key(&ref_id) {
             self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind",
-                                             ref_id)[]);
+                                             ref_id));
         }
-        let def = (*def_map)[ref_id];
+        let def = def_map[ref_id].full_def();
         match def {
             def::DefMod(_) |
             def::DefForeignMod(_) => Some(recorder::ModRef),
             def::DefStruct(_) => Some(recorder::StructRef),
             def::DefTy(..) |
             def::DefAssociatedTy(..) |
-            def::DefAssociatedPath(..) |
             def::DefTrait(_) => Some(recorder::TypeRef),
             def::DefStatic(_, _) |
             def::DefConst(_) |
@@ -250,15 +249,13 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
 
             def::DefSelfTy(_) |
             def::DefRegion(_) |
-            def::DefTyParamBinder(_) |
             def::DefLabel(_) |
-            def::DefStaticMethod(..) |
             def::DefTyParam(..) |
             def::DefUse(_) |
             def::DefMethod(..) |
             def::DefPrimTy(_) => {
                 self.sess.span_bug(span, &format!("lookup_def_kind for unexpected item: {:?}",
-                                                 def)[]);
+                                                 def));
             },
         }
     }
@@ -279,7 +276,7 @@ fn process_formals(&mut self, formals: &Vec<ast::Arg>, qualname: &str) {
                                     span_utils.span_for_last_ident(p.span),
                                     id,
                                     qualname,
-                                    &path_to_string(p)[],
+                                    &path_to_string(p),
                                     &typ[..]);
             }
             self.collected_paths.clear();
@@ -302,7 +299,7 @@ fn process_method(&mut self, method: &ast::Method) {
                     match item.node {
                         ast::ItemImpl(_, _, _, _, ref ty, _) => {
                             let mut result = String::from_str("<");
-                            result.push_str(&ty_to_string(&**ty)[]);
+                            result.push_str(&ty_to_string(&**ty));
 
                             match ty::trait_of_item(&self.analysis.ty_cx,
                                                     ast_util::local_def(method.id)) {
@@ -319,7 +316,7 @@ fn process_method(&mut self, method: &ast::Method) {
                         _ => {
                             self.sess.span_bug(method.span,
                                                &format!("Container {} for method {} not an impl?",
-                                                       impl_id.node, method.id)[]);
+                                                       impl_id.node, method.id));
                         },
                     }
                 },
@@ -329,7 +326,7 @@ fn process_method(&mut self, method: &ast::Method) {
                                            "Container {} for method {} is not a node item {:?}",
                                            impl_id.node,
                                            method.id,
-                                           self.analysis.ty_cx.map.get(impl_id.node))[]);
+                                           self.analysis.ty_cx.map.get(impl_id.node)));
                 },
             },
             None => match ty::trait_of_item(&self.analysis.ty_cx,
@@ -343,14 +340,14 @@ fn process_method(&mut self, method: &ast::Method) {
                         _ => {
                             self.sess.span_bug(method.span,
                                                &format!("Could not find container {} for method {}",
-                                                       def_id.node, method.id)[]);
+                                                       def_id.node, method.id));
                         }
                     }
                 },
                 None => {
                     self.sess.span_bug(method.span,
                                        &format!("Could not find container for method {}",
-                                               method.id)[]);
+                                               method.id));
                 },
             },
         };
@@ -442,7 +439,7 @@ fn process_struct_field_def(&mut self,
                                                          scope_id),
                     None => self.sess.span_bug(field.span,
                                                &format!("Could not find sub-span for field {}",
-                                                       qualname)[]),
+                                                       qualname)),
                 }
             },
             _ => (),
@@ -528,7 +525,7 @@ fn process_static(&mut self,
                             &get_ident(item.ident),
                             &qualname[..],
                             &value[..],
-                            &ty_to_string(&*typ)[],
+                            &ty_to_string(&*typ),
                             self.cur_scope);
 
         // walk type and init value
@@ -551,7 +548,7 @@ fn process_const(&mut self,
                             &get_ident(item.ident),
                             &qualname[..],
                             "",
-                            &ty_to_string(&*typ)[],
+                            &ty_to_string(&*typ),
                             self.cur_scope);
 
         // walk type and init value
@@ -603,7 +600,7 @@ fn process_enum(&mut self,
                                                 &val[..]),
             None => self.sess.span_bug(item.span,
                                        &format!("Could not find subspan for enum {}",
-                                               enum_name)[]),
+                                               enum_name)),
         }
         for variant in &enum_definition.variants {
             let name = get_ident(variant.node.name);
@@ -662,24 +659,22 @@ fn process_impl(&mut self,
         let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
         match typ.node {
             // Common case impl for a struct or something basic.
-            ast::TyPath(ref path, id) => {
-                match self.lookup_type_ref(id) {
-                    Some(id) => {
-                        let sub_span = self.span.sub_span_for_type_name(path.span);
-                        self.fmt.ref_str(recorder::TypeRef,
-                                         path.span,
-                                         sub_span,
-                                         id,
-                                         self.cur_scope);
-                        self.fmt.impl_str(path.span,
-                                          sub_span,
-                                          item.id,
-                                          Some(id),
-                                          trait_id,
-                                          self.cur_scope);
-                    },
-                    None => ()
-                }
+            ast::TyPath(None, ref path) => {
+                let sub_span = self.span.sub_span_for_type_name(path.span);
+                let self_id = self.lookup_type_ref(typ.id).map(|id| {
+                    self.fmt.ref_str(recorder::TypeRef,
+                                     path.span,
+                                     sub_span,
+                                     id,
+                                     self.cur_scope);
+                    id
+                });
+                self.fmt.impl_str(path.span,
+                                  sub_span,
+                                  item.id,
+                                  self_id,
+                                  trait_id,
+                                  self.cur_scope);
             },
             _ => {
                 // Less useful case, impl for a compound type.
@@ -797,9 +792,9 @@ fn process_path(&mut self,
             self.sess.span_bug(span,
                                &format!("def_map has no key for {} in visit_expr", id));
         }
-        let def = &(*def_map)[id];
+        let def = def_map[id].full_def();
         let sub_span = self.span.span_for_last_ident(span);
-        match *def {
+        match def {
             def::DefUpvar(..) |
             def::DefLocal(..) |
             def::DefStatic(..) |
@@ -819,8 +814,7 @@ fn process_path(&mut self,
                                                       sub_span,
                                                       def_id,
                                                       self.cur_scope),
-            def::DefStaticMethod(declid, provenence) |
-            def::DefMethod(declid, _, provenence) => {
+            def::DefMethod(declid, provenence) => {
                 let sub_span = self.span.sub_span_for_meth_name(span);
                 let defid = if declid.krate == ast::LOCAL_CRATE {
                     let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
@@ -872,11 +866,18 @@ fn process_path(&mut self,
                                     &format!("Unexpected def kind while looking \
                                               up path in `{}`: `{:?}`",
                                              self.span.snippet(span),
-                                             *def)[]),
+                                             def)),
         }
         // modules or types in the path prefix
-        match *def {
-            def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path),
+        match def {
+            def::DefMethod(did, _) => {
+                let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did);
+                if let ty::MethodTraitItem(m) = ti {
+                    if m.explicit_self == ty::StaticExplicitSelfCategory {
+                        self.write_sub_path_trait_truncated(path);
+                    }
+                }
+            }
             def::DefLocal(_) |
             def::DefStatic(_,_) |
             def::DefConst(..) |
@@ -1002,28 +1003,39 @@ fn process_pat(&mut self, p:&ast::Pat) {
             ast::PatStruct(ref path, ref fields, _) => {
                 self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef));
                 visit::walk_path(self, path);
-                let struct_def = match self.lookup_type_ref(p.id) {
-                    Some(sd) => sd,
-                    None => {
-                        self.sess.span_bug(p.span,
-                                           &format!("Could not find struct_def for `{}`",
-                                                   self.span.snippet(p.span))[]);
+
+                let def = self.analysis.ty_cx.def_map.borrow()[p.id].full_def();
+                let struct_def = match def {
+                    def::DefConst(..) => None,
+                    def::DefVariant(_, variant_id, _) => Some(variant_id),
+                    _ => {
+                        match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) {
+                            None => {
+                                self.sess.span_bug(p.span,
+                                                   &format!("Could not find struct_def for `{}`",
+                                                            self.span.snippet(p.span)));
+                            }
+                            Some(def_id) => Some(def_id),
+                        }
                     }
                 };
-                for &Spanned { node: ref field, span } in fields {
-                    let sub_span = self.span.span_for_first_ident(span);
-                    let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
-                    for f in fields {
-                        if f.name == field.ident.name {
-                            self.fmt.ref_str(recorder::VarRef,
-                                             span,
-                                             sub_span,
-                                             f.id,
-                                             self.cur_scope);
-                            break;
+
+                if let Some(struct_def) = struct_def {
+                    let struct_fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
+                    for &Spanned { node: ref field, span } in fields {
+                        let sub_span = self.span.span_for_first_ident(span);
+                        for f in &struct_fields {
+                            if f.name == field.ident.name {
+                                self.fmt.ref_str(recorder::VarRef,
+                                                 span,
+                                                 sub_span,
+                                                 f.id,
+                                                 self.cur_scope);
+                                break;
+                            }
                         }
+                        self.visit_pat(&*field.pat);
                     }
-                    self.visit_pat(&*field.pat);
                 }
             }
             ast::PatEnum(ref path, _) => {
@@ -1255,7 +1267,7 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
                     None => {
                         self.sess.span_bug(method_type.span,
                                            &format!("Could not find trait for method {}",
-                                                   method_type.id)[]);
+                                                   method_type.id));
                     },
                 };
 
@@ -1294,8 +1306,8 @@ fn visit_ty(&mut self, t: &ast::Ty) {
         }
 
         match t.node {
-            ast::TyPath(ref path, id) => {
-                match self.lookup_type_ref(id) {
+            ast::TyPath(_, ref path) => {
+                match self.lookup_type_ref(t.id) {
                     Some(id) => {
                         let sub_span = self.span.sub_span_for_type_name(t.span);
                         self.fmt.ref_str(recorder::TypeRef,
@@ -1325,16 +1337,10 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 // Don't need to do anything for function calls,
                 // because just walking the callee path does what we want.
                 visit::walk_expr(self, ex);
-            },
-            ast::ExprPath(ref path) => {
-                self.process_path(ex.id, path.span, path, None);
-                visit::walk_path(self, path);
             }
-            ast::ExprQPath(ref qpath) => {
-                let mut path = qpath.trait_ref.path.clone();
-                path.segments.push(qpath.item_path.clone());
-                self.process_path(ex.id, ex.span, &path, None);
-                visit::walk_qpath(self, ex.span, &**qpath);
+            ast::ExprPath(_, ref path) => {
+                self.process_path(ex.id, path.span, path, None);
+                visit::walk_expr(self, ex);
             }
             ast::ExprStruct(ref path, ref fields, ref base) =>
                 self.process_struct_lit(ex, path, fields, base),
@@ -1362,7 +1368,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                         }
                     }
                     _ => self.sess.span_bug(ex.span,
-                                            &format!("Expected struct type, found {:?}", ty)[]),
+                                            &format!("Expected struct type, found {:?}", ty)),
                 }
             },
             ast::ExprTupField(ref sub_ex, idx) => {
@@ -1391,7 +1397,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                     ty::ty_tup(_) => {}
                     _ => self.sess.span_bug(ex.span,
                                             &format!("Expected struct or tuple \
-                                                      type, found {:?}", ty)[]),
+                                                      type, found {:?}", ty)),
                 }
             },
             ast::ExprClosure(_, ref decl, ref body) => {
@@ -1400,7 +1406,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 }
 
                 let mut id = String::from_str("$");
-                id.push_str(&ex.id.to_string()[]);
+                id.push_str(&ex.id.to_string());
                 self.process_formals(&decl.inputs, &id[..]);
 
                 // walk arg and return types
@@ -1448,10 +1454,10 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
             if !def_map.contains_key(&id) {
                 self.sess.span_bug(p.span,
                                    &format!("def_map has no key for {} in visit_arm",
-                                           id)[]);
+                                           id));
             }
-            let def = &(*def_map)[id];
-            match *def {
+            let def = def_map[id].full_def();
+            match def {
                 def::DefLocal(id)  => {
                     let value = if *immut {
                         self.span.snippet(p.span).to_string()
@@ -1463,7 +1469,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                     self.fmt.variable_str(p.span,
                                           Some(p.span),
                                           id,
-                                          &path_to_string(p)[],
+                                          &path_to_string(p),
                                           &value[..],
                                           "")
                 }
@@ -1474,7 +1480,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                 def::DefStatic(_, _) => {}
                 def::DefConst(..) => {}
                 _ => error!("unexpected definition kind when processing collected paths: {:?}",
-                            *def)
+                            def)
             }
         }
         for &(id, ref path, ref_kind) in &paths_to_process {
@@ -1519,7 +1525,7 @@ fn visit_local(&mut self, l: &ast::Local) {
             self.fmt.variable_str(p.span,
                                   sub_span,
                                   id,
-                                  &path_to_string(p)[],
+                                  &path_to_string(p),
                                   &value[..],
                                   &typ[..]);
         }
@@ -1540,7 +1546,7 @@ pub fn process_crate(sess: &Session,
     }
 
     assert!(analysis.glob_map.is_some());
-    let cratename = match attr::find_crate_name(&krate.attrs[]) {
+    let cratename = match attr::find_crate_name(&krate.attrs) {
         Some(name) => name.to_string(),
         None => {
             info!("Could not find crate name, using 'unknown_crate'");
@@ -1561,7 +1567,7 @@ pub fn process_crate(sess: &Session,
 
     match fs::mkdir_recursive(&root_path, old_io::USER_RWX) {
         Err(e) => sess.err(&format!("Could not create directory {}: {}",
-                           root_path.display(), e)[]),
+                           root_path.display(), e)),
         _ => (),
     }
 
@@ -1578,7 +1584,7 @@ pub fn process_crate(sess: &Session,
         Ok(f) => box f,
         Err(e) => {
             let disp = root_path.display();
-            sess.fatal(&format!("Could not open {}: {}", disp, e)[]);
+            sess.fatal(&format!("Could not open {}: {}", disp, e));
         }
     };
     root_path.pop();
index 08e36bb1d85bb3eefc504b5c81b7244c7fff5ba5..937f2d07677aa790141757ee034ee08135735f5f 100644 (file)
@@ -162,7 +162,7 @@ pub fn make_values_str(&self,
         if values.len() != fields.len() {
             self.span.sess.span_bug(span, &format!(
                 "Mismatch between length of fields for '{}', expected '{}', found '{}'",
-                kind, fields.len(), values.len())[]);
+                kind, fields.len(), values.len()));
         }
 
         let values = values.iter().map(|s| {
@@ -191,7 +191,7 @@ pub fn record_without_span(&mut self,
         if needs_span {
             self.span.sess.span_bug(span, &format!(
                 "Called record_without_span for '{}' which does requires a span",
-                label)[]);
+                label));
         }
         assert!(!dump_spans);
 
@@ -268,7 +268,7 @@ pub fn variable_str(&mut self,
         // variable def's node id
         let mut qualname = String::from_str(name);
         qualname.push_str("$");
-        qualname.push_str(&id.to_string()[]);
+        qualname.push_str(&id.to_string());
         self.check_and_record(Variable,
                               span,
                               sub_span,
index 223d46e4e4a93ebbb902c7f1d49fecfa031b77b6..8de046fa6ebb6c8486604be025597ffd6684a976 100644 (file)
@@ -219,7 +219,7 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
             let loc = self.sess.codemap().lookup_char_pos(span.lo);
             self.sess.span_bug(span,
                 &format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
-                        self.snippet(span), loc.file.name, loc.line)[]);
+                        self.snippet(span), loc.file.name, loc.line));
         }
         if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
             return self.make_sub_span(span, Some(prev.sp));
@@ -238,6 +238,7 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
         let mut toks = self.retokenise_span(span);
         // We keep track of how many brackets we're nested in
         let mut bracket_count = 0;
+        let mut found_ufcs_sep = false;
         loop {
             let ts = toks.real_token();
             if ts.tok == token::Eof {
@@ -245,7 +246,7 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
                     let loc = self.sess.codemap().lookup_char_pos(span.lo);
                     self.sess.span_bug(span, &format!(
                         "Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
-                         self.snippet(span), loc.file.name, loc.line)[]);
+                         self.snippet(span), loc.file.name, loc.line));
                 }
                 return result
             }
@@ -254,13 +255,20 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
             }
             bracket_count += match ts.tok {
                 token::Lt => 1,
-                token::Gt => -1,
+                token::Gt => {
+                    // Ignore the `>::` in `<Type as Trait>::AssocTy`.
+                    if !found_ufcs_sep && bracket_count == 0 {
+                        found_ufcs_sep = true;
+                        0
+                    } else {
+                        -1
+                    }
+                }
                 token::BinOp(token::Shl) => 2,
                 token::BinOp(token::Shr) => -2,
                 _ => 0
             };
-            if ts.tok.is_ident() &&
-               bracket_count == nesting {
+            if ts.tok.is_ident() && bracket_count == nesting {
                 result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
             }
         }
index 2826afb71a2c23cfcc945a66c908b6c806a7a3c3..9a121a8830b2b8d1b94d41e63e527463db1614f8 100644 (file)
@@ -444,7 +444,7 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let _indenter = indenter();
 
     m.iter().filter_map(|br| {
-        e(&br.pats[]).map(|pats| {
+        e(&br.pats).map(|pats| {
             let this = br.pats[col];
             let mut bound_ptrs = br.bound_ptrs.clone();
             match this.node {
@@ -598,7 +598,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
                 // This is either an enum variant or a variable binding.
-                let opt_def = tcx.def_map.borrow().get(&cur.id).cloned();
+                let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
                     Some(def::DefVariant(enum_id, var_id, _)) => {
                         let variant = ty::enum_variant_with_id(tcx, enum_id, var_id);
@@ -678,7 +678,7 @@ fn bind_subslice_pat(bcx: Block,
 }
 
 fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 left_ty: Ty,
+                                 left_ty: Ty<'tcx>,
                                  before: uint,
                                  after: uint,
                                  val: ValueRef)
@@ -725,14 +725,14 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
         match pat.node {
             ast::PatTup(_) => true,
             ast::PatStruct(..) => {
-                match tcx.def_map.borrow().get(&pat.id) {
-                    Some(&def::DefVariant(..)) => false,
+                match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                    Some(def::DefVariant(..)) => false,
                     _ => true,
                 }
             }
             ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
-                match tcx.def_map.borrow().get(&pat.id) {
-                    Some(&def::DefStruct(..)) => true,
+                match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                    Some(def::DefStruct(..)) => true,
                     _ => false
                 }
             }
@@ -825,7 +825,7 @@ fn compare_str<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         let did = langcall(cx,
                            None,
                            &format!("comparison of `{}`",
-                                   cx.ty_to_string(rhs_t))[],
+                                   cx.ty_to_string(rhs_t)),
                            StrEqFnLangItem);
         let t = ty::mk_str_slice(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ast::MutImmutable);
         // The comparison function gets the slices by value, so we have to make copies here. Even
@@ -1277,20 +1277,20 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
 fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
     let (vid, field) = match discr.node {
-        ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
+        ast::ExprPath(..) => match bcx.def(discr.id) {
             def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None),
             _ => return false
         },
         ast::ExprField(ref base, field) => {
-            let vid = match bcx.tcx().def_map.borrow().get(&base.id) {
-                Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid,
+            let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
+                Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::NamedField(field.node.name)))
         },
         ast::ExprTupField(ref base, field) => {
-            let vid = match bcx.tcx().def_map.borrow().get(&base.id) {
-                Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid,
+            let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
+                Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::PositionalField(field.node)))
@@ -1375,7 +1375,7 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
                                  "__llmatch");
                 trmode = TrByCopy(alloca_no_lifetime(bcx,
                                          llvariable_ty,
-                                         &bcx.ident(ident)[]));
+                                         &bcx.ident(ident)));
             }
             ast::BindByValue(_) => {
                 // in this case, the final type of the variable will be T,
@@ -1383,13 +1383,13 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
                 // above
                 llmatch = alloca_no_lifetime(bcx,
                                  llvariable_ty.ptr_to(),
-                                 &bcx.ident(ident)[]);
+                                 &bcx.ident(ident));
                 trmode = TrByMove;
             }
             ast::BindByRef(_) => {
                 llmatch = alloca_no_lifetime(bcx,
                                  llvariable_ty,
-                                 &bcx.ident(ident)[]);
+                                 &bcx.ident(ident));
                 trmode = TrByRef;
             }
         };
@@ -1610,7 +1610,7 @@ fn mk_binding_alloca<'blk, 'tcx, A, F>(bcx: Block<'blk, 'tcx>,
     let var_ty = node_id_type(bcx, p_id);
 
     // Allocate memory on stack for the binding.
-    let llval = alloc_ty(bcx, var_ty, &bcx.ident(*ident)[]);
+    let llval = alloc_ty(bcx, var_ty, &bcx.ident(*ident));
 
     // Subtle: be sure that we *populate* the memory *before*
     // we schedule the cleanup.
@@ -1648,7 +1648,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     if bcx.sess().asm_comments() {
         add_comment(bcx, &format!("bind_irrefutable_pat(pat={})",
-                                 pat.repr(bcx.tcx()))[]);
+                                 pat.repr(bcx.tcx())));
     }
 
     let _indenter = indenter();
@@ -1689,7 +1689,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
         ast::PatEnum(_, ref sub_pats) => {
-            let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).cloned();
+            let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
             match opt_def {
                 Some(def::DefVariant(enum_id, var_id, _)) => {
                     let repr = adt::represent_node(bcx, pat.id);
index eaf6eaa2f089d1273bec3b9f574fa24be70d68dc..3ea14d3c58929dd5967c0a9893bb29a7e1233ca8 100644 (file)
@@ -177,7 +177,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         ty::ty_enum(def_id, substs) => {
             let cases = get_cases(cx.tcx(), def_id, substs);
-            let hint = *ty::lookup_repr_hints(cx.tcx(), def_id)[].get(0)
+            let hint = *ty::lookup_repr_hints(cx.tcx(), def_id).get(0)
                 .unwrap_or(&attr::ReprAny);
 
             let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
@@ -210,7 +210,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 cx.sess().bug(&format!("non-C-like enum {} with specified \
                                       discriminants",
                                       ty::item_path_str(cx.tcx(),
-                                                        def_id))[]);
+                                                        def_id)));
             }
 
             if cases.len() == 1 {
@@ -228,7 +228,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 let mut discr = 0;
                 while discr < 2 {
                     if cases[1 - discr].is_zerolen(cx, t) {
-                        let st = mk_struct(cx, &cases[discr].tys[],
+                        let st = mk_struct(cx, &cases[discr].tys,
                                            false, t);
                         match cases[discr].find_ptr(cx) {
                             Some(ref df) if df.len() == 1 && st.fields.len() == 1 => {
@@ -318,7 +318,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             let fields : Vec<_> = cases.iter().map(|c| {
                 let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity));
-                ftys.push_all(&c.tys[]);
+                ftys.push_all(&c.tys);
                 if dtor { ftys.push(cx.tcx().types.bool); }
                 mk_struct(cx, &ftys[..], false, t)
             }).collect();
@@ -328,7 +328,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             General(ity, fields, dtor)
         }
         _ => cx.sess().bug(&format!("adt::represent_type called on non-ADT type: {}",
-                           ty_to_string(cx.tcx(), t))[])
+                           ty_to_string(cx.tcx(), t)))
     }
 }
 
@@ -414,7 +414,7 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
 
 impl<'tcx> Case<'tcx> {
     fn is_zerolen<'a>(&self, cx: &CrateContext<'a, 'tcx>, scapegoat: Ty<'tcx>) -> bool {
-        mk_struct(cx, &self.tys[], false, scapegoat).size == 0
+        mk_struct(cx, &self.tys, false, scapegoat).size == 0
     }
 
     fn find_ptr<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> Option<DiscrField> {
@@ -504,7 +504,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
             return ity;
         }
         attr::ReprExtern => {
-            attempts = match &cx.sess().target.target.arch[] {
+            attempts = match &cx.sess().target.target.arch[..] {
                 // WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32`
                 // appears to be used on Linux and NetBSD, but some systems may use the variant
                 // corresponding to `choose_shortest`.  However, we don't run on those yet...?
@@ -624,7 +624,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     match *r {
         CEnum(..) | General(..) | RawNullablePointer { .. } => { }
         Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } =>
-            llty.set_struct_body(&struct_llfields(cx, st, false, false)[],
+            llty.set_struct_body(&struct_llfields(cx, st, false, false),
                                  st.packed)
     }
 }
@@ -640,7 +640,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => {
             match name {
                 None => {
-                    Type::struct_(cx, &struct_llfields(cx, st, sizing, dst)[],
+                    Type::struct_(cx, &struct_llfields(cx, st, sizing, dst),
                                   st.packed)
                 }
                 Some(name) => { assert_eq!(sizing, false); Type::named_struct(cx, name) }
@@ -699,7 +699,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
         st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty))
             .map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
     } else {
-        st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect()
+        st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect()
     }
 }
 
@@ -965,7 +965,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
             for (discr, case) in cases.iter().enumerate() {
                 let mut variant_cx = fcx.new_temp_block(
-                    &format!("enum-variant-iter-{}", &discr.to_string())[]
+                    &format!("enum-variant-iter-{}", &discr.to_string())
                 );
                 let rhs_val = C_integral(ll_inttype(ccx, ity), discr as u64, true);
                 AddCase(llswitch, rhs_val, variant_cx.llbb);
@@ -1070,7 +1070,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
             if discr == nndiscr {
                 C_struct(ccx, &build_const_struct(ccx,
                                                  nonnull,
-                                                 vals)[],
+                                                 vals),
                          false)
             } else {
                 let vals = nonnull.fields.iter().map(|&ty| {
@@ -1080,7 +1080,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr
                 }).collect::<Vec<ValueRef>>();
                 C_struct(ccx, &build_const_struct(ccx,
                                                  nonnull,
-                                                 &vals[..])[],
+                                                 &vals[..]),
                          false)
             }
         }
index 3091c852f5587baa80a11f567d4cc31104f72f43..b18b7b75d32fc1fc65acd2980779716b1d74ec33 100644 (file)
@@ -301,7 +301,7 @@ pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                    self_type.repr(ccx.tcx()));
             (&function_type.sig, RustCall, Some(llenvironment_type))
         }
-        _ => panic!("expected closure or fn")
+        _ => ccx.sess().bug("expected closure or fn")
     };
 
     let sig = ty::erase_late_bound_regions(ccx.tcx(), sig);
@@ -365,7 +365,7 @@ fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         Err(s) => {
             bcx.sess().fatal(&format!("allocation of `{}` {}",
                                      bcx.ty_to_string(info_ty),
-                                     s)[]);
+                                     s));
         }
     }
 }
@@ -435,7 +435,7 @@ pub fn set_inline_hint(f: ValueRef) {
 pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRef) {
     use syntax::attr::*;
     // Set the inline hint if there is one
-    match find_inline_attr(attrs) {
+    match find_inline_attr(Some(ccx.sess().diagnostic()), attrs) {
         InlineHint   => set_inline_hint(llfn),
         InlineAlways => set_always_inline(llfn),
         InlineNever  => set_no_inline(llfn),
@@ -444,7 +444,7 @@ pub fn set_llvm_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: Val
 
     for attr in attrs {
         let mut used = true;
-        match &attr.name()[] {
+        match &attr.name()[..] {
             "no_stack_check" => unset_split_stack(llfn),
             "no_split_stack" => {
                 unset_split_stack(llfn);
@@ -486,7 +486,7 @@ pub fn unset_split_stack(f: ValueRef) {
 // silently mangles such symbols, breaking our linkage model.
 pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: String) {
     if ccx.all_llvm_symbols().borrow().contains(&sym) {
-        ccx.sess().bug(&format!("duplicate LLVM symbol: {}", sym)[]);
+        ccx.sess().bug(&format!("duplicate LLVM symbol: {}", sym));
     }
     ccx.all_llvm_symbols().borrow_mut().insert(sym);
 }
@@ -541,7 +541,7 @@ pub fn bin_op_to_icmp_predicate(ccx: &CrateContext, op: ast::BinOp_, signed: boo
         ast::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE },
         op => {
             ccx.sess().bug(&format!("comparison_op_to_icmp_predicate: expected \
-                                     comparison operator, found {:?}", op)[]);
+                                     comparison operator, found {:?}", op));
         }
     }
 }
@@ -557,7 +557,7 @@ pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: ast::BinOp_)
         ast::BiGe => llvm::RealOGE,
         op => {
             ccx.sess().bug(&format!("comparison_op_to_fcmp_predicate: expected \
-                                     comparison operator, found {:?}", op)[]);
+                                     comparison operator, found {:?}", op));
         }
     }
 }
@@ -676,8 +676,7 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
                   let val = if common::type_is_sized(cx.tcx(), field_ty) {
                       llfld_a
                   } else {
-                      let boxed_ty = ty::mk_open(cx.tcx(), field_ty);
-                      let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter");
+                      let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
                       Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
                       Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
                       scratch.val
@@ -735,8 +734,8 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
                       let variant_cx =
                           fcx.new_temp_block(
                               &format!("enum-iter-variant-{}",
-                                      &variant.disr_val.to_string()[])
-                              []);
+                                      &variant.disr_val.to_string())
+                              );
                       match adt::trans_case(cx, &*repr, variant.disr_val) {
                           _match::SingleResult(r) => {
                               AddCase(llswitch, r.val, variant_cx.llbb)
@@ -761,7 +760,7 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
       }
       _ => {
           cx.sess().unimpl(&format!("type in iter_structural_ty: {}",
-                                   ty_to_string(cx.tcx(), t))[])
+                                   ty_to_string(cx.tcx(), t)))
       }
     }
     return cx;
@@ -843,7 +842,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
         }
         _ => {
             cx.sess().bug(&format!("fail-if-zero on unexpected type: {}",
-                                  ty_to_string(cx.tcx(), rhs_t))[]);
+                                  ty_to_string(cx.tcx(), rhs_t)));
         }
     };
     let bcx = with_cond(cx, is_zero, |bcx| {
@@ -1116,7 +1115,7 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
 pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
     let _icx = push_ctxt("call_memcpy");
     let ccx = cx.ccx();
-    let key = match &ccx.sess().target.target.target_pointer_width[] {
+    let key = match &ccx.sess().target.target.target_pointer_width[..] {
         "32" => "llvm.memcpy.p0i8.p0i8.i32",
         "64" => "llvm.memcpy.p0i8.p0i8.i64",
         tws => panic!("Unsupported target word size for memcpy: {}", tws),
@@ -1163,7 +1162,7 @@ fn memzero<'a, 'tcx>(b: &Builder<'a, 'tcx>, llptr: ValueRef, ty: Ty<'tcx>) {
 
     let llty = type_of::type_of(ccx, ty);
 
-    let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[] {
+    let intrinsic_key = match &ccx.sess().target.target.target_pointer_width[..] {
         "32" => "llvm.memset.p0i8.i32",
         "64" => "llvm.memset.p0i8.i64",
         tws => panic!("Unsupported target word size for memset: {}", tws),
@@ -1353,7 +1352,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
 // the clobbering of the existing value in the return slot.
 fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
     for n in cfg.graph.depth_traverse(cfg.entry) {
-        match tcx.map.find(n.id) {
+        match tcx.map.find(n.id()) {
             Some(ast_map::NodeExpr(ex)) => {
                 if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
                     let mut visitor = FindNestedReturn::new();
@@ -1833,14 +1832,14 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         closure::ClosureEnv::NotClosure => {
             copy_args_to_allocas(bcx,
                                  arg_scope,
-                                 &decl.inputs[],
+                                 &decl.inputs,
                                  arg_datums)
         }
         closure::ClosureEnv::Closure(_) => {
             copy_closure_args_to_allocas(
                 bcx,
                 arg_scope,
-                &decl.inputs[],
+                &decl.inputs,
                 arg_datums,
                 &monomorphized_arg_types[..])
         }
@@ -1964,7 +1963,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         _ => ccx.sess().bug(
             &format!("trans_enum_variant_constructor: \
                      unexpected ctor return type {}",
-                     ctor_ty.repr(tcx))[])
+                     ctor_ty.repr(tcx)))
     };
 
     // Get location to store the result. If the user does not care about
@@ -2042,7 +2041,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
         _ => ccx.sess().bug(
             &format!("trans_enum_variant_or_tuple_like_struct: \
                      unexpected ctor return type {}",
-                    ty_to_string(ccx.tcx(), ctor_ty))[])
+                    ty_to_string(ccx.tcx(), ctor_ty)))
     };
 
     let (arena, fcx): (TypedArena<_>, FunctionContext);
@@ -2143,7 +2142,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span,
                             *lvlsrc.unwrap(), Some(sp),
                             &format!("enum variant is more than three times larger \
                                      ({} bytes) than the next largest (ignoring padding)",
-                                    largest)[]);
+                                    largest));
 
         ccx.sess().span_note(enum_def.variants[largest_index].span,
                              "this variant is the largest");
@@ -2261,7 +2260,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
     match item.node {
       ast::ItemFn(ref decl, _fn_style, abi, ref generics, ref body) => {
         if !generics.is_type_parameterized() {
-            let trans_everywhere = attr::requests_inline(&item.attrs[]);
+            let trans_everywhere = attr::requests_inline(&item.attrs);
             // Ignore `trans_everywhere` for cross-crate inlined items
             // (`from_external`).  `trans_item` will be called once for each
             // compilation unit that references the item, so it will still get
@@ -2273,7 +2272,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                     foreign::trans_rust_fn_with_foreign_abi(ccx,
                                                             &**decl,
                                                             &**body,
-                                                            &item.attrs[],
+                                                            &item.attrs,
                                                             llfn,
                                                             empty_substs,
                                                             item.id,
@@ -2285,7 +2284,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                              llfn,
                              empty_substs,
                              item.id,
-                             &item.attrs[]);
+                             &item.attrs);
                 }
                 update_linkage(ccx,
                                llfn,
@@ -2332,7 +2331,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
 
           // Do static_assert checking. It can't really be done much earlier
           // because we need to get the value of the bool out of LLVM
-          if attr::contains_name(&item.attrs[], "static_assert") {
+          if attr::contains_name(&item.attrs, "static_assert") {
               if m == ast::MutMutable {
                   ccx.sess().span_fatal(expr.span,
                                         "cannot have static_assert on a mutable \
@@ -2410,12 +2409,15 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                          node_id: ast::NodeId,
                          node_type: Ty<'tcx>)
                          -> ValueRef {
-    match node_type.sty {
-        ty::ty_bare_fn(_, ref f) => {
-            assert!(f.abi == Rust || f.abi == RustCall);
+    if let ty::ty_bare_fn(_, ref f) = node_type.sty {
+        if f.abi != Rust && f.abi != RustCall {
+            ccx.sess().span_bug(sp, &format!("only the `{}` or `{}` calling conventions are valid \
+                                              for this function; `{}` was specified",
+                                              Rust.name(), RustCall.name(), f.abi.name()));
         }
-        _ => panic!("expected bare rust fn")
-    };
+    } else {
+        ccx.sess().span_bug(sp, "expected bare rust function")
+    }
 
     let llfn = decl_rust_fn(ccx, node_type, &sym[..]);
     finish_register_fn(ccx, sp, sym, node_id, llfn);
@@ -2746,7 +2748,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
     let val = match item {
         ast_map::NodeItem(i) => {
             let ty = ty::node_id_to_type(ccx.tcx(), i.id);
-            let sym = || exported_name(ccx, id, ty, &i.attrs[]);
+            let sym = || exported_name(ccx, id, ty, &i.attrs);
 
             let v = match i.node {
                 ast::ItemStatic(_, _, ref expr) => {
@@ -2773,13 +2775,13 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                         if contains_null(&sym[..]) {
                             ccx.sess().fatal(
                                 &format!("Illegal null byte in export_name \
-                                         value: `{}`", sym)[]);
+                                         value: `{}`", sym));
                         }
                         let buf = CString::new(sym.clone()).unwrap();
                         let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
                                                     buf.as_ptr());
 
-                        if attr::contains_name(&i.attrs[],
+                        if attr::contains_name(&i.attrs,
                                                "thread_local") {
                             llvm::set_thread_local(g, true);
                         }
@@ -2798,19 +2800,19 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                                                                    sym,
                                                                    i.id)
                     };
-                    set_llvm_fn_attrs(ccx, &i.attrs[], llfn);
+                    set_llvm_fn_attrs(ccx, &i.attrs, llfn);
                     llfn
                 }
 
-                _ => panic!("get_item_val: weird result in table")
+                _ => ccx.sess().bug("get_item_val: weird result in table")
             };
 
-            match attr::first_attr_value_str_by_name(&i.attrs[],
+            match attr::first_attr_value_str_by_name(&i.attrs,
                                                      "link_section") {
                 Some(sect) => {
                     if contains_null(&sect) {
                         ccx.sess().fatal(&format!("Illegal null byte in link_section value: `{}`",
-                                                 &sect)[]);
+                                                 &sect));
                     }
                     unsafe {
                         let buf = CString::new(sect.as_bytes()).unwrap();
@@ -2866,7 +2868,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             let args = match v.node.kind {
                 ast::TupleVariantKind(ref args) => args,
                 ast::StructVariantKind(_) => {
-                    panic!("struct variant kind unexpected in get_item_val")
+                    ccx.sess().bug("struct variant kind unexpected in get_item_val")
                 }
             };
             assert!(args.len() != 0);
@@ -2876,13 +2878,13 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             let sym = exported_name(ccx,
                                     id,
                                     ty,
-                                    &enm.attrs[]);
+                                    &enm.attrs);
 
             llfn = match enm.node {
                 ast::ItemEnum(_, _) => {
                     register_fn(ccx, (*v).span, sym, id, ty)
                 }
-                _ => panic!("NodeVariant, shouldn't happen")
+                _ => ccx.sess().bug("NodeVariant, shouldn't happen")
             };
             set_inline_hint(llfn);
             llfn
@@ -2903,7 +2905,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             let sym = exported_name(ccx,
                                     id,
                                     ty,
-                                    &struct_item.attrs[]);
+                                    &struct_item.attrs);
             let llfn = register_fn(ccx, struct_item.span,
                                    sym, ctor_id, ty);
             set_inline_hint(llfn);
@@ -2912,7 +2914,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 
         ref variant => {
             ccx.sess().bug(&format!("get_item_val(): unexpected variant: {:?}",
-                                   variant)[])
+                                   variant))
         }
     };
 
@@ -2933,11 +2935,19 @@ fn register_method(ccx: &CrateContext, id: ast::NodeId,
                    m: &ast::Method) -> ValueRef {
     let mty = ty::node_id_to_type(ccx.tcx(), id);
 
-    let sym = exported_name(ccx, id, mty, &m.attrs[]);
+    let sym = exported_name(ccx, id, mty, &m.attrs);
 
-    let llfn = register_fn(ccx, m.span, sym, id, mty);
-    set_llvm_fn_attrs(ccx, &m.attrs[], llfn);
-    llfn
+    if let ty::ty_bare_fn(_, ref f) = mty.sty {
+        let llfn = if f.abi == Rust || f.abi == RustCall {
+            register_fn(ccx, m.span, sym, id, mty)
+        } else {
+            foreign::register_rust_fn_with_foreign_abi(ccx, m.span, sym, id)
+        };
+        set_llvm_fn_attrs(ccx, &m.attrs, llfn);
+        return llfn;
+    } else {
+        ccx.sess().span_bug(m.span, "expected bare rust function");
+    }
 }
 
 pub fn crate_ctxt_to_encode_parms<'a, 'tcx>(cx: &'a SharedCrateContext<'tcx>,
@@ -3104,7 +3114,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
     let link_meta = link::build_link_meta(&tcx.sess, krate, name);
 
     let codegen_units = tcx.sess.opts.cg.codegen_units;
-    let shared_ccx = SharedCrateContext::new(&link_meta.crate_name[],
+    let shared_ccx = SharedCrateContext::new(&link_meta.crate_name,
                                              codegen_units,
                                              tcx,
                                              export_map,
@@ -3206,7 +3216,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
         llmod: shared_ccx.metadata_llmod(),
     };
     let formats = shared_ccx.tcx().dependency_formats.borrow().clone();
-    let no_builtins = attr::contains_name(&krate.attrs[], "no_builtins");
+    let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
 
     let translation = CrateTranslation {
         modules: modules,
index 7abcdd07cc5da6a0ea6bb4827ce190ddcbe54969..0ff5264c00f0f8346ebd9d3180affdf7787c9216 100644 (file)
@@ -109,7 +109,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
                         atys: &[Type],
                         rty: Type,
                         ret_def: bool) -> FnType {
-    match &ccx.sess().target.target.arch[] {
+    match &ccx.sess().target.target.arch[..] {
         "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def),
         "x86_64" => if ccx.sess().target.target.options.is_like_windows {
             cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def)
@@ -128,6 +128,6 @@ pub fn compute_abi_info(ccx: &CrateContext,
         "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
         "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def),
         a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
-                              []),
+                              ),
     }
 }
index 3d3e35cd776f0fd311affbe03d9188f46312d44c..59fcd5492ebde534e3be049a8331a631c9cc8dec 100644 (file)
@@ -93,7 +93,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
 
     // pick out special kinds of expressions that can be called:
     match expr.node {
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             return trans_def(bcx, bcx.def(expr.id), expr);
         }
         _ => {}
@@ -118,7 +118,7 @@ fn datum_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                     expr.span,
                     &format!("type of callee is neither bare-fn nor closure: \
                              {}",
-                            bcx.ty_to_string(datum.ty))[]);
+                            bcx.ty_to_string(datum.ty)));
             }
         }
     }
@@ -165,13 +165,11 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
                 Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
             }
-            def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
-            def::DefStaticMethod(did, def::FromImpl(_)) => {
+            def::DefFn(did, _) | def::DefMethod(did, def::FromImpl(_)) => {
                 fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
                                             bcx.fcx.param_substs).val)
             }
-            def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
-            def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
+            def::DefMethod(meth_did, def::FromTrait(trait_did)) => {
                 fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
                                                                 meth_did,
                                                                 trait_did,
@@ -209,13 +207,12 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
             def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
-            def::DefUse(..) | def::DefTyParamBinder(..) |
-            def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) |
-            def::DefSelfTy(..) | def::DefAssociatedPath(..) => {
+            def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) |
+            def::DefTyParam(..) | def::DefSelfTy(..) => {
                 bcx.tcx().sess.span_bug(
                     ref_expr.span,
                     &format!("cannot translate def {:?} \
-                             to a callable thing!", def)[]);
+                             to a callable thing!", def));
             }
         }
     }
@@ -298,7 +295,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
 
             _ => {
                 tcx.sess.bug(&format!("trans_fn_pointer_shim invoked on invalid type: {}",
-                                           bare_fn_ty.repr(tcx))[]);
+                                           bare_fn_ty.repr(tcx)));
             }
         };
     let sig = ty::erase_late_bound_regions(tcx, sig);
@@ -765,8 +762,16 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     if is_rust_fn {
         let mut llargs = Vec::new();
 
-        if let (ty::FnConverging(ret_ty), Some(llretslot)) = (ret_ty, opt_llretslot) {
+        if let (ty::FnConverging(ret_ty), Some(mut llretslot)) = (ret_ty, opt_llretslot) {
             if type_of::return_uses_outptr(ccx, ret_ty) {
+                let llformal_ret_ty = type_of::type_of(ccx, ret_ty).ptr_to();
+                let llret_ty = common::val_ty(llretslot);
+                if llformal_ret_ty != llret_ty {
+                    // this could happen due to e.g. subtyping
+                    debug!("casting actual return type ({}) to match formal ({})",
+                        bcx.llty_str(llret_ty), bcx.llty_str(llformal_ret_ty));
+                    llretslot = PointerCast(bcx, llretslot, llformal_ret_ty);
+                }
                 llargs.push(llretslot);
             }
         }
index 85e53618f6da9c7ed664b3a0e1643664d59eaab8..a3705a67cdc5a4e37f30dbff6bf3e5bdb5b86a3b 100644 (file)
@@ -513,7 +513,7 @@ fn schedule_clean_in_ast_scope(&self,
 
         self.ccx.sess().bug(
             &format!("no cleanup scope {} found",
-                    self.ccx.tcx().map.node_to_string(cleanup_scope))[]);
+                    self.ccx.tcx().map.node_to_string(cleanup_scope)));
     }
 
     /// Schedules a cleanup to occur in the top-most scope, which must be a temporary scope.
@@ -695,7 +695,7 @@ fn trans_cleanups_to_exit_scope(&'blk self,
                     LoopExit(id, _) => {
                         self.ccx.sess().bug(&format!(
                                 "cannot exit from scope {}, \
-                                not in scope", id)[]);
+                                not in scope", id));
                     }
                 }
             }
@@ -1135,7 +1135,7 @@ pub fn temporary_scope(tcx: &ty::ctxt,
         }
         None => {
             tcx.sess.bug(&format!("no temporary scope available for expr {}",
-                                 id)[])
+                                 id))
         }
     }
 }
index a9cda94bebac52513d98848c30cf01ca6a7262d5..d8fc6df2685dd5d9656ee561e0dd9a5565b90371 100644 (file)
@@ -120,14 +120,16 @@ fn fold_substs(&mut self,
 // Is the type's representation size known at compile time?
 pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     let param_env = ty::empty_parameter_environment(tcx);
-    ty::type_is_sized(&param_env, DUMMY_SP, ty)
-}
-
-pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        ty::ty_open(_) => true,
-        _ => type_is_sized(cx, ty),
+    // FIXME(#4287) This can cause errors due to polymorphic recursion,
+    // a better span should be provided, if available.
+    let err_count = tcx.sess.err_count();
+    let is_sized = ty::type_is_sized(&param_env, DUMMY_SP, ty);
+    // Those errors aren't fatal, but an incorrect result can later
+    // trip over asserts in both rustc's trans and LLVM.
+    if err_count < tcx.sess.err_count() {
+        tcx.sess.abort_if_errors();
     }
+    is_sized
 }
 
 pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -211,9 +213,7 @@ fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
-pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
-                         ty: Ty<'tcx>)
-                         -> bool {
+pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     ty::type_contents(cx, ty).needs_drop(cx)
 }
 
@@ -278,7 +278,7 @@ pub fn gensym_name(name: &str) -> PathElem {
     let num = token::gensym(name).usize();
     // use one colon which will get translated to a period by the mangler, and
     // we're guaranteed that `num` is globally unique for this crate.
-    PathName(token::gensym(&format!("{}:{}", name, num)[]))
+    PathName(token::gensym(&format!("{}:{}", name, num)))
 }
 
 #[derive(Copy)]
@@ -603,10 +603,10 @@ pub fn expr_to_string(&self, e: &ast::Expr) -> String {
 
     pub fn def(&self, nid: ast::NodeId) -> def::Def {
         match self.tcx().def_map.borrow().get(&nid) {
-            Some(v) => v.clone(),
+            Some(v) => v.full_def(),
             None => {
                 self.tcx().sess.bug(&format!(
-                    "no def associated with node id {}", nid)[]);
+                    "no def associated with node id {}", nid));
             }
         }
     }
@@ -774,6 +774,10 @@ pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
     C_integral(Type::i32(ccx), i as u64, true)
 }
 
+pub fn C_u32(ccx: &CrateContext, i: u32) -> ValueRef {
+    C_integral(Type::i32(ccx), i as u64, false)
+}
+
 pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
     C_integral(Type::i64(ccx), i, false)
 }
@@ -1011,7 +1015,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 span,
                 &format!("Encountered error `{}` selecting `{}` during trans",
                         e.repr(tcx),
-                        trait_ref.repr(tcx))[])
+                        trait_ref.repr(tcx)))
         }
     };
 
@@ -1104,7 +1108,7 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
                 infcx.tcx.sess.span_bug(
                     span,
                     &format!("Encountered errors `{}` fulfilling during trans",
-                            errors.repr(infcx.tcx))[]);
+                            errors.repr(infcx.tcx)));
             }
         }
     }
@@ -1144,7 +1148,7 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     if substs.types.any(|t| ty::type_needs_infer(*t)) {
             tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
-                                 node, substs.repr(tcx))[]);
+                                 node, substs.repr(tcx)));
         }
 
         monomorphize::apply_param_substs(tcx,
index 7705b53ee38c69ad7a4c74254666fc3901776dbe..c1d22cc973c240c209b88dce5d1d5c8728c2eb70 100644 (file)
@@ -54,7 +54,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
                 _ => cx.sess().span_bug(lit.span,
                         &format!("integer literal has type {} (expected int \
                                  or uint)",
-                                ty_to_string(cx.tcx(), lit_int_ty))[])
+                                ty_to_string(cx.tcx(), lit_int_ty)))
             }
         }
         ast::LitFloat(ref fs, t) => {
@@ -146,13 +146,13 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 (const_deref_ptr(cx, v), mt.ty)
             } else {
                 // Derefing a fat pointer does not change the representation,
-                // just the type to ty_open.
-                (v, ty::mk_open(cx.tcx(), mt.ty))
+                // just the type to the unsized contents.
+                (v, mt.ty)
             }
         }
         None => {
             cx.sess().bug(&format!("unexpected dereferenceable type {}",
-                                   ty_to_string(cx.tcx(), ty))[])
+                                   ty_to_string(cx.tcx(), ty)))
         }
     }
 }
@@ -174,7 +174,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     } else {
         ccx.sess().span_bug(ref_expr.span,
                             &format!("get_const_val given non-constant item {}",
-                                     item.repr(ccx.tcx()))[]);
+                                     item.repr(ccx.tcx())));
     }
 }
 
@@ -193,8 +193,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           -> ValueRef {
     // Special-case constants to cache a common global for all uses.
     match expr.node {
-        ast::ExprPath(_) => {
-            let def = ccx.tcx().def_map.borrow()[expr.id];
+        ast::ExprPath(..) => {
+            let def = ccx.tcx().def_map.borrow()[expr.id].full_def();
             match def {
                 def::DefConst(def_id) => {
                     if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
@@ -290,18 +290,10 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         // an optimisation, it is necessary for mutable vectors to
                         // work properly.
                         ty = match ty::deref(ty, true) {
-                            Some(mt) => {
-                                if type_is_sized(cx.tcx(), mt.ty) {
-                                    mt.ty
-                                } else {
-                                    // Derefing a fat pointer does not change the representation,
-                                    // just the type to ty_open.
-                                    ty::mk_open(cx.tcx(), mt.ty)
-                                }
-                            }
+                            Some(mt) => mt.ty,
                             None => {
                                 cx.sess().bug(&format!("unexpected dereferenceable type {}",
-                                                       ty_to_string(cx.tcx(), ty))[])
+                                                       ty_to_string(cx.tcx(), ty)))
                             }
                         }
                     }
@@ -309,7 +301,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
                 Some(autoref) => {
                     cx.sess().span_bug(e.span,
-                        &format!("unimplemented const first autoref {:?}", autoref)[])
+                        &format!("unimplemented const first autoref {:?}", autoref))
                 }
             };
             match second_autoref {
@@ -319,11 +311,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     llconst = addr_of(cx, llconst, "autoref", e.id);
                 }
                 Some(box ty::AutoUnsize(ref k)) => {
-                    let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
                     let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
                         |t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t));
 
-                    let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to());
+                    let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
+                    let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
+                    let base = ptrcast(llconst, ptr_ty);
                     let prev_const = cx.const_unsized().borrow_mut()
                                        .insert(base, llconst);
                     assert!(prev_const.is_none() || prev_const == Some(llconst));
@@ -333,7 +326,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
                 Some(autoref) => {
                     cx.sess().span_bug(e.span,
-                        &format!("unimplemented const second autoref {:?}", autoref)[])
+                        &format!("unimplemented const second autoref {:?}", autoref))
                 }
             }
         }
@@ -351,7 +344,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         cx.sess().bug(&format!("const {} of type {} has size {} instead of {}",
                          e.repr(cx.tcx()), ty_to_string(cx.tcx(), ety_adjusted),
-                         csize, tsize)[]);
+                         csize, tsize));
     }
     (llconst, ety_adjusted)
 }
@@ -366,7 +359,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     };
     unsafe {
         let _icx = push_ctxt("const_expr");
-        return match e.node {
+        match e.node {
           ast::ExprLit(ref lit) => {
               const_lit(cx, e, &**lit)
           }
@@ -386,7 +379,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let (te2, _) = const_expr(cx, &**e2, param_substs);
             let te2 = base::cast_shift_const_rhs(b, te1, te2);
 
-            return match b.node {
+            match b.node {
               ast::BiAdd   => {
                 if is_float { llvm::LLVMConstFAdd(te1, te2) }
                 else        { llvm::LLVMConstAdd(te1, te2) }
@@ -440,7 +433,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::ExprUnary(u, ref e) => {
             let (te, ty) = const_expr(cx, &**e, param_substs);
             let is_float = ty::type_is_fp(ty);
-            return match u {
+            match u {
               ast::UnUniq | ast::UnDeref => {
                 const_deref(cx, te, ty).0
               }
@@ -477,16 +470,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               };
               let (arr, len) = match bt.sty {
                   ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
-                  ty::ty_open(ty) => match ty.sty {
-                      ty::ty_vec(_, None) | ty::ty_str => {
-                          let e1 = const_get_elt(cx, bv, &[0]);
-                          (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
-                      },
-                      _ => cx.sess().span_bug(base.span,
-                                              &format!("index-expr base must be a vector \
-                                                       or string type, found {}",
-                                                      ty_to_string(cx.tcx(), bt))[])
-                  },
+                  ty::ty_vec(_, None) | ty::ty_str => {
+                      let e1 = const_get_elt(cx, bv, &[0]);
+                      (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
+                  }
                   ty::ty_rptr(_, mt) => match mt.ty.sty {
                       ty::ty_vec(_, Some(u)) => {
                           (const_deref_ptr(cx, bv), C_uint(cx, u))
@@ -494,12 +481,12 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                       _ => cx.sess().span_bug(base.span,
                                               &format!("index-expr base must be a vector \
                                                        or string type, found {}",
-                                                      ty_to_string(cx.tcx(), bt))[])
+                                                      ty_to_string(cx.tcx(), bt)))
                   },
                   _ => cx.sess().span_bug(base.span,
                                           &format!("index-expr base must be a vector \
                                                    or string type, found {}",
-                                                  ty_to_string(cx.tcx(), bt))[])
+                                                  ty_to_string(cx.tcx(), bt)))
               };
 
               let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
@@ -527,8 +514,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             if expr::cast_is_noop(basety, ety) {
                 return v;
             }
-            return match (expr::cast_type_kind(cx.tcx(), basety),
-                           expr::cast_type_kind(cx.tcx(), ety)) {
+            match (expr::cast_type_kind(cx.tcx(), basety),
+                   expr::cast_type_kind(cx.tcx(), ety)) {
 
               (expr::cast_integral, expr::cast_integral) => {
                 let s = ty::type_is_signed(basety) as Bool;
@@ -595,15 +582,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                       _ => break,
                   }
               }
-              let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned();
+              let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
               if let Some(def::DefStatic(def_id, _)) = opt_def {
-                  return get_static_val(cx, def_id, ety);
+                  get_static_val(cx, def_id, ety)
+              } else {
+                  // If this isn't the address of a static, then keep going through
+                  // normal constant evaluation.
+                  let (v, _) = const_expr(cx, &**sub, param_substs);
+                  addr_of(cx, v, "ref", e.id)
               }
-
-              // If this isn't the address of a static, then keep going through
-              // normal constant evaluation.
-              let (v, _) = const_expr(cx, &**sub, param_substs);
-              addr_of(cx, v, "ref", e.id)
           }
           ast::ExprAddrOf(ast::MutMutable, ref sub) => {
               let (v, _) = const_expr(cx, &**sub, param_substs);
@@ -676,10 +663,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 C_array(llunitty, &vs[..])
             }
           }
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
-            let def = cx.tcx().def_map.borrow()[e.id];
+          ast::ExprPath(..) => {
+            let def = cx.tcx().def_map.borrow()[e.id].full_def();
             match def {
-                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
+                def::DefFn(..) | def::DefMethod(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
                 def::DefConst(def_id) => {
@@ -714,7 +701,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           }
           ast::ExprCall(ref callee, ref args) => {
-              let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned();
+              let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def());
               let arg_vals = map_list(&args[..]);
               match opt_def {
                   Some(def::DefStruct(_)) => {
@@ -753,7 +740,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           }
           _ => cx.sess().span_bug(e.span,
                   "bad constant expression type in consts::const_expr")
-        };
+        }
     }
 }
 
index eb07bdb7ba11bb6a860a2c71a1b462f440d196e5..3586a9dda20675bbc89752d0a45f6cd9d6d24750 100644 (file)
@@ -378,7 +378,7 @@ fn new(shared: &SharedCrateContext<'tcx>,
                                           .target
                                           .target
                                           .data_layout
-                                          []);
+                                          );
 
             let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
                 Some(debuginfo::CrateDebugContext::new(llmod))
@@ -731,7 +731,7 @@ pub fn trait_cache(&self) -> &RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>,
     /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
     /// address space on 64-bit ARMv8 and x86_64.
     pub fn obj_size_bound(&self) -> u64 {
-        match &self.sess().target.target.target_pointer_width[] {
+        match &self.sess().target.target.target_pointer_width[..] {
             "32" => 1 << 31,
             "64" => 1 << 47,
             _ => unreachable!() // error handled by config::build_target_config
@@ -741,7 +741,7 @@ pub fn obj_size_bound(&self) -> u64 {
     pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! {
         self.sess().fatal(
             &format!("the type `{}` is too big for the current architecture",
-                    obj.repr(self.tcx()))[])
+                    obj.repr(self.tcx())))
     }
 }
 
index 26e12a1af403dac45981d8bd2e4751c9f60fec69..ad96c506c9ddf14333af894780629a2dc254f47b 100644 (file)
@@ -12,6 +12,7 @@
 use middle::def;
 use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem};
 use trans::base::*;
+use trans::basic_block::BasicBlock;
 use trans::build::*;
 use trans::callee;
 use trans::cleanup::CleanupMethods;
@@ -40,7 +41,7 @@ pub fn trans_stmt<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     debug!("trans_stmt({})", s.repr(cx.tcx()));
 
     if cx.sess().asm_comments() {
-        add_span_comment(cx, s.span, &s.repr(cx.tcx())[]);
+        add_span_comment(cx, s.span, &s.repr(cx.tcx()));
     }
 
     let mut bcx = cx;
@@ -280,6 +281,12 @@ pub fn trans_loop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     fcx.pop_loop_cleanup_scope(loop_expr.id);
 
+    // If there are no predecessors for the next block, we just translated an endless loop and the
+    // next block is unreachable
+    if BasicBlock(next_bcx_in.llbb).pred_iter().next().is_none() {
+        Unreachable(next_bcx_in);
+    }
+
     return next_bcx_in;
 }
 
@@ -299,11 +306,10 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let loop_id = match opt_label {
         None => fcx.top_loop_scope(),
         Some(_) => {
-            match bcx.tcx().def_map.borrow().get(&expr.id) {
-                Some(&def::DefLabel(loop_id)) => loop_id,
-                ref r => {
-                    bcx.tcx().sess.bug(&format!("{:?} in def-map for label",
-                                               r)[])
+            match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def())  {
+                Some(def::DefLabel(loop_id)) => loop_id,
+                r => {
+                    bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
                 }
             }
         }
@@ -368,9 +374,9 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     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[]);
+    let filename = token::intern_and_get_ident(&loc.file.name);
     let filename = C_str_slice(ccx, filename);
-    let line = C_uint(ccx, loc.line);
+    let line = C_u32(ccx, loc.line as u32);
     let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false);
     let expr_file_line = consts::addr_of(ccx, expr_file_line_const,
                                          "panic_loc", call_info.id);
@@ -395,11 +401,11 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // 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[]);
+    let filename = token::intern_and_get_ident(&loc.file.name);
 
     // Invoke the lang item
     let filename = C_str_slice(ccx,  filename);
-    let line = C_uint(ccx, loc.line);
+    let line = C_u32(ccx, loc.line as u32);
     let file_line_const = C_struct(ccx, &[filename, line], false);
     let file_line = consts::addr_of(ccx, file_line_const,
                                     "panic_bounds_check_loc", call_info.id);
index f4a5ba98b676749f76f42b73fc9d19e2001c8efb..8262dbf55ddaefe0ca376064cff207eb648c27d9 100644 (file)
 /// A `Datum` encapsulates the result of evaluating an expression.  It
 /// describes where the value is stored, what Rust type the value has,
 /// whether it is addressed by reference, and so forth. Please refer
-/// the section on datums in `doc.rs` for more details.
+/// the section on datums in `README.md` for more details.
 #[derive(Clone, Copy)]
 pub struct Datum<'tcx, K> {
     /// The llvm value.  This is either a pointer to the Rust value or
@@ -492,8 +492,6 @@ pub fn to_lvalue_datum<'blk>(self,
                                  -> DatumBlock<'blk, 'tcx, Lvalue> {
         debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx()));
 
-        assert!(lltype_is_sized(bcx.tcx(), self.ty),
-                "Trying to convert unsized value to lval");
         self.match_kind(
             |l| DatumBlock::new(bcx, l),
             |r| {
@@ -549,15 +547,10 @@ pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
                                 -> Datum<'tcx, Lvalue> where
         F: FnOnce(ValueRef) -> ValueRef,
     {
-        let val = match self.ty.sty {
-            _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
-            ty::ty_open(_) => {
-                let base = Load(bcx, expr::get_dataptr(bcx, self.val));
-                gep(base)
-            }
-            _ => bcx.tcx().sess.bug(
-                &format!("Unexpected unsized type in get_element: {}",
-                        bcx.ty_to_string(self.ty))[])
+        let val = if type_is_sized(bcx.tcx(), self.ty) {
+            gep(self.val)
+        } else {
+            gep(Load(bcx, expr::get_dataptr(bcx, self.val)))
         };
         Datum {
             val: val,
@@ -566,7 +559,8 @@ pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
         }
     }
 
-    pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) {
+    pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>)
+                                      -> (ValueRef, ValueRef) {
         //! Converts a vector into the slice pair.
 
         tvec::get_base_and_len(bcx, self.val, self.ty)
index fc0129239aac7e9b316749ef013d818c528b7602..d70a904b81189fde012837d6b320799e493eabe5 100644 (file)
@@ -286,7 +286,7 @@ fn register_type_with_metadata<'a>(&mut self,
                                        metadata: DIType) {
         if self.type_to_metadata.insert(type_, metadata).is_some() {
             cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!",
-                                   ppaux::ty_to_string(cx.tcx(), type_))[]);
+                                   ppaux::ty_to_string(cx.tcx(), type_)));
         }
     }
 
@@ -299,7 +299,7 @@ fn register_unique_id_with_metadata(&mut self,
         if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
             let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
             cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!",
-                                  &unique_type_id_str[..])[]);
+                                  &unique_type_id_str[..]));
         }
     }
 
@@ -412,7 +412,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
             ty::ty_vec(inner_type, optional_length) => {
                 match optional_length {
                     Some(len) => {
-                        unique_type_id.push_str(&format!("[{}]", len)[]);
+                        unique_type_id.push_str(&format!("[{}]", len));
                     }
                     None => {
                         unique_type_id.push_str("[]");
@@ -481,8 +481,8 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
             },
             _ => {
                 cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
-                                      &ppaux::ty_to_string(cx.tcx(), type_)[],
-                                      type_.sty)[])
+                                      &ppaux::ty_to_string(cx.tcx(), type_),
+                                      type_.sty))
             }
         };
 
@@ -525,7 +525,7 @@ fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
 
             output.push_str(crate_hash.as_str());
             output.push_str("/");
-            output.push_str(&format!("{:x}", def_id.node)[]);
+            output.push_str(&format!("{:x}", def_id.node));
 
             // Maybe check that there is no self type here.
 
@@ -600,7 +600,7 @@ fn get_unique_type_id_of_enum_variant<'a>(&mut self,
                                               -> UniqueTypeId {
         let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
         let enum_variant_type_id = format!("{}::{}",
-                                           &self.get_unique_type_id_as_string(enum_type_id)[],
+                                           &self.get_unique_type_id_as_string(enum_type_id),
                                            variant_name);
         let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
         UniqueTypeId(interner_key)
@@ -783,19 +783,19 @@ pub fn create_global_var_metadata(cx: &CrateContext,
                                          create_global_var_metadata() -
                                          Captured var-id refers to \
                                          unexpected ast_item variant: {:?}",
-                                        var_item)[])
+                                        var_item))
                 }
             }
         },
         _ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \
                                     - Captured var-id refers to unexpected \
                                     ast_map variant: {:?}",
-                                   var_item)[])
+                                   var_item))
     };
 
     let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
         let loc = span_start(cx, span);
-        (file_metadata(cx, &loc.file.name[]), loc.line as c_uint)
+        (file_metadata(cx, &loc.file.name), loc.line as c_uint)
     } else {
         (UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER)
     };
@@ -847,7 +847,7 @@ pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
             None => {
                 bcx.sess().span_bug(span,
                     &format!("no entry in lllocals table for {}",
-                            node_id)[]);
+                            node_id));
             }
         };
 
@@ -903,7 +903,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                 "debuginfo::create_captured_var_metadata() - \
                                  Captured var-id refers to unexpected \
                                  ast_map variant: {:?}",
-                                 ast_item)[]);
+                                 ast_item));
                 }
             }
         }
@@ -913,7 +913,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         &format!("debuginfo::create_captured_var_metadata() - \
                                  Captured var-id refers to unexpected \
                                  ast_map variant: {:?}",
-                                ast_item)[]);
+                                ast_item));
         }
     };
 
@@ -1025,7 +1025,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
             None => {
                 bcx.sess().span_bug(span,
                     &format!("no entry in lllocals table for {}",
-                            node_id)[]);
+                            node_id));
             }
         };
 
@@ -1319,7 +1319,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     cx.sess()
                       .bug(&format!("create_function_debug_context: \
                                     unexpected sort of node: {:?}",
-                                    fnitem)[])
+                                    fnitem))
                 }
             }
         }
@@ -1330,7 +1330,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         _ => cx.sess().bug(&format!("create_function_debug_context: \
                                     unexpected sort of node: {:?}",
-                                   fnitem)[])
+                                   fnitem))
     };
 
     // This can be the case for functions inlined from another crate
@@ -1339,7 +1339,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     }
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, &loc.file.name[]);
+    let file_metadata = file_metadata(cx, &loc.file.name);
 
     let function_type_metadata = unsafe {
         let fn_signature = get_function_signature(cx,
@@ -1751,7 +1751,7 @@ fn scope_metadata(fcx: &FunctionContext,
 
             fcx.ccx.sess().span_bug(error_reporting_span,
                 &format!("debuginfo: Could not find scope info for node {:?}",
-                        node)[]);
+                        node));
         }
     }
 }
@@ -1947,7 +1947,7 @@ fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult {
                         cx.sess().bug(&format!("Forward declaration of potentially recursive type \
                                               '{}' was not found in TypeMap!",
                                               ppaux::ty_to_string(cx.tcx(), unfinished_type))
-                                      []);
+                                      );
                     }
                 }
 
@@ -2370,7 +2370,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                     .iter()
                                     .map(|&t| type_of::type_of(cx, t))
                                     .collect::<Vec<_>>()
-                                    [],
+                                    ,
                       struct_def.packed);
     // Could do some consistency checks here: size, align, field count, discr type
 
@@ -2437,7 +2437,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
     let loc = span_start(cx, definition_span);
-    let file_metadata = file_metadata(cx, &loc.file.name[]);
+    let file_metadata = file_metadata(cx, &loc.file.name);
 
     let variants = ty::enum_variants(cx.tcx(), enum_def_id);
 
@@ -2624,7 +2624,7 @@ fn set_members_of_composite_type(cx: &CrateContext,
                                         Please use a rustc built with anewer \
                                         version of LLVM.",
                                        llvm_version_major,
-                                       llvm_version_minor)[]);
+                                       llvm_version_minor));
             } else {
                 cx.sess().bug("debuginfo::set_members_of_composite_type() - \
                                Already completed forward declaration re-encountered.");
@@ -2786,7 +2786,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     assert!(member_descriptions.len() == member_llvm_types.len());
 
     let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, &loc.file.name[]);
+    let file_metadata = file_metadata(cx, &loc.file.name);
 
     let metadata = composite_type_metadata(cx,
                                            slice_llvm_type,
@@ -2865,7 +2865,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
             cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
                                    trait_pointer_metadata(): {}",
-                                   &pp_type_name[..])[]);
+                                   &pp_type_name[..]));
         }
     };
 
@@ -3005,7 +3005,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         _ => {
             cx.sess().bug(&format!("debuginfo: unexpected type in type_metadata: {:?}",
-                                  sty)[])
+                                  sty))
         }
     };
 
@@ -3248,7 +3248,7 @@ fn with_new_scope<F>(cx: &CrateContext,
     {
         // Create a new lexical scope and push it onto the stack
         let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
-        let file_metadata = file_metadata(cx, &loc.file.name[]);
+        let file_metadata = file_metadata(cx, &loc.file.name);
         let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
         let scope_metadata = unsafe {
@@ -3370,7 +3370,7 @@ fn walk_pattern(cx: &CrateContext,
                     if need_new_scope {
                         // Create a new lexical scope and push it onto the stack
                         let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
-                        let file_metadata = file_metadata(cx, &loc.file.name[]);
+                        let file_metadata = file_metadata(cx, &loc.file.name);
                         let parent_scope = scope_stack.last().unwrap().scope_metadata;
 
                         let scope_metadata = unsafe {
@@ -3487,8 +3487,7 @@ fn walk_expr(cx: &CrateContext,
             ast::ExprLit(_)   |
             ast::ExprBreak(_) |
             ast::ExprAgain(_) |
-            ast::ExprPath(_)  |
-            ast::ExprQPath(_) => {}
+            ast::ExprPath(..) => {}
 
             ast::ExprCast(ref sub_exp, _)     |
             ast::ExprAddrOf(_, ref sub_exp)  |
@@ -3828,11 +3827,10 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         ty::ty_err |
         ty::ty_infer(_) |
-        ty::ty_open(_) |
         ty::ty_projection(..) |
         ty::ty_param(_) => {
             cx.sess().bug(&format!("debuginfo: Trying to create type name for \
-                unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]);
+                unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)));
         }
     }
 
@@ -3915,13 +3913,13 @@ fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
                 None => {}
             }
             let string = token::get_name(node.name);
-            output.push_str(&format!("{}", string.len())[]);
+            output.push_str(&format!("{}", string.len()));
             output.push_str(&string);
         }
 
         let mut name = String::from_str("_ZN");
         fill_nested(self, &mut name);
-        name.push_str(&format!("{}", item_name.len())[]);
+        name.push_str(&format!("{}", item_name.len()));
         name.push_str(item_name);
         name.push('E');
         name
@@ -3929,7 +3927,7 @@ fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
 }
 
 fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
-    &cx.link_meta().crate_name[]
+    &cx.link_meta().crate_name
 }
 
 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
@@ -4005,7 +4003,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
             None => {
                 cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
                                        path too short for {:?}",
-                                      def_id)[]);
+                                      def_id));
             }
         }
     })
index 1af9fa87c6b7d2f6fd7bf31ce2877ebe46ecb36c..5cc1baf66c6219806e17520f42b2e224413ea45f 100644 (file)
@@ -143,7 +143,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // it prefers in-place instantiation, likely because it contains
             // `[x; N]` somewhere within.
             match expr.node {
-                ast::ExprPath(_) | ast::ExprQPath(_) => {
+                ast::ExprPath(..) => {
                     match bcx.def(expr.id) {
                         def::DefConst(did) => {
                             let expr = consts::get_const_expr(bcx.ccx(), did, expr);
@@ -308,7 +308,7 @@ fn identity<T>(t: T) -> T { t }
                 unsized_info(ccx, k, id, ty_substs[tp_index], param_substs, identity)
             }
             _ => ccx.sess().bug(&format!("UnsizeStruct with bad sty: {}",
-                                         unadjusted_ty.repr(ccx.tcx()))[])
+                                         unadjusted_ty.repr(ccx.tcx())))
         },
         &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => {
             // Note that we preserve binding levels here:
@@ -451,8 +451,6 @@ fn unsize_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let datum_ty = datum.ty;
         let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
         debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx()));
-        let dest_ty = ty::mk_open(tcx, unsized_ty);
-        debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
 
         let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs,
                                 |t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t));
@@ -462,20 +460,16 @@ fn unsize_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                  datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
         // Compute the base pointer. This doesn't change the pointer value,
         // but merely its type.
-        let base = match *k {
-            ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => {
-                PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
-            }
-            ty::UnsizeLength(..) => {
-                GEPi(bcx, lval.val, &[0, 0])
-            }
-        };
+        let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to();
+        let base = PointerCast(bcx, lval.val, ptr_ty);
 
-        let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
-        Store(bcx, base, get_dataptr(bcx, scratch.val));
-        Store(bcx, info, get_len(bcx, scratch.val));
+        let llty = type_of::type_of(bcx.ccx(), unsized_ty);
+        // HACK(eddyb) get around issues with lifetime intrinsics.
+        let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr");
+        Store(bcx, base, get_dataptr(bcx, scratch));
+        Store(bcx, info, get_len(bcx, scratch));
 
-        DatumBlock::new(bcx, scratch.to_expr_datum())
+        DatumBlock::new(bcx, Datum::new(scratch, unsized_ty, LvalueExpr))
     }
 
     fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -524,7 +518,7 @@ fn unsize_unique_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let unboxed_ty = match datum_ty.sty {
             ty::ty_uniq(t) => t,
             _ => bcx.sess().bug(&format!("Expected ty_uniq, found {}",
-                                        bcx.ty_to_string(datum_ty))[])
+                                        bcx.ty_to_string(datum_ty)))
         };
         let result_ty = ty::mk_uniq(tcx, ty::unsize_ty(tcx, unboxed_ty, k, expr.span));
 
@@ -635,7 +629,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans(bcx, &**e)
         }
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             trans_def(bcx, expr, bcx.def(expr.id))
         }
         ast::ExprField(ref base, ident) => {
@@ -696,7 +690,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 expr.span,
                 &format!("trans_rvalue_datum_unadjusted reached \
                          fall-through case: {:?}",
-                        expr.node)[]);
+                        expr.node));
         }
     }
 }
@@ -711,7 +705,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_rec_field");
 
     let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
-    let bare_ty = ty::unopen_type(base_datum.ty);
+    let bare_ty = base_datum.ty;
     let repr = adt::represent_type(bcx.ccx(), bare_ty);
     with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
         let ix = get_idx(bcx.tcx(), field_tys);
@@ -723,7 +717,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         if type_is_sized(bcx.tcx(), d.ty) {
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
         } else {
-            let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), "");
+            let scratch = rvalue_scratch_datum(bcx, d.ty, "");
             Store(bcx, d.val, get_dataptr(bcx, scratch.val));
             let info = Load(bcx, get_len(bcx, base_datum.val));
             Store(bcx, info, get_len(bcx, scratch.val));
@@ -809,7 +803,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             if type_is_sized(bcx.tcx(), elt_ty) {
                 Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
             } else {
-                Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr)
+                Datum::new(datum.val, elt_ty, LvalueExpr)
             }
         }
         None => {
@@ -881,7 +875,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let _icx = push_ctxt("trans_def_lvalue");
     match def {
-        def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) |
+        def::DefFn(..) | def::DefMethod(..) |
         def::DefStruct(_) | def::DefVariant(..) => {
             let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
                                                 bcx.fcx.param_substs);
@@ -1020,7 +1014,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 expr.span,
                 &format!("trans_rvalue_stmt_unadjusted reached \
                          fall-through case: {:?}",
-                        expr.node)[]);
+                        expr.node));
         }
     }
 }
@@ -1039,7 +1033,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans_into(bcx, &**e, dest)
         }
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
         ast::ExprIf(ref cond, ref thn, ref els) => {
@@ -1216,7 +1210,7 @@ fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
                 expr.span,
                 &format!("trans_rvalue_dps_unadjusted reached fall-through \
                          case: {:?}",
-                        expr.node)[]);
+                        expr.node));
         }
     }
 }
@@ -1266,7 +1260,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         _ => {
             bcx.tcx().sess.span_bug(ref_expr.span, &format!(
                 "Non-DPS def {:?} referened by {}",
-                def, bcx.node_id_to_string(ref_expr.id))[]);
+                def, bcx.node_id_to_string(ref_expr.id)));
         }
     }
 }
@@ -1281,12 +1275,10 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     match def {
         def::DefFn(did, _) |
         def::DefStruct(did) | def::DefVariant(_, did, _) |
-        def::DefStaticMethod(did, def::FromImpl(_)) |
-        def::DefMethod(did, _, def::FromImpl(_)) => {
+        def::DefMethod(did, def::FromImpl(_)) => {
             callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
         }
-        def::DefStaticMethod(impl_did, def::FromTrait(trait_did)) |
-        def::DefMethod(impl_did, _, def::FromTrait(trait_did)) => {
+        def::DefMethod(impl_did, def::FromTrait(trait_did)) => {
             meth::trans_static_method_callee(ccx, impl_did,
                                              trait_did, ref_expr.id,
                                              param_substs)
@@ -1295,7 +1287,7 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             ccx.tcx().sess.span_bug(ref_expr.span, &format!(
                     "trans_def_fn_unadjusted invoked on: {:?} for {}",
                     def,
-                    ref_expr.repr(ccx.tcx()))[]);
+                    ref_expr.repr(ccx.tcx())));
         }
     }
 }
@@ -1315,7 +1307,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 None => {
                     bcx.sess().bug(&format!(
                         "trans_local_var: no llval for upvar {} found",
-                        nid)[]);
+                        nid));
                 }
             }
         }
@@ -1325,7 +1317,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 None => {
                     bcx.sess().bug(&format!(
                         "trans_local_var: no datum for local/arg {} found",
-                        nid)[]);
+                        nid));
                 }
             };
             debug!("take_local(nid={}, v={}, ty={})",
@@ -1335,7 +1327,7 @@ pub fn trans_local_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         _ => {
             bcx.sess().unimpl(&format!(
                 "unsupported def type in trans_local_var: {:?}",
-                def)[]);
+                def));
         }
     }
 }
@@ -1358,7 +1350,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
         }
 
         ty::ty_tup(ref v) => {
-            op(0, &tup_fields(&v[..])[])
+            op(0, &tup_fields(&v[..]))
         }
 
         ty::ty_enum(_, substs) => {
@@ -1368,10 +1360,10 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
                     tcx.sess.bug(&format!(
                         "cannot get field types from the enum type {} \
                          without a node ID",
-                        ty.repr(tcx))[]);
+                        ty.repr(tcx)));
                 }
                 Some(node_id) => {
-                    let def = tcx.def_map.borrow()[node_id].clone();
+                    let def = tcx.def_map.borrow()[node_id].full_def();
                     match def {
                         def::DefVariant(enum_id, variant_id, _) => {
                             let variant_info = ty::enum_variant_with_id(
@@ -1392,7 +1384,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
         _ => {
             tcx.sess.bug(&format!(
                 "cannot get field types from the type {}",
-                ty.repr(tcx))[]);
+                ty.repr(tcx)));
         }
     }
 }
@@ -1671,7 +1663,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                            lval: Datum<'tcx, Lvalue>)
                            -> DatumBlock<'blk, 'tcx, Expr> {
-    let dest_ty = ty::close_type(bcx.tcx(), lval.ty);
+    let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty);
     let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
     memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
 
@@ -1685,16 +1677,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
     let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
-    match sub_datum.ty.sty {
-        ty::ty_open(_) => {
-            // Opened DST value, close to a fat pointer
-            ref_fat_ptr(bcx, sub_datum)
-        }
-        _ => {
-            // Sized value, ref to a thin pointer
-            let ty = expr_ty(bcx, expr);
-            immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
-        }
+    if !type_is_sized(bcx.tcx(), sub_datum.ty) {
+        // DST lvalue, close to a fat pointer
+        ref_fat_ptr(bcx, sub_datum)
+    } else {
+        // Sized value, ref to a thin pointer
+        let ty = expr_ty(bcx, expr);
+        immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
     }
 }
 
@@ -2097,7 +2086,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                             t_in.repr(bcx.tcx()),
                                             k_in,
                                             t_out.repr(bcx.tcx()),
-                                            k_out)[])
+                                            k_out))
                 }
             }
         }
@@ -2106,7 +2095,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     t_in.repr(bcx.tcx()),
                                     k_in,
                                     t_out.repr(bcx.tcx()),
-                                    k_out)[])
+                                    k_out))
     };
     return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock();
 }
@@ -2234,16 +2223,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             if type_is_sized(bcx.tcx(), content_ty) {
                 deref_owned_pointer(bcx, expr, datum, content_ty)
             } else {
-                // A fat pointer and an opened DST value have the same
-                // representation just different types. Since there is no
-                // temporary for `*e` here (because it is unsized), we cannot
-                // emulate the sized object code path for running drop glue and
-                // free. Instead, we schedule cleanup for `e`, turning it into
-                // an lvalue.
+                // A fat pointer and a DST lvalue have the same representation
+                // just different types. Since there is no temporary for `*e`
+                // here (because it is unsized), we cannot emulate the sized
+                // object code path for running drop glue and free. Instead,
+                // we schedule cleanup for `e`, turning it into an lvalue.
                 let datum = unpack_datum!(
                     bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
 
-                let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr);
+                let datum = Datum::new(datum.val, content_ty, LvalueExpr);
                 DatumBlock::new(bcx, datum)
             }
         }
@@ -2260,11 +2248,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // owner (or, in the case of *T, by the user).
                 DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
             } else {
-                // A fat pointer and an opened DST value have the same representation
+                // A fat pointer and a DST lvalue have the same representation
                 // just different types.
-                DatumBlock::new(bcx, Datum::new(datum.val,
-                                                ty::mk_open(bcx.tcx(), content_ty),
-                                                LvalueExpr))
+                DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr))
             }
         }
 
@@ -2272,7 +2258,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             bcx.tcx().sess.span_bug(
                 expr.span,
                 &format!("deref invoked on expr of illegal type {}",
-                        datum.ty.repr(bcx.tcx()))[]);
+                        datum.ty.repr(bcx.tcx())));
         }
     };
 
index 4508fe21a65fadb90abcf37975190fd609b13139..efae76c5ef41c76027b149666d001858e9f058ae 100644 (file)
@@ -111,7 +111,7 @@ pub fn register_static(ccx: &CrateContext,
     let llty = type_of::type_of(ccx, ty);
 
     let ident = link_name(foreign_item);
-    match attr::first_attr_value_str_by_name(&foreign_item.attrs[],
+    match attr::first_attr_value_str_by_name(&foreign_item.attrs,
                                              "linkage") {
         // If this is a static with a linkage specified, then we need to handle
         // it a little specially. The typesystem prevents things like &T and
@@ -240,11 +240,11 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
     let fn_type = cabi::compute_abi_info(ccx,
-                                         &llsig.llarg_tys[],
+                                         &llsig.llarg_tys,
                                          llsig.llret_ty,
                                          llsig.ret_def);
 
-    let arg_tys: &[cabi::ArgType] = &fn_type.arg_tys[];
+    let arg_tys: &[cabi::ArgType] = &fn_type.arg_tys;
 
     let mut llargs_foreign = Vec::new();
 
@@ -439,7 +439,7 @@ fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
                 tcx.sess.span_err(ast_ty.span,
                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
                                         may result in invalid code",
-                                       pprust::ty_to_string(ast_ty))[]);
+                                       pprust::ty_to_string(ast_ty)));
                 tcx.sess.span_help(ast_ty.span,
                                    "add #![feature(simd_ffi)] to the crate attributes to enable");
             }
@@ -603,7 +603,7 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 ccx.sess().bug(&format!("build_rust_fn: extern fn {} has ty {}, \
                                         expected a bare fn ty",
                                        ccx.tcx().map.path_to_string(id),
-                                       t.repr(tcx))[]);
+                                       t.repr(tcx)));
             }
         };
 
@@ -868,9 +868,9 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 // the massive simplifications that have occurred.
 
 pub fn link_name(i: &ast::ForeignItem) -> InternedString {
-    match attr::first_attr_value_str_by_name(&i.attrs[], "link_name") {
+    match attr::first_attr_value_str_by_name(&i.attrs, "link_name") {
         Some(ln) => ln.clone(),
-        None => match weak_lang_items::link_name(&i.attrs[]) {
+        None => match weak_lang_items::link_name(&i.attrs) {
             Some(name) => name,
             None => token::get_ident(i.ident),
         }
@@ -913,7 +913,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs);
     let fn_ty = cabi::compute_abi_info(ccx,
-                                       &llsig.llarg_tys[],
+                                       &llsig.llarg_tys,
                                        llsig.llret_ty,
                                        llsig.ret_def);
     debug!("foreign_types_for_fn_ty(\
@@ -922,7 +922,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            fn_ty={} -> {}, \
            ret_def={}",
            ty.repr(ccx.tcx()),
-           ccx.tn().types_to_str(&llsig.llarg_tys[]),
+           ccx.tn().types_to_str(&llsig.llarg_tys),
            ccx.tn().type_to_string(llsig.llret_ty),
            ccx.tn().types_to_str(&fn_ty.arg_tys.iter().map(|t| t.ty).collect::<Vec<_>>()),
            ccx.tn().type_to_string(fn_ty.ret_ty.ty),
index 268b65c6ceb30c14f9af1889c890a870712e7fd8..c14683aeade058407b940b8a4f61ee856e5f7536 100644 (file)
@@ -34,7 +34,7 @@
 use trans::machine::*;
 use trans::tvec;
 use trans::type_::Type;
-use trans::type_of::{type_of, sizing_type_of, align_of};
+use trans::type_of::{self, type_of, sizing_type_of, align_of};
 use middle::ty::{self, Ty};
 use util::ppaux::{ty_to_short_str, Repr};
 use util::ppaux;
@@ -243,7 +243,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             sig.inputs[0]
         }
         _ => bcx.sess().bug(&format!("Expected function type, found {}",
-                                    bcx.ty_to_string(fty))[])
+                                    bcx.ty_to_string(fty)))
     };
 
     let (struct_data, info) = if type_is_sized(bcx.tcx(), t) {
@@ -265,8 +265,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         assert_eq!(params.len(), 1);
         let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
             // The dtor expects a fat pointer, so make one, even if we have to fake it.
-            let boxed_ty = ty::mk_open(bcx.tcx(), t);
-            let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self");
+            let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
             Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
             Store(bcx,
                   // If we just had a thin pointer, make a fat pointer by sticking
@@ -284,20 +283,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // Add all the fields as a value which needs to be cleaned at the end of
         // this scope. Iterate in reverse order so a Drop impl doesn't reverse
         // the order in which fields get dropped.
-        for (i, ty) in st.fields.iter().enumerate().rev() {
+        for (i, &ty) in st.fields.iter().enumerate().rev() {
             let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
 
-            let val = if type_is_sized(bcx.tcx(), *ty) {
+            let val = if type_is_sized(bcx.tcx(), ty) {
                 llfld_a
             } else {
-                let boxed_ty = ty::mk_open(bcx.tcx(), *ty);
-                let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field");
+                let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field");
                 Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
                 Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
                 scratch.val
             };
-            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
-                                             val, *ty);
+            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty);
         }
 
         let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
@@ -370,7 +367,7 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info:
              C_uint(bcx.ccx(), unit_align))
         }
         _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}",
-                                    bcx.ty_to_string(t))[])
+                                    bcx.ty_to_string(t)))
     }
 }
 
@@ -443,7 +440,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                         bcx.sess().warn(&format!("Ignoring drop flag in destructor for {}\
                                                  because the struct is unsized. See issue\
                                                  #16758",
-                                                bcx.ty_to_string(t))[]);
+                                                bcx.ty_to_string(t)));
                         trans_struct_drop(bcx, t, v0, dtor, did, substs)
                     }
                 }
@@ -502,7 +499,10 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     // tydescs.
     assert!(!ccx.finished_tydescs().get());
 
-    let llty = type_of(ccx, t);
+    // This really shouldn't be like this, size/align will be wrong for
+    // unsized types (i.e. [T] will have the size/align of T).
+    // But we need it until we split this out into a "type name" intrinsic.
+    let llty = type_of::in_memory_type_of(ccx, t);
 
     if ccx.sess().count_type_sizes() {
         println!("{}\t{}", llsize_of_real(ccx, llty),
@@ -521,7 +521,7 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     note_unique_llvm_symbol(ccx, name);
 
     let ty_name = token::intern_and_get_ident(
-        &ppaux::ty_to_string(ccx.tcx(), t)[]);
+        &ppaux::ty_to_string(ccx.tcx(), t));
     let ty_name = C_str_slice(ccx, ty_name);
 
     debug!("--- declare_tydesc {}", ppaux::ty_to_string(ccx.tcx(), t));
@@ -540,7 +540,7 @@ fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
     let fn_nm = mangle_internal_name_by_type_and_seq(
         ccx,
         t,
-        &format!("glue_{}", name)[]);
+        &format!("glue_{}", name));
     let llfn = decl_cdecl_fn(ccx, &fn_nm[..], llfnty, ty::mk_nil(ccx.tcx()));
     note_unique_llvm_symbol(ccx, fn_nm.clone());
     return (fn_nm, llfn);
index a1b66ed94f06bc8dfed134ea44cace4fd76e274d..993c9eae45bf6326f016693dea46bb25dfe043ec 100644 (file)
@@ -36,7 +36,7 @@
 use util::ppaux::{Repr, ty_to_string};
 
 pub fn get_simple_intrinsic(ccx: &CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
-    let name = match &token::get_ident(item.ident)[] {
+    let name = match &token::get_ident(item.ident)[..] {
         "sqrtf32" => "llvm.sqrt.f32",
         "sqrtf64" => "llvm.sqrt.f64",
         "powif32" => "llvm.powi.f32",
index 1d5d24a64036dd6d69760ae564c7ce8dc6595f49..3411f12886d2266c959bfecb0f1a5d6975045e6b 100644 (file)
@@ -79,7 +79,7 @@ pub fn trans_impl(ccx: &CrateContext,
         match *impl_item {
             ast::MethodImplItem(ref method) => {
                 if method.pe_generics().ty_params.len() == 0 {
-                    let trans_everywhere = attr::requests_inline(&method.attrs[]);
+                    let trans_everywhere = attr::requests_inline(&method.attrs);
                     for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
                         let llfn = get_item_val(ccx, method.id);
                         let empty_substs = tcx.mk_substs(Substs::trans_empty());
@@ -305,7 +305,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
         _ => {
             tcx.sess.bug(&format!("static call to invalid vtable: {}",
-                                 vtbl.repr(tcx))[]);
+                                 vtbl.repr(tcx)));
         }
     }
 }
@@ -390,10 +390,11 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             Callee { bcx: bcx, data: Fn(llfn) }
         }
         traits::VtableBuiltin(..) |
+        traits::VtableDefaultImpl(..) |
         traits::VtableParam(..) => {
             bcx.sess().bug(
                 &format!("resolved vtable bad vtable {} in trans",
-                        vtable.repr(bcx.tcx()))[]);
+                        vtable.repr(bcx.tcx())));
         }
     }
 }
@@ -714,6 +715,8 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let methods = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| {
         let vtable = fulfill_obligation(ccx, DUMMY_SP, trait_ref.clone());
         match vtable {
+            // Should default trait error here?
+            traits::VtableDefaultImpl(_) |
             traits::VtableBuiltin(_) => {
                 Vec::new().into_iter()
             }
@@ -749,7 +752,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 tcx.sess.bug(
                     &format!("resolved vtable for {} to bad vtable {} in trans",
                             trait_ref.repr(tcx),
-                            vtable.repr(tcx))[]);
+                            vtable.repr(tcx)));
             }
         }
     });
@@ -815,9 +818,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                         param_substs,
                         substs.clone()).val;
 
-                    // currently, at least, by-value self is not object safe
-                    assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
-
                     Some(fn_ref).into_iter()
                 }
             }
index ec48ab0d34a06b60d84d5312084649225a4816bd..5ab1ec2a69eda56f5aef11c173feae75c06871d2 100644 (file)
@@ -177,7 +177,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                   ..
               } => {
                   let d = mk_lldecl(abi);
-                  let needs_body = setup_lldecl(d, &i.attrs[]);
+                  let needs_body = setup_lldecl(d, &i.attrs);
                   if needs_body {
                       if abi != abi::Rust {
                           foreign::trans_rust_fn_with_foreign_abi(
@@ -220,7 +220,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             match *ii {
                 ast::MethodImplItem(ref mth) => {
                     let d = mk_lldecl(abi::Rust);
-                    let needs_body = setup_lldecl(d, &mth.attrs[]);
+                    let needs_body = setup_lldecl(d, &mth.attrs);
                     if needs_body {
                         trans_fn(ccx,
                                  mth.pe_fn_decl(),
@@ -241,7 +241,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             match *method {
                 ast::ProvidedMethod(ref mth) => {
                     let d = mk_lldecl(abi::Rust);
-                    let needs_body = setup_lldecl(d, &mth.attrs[]);
+                    let needs_body = setup_lldecl(d, &mth.attrs);
                     if needs_body {
                         trans_fn(ccx, mth.pe_fn_decl(), mth.pe_body(), d,
                                  psubsts, mth.id, &[]);
@@ -250,7 +250,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 }
                 _ => {
                     ccx.sess().bug(&format!("can't monomorphize a {:?}",
-                                           map_node)[])
+                                           map_node))
                 }
             }
         }
@@ -258,7 +258,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let d = mk_lldecl(abi::Rust);
             set_inline_hint(d);
             base::trans_tuple_struct(ccx,
-                                     &struct_def.fields[],
+                                     &struct_def.fields,
                                      struct_def.ctor_id.expect("ast-mapped tuple struct \
                                                                 didn't have a ctor id"),
                                      psubsts,
@@ -276,7 +276,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ast_map::NodePat(..) |
         ast_map::NodeLocal(..) => {
             ccx.sess().bug(&format!("can't monomorphize a {:?}",
-                                   map_node)[])
+                                   map_node))
         }
     };
 
index 7b59e0258ee224c4ec6cdd91e4c012afa800c072..d3acd23e6416d8537fbd4e2e356019af8f5a50a5 100644 (file)
@@ -372,38 +372,31 @@ pub fn get_fixed_base_and_len(bcx: Block,
     (base, len)
 }
 
-fn get_slice_base_and_len(bcx: Block,
-                          llval: ValueRef)
-                          -> (ValueRef, ValueRef) {
-    let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
-    let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
-    (base, len)
-}
-
 /// Converts a vector into the slice pair.  The vector should be stored in `llval` which should be
 /// by-reference.  If you have a datum, you would probably prefer to call
 /// `Datum::get_base_and_len()` which will handle any conversions for you.
-pub fn get_base_and_len(bcx: Block,
-                        llval: ValueRef,
-                        vec_ty: Ty)
-                        -> (ValueRef, ValueRef) {
+pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                    llval: ValueRef,
+                                    vec_ty: Ty<'tcx>)
+                                    -> (ValueRef, ValueRef) {
     let ccx = bcx.ccx();
 
     match vec_ty.sty {
         ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
-        ty::ty_open(ty) => match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
-            _ => ccx.sess().bug("unexpected type in get_base_and_len")
-        },
+        ty::ty_vec(_, None) | ty::ty_str => {
+            let base = Load(bcx, expr::get_dataptr(bcx, llval));
+            let len = Load(bcx, expr::get_len(bcx, llval));
+            (base, len)
+        }
 
         // Only used for pattern matching.
-        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
-            ty::ty_vec(_, Some(n)) => {
-                let base = GEPi(bcx, Load(bcx, llval), &[0, 0]);
-                (base, C_uint(ccx, n))
-            }
-            _ => ccx.sess().bug("unexpected type in get_base_and_len"),
+        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+            let inner = if type_is_sized(bcx.tcx(), ty) {
+                Load(bcx, llval)
+            } else {
+                llval
+            };
+            get_base_and_len(bcx, inner, ty)
         },
         _ => ccx.sess().bug("unexpected type in get_base_and_len"),
     }
index ad83135a0d46fa3681df8b6f4d6bc2cb8b7d7d64..d5ec18e641b7963de9a11ff5cfb71f36f785c8e2 100644 (file)
@@ -109,7 +109,7 @@ pub fn i8p(ccx: &CrateContext) -> Type {
     }
 
     pub fn int(ccx: &CrateContext) -> Type {
-        match &ccx.tcx().sess.target.target.target_pointer_width[] {
+        match &ccx.tcx().sess.target.target.target_pointer_width[..] {
             "32" => Type::i32(ccx),
             "64" => Type::i64(ccx),
             tws => panic!("Unsupported target word size for int: {}", tws),
@@ -232,14 +232,6 @@ pub fn vtable_ptr(ccx: &CrateContext) -> Type {
         Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
     }
 
-    pub fn opaque_trait(ccx: &CrateContext) -> Type {
-        Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false)
-    }
-
-    pub fn opaque_trait_data(ccx: &CrateContext) -> Type {
-        Type::i8(ccx)
-    }
-
     pub fn kind(&self) -> TypeKind {
         unsafe {
             llvm::LLVMGetTypeKind(self.to_ref())
index 489b56bbe6825f567968c2bc802549a21fcaf34b..97278eb0512e226ea0018c27258bbe79ed42ccd1 100644 (file)
@@ -10,8 +10,6 @@
 
 #![allow(non_camel_case_types)]
 
-pub use self::named_ty::*;
-
 use middle::subst;
 use trans::adt;
 use trans::common::*;
@@ -183,9 +181,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     }
 
     let llsizingty = match t.sty {
-        _ if !lltype_is_sized(cx.tcx(), t) => {
-            cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type",
-                                  ppaux::ty_to_string(cx.tcx(), t))[])
+        _ if !type_is_sized(cx.tcx(), t) => {
+            Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
         }
 
         ty::ty_bool => Type::bool(cx),
@@ -232,15 +229,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::ty_open(_) => {
-            Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
-        }
-
         ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
             cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
-                                  ppaux::ty_to_string(cx.tcx(), t))[])
+                                  ppaux::ty_to_string(cx.tcx(), t)))
         }
-        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable")
+        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
     };
 
     cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
@@ -270,25 +263,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     }
 }
 
-// NB: If you update this, be sure to update `sizing_type_of()` as well.
-pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-        // It is possible to end up here with a sized type. This happens with a
-        // struct which might be unsized, but is monomorphised to a sized type.
-        // In this case we'll fake a fat pointer with no unsize info (we use 0).
-        // However, its still a fat pointer, so we need some type use.
-        if type_is_sized(cx.tcx(), t) {
-            return Type::i8p(cx);
-        }
-
-        match unsized_part_of_type(cx.tcx(), t).sty {
-            ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)),
-            ty::ty_trait(_) => Type::vtable_ptr(cx),
-            _ => panic!("Unexpected type returned from unsized_part_of_type : {}",
-                       t.repr(cx.tcx()))
-        }
-    }
+/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
+/// This is the right LLVM type for an alloca containg a value of that type,
+/// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
+/// For unsized types, the returned type is a fat pointer, thus the resulting
+/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
+/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
+/// This is needed due to the treatment of immediate values, as a fat pointer
+/// is too large for it to be placed in SSA value (by our rules).
+/// For the raw type without far pointer indirection, see `in_memory_type_of`.
+pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
+    let ty = if !type_is_sized(cx.tcx(), ty) {
+        ty::mk_imm_ptr(cx.tcx(), ty)
+    } else {
+        ty
+    };
+    in_memory_type_of(cx, ty)
+}
 
+/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
+/// This is the right LLVM type for a field/array element of that type,
+/// and is the same as `type_of` for all Sized types.
+/// Unsized types, however, are represented by a "minimal unit", e.g.
+/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
+/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
+/// If the type is an unsized struct, the regular layout is generated,
+/// with the inner-most trailing unsized field using the "minimal unit"
+/// of that field's type - this is useful for taking the address of
+/// that field and ensuring the struct has the right alignment.
+/// For the LLVM type of a value as a whole, see `type_of`.
+/// NB: If you update this, be sure to update `sizing_type_of()` as well.
+pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     // Check the cache.
     match cx.lltypes().borrow().get(&t) {
         Some(&llty) => return llty,
@@ -307,7 +312,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
     let t_norm = erase_regions(cx.tcx(), &t);
 
     if t != t_norm {
-        let llty = type_of(cx, t_norm);
+        let llty = in_memory_type_of(cx, t_norm);
         debug!("--> normalized {} {:?} to {} {:?} llty={}",
                 t.repr(cx.tcx()),
                 t,
@@ -331,10 +336,10 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
           // of the enum's variants refers to the enum itself.
           let repr = adt::represent_type(cx, t);
           let tps = substs.types.get_slice(subst::TypeSpace);
-          let name = llvm_type_name(cx, an_enum, did, tps);
+          let name = llvm_type_name(cx, did, tps);
           adt::incomplete_type_of(cx, &*repr, &name[..])
       }
-      ty::ty_closure(did, _, ref substs) => {
+      ty::ty_closure(..) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache.
           let repr = adt::represent_type(cx, t);
@@ -342,41 +347,47 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
           // inherited from their environment, so we use entire
           // contents of the VecPerParamSpace to to construct the llvm
           // name
-          let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice());
-          adt::incomplete_type_of(cx, &*repr, &name[..])
+          adt::incomplete_type_of(cx, &*repr, "closure")
       }
 
       ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
-          match ty.sty {
-              ty::ty_str => {
+          if !type_is_sized(cx.tcx(), ty) {
+              if let ty::ty_str = ty.sty {
                   // This means we get a nicer name in the output (str is always
                   // unsized).
                   cx.tn().find_type("str_slice").unwrap()
+              } else {
+                  let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
+                  let unsized_part = unsized_part_of_type(cx.tcx(), ty);
+                  let info_ty = match unsized_part.sty {
+                      ty::ty_str | ty::ty_vec(..) => {
+                          Type::uint_from_ty(cx, ast::TyUs(false))
+                      }
+                      ty::ty_trait(_) => Type::vtable_ptr(cx),
+                      _ => panic!("Unexpected type returned from \
+                                   unsized_part_of_type: {} for ty={}",
+                                  unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
+                  };
+                  Type::struct_(cx, &[ptr_ty, info_ty], false)
               }
-              ty::ty_trait(..) => Type::opaque_trait(cx),
-              _ if !type_is_sized(cx.tcx(), ty) => {
-                  let p_ty = type_of(cx, ty).ptr_to();
-                  Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false)
-              }
-              _ => type_of(cx, ty).ptr_to(),
+          } else {
+              in_memory_type_of(cx, ty).ptr_to()
           }
       }
 
       ty::ty_vec(ty, Some(size)) => {
           let size = size as u64;
-          let llty = type_of(cx, ty);
+          let llty = in_memory_type_of(cx, ty);
           ensure_array_fits_in_address_space(cx, llty, size, t);
           Type::array(&llty, size)
       }
-      ty::ty_vec(ty, None) => {
-          type_of(cx, ty)
-      }
 
-      ty::ty_trait(..) => {
-          Type::opaque_trait_data(cx)
-      }
-
-      ty::ty_str => Type::i8(cx),
+      // Unsized slice types (and str) have the type of their element, and
+      // traits have the type of u8. This is so that the data pointer inside
+      // fat pointers is of the right type (e.g. for array accesses), even
+      // when taking the address of an unsized field in a struct.
+      ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
+      ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
 
       ty::ty_bare_fn(..) => {
           type_of_fn_from_ty(cx, t).ptr_to()
@@ -388,7 +399,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
       }
       ty::ty_struct(did, ref substs) => {
           if ty::type_is_simd(cx.tcx(), t) {
-              let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
+              let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
               let n = ty::simd_size(cx.tcx(), t) as u64;
               ensure_array_fits_in_address_space(cx, llet, n, t);
               Type::vector(&llet, n)
@@ -398,29 +409,11 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
               // infinite recursion with recursive struct types.
               let repr = adt::represent_type(cx, t);
               let tps = substs.types.get_slice(subst::TypeSpace);
-              let name = llvm_type_name(cx, a_struct, did, tps);
+              let name = llvm_type_name(cx, did, tps);
               adt::incomplete_type_of(cx, &*repr, &name[..])
           }
       }
 
-      ty::ty_open(t) => match t.sty {
-          ty::ty_struct(..) => {
-              let p_ty = type_of(cx, t).ptr_to();
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_vec(ty, None) => {
-              let p_ty = type_of(cx, ty).ptr_to();
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_str => {
-              let p_ty = Type::i8p(cx);
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_trait(..) => Type::opaque_trait(cx),
-          _ => cx.sess().bug(&format!("ty_open with sized type: {}",
-                                     ppaux::ty_to_string(cx.tcx(), t))[])
-      },
-
       ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
       ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
       ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
@@ -444,7 +437,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
         _ => ()
     }
 
-    return llty;
+    llty
 }
 
 pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
@@ -453,37 +446,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     machine::llalign_of_min(cx, llty)
 }
 
-// Want refinements! (Or case classes, I guess
-#[derive(Copy)]
-pub enum named_ty {
-    a_struct,
-    an_enum,
-    a_closure,
-}
-
-pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                what: named_ty,
-                                did: ast::DefId,
-                                tps: &[Ty<'tcx>])
-                                -> String {
-    let name = match what {
-        a_struct => "struct",
-        an_enum => "enum",
-        a_closure => return "closure".to_string(),
-    };
-
+fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                            did: ast::DefId,
+                            tps: &[Ty<'tcx>])
+                            -> String {
     let base = ty::item_path_str(cx.tcx(), did);
     let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
     let tstr = if strings.is_empty() {
         base
     } else {
-        format!("{}<{:?}>", base, strings)
+        format!("{}<{}>", base, strings.connect(", "))
     };
 
     if did.krate == 0 {
-        format!("{}.{}", name, tstr)
+        tstr
     } else {
-        format!("{}.{}[{}{}]", name, tstr, "#", did.krate)
+        format!("{}.{}", did.krate, tstr)
     }
 }
 
index e3c1c66f78c9c47774ee1740b52a42a538f45c37..844635117b5e988545db9576d2c9cc6d7858a428 100644 (file)
 //! case but `&a` in the second.  Basically, defaults that appear inside
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
-use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
+use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
 use middle::const_eval;
 use middle::def;
 use middle::resolve_lifetime as rl;
+use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::traits;
 use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
              ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
-use TypeAndSubsts;
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::DefIdMap;
 use util::ppaux::{self, Repr, UserString};
 
-use std::rc::Rc;
 use std::iter::{repeat, AdditiveIterator};
+use std::rc::Rc;
+use std::slice;
 use syntax::{abi, ast, ast_util};
 use syntax::codemap::Span;
 use syntax::parse::token;
 pub trait AstConv<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
 
-    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx>;
+    fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
+                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>;
+
+    fn get_trait_def(&self, span: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>;
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
+    fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
+                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;
 
     /// Return an (optional) substitution to convert bound type parameters that
     /// are in scope into free ones. This function should only return Some
@@ -195,7 +201,7 @@ pub fn opt_ast_region_to_region<'tcx>(
                                     help_name
                                 } else {
                                     format!("one of {}'s {} elided lifetimes", help_name, n)
-                                })[]);
+                                })[..]);
 
                                 if len == 2 && i == 0 {
                                     m.push_str(" or ");
@@ -245,8 +251,10 @@ pub fn opt_ast_region_to_region<'tcx>(
 pub fn ast_path_substs_for_ty<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
-    path: &ast::Path)
+    item_segment: &ast::PathSegment)
     -> Substs<'tcx>
 {
     let tcx = this.tcx();
@@ -262,27 +270,36 @@ pub fn ast_path_substs_for_ty<'tcx>(
     assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
     assert!(decl_generics.types.all(|d| d.space != FnSpace));
 
-    let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
+    let (regions, types, assoc_bindings) = match item_segment.parameters {
         ast::AngleBracketedParameters(ref data) => {
-            convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data)
+            convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
         }
         ast::ParenthesizedParameters(ref data) => {
-            span_err!(tcx.sess, path.span, E0214,
+            span_err!(tcx.sess, span, E0214,
                 "parenthesized parameters may only be used with a trait");
-            convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data)
+            convert_parenthesized_parameters(this, rscope, span, decl_generics, data)
         }
     };
 
     prohibit_projections(this.tcx(), &assoc_bindings);
 
     create_substs_for_ast_path(this,
-                               path.span,
+                               span,
+                               param_mode,
                                decl_generics,
                                None,
                                types,
                                regions)
 }
 
+#[derive(PartialEq, Eq)]
+pub enum PathParamMode {
+    // Any path in a type context.
+    Explicit,
+    // The `module::Type` in `module::Type::method` in an expression.
+    Optional
+}
+
 fn create_region_substs<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
@@ -305,9 +322,9 @@ fn create_region_substs<'tcx>(
             rscope.anon_regions(span, expected_num_region_params);
 
         if supplied_num_region_params != 0 || anon_regions.is_err() {
-            span_err!(tcx.sess, span, E0107,
-                      "wrong number of lifetime parameters: expected {}, found {}",
-                      expected_num_region_params, supplied_num_region_params);
+            report_lifetime_number_error(tcx, span,
+                                         supplied_num_region_params,
+                                         expected_num_region_params);
         }
 
         match anon_regions {
@@ -330,6 +347,7 @@ fn create_region_substs<'tcx>(
 fn create_substs_for_ast_path<'tcx>(
     this: &AstConv<'tcx>,
     span: Span,
+    param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     types_provided: Vec<Ty<'tcx>>,
@@ -348,38 +366,29 @@ fn create_substs_for_ast_path<'tcx>(
 
     // Convert the type parameters supplied by the user.
     let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
-    let supplied_ty_param_count = types_provided.len();
     let formal_ty_param_count = ty_param_defs.len();
     let required_ty_param_count = ty_param_defs.iter()
                                                .take_while(|x| x.default.is_none())
                                                .count();
 
-    let mut type_substs = types_provided;
+    // Fill with `ty_infer` if no params were specified, as long as
+    // they were optional (e.g. paths inside expressions).
+    let mut type_substs = if param_mode == PathParamMode::Optional &&
+                             types_provided.is_empty() {
+        (0..formal_ty_param_count).map(|_| this.ty_infer(span)).collect()
+    } else {
+        types_provided
+    };
+
+    let supplied_ty_param_count = type_substs.len();
+    check_type_argument_count(this.tcx(), span, supplied_ty_param_count,
+                              required_ty_param_count, formal_ty_param_count);
+
     if supplied_ty_param_count < required_ty_param_count {
-        let expected = if required_ty_param_count < formal_ty_param_count {
-            "expected at least"
-        } else {
-            "expected"
-        };
-        span_err!(this.tcx().sess, span, E0243,
-                  "wrong number of type arguments: {} {}, found {}",
-                  expected,
-                  required_ty_param_count,
-                  supplied_ty_param_count);
         while type_substs.len() < required_ty_param_count {
             type_substs.push(tcx.types.err);
         }
     } else if supplied_ty_param_count > formal_ty_param_count {
-        let expected = if required_ty_param_count < formal_ty_param_count {
-            "expected at most"
-        } else {
-            "expected"
-        };
-        span_err!(this.tcx().sess, span, E0244,
-                  "wrong number of type arguments: {} {}, found {}",
-                  expected,
-                  formal_ty_param_count,
-                  supplied_ty_param_count);
         type_substs.truncate(formal_ty_param_count);
     }
     assert!(type_substs.len() >= required_ty_param_count &&
@@ -431,7 +440,7 @@ fn create_substs_for_ast_path<'tcx>(
         }
     }
 
-    return substs;
+    substs
 }
 
 struct ConvertedBinding<'tcx> {
@@ -591,9 +600,9 @@ pub fn instantiate_poly_trait_ref<'tcx>(
     // lifetimes. Oh well, not there yet.
     let shifted_rscope = ShiftedRscope::new(rscope);
 
-    let trait_ref =
-        instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
-                              self_ty, Some(&mut projections));
+    let trait_ref = instantiate_trait_ref(this, &shifted_rscope,
+                                          &ast_trait_ref.trait_ref,
+                                          None, self_ty, Some(&mut projections));
 
     for projection in projections {
         poly_projections.push(ty::Binder(projection));
@@ -611,26 +620,31 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 pub fn instantiate_trait_ref<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
-    ast_trait_ref: &ast::TraitRef,
+    trait_ref: &ast::TraitRef,
+    impl_id: Option<ast::NodeId>,
     self_ty: Option<Ty<'tcx>>,
     projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
     -> Rc<ty::TraitRef<'tcx>>
 {
-    match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
+    let path = &trait_ref.path;
+    match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
         def::DefTrait(trait_def_id) => {
             let trait_ref = ast_path_to_trait_ref(this,
                                                   rscope,
+                                                  path.span,
+                                                  PathParamMode::Explicit,
                                                   trait_def_id,
                                                   self_ty,
-                                                  &ast_trait_ref.path,
+                                                  path.segments.last().unwrap(),
                                                   projections);
-            this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone());
+            if let Some(id) = impl_id {
+                this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
+            }
             trait_ref
         }
         _ => {
-            span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245,
-                "`{}` is not a trait",
-                        ast_trait_ref.path.user_string(this.tcx()));
+            span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
+                        path.user_string(this.tcx()));
         }
     }
 }
@@ -638,8 +652,10 @@ pub fn instantiate_trait_ref<'tcx>(
 fn object_path_to_poly_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     trait_def_id: ast::DefId,
-    path: &ast::Path,
+    trait_segment: &ast::PathSegment,
     mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
@@ -650,9 +666,11 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     let mut tmp = Vec::new();
     let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
                                                      &shifted_rscope,
+                                                     span,
+                                                     param_mode,
                                                      trait_def_id,
                                                      None,
-                                                     path,
+                                                     trait_segment,
                                                      Some(&mut tmp)));
     projections.extend(tmp.into_iter().map(ty::Binder));
     trait_ref
@@ -661,48 +679,58 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
 fn ast_path_to_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
-    path: &ast::Path,
+    trait_segment: &ast::PathSegment,
     mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
     -> Rc<ty::TraitRef<'tcx>>
 {
-    debug!("ast_path_to_trait_ref {:?}", path);
-    let trait_def = this.get_trait_def(trait_def_id);
+    debug!("ast_path_to_trait_ref {:?}", trait_segment);
+    let trait_def = match this.get_trait_def(span, trait_def_id) {
+        Ok(trait_def) => trait_def,
+        Err(ErrorReported) => {
+            // No convenient way to recover from a cycle here. Just bail. Sorry!
+            this.tcx().sess.abort_if_errors();
+            this.tcx().sess.bug("ErrorReported returned, but no errors reports?")
+        }
+    };
 
-    let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
+    let (regions, types, assoc_bindings) = match trait_segment.parameters {
         ast::AngleBracketedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
             if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
-                span_err!(this.tcx().sess, path.span, E0215,
+                span_err!(this.tcx().sess, span, E0215,
                                          "angle-bracket notation is not stable when \
                                          used with the `Fn` family of traits, use parentheses");
-                span_help!(this.tcx().sess, path.span,
+                span_help!(this.tcx().sess, span,
                            "add `#![feature(unboxed_closures)]` to \
                             the crate attributes to enable");
             }
 
-            convert_angle_bracketed_parameters(this, rscope, path.span, &trait_def.generics, data)
+            convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data)
         }
         ast::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
             if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
-                span_err!(this.tcx().sess, path.span, E0216,
+                span_err!(this.tcx().sess, span, E0216,
                                          "parenthetical notation is only stable when \
                                          used with the `Fn` family of traits");
-                span_help!(this.tcx().sess, path.span,
+                span_help!(this.tcx().sess, span,
                            "add `#![feature(unboxed_closures)]` to \
                             the crate attributes to enable");
             }
 
-            convert_parenthesized_parameters(this, rscope, path.span, &trait_def.generics, data)
+            convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data)
         }
     };
 
     let substs = create_substs_for_ast_path(this,
-                                            path.span,
+                                            span,
+                                            param_mode,
                                             &trait_def.generics,
                                             self_ty,
                                             types,
@@ -835,78 +863,36 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
     })
 }
 
-pub fn ast_path_to_ty<'tcx>(
+fn ast_path_to_ty<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     did: ast::DefId,
-    path: &ast::Path)
-    -> TypeAndSubsts<'tcx>
+    item_segment: &ast::PathSegment)
+    -> Ty<'tcx>
 {
     let tcx = this.tcx();
-    let ty::TypeScheme {
-        generics,
-        ty: decl_ty
-    } = this.get_item_type_scheme(did);
-
-    let substs = ast_path_substs_for_ty(this,
-                                        rscope,
-                                        &generics,
-                                        path);
-    let ty = decl_ty.subst(tcx, &substs);
-    TypeAndSubsts { substs: substs, ty: ty }
-}
-
-/// Converts the given AST type to a built-in type. A "built-in type" is, at
-/// present, either a core numeric type, a string, or `Box`.
-pub fn ast_ty_to_builtin_ty<'tcx>(
-        this: &AstConv<'tcx>,
-        rscope: &RegionScope,
-        ast_ty: &ast::Ty)
-        -> Option<Ty<'tcx>> {
-    match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
-        Some(typ) => return Some(typ),
-        None => {}
-    }
+    let (generics, decl_ty) = match this.get_item_type_scheme(span, did) {
+        Ok(ty::TypeScheme { generics,  ty: decl_ty }) => {
+            (generics, decl_ty)
+        }
+        Err(ErrorReported) => {
+            return tcx.types.err;
+        }
+    };
 
-    match ast_ty.node {
-        ast::TyPath(ref path, id) => {
-            let a_def = match this.tcx().def_map.borrow().get(&id) {
-                None => {
-                    this.tcx()
-                        .sess
-                        .span_bug(ast_ty.span,
-                                  &format!("unbound path {}",
-                                          path.repr(this.tcx()))[])
-                }
-                Some(&d) => d
-            };
+    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.
-            match a_def {
-                def::DefTy(did, _) |
-                def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
-                    let ty = ast_path_to_ty(this, rscope, did, path).ty;
-                    match ty.sty {
-                        ty::ty_struct(struct_def_id, ref substs) => {
-                            assert_eq!(struct_def_id, did);
-                            assert_eq!(substs.types.len(TypeSpace), 1);
-                            let referent_ty = *substs.types.get(TypeSpace, 0);
-                            Some(ty::mk_uniq(this.tcx(), referent_ty))
-                        }
-                        _ => {
-                            this.tcx().sess.span_bug(
-                                path.span,
-                                &format!("converting `Box` to `{}`",
-                                        ty.repr(this.tcx()))[]);
-                        }
-                    }
-                }
-                _ => None
-            }
-        }
-        _ => None
+    // FIXME(#12938): This is a hack until we have full support for DST.
+    if Some(did) == this.tcx().lang_items.owned_box() {
+        assert_eq!(substs.types.len(TypeSpace), 1);
+        return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0));
     }
+
+    decl_ty.subst(this.tcx(), &substs)
 }
 
 type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
@@ -929,14 +915,20 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
      */
 
     match ty.node {
-        ast::TyPath(ref path, id) => {
-            match this.tcx().def_map.borrow().get(&id) {
-                Some(&def::DefTrait(trait_def_id)) => {
+        ast::TyPath(None, ref path) => {
+            let def = match this.tcx().def_map.borrow().get(&ty.id) {
+                Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def),
+                _ => None
+            };
+            match def {
+                Some(def::DefTrait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
                     let trait_ref = object_path_to_poly_trait_ref(this,
                                                                   rscope,
+                                                                  path.span,
+                                                                  PathParamMode::Explicit,
                                                                   trait_def_id,
-                                                                  path,
+                                                                  path.segments.last().unwrap(),
                                                                   &mut projection_bounds);
                     Ok((trait_ref, projection_bounds))
                 }
@@ -1000,44 +992,60 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
 }
 
 fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
-                                   ast_ty: &ast::Ty,
-                                   provenance: def::TyParamProvenance,
-                                   assoc_name: ast::Name)
-                                   -> Ty<'tcx>
+                                   span: Span,
+                                   ty: Ty<'tcx>,
+                                   ty_path_def: def::Def,
+                                   item_segment: &ast::PathSegment)
+                                   -> (Ty<'tcx>, def::Def)
 {
     let tcx = this.tcx();
-    let ty_param_def_id = provenance.def_id();
-
-    let mut suitable_bounds: Vec<_>;
-    let ty_param_name: ast::Name;
-    { // contain scope of refcell:
-        let ty_param_defs = tcx.ty_param_defs.borrow();
-        let ty_param_def = &ty_param_defs[ty_param_def_id.node];
-        ty_param_name = ty_param_def.name;
-
-        // FIXME(#20300) -- search where clauses, not bounds
-        suitable_bounds =
-            traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds)
-            .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
-            .collect();
-    }
+    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
+    };
+
+    let ty_param_node_id = if is_param {
+        ty_path_def.local_node_id()
+    } else {
+        span_err!(tcx.sess, span, E0223,
+                "ambiguous associated type; specify the type using the syntax \
+                `<{} as Trait>::{}`",
+                ty.user_string(tcx), token::get_name(assoc_name));
+        return (tcx.types.err, ty_path_def);
+    };
+
+    let ty_param_name = tcx.ty_param_defs.borrow()[ty_param_node_id].name;
+
+    // FIXME(#20300) -- search where clauses, not bounds
+    let bounds =
+        this.get_type_parameter_bounds(span, ty_param_node_id)
+            .unwrap_or(Vec::new());
+
+    let mut suitable_bounds: Vec<_> =
+        traits::transitive_bounds(tcx, &bounds)
+        .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
+        .collect();
 
     if suitable_bounds.len() == 0 {
-        span_err!(tcx.sess, ast_ty.span, E0220,
+        span_err!(tcx.sess, span, E0220,
                           "associated type `{}` not found for type parameter `{}`",
                                   token::get_name(assoc_name),
                                   token::get_name(ty_param_name));
-        return this.tcx().types.err;
+        return (this.tcx().types.err, ty_path_def);
     }
 
     if suitable_bounds.len() > 1 {
-        span_err!(tcx.sess, ast_ty.span, E0221,
+        span_err!(tcx.sess, span, E0221,
                           "ambiguous associated type `{}` in bounds of `{}`",
                                   token::get_name(assoc_name),
                                   token::get_name(ty_param_name));
 
         for suitable_bound in &suitable_bounds {
-            span_note!(this.tcx().sess, ast_ty.span,
+            span_note!(this.tcx().sess, span,
                        "associated type `{}` could derive from `{}`",
                        token::get_name(ty_param_name),
                        suitable_bound.user_string(this.tcx()));
@@ -1045,7 +1053,32 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 
     let suitable_bound = suitable_bounds.pop().unwrap().clone();
-    return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name);
+    let trait_did = suitable_bound.0.def_id;
+
+    let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name);
+
+    let item_did = if trait_did.krate == ast::LOCAL_CRATE {
+        // `ty::trait_items` used below requires information generated
+        // 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) => {
+                trait_items.iter().filter_map(|i| {
+                    if let ast::TypeTraitItem(ref assoc) = *i {
+                        if assoc.ty_param.ident.name == assoc_name {
+                            return Some(ast_util::local_def(assoc.ty_param.id));
+                        }
+                    }
+                    None
+                }).next().expect("missing associated type")
+            }
+            _ => unreachable!()
+        }
+    } else {
+        let trait_items = ty::trait_items(this.tcx(), trait_did);
+        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))
 }
 
 fn trait_defines_associated_type_named(this: &AstConv,
@@ -1060,31 +1093,43 @@ fn trait_defines_associated_type_named(this: &AstConv,
 
 fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
                      rscope: &RegionScope,
-                     ast_ty: &ast::Ty, // the TyQPath
-                     qpath: &ast::QPath)
+                     span: Span,
+                     param_mode: PathParamMode,
+                     opt_self_ty: Option<Ty<'tcx>>,
+                     trait_def_id: ast::DefId,
+                     trait_segment: &ast::PathSegment,
+                     item_segment: &ast::PathSegment)
                      -> Ty<'tcx>
 {
-    debug!("qpath_to_ty(ast_ty={})",
-           ast_ty.repr(this.tcx()));
+    let tcx = this.tcx();
+
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
 
-    let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
+    let self_ty = if let Some(ty) = opt_self_ty {
+        ty
+    } else {
+        let path_str = ty::item_path_str(tcx, trait_def_id);
+        span_err!(tcx.sess, span, E0223,
+                  "ambiguous associated type; specify the type using the syntax \
+                   `<Type as {}>::{}`",
+                   path_str, &token::get_ident(item_segment.identifier));
+        return tcx.types.err;
+    };
 
-    debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
+    debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
 
-    let trait_ref = instantiate_trait_ref(this,
+    let trait_ref = ast_path_to_trait_ref(this,
                                           rscope,
-                                          &*qpath.trait_ref,
-                                          Some(self_type),
+                                          span,
+                                          param_mode,
+                                          trait_def_id,
+                                          Some(self_ty),
+                                          trait_segment,
                                           None);
 
-    debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
+    debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
 
-    // `<T as Trait>::U<V>` shouldn't parse right now.
-    assert!(qpath.item_path.parameters.is_empty());
-
-    return this.projected_ty(ast_ty.span,
-                             trait_ref,
-                             qpath.item_path.identifier.name);
+    this.projected_ty(span, trait_ref, item_segment.identifier.name)
 }
 
 /// Convert a type supplied as value for a type argument from AST into our
@@ -1120,6 +1165,96 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
+pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
+                                        rscope: &RegionScope,
+                                        span: Span,
+                                        param_mode: PathParamMode,
+                                        def: &mut def::Def,
+                                        opt_self_ty: Option<Ty<'tcx>>,
+                                        segments: &[ast::PathSegment],
+                                        assoc_segments: &[ast::PathSegment])
+                                        -> Ty<'tcx> {
+    let tcx = this.tcx();
+
+    let base_ty = match *def {
+        def::DefTrait(trait_def_id) => {
+            // N.B. this case overlaps somewhat with
+            // TyObjectSum, see that fn for details
+            let mut projection_bounds = Vec::new();
+
+            let trait_ref = object_path_to_poly_trait_ref(this,
+                                                          rscope,
+                                                          span,
+                                                          param_mode,
+                                                          trait_def_id,
+                                                          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, &[])
+        }
+        def::DefTy(did, _) | def::DefStruct(did) => {
+            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
+            ast_path_to_ty(this, rscope, span,
+                           param_mode, did,
+                           segments.last().unwrap())
+        }
+        def::DefTyParam(space, index, _, name) => {
+            check_path_args(tcx, 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
+            // trait, which we rely upon in various places when creating
+            // substs
+            check_path_args(tcx, 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())
+        }
+        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 {
+                tcx.sess.span_bug(span,
+                                  &format!("found module name used as a type: {}",
+                                           tcx.map.node_to_string(id.node)));
+            }
+        }
+        def::DefPrimTy(prim_ty) => {
+            prim_ty_to_ty(tcx, segments, prim_ty)
+        }
+        _ => {
+            span_fatal!(tcx.sess, span, E0248,
+                        "found value name used as a type: {:?}", *def);
+        }
+    };
+
+    // If any associated type segments remain, attempt to resolve them.
+    let mut ty = base_ty;
+    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);
+        ty = a_ty;
+        *def = a_def;
+    }
+    ty
+}
+
 /// Parses the programmer's textual representation of a type into our
 /// internal notion of a type.
 pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
@@ -1146,173 +1281,128 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
     ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
     drop(ast_ty_to_ty_cache);
 
-    let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
-        match ast_ty.node {
-            ast::TyVec(ref ty) => {
-                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
-            }
-            ast::TyObjectSum(ref ty, ref bounds) => {
-                match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) {
-                    Ok((trait_ref, projection_bounds)) => {
-                        trait_ref_to_object_type(this,
-                                                 rscope,
-                                                 ast_ty.span,
-                                                 trait_ref,
-                                                 projection_bounds,
-                                                 &bounds[..])
-                    }
-                    Err(ErrorReported) => {
-                        this.tcx().types.err
-                    }
+    let typ = match ast_ty.node {
+        ast::TyVec(ref ty) => {
+            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
+        }
+        ast::TyObjectSum(ref ty, ref bounds) => {
+            match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) {
+                Ok((trait_ref, projection_bounds)) => {
+                    trait_ref_to_object_type(this,
+                                             rscope,
+                                             ast_ty.span,
+                                             trait_ref,
+                                             projection_bounds,
+                                             bounds)
                 }
-            }
-            ast::TyPtr(ref mt) => {
-                ty::mk_ptr(tcx, ty::mt {
-                    ty: ast_ty_to_ty(this, rscope, &*mt.ty),
-                    mutbl: mt.mutbl
-                })
-            }
-            ast::TyRptr(ref region, ref mt) => {
-                let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
-                debug!("ty_rptr r={}", r.repr(this.tcx()));
-                let rscope1 =
-                    &ObjectLifetimeDefaultRscope::new(
-                        rscope,
-                        Some(ty::ObjectLifetimeDefault::Specific(r)));
-                let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
-                ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
-            }
-            ast::TyTup(ref fields) => {
-                let flds = fields.iter()
-                                 .map(|t| ast_ty_to_ty(this, rscope, &**t))
-                                 .collect();
-                ty::mk_tup(tcx, flds)
-            }
-            ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
-            ast::TyBareFn(ref bf) => {
-                if bf.decl.variadic && bf.abi != abi::C {
-                    span_err!(tcx.sess, ast_ty.span, E0222,
-                                      "variadic function must have C calling convention");
+                Err(ErrorReported) => {
+                    this.tcx().types.err
                 }
-                let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
-                ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
             }
-            ast::TyPolyTraitRef(ref bounds) => {
-                conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
+        }
+        ast::TyPtr(ref mt) => {
+            ty::mk_ptr(tcx, ty::mt {
+                ty: ast_ty_to_ty(this, rscope, &*mt.ty),
+                mutbl: mt.mutbl
+            })
+        }
+        ast::TyRptr(ref region, ref mt) => {
+            let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
+            debug!("ty_rptr r={}", r.repr(this.tcx()));
+            let rscope1 =
+                &ObjectLifetimeDefaultRscope::new(
+                    rscope,
+                    Some(ty::ObjectLifetimeDefault::Specific(r)));
+            let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
+            ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
+        }
+        ast::TyTup(ref fields) => {
+            let flds = fields.iter()
+                             .map(|t| ast_ty_to_ty(this, rscope, &**t))
+                             .collect();
+            ty::mk_tup(tcx, flds)
+        }
+        ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
+        ast::TyBareFn(ref bf) => {
+            if bf.decl.variadic && bf.abi != abi::C {
+                span_err!(tcx.sess, ast_ty.span, E0222,
+                          "variadic function must have C calling convention");
             }
-            ast::TyPath(ref path, id) => {
-                let a_def = match tcx.def_map.borrow().get(&id) {
-                    None => {
-                        tcx.sess
-                           .span_bug(ast_ty.span,
-                                     &format!("unbound path {}",
-                                             path.repr(tcx))[])
-                    }
-                    Some(&d) => d
-                };
-                match a_def {
-                    def::DefTrait(trait_def_id) => {
-                        // N.B. this case overlaps somewhat with
-                        // TyObjectSum, see that fn for details
-                        let mut projection_bounds = Vec::new();
-
-                        let trait_ref = object_path_to_poly_trait_ref(this,
-                                                                      rscope,
-                                                                      trait_def_id,
-                                                                      path,
-                                                                      &mut projection_bounds);
-
-                        trait_ref_to_object_type(this, rscope, path.span,
-                                                 trait_ref, projection_bounds, &[])
-                    }
-                    def::DefTy(did, _) | def::DefStruct(did) => {
-                        ast_path_to_ty(this, rscope, did, path).ty
-                    }
-                    def::DefTyParam(space, index, _, name) => {
-                        check_path_args(tcx, path, 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
-                        // trait, which we rely upon in various places when creating
-                        // substs
-                        check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                        ty::mk_self_type(tcx)
-                    }
-                    def::DefMod(id) => {
-                        span_fatal!(tcx.sess, ast_ty.span, E0247,
-                            "found module name used as a type: {}",
-                                    tcx.map.node_to_string(id.node));
-                    }
-                    def::DefPrimTy(_) => {
-                        panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
-                    }
-                    def::DefAssociatedTy(trait_type_id) => {
-                        let path_str = tcx.map.path_to_string(
-                            tcx.map.get_parent(trait_type_id.node));
-                        span_err!(tcx.sess, ast_ty.span, E0223,
-                                          "ambiguous associated \
-                                                   type; specify the type \
-                                                   using the syntax `<Type \
-                                                   as {}>::{}`",
-                                                  path_str,
-                                                  &token::get_ident(
-                                                      path.segments
-                                                          .last()
-                                                          .unwrap()
-                                                          .identifier));
-                        this.tcx().types.err
-                    }
-                    def::DefAssociatedPath(provenance, assoc_ident) => {
-                        associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
-                    }
-                    _ => {
-                        span_fatal!(tcx.sess, ast_ty.span, E0248,
-                                            "found value name used \
-                                                     as a type: {:?}",
-                                                    a_def);
-                    }
+            let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
+            ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
+        }
+        ast::TyPolyTraitRef(ref bounds) => {
+            conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
+        }
+        ast::TyPath(ref maybe_qself, ref path) => {
+            let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
+                d
+            } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
+                // Create some fake resolution that can't possibly be a type.
+                def::PathResolution {
+                    base_def: def::DefMod(ast_util::local_def(ast::CRATE_NODE_ID)),
+                    last_private: LastMod(AllPublic),
+                    depth: path.segments.len()
                 }
+            } else {
+                tcx.sess.span_bug(ast_ty.span,
+                                  &format!("unbound path {}", ast_ty.repr(tcx)))
+            };
+            let mut 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,
+                                                opt_self_ty,
+                                                &path.segments[..base_ty_end],
+                                                &path.segments[base_ty_end..]);
+
+            if path_res.depth != 0 && ty.sty != ty::ty_err {
+                // Write back the new resolution.
+                tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution {
+                    base_def: def,
+                    last_private: path_res.last_private,
+                    depth: 0
+                });
             }
-            ast::TyQPath(ref qpath) => {
-                qpath_to_ty(this, rscope, ast_ty, &**qpath)
-            }
-            ast::TyFixedLengthVec(ref ty, ref e) => {
-                match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
-                    Ok(ref r) => {
-                        match *r {
-                            const_eval::const_int(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
-                                           Some(i as uint)),
-                            const_eval::const_uint(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
-                                           Some(i as uint)),
-                            _ => {
-                                span_fatal!(tcx.sess, ast_ty.span, E0249,
-                                            "expected constant expr for array length");
-                            }
+
+            ty
+        }
+        ast::TyFixedLengthVec(ref ty, ref e) => {
+            match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
+                Ok(r) => {
+                    match r {
+                        const_eval::const_int(i) =>
+                            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
+                                        Some(i as uint)),
+                        const_eval::const_uint(i) =>
+                            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
+                                        Some(i as uint)),
+                        _ => {
+                            span_fatal!(tcx.sess, ast_ty.span, E0249,
+                                        "expected constant expr for array length");
                         }
                     }
-                    Err(ref r) => {
-                        span_fatal!(tcx.sess, ast_ty.span, E0250,
-                            "expected constant expr for array \
-                                     length: {}",
-                                    *r);
-                    }
                 }
-            }
-            ast::TyTypeof(ref _e) => {
-                tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
-            }
-            ast::TyInfer => {
-                // TyInfer also appears as the type of arguments or return
-                // values in a ExprClosure, or as
-                // the type of local variables. Both of these cases are
-                // handled specially and will not descend into this routine.
-                this.ty_infer(ast_ty.span)
+                Err(r) => {
+                    span_fatal!(tcx.sess, ast_ty.span, E0250,
+                                "expected constant expr for array length: {}", r);
+                }
             }
         }
-    });
+        ast::TyTypeof(ref _e) => {
+            tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
+        }
+        ast::TyInfer => {
+            // TyInfer also appears as the type of arguments or return
+            // values in a ExprClosure, or as
+            // the type of local variables. Both of these cases are
+            // handled specially and will not descend into this routine.
+            this.ty_infer(ast_ty.span)
+        }
+    };
 
     tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
     return typ;
@@ -1419,7 +1509,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
     let input_params = if self_ty.is_some() {
         &decl.inputs[1..]
     } else {
-        &decl.inputs[]
+        &decl.inputs[..]
     };
     let input_tys = input_params.iter().map(|a| ty_of_arg(this, &rb, a, None));
     let input_pats: Vec<String> = input_params.iter()
@@ -1820,7 +1910,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
     for ast_bound in ast_bounds {
         match *ast_bound {
             ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
-                match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
+                match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
                     def::DefTrait(trait_did) => {
                         match trait_def_ids.get(&trait_did) {
                             // Already seen this trait. We forbid
@@ -1847,7 +1937,16 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                         if ty::try_add_builtin_trait(tcx,
                                                      trait_did,
                                                      &mut builtin_bounds) {
-                            // FIXME(#20302) -- we should check for things like Copy<T>
+                            let segments = &b.trait_ref.path.segments;
+                            let parameters = &segments[segments.len() - 1].parameters;
+                            if parameters.types().len() > 0 {
+                                check_type_argument_count(tcx, b.trait_ref.path.span,
+                                                          parameters.types().len(), 0, 0);
+                            }
+                            if parameters.lifetimes().len() > 0{
+                                report_lifetime_number_error(tcx, b.trait_ref.path.span,
+                                                             parameters.lifetimes().len(), 0);
+                            }
                             continue; // success
                         }
                     }
@@ -1880,3 +1979,34 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
             "associated type bindings are not allowed here");
     }
 }
+
+fn check_type_argument_count(tcx: &ty::ctxt, span: Span, supplied: usize,
+                             required: usize, accepted: usize) {
+    if supplied < required {
+        let expected = if required < accepted {
+            "expected at least"
+        } else {
+            "expected"
+        };
+        span_err!(tcx.sess, span, E0243,
+                  "wrong number of type arguments: {} {}, found {}",
+                  expected, required, supplied);
+    } else if supplied > accepted {
+        let expected = if required < accepted {
+            "expected at most"
+        } else {
+            "expected"
+        };
+        span_err!(tcx.sess, span, E0244,
+                  "wrong number of type arguments: {} {}, found {}",
+                  expected,
+                  accepted,
+                  supplied);
+    }
+}
+
+fn report_lifetime_number_error(tcx: &ty::ctxt, span: Span, number: usize, expected: usize) {
+    span_err!(tcx.sess, span, E0107,
+              "wrong number of lifetime parameters: expected {}, found {}",
+              expected, number);
+}
index 34c52981b794dff838208073f38a0d048a9cb59f..dd2ab6c6b13ca5d5ee273eb59080b04edc962333 100644 (file)
@@ -103,7 +103,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
         ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
-            let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
+            let const_did = tcx.def_map.borrow()[pat.id].def_id();
             let const_scheme = ty::lookup_item_type(tcx, const_did);
             assert!(const_scheme.generics.is_empty());
             let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
@@ -433,7 +433,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    let def = tcx.def_map.borrow()[pat.id].clone();
+    let def = tcx.def_map.borrow()[pat.id].full_def();
     let (enum_def_id, variant_def_id) = match def {
         def::DefTrait(_) => {
             let name = pprust::path_to_string(path);
@@ -470,7 +470,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
     };
 
     instantiate_path(pcx.fcx,
-                     path,
+                     &path.segments,
                      ty::lookup_item_type(tcx, enum_def_id),
                      &ty::lookup_predicates(tcx, enum_def_id),
                      None,
@@ -502,7 +502,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    let def = tcx.def_map.borrow()[pat.id].clone();
+    let def = tcx.def_map.borrow()[pat.id].full_def();
     let enum_def = def.variant_def_ids()
         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
 
@@ -517,7 +517,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     } else {
         ctor_scheme
     };
-    instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id);
+    instantiate_path(pcx.fcx, &path.segments,
+                     path_scheme, &ctor_predicates,
+                     None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
index 4aaaf4ffe5ab3028aa982a204df157ec4d289670..f65e585d23edd3c8c11e2ac3c11db443db9bd7ed 100644 (file)
@@ -161,12 +161,6 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
                 //   entering the fn check. We should do this after
                 //   the fn check, then we can call this case a bug().
             }
-
-            ty::ty_open(_) => {
-                self.tcx().sess.bug(
-                    &format!("Unexpected type encountered while doing wf check: {}",
-                            ty.repr(self.tcx()))[]);
-            }
         }
     }
 
index dfbfc86c659704db316a77dc8f6cf8347126676a..d7db21f3a2f762350f94f0636886695f8b203fbf 100644 (file)
@@ -331,7 +331,7 @@ fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R wh
                 self.tcx().sess.span_bug(
                     self.span,
                     &format!("self-type `{}` for ObjectPick never dereferenced to an object",
-                            self_ty.repr(self.tcx()))[])
+                            self_ty.repr(self.tcx())))
             }
         }
     }
@@ -386,7 +386,7 @@ fn unify_receivers(&mut self,
                     &format!(
                         "{} was a subtype of {} but now is not?",
                         self_ty.repr(self.tcx()),
-                        method_self_ty.repr(self.tcx()))[]);
+                        method_self_ty.repr(self.tcx())));
             }
         }
     }
@@ -404,26 +404,9 @@ fn instantiate_method_sig(&mut self,
                all_substs.repr(self.tcx()));
 
         // Instantiate the bounds on the method with the
-        // type/early-bound-regions substitutions performed.  The only
-        // late-bound-regions that can appear in bounds are from the
-        // impl, and those were already instantiated above.
-        //
-        // FIXME(DST). Super hack. For a method on a trait object
-        // `Trait`, the generic signature requires that
-        // `Self:Trait`. Since, for an object, we bind `Self` to the
-        // type `Trait`, this leads to an obligation
-        // `Trait:Trait`. Until such time we DST is fully implemented,
-        // that obligation is not necessarily satisfied. (In the
-        // future, it would be.) But we know that the true `Self` DOES implement
-        // the trait. So we just delete this requirement. Hack hack hack.
-        let mut method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
-        match pick.kind {
-            probe::ObjectPick(..) => {
-                assert_eq!(method_predicates.predicates.get_slice(subst::SelfSpace).len(), 1);
-                method_predicates.predicates.pop(subst::SelfSpace);
-            }
-            _ => { }
-        }
+        // type/early-bound-regions substitutions performed. There can
+        // be no late-bound regions appearing here.
+        let method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
         let method_predicates = self.fcx.normalize_associated_types_in(self.span,
                                                                        &method_predicates);
 
index ffbc8ad020ab7819af598d980947e4f59a1c295b..7ef2db2c28d883f59c4f36a2fd34120aad269704 100644 (file)
@@ -8,12 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Method lookup: the secret sauce of Rust. See `doc.rs`.
+//! Method lookup: the secret sauce of Rust. See `README.md`.
 
 use astconv::AstConv;
 use check::{FnCtxt};
 use check::vtable;
 use check::vtable::select_new_fcx_obligations;
+use middle::def;
+use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
 use middle::subst;
 use middle::traits;
 use middle::ty::*;
@@ -66,7 +68,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         call_expr_id: ast::NodeId)
                         -> bool
 {
-    match probe::probe(fcx, span, method_name, self_ty, call_expr_id) {
+    let mode = probe::Mode::MethodCall;
+    match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) {
         Ok(..) => true,
         Err(NoMatch(..)) => false,
         Err(Ambiguity(..)) => true,
@@ -103,8 +106,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
            call_expr.repr(fcx.tcx()),
            self_expr.repr(fcx.tcx()));
 
+    let mode = probe::Mode::MethodCall;
     let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty);
-    let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id));
+    let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id));
     Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
 }
 
@@ -272,7 +276,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                 span,
                                 &format!(
                                     "trait method is &self but first arg is: {}",
-                                    transformed_self_ty.repr(fcx.tcx()))[]);
+                                    transformed_self_ty.repr(fcx.tcx())));
                         }
                     }
                 }
@@ -282,7 +286,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         span,
                         &format!(
                             "unexpected explicit self type in operator method: {:?}",
-                            method_ty.explicit_self)[]);
+                            method_ty.explicit_self));
                 }
             }
         }
@@ -301,6 +305,29 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Some(callee)
 }
 
+pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                              span: Span,
+                              method_name: ast::Name,
+                              self_ty: Ty<'tcx>,
+                              expr_id: ast::NodeId)
+                              -> Result<(def::Def, LastPrivate), MethodError>
+{
+    let mode = probe::Mode::Path;
+    let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
+    let def_id = pick.method_ty.def_id;
+    let mut lp = LastMod(AllPublic);
+    let provenance = match pick.kind {
+        probe::InherentImplPick(impl_def_id) => {
+            if pick.method_ty.vis != ast::Public {
+                lp = LastMod(DependsOn(def_id));
+            }
+            def::FromImpl(impl_def_id)
+        }
+        _ => def::FromTrait(pick.method_ty.container.id())
+    };
+    Ok((def::DefMethod(def_id, provenance), lp))
+}
+
 
 /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
 /// index (or `None`, if no such method).
index 978fbbbcffc33e7dfec2e527fb4bc9dff9e8a030..f24da78bc7d3974ea304f5c8f38f9d1f80a237ec 100644 (file)
@@ -37,6 +37,7 @@
 struct ProbeContext<'a, 'tcx:'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     span: Span,
+    mode: Mode,
     method_name: ast::Name,
     steps: Rc<Vec<CandidateStep<'tcx>>>,
     opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>,
@@ -108,17 +109,30 @@ pub enum PickAdjustment {
     AutoRef(ast::Mutability, Box<PickAdjustment>),
 }
 
+#[derive(PartialEq, Eq, Copy)]
+pub enum Mode {
+    // An expression of the form `receiver.method_name(...)`.
+    // Autoderefs are performed on `receiver`, lookup is done based on the
+    // `self` argument  of the method, and static methods aren't considered.
+    MethodCall,
+    // An expression of the form `Type::method` or `<T>::method`.
+    // No autoderefs are performed, lookup is done based on the type each
+    // implementation is for, and static methods are included.
+    Path
+}
+
 pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                        span: Span,
+                       mode: Mode,
                        method_name: ast::Name,
                        self_ty: Ty<'tcx>,
-                       call_expr_id: ast::NodeId)
+                       scope_expr_id: ast::NodeId)
                        -> PickResult<'tcx>
 {
-    debug!("probe(self_ty={}, method_name={}, call_expr_id={})",
+    debug!("probe(self_ty={}, method_name={}, scope_expr_id={})",
            self_ty.repr(fcx.tcx()),
            method_name,
-           call_expr_id);
+           scope_expr_id);
 
     // FIXME(#18741) -- right now, creating the steps involves evaluating the
     // `*` operator, which registers obligations that then escape into
@@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // it ride, although it's really not great, and in fact could I
     // think cause spurious errors. Really though this part should
     // take place in the `fcx.infcx().probe` below.
-    let steps = match create_steps(fcx, span, self_ty) {
-        Some(steps) => steps,
-        None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
+    let steps = if mode == Mode::MethodCall {
+        match create_steps(fcx, span, self_ty) {
+            Some(steps) => steps,
+            None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
+        }
+    } else {
+        vec![CandidateStep {
+            self_ty: self_ty,
+            adjustment: AutoDeref(0)
+        }]
     };
 
     // Create a list of simplified self types, if we can.
@@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // this creates one big transaction so that all type variables etc
     // that we create during the probe process are removed later
-    let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
     fcx.infcx().probe(|_| {
-        let (steps, opt_simplified_steps) = dummy.take().unwrap();
-        let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
+        let mut probe_cx = ProbeContext::new(fcx,
+                                             span,
+                                             mode,
+                                             method_name,
+                                             steps,
+                                             opt_simplified_steps);
         probe_cx.assemble_inherent_candidates();
-        try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id));
+        try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id));
         probe_cx.pick()
     })
 }
@@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn new(fcx: &'a FnCtxt<'a,'tcx>,
            span: Span,
+           mode: Mode,
            method_name: ast::Name,
            steps: Vec<CandidateStep<'tcx>>,
            opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>)
@@ -206,6 +231,7 @@ fn new(fcx: &'a FnCtxt<'a,'tcx>,
         ProbeContext {
             fcx: fcx,
             span: span,
+            mode: mode,
             method_name: method_name,
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
@@ -255,6 +281,11 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::ty_closure(did, _, _) => {
                 self.assemble_inherent_impl_candidates_for_type(did);
             }
+            ty::ty_uniq(_) => {
+                if let Some(box_did) = self.tcx().lang_items.owned_box() {
+                    self.assemble_inherent_impl_candidates_for_type(box_did);
+                }
+            }
             ty::ty_param(p) => {
                 self.assemble_inherent_candidates_from_param(self_ty, p);
             }
@@ -292,11 +323,12 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
             return self.record_static_candidate(ImplSource(impl_def_id));
         }
 
-        let impl_substs = self.impl_substs(impl_def_id);
+        let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
+        let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty);
 
         // Determine the receiver type that the method itself expects.
         let xform_self_ty =
-            self.xform_self_ty(&method, &impl_substs);
+            self.xform_self_ty(&method, impl_ty, &impl_substs);
 
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
@@ -330,7 +362,9 @@ fn assemble_inherent_candidates_from_object(&mut self,
                                                           new_trait_ref.def_id,
                                                           method_num);
 
-            let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs);
+            let xform_self_ty = this.xform_self_ty(&m,
+                                                   new_trait_ref.self_ty(),
+                                                   new_trait_ref.substs);
 
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
@@ -373,7 +407,9 @@ fn assemble_inherent_candidates_from_param(&mut self,
                 this.erase_late_bound_regions(&poly_trait_ref);
 
             let xform_self_ty =
-                this.xform_self_ty(&m, trait_ref.substs);
+                this.xform_self_ty(&m,
+                                   trait_ref.self_ty(),
+                                   trait_ref.substs);
 
             debug!("found match: trait_ref={} substs={} m={}",
                    trait_ref.repr(this.tcx()),
@@ -540,7 +576,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
                 continue;
             }
 
-            let impl_substs = self.impl_substs(impl_def_id);
+            let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id);
 
             debug!("impl_substs={}", impl_substs.repr(self.tcx()));
 
@@ -553,7 +589,9 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
 
             // Determine the receiver type that the method itself expects.
             let xform_self_ty =
-                self.xform_self_ty(&method, impl_trait_ref.substs);
+                self.xform_self_ty(&method,
+                                   impl_trait_ref.self_ty(),
+                                   impl_trait_ref.substs);
 
             debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
 
@@ -630,7 +668,9 @@ fn assemble_closure_candidates(&mut self,
                                                              &trait_def.generics,
                                                              step.self_ty);
 
-            let xform_self_ty = self.xform_self_ty(&method_ty, &substs);
+            let xform_self_ty = self.xform_self_ty(&method_ty,
+                                                   step.self_ty,
+                                                   &substs);
             self.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 method_ty: method_ty.clone(),
@@ -684,7 +724,9 @@ fn assemble_projection_candidates(&mut self,
                        bound.repr(self.tcx()));
 
                 if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
-                    let xform_self_ty = self.xform_self_ty(&method, bound.substs);
+                    let xform_self_ty = self.xform_self_ty(&method,
+                                                           bound.self_ty(),
+                                                           bound.substs);
 
                     debug!("assemble_projection_candidates: bound={} xform_self_ty={}",
                            bound.repr(self.tcx()),
@@ -714,7 +756,9 @@ fn assemble_where_clause_candidates(&mut self,
                           .filter(|b| b.def_id() == trait_def_id)
         {
             let bound = self.erase_late_bound_regions(&poly_bound);
-            let xform_self_ty = self.xform_self_ty(&method_ty, bound.substs);
+            let xform_self_ty = self.xform_self_ty(&method_ty,
+                                                   bound.self_ty(),
+                                                   bound.substs);
 
             debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
                    bound.repr(self.tcx()),
@@ -878,7 +922,7 @@ fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
         debug!("pick_method(self_ty={})", self.infcx().ty_to_string(self_ty));
 
         debug!("searching inherent candidates");
-        match self.consider_candidates(self_ty, &self.inherent_candidates[]) {
+        match self.consider_candidates(self_ty, &self.inherent_candidates) {
             None => {}
             Some(pick) => {
                 return Some(pick);
@@ -886,7 +930,7 @@ fn pick_method(&mut self, self_ty: Ty<'tcx>) -> Option<PickResult<'tcx>> {
         }
 
         debug!("searching extension candidates");
-        self.consider_candidates(self_ty, &self.extension_candidates[])
+        self.consider_candidates(self_ty, &self.extension_candidates)
     }
 
     fn consider_candidates(&self,
@@ -1023,7 +1067,9 @@ fn has_applicable_self(&self, method: &ty::Method) -> bool {
         // "fast track" -- check for usage of sugar
         match method.explicit_self {
             ty::StaticExplicitSelfCategory => {
-                // fallthrough
+                if self.mode == Mode::Path {
+                    return true;
+                }
             }
             ty::ByValueExplicitSelfCategory |
             ty::ByReferenceExplicitSelfCategory(..) |
@@ -1047,11 +1093,13 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
 
     fn xform_self_ty(&self,
                      method: &Rc<ty::Method<'tcx>>,
+                     impl_ty: Ty<'tcx>,
                      substs: &subst::Substs<'tcx>)
                      -> Ty<'tcx>
     {
-        debug!("xform_self_ty(self_ty={}, substs={})",
-               method.fty.sig.0.inputs[0].repr(self.tcx()),
+        debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})",
+               impl_ty.repr(self.tcx()),
+               method.fty.sig.0.inputs.get(0).repr(self.tcx()),
                substs.repr(self.tcx()));
 
         assert!(!substs.has_escaping_regions());
@@ -1063,6 +1111,11 @@ fn xform_self_ty(&self,
         // if there are any.
         assert_eq!(substs.types.len(subst::FnSpace), 0);
         assert_eq!(substs.regions().len(subst::FnSpace), 0);
+
+        if self.mode == Mode::Path {
+            return impl_ty;
+        }
+
         let placeholder;
         let mut substs = substs;
         if
@@ -1094,9 +1147,10 @@ fn xform_self_ty(&self,
         xform_self_ty
     }
 
-    fn impl_substs(&self,
-                   impl_def_id: ast::DefId)
-                   -> subst::Substs<'tcx>
+    /// Get the type of an impl and generate substitutions with placeholders.
+    fn impl_ty_and_substs(&self,
+                          impl_def_id: ast::DefId)
+                          -> (Ty<'tcx>, subst::Substs<'tcx>)
     {
         let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id);
 
@@ -1108,7 +1162,8 @@ fn impl_substs(&self,
             impl_pty.generics.regions.map(
                 |_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static
 
-        subst::Substs::new(type_vars, region_placeholders)
+        let substs = subst::Substs::new(type_vars, region_placeholders);
+        (impl_pty.ty, substs)
     }
 
     /// Replace late-bound-regions bound by `value` with `'static` using
index 1639772103b7aef5f95e7c5b6a6674d99b083152..9832fe1cb6eacd35ebf8ac3723829c28a68a129b 100644 (file)
@@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               span: Span,
                               rcvr_ty: Ty<'tcx>,
                               method_name: ast::Name,
-                              callee_expr: &ast::Expr,
+                              rcvr_expr: Option<&ast::Expr>,
                               error: MethodError)
 {
     // avoid suggestions when we don't know what's going on.
@@ -46,16 +46,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let cx = fcx.tcx();
             let method_ustring = method_name.user_string(cx);
 
-            // True if the type is a struct and contains a field with
-            // the same name as the not-found method
-            let is_field = match rcvr_ty.sty {
-                ty::ty_struct(did, _) =>
-                    ty::lookup_struct_fields(cx, did)
-                        .iter()
-                        .any(|f| f.name.user_string(cx) == method_ustring),
-                _ => false
-            };
-
             fcx.type_error_message(
                 span,
                 |actual| {
@@ -68,10 +58,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 None);
 
             // If the method has the name of a field, give a help note
-            if is_field {
-                cx.sess.span_note(span,
-                    &format!("use `(s.{0})(...)` if you meant to call the \
-                            function stored in the `{0}` field", method_ustring)[]);
+            if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) {
+                let fields = ty::lookup_struct_fields(cx, did);
+                if fields.iter().any(|f| f.name == method_name) {
+                    cx.sess.span_note(span,
+                        &format!("use `(s.{0})(...)` if you meant to call the \
+                                 function stored in the `{0}` field", method_ustring));
+                }
             }
 
             if static_sources.len() > 0 {
@@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 report_candidates(fcx, span, method_name, static_sources);
             }
 
-            suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits)
+            suggest_traits_to_import(fcx, span, rcvr_ty, method_name,
+                                     rcvr_expr, out_of_scope_traits)
         }
 
         MethodError::Ambiguity(sources) => {
@@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
 
         MethodError::ClosureAmbiguity(trait_def_id) => {
-            fcx.sess().span_err(
-                span,
-                &*format!("the `{}` method from the `{}` trait cannot be explicitly \
-                           invoked on this closure as we have not yet inferred what \
-                           kind of closure it is; use overloaded call notation instead \
-                           (e.g., `{}()`)",
-                          method_name.user_string(fcx.tcx()),
-                          ty::item_path_str(fcx.tcx(), trait_def_id),
-                          pprust::expr_to_string(callee_expr)));
+            let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
+                               invoked on this closure as we have not yet inferred what \
+                               kind of closure it is",
+                               method_name.user_string(fcx.tcx()),
+                               ty::item_path_str(fcx.tcx(), trait_def_id));
+            let msg = if let Some(callee) = rcvr_expr {
+                format!("{}; use overloaded call notation instead (e.g., `{}()`)",
+                        msg, pprust::expr_to_string(callee))
+            } else {
+                msg
+            };
+            fcx.sess().span_err(span, &msg);
         }
     }
 
@@ -156,6 +153,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       span: Span,
                                       rcvr_ty: Ty<'tcx>,
                                       method_name: ast::Name,
+                                      rcvr_expr: Option<&ast::Expr>,
                                       valid_out_of_scope_traits: Vec<ast::DefId>)
 {
     let tcx = fcx.tcx();
@@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         return
     }
 
-    let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty);
+    let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr);
 
     // there's no implemented traits, so lets suggest some traits to
     // implement, by finding ones that have the method name, and are
@@ -233,33 +231,39 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// autoderefs of `rcvr_ty`.
 fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   span: Span,
-                                  rcvr_ty: Ty<'tcx>) -> bool {
-    check::autoderef(fcx, span, rcvr_ty, None,
-                     check::UnresolvedTypeAction::Ignore, check::NoPreference,
-                     |&: ty, _| {
-        let is_local = match ty.sty {
+                                  rcvr_ty: Ty<'tcx>,
+                                  rcvr_expr: Option<&ast::Expr>) -> bool {
+    fn is_local(ty: Ty) -> bool {
+        match ty.sty {
             ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did),
 
             ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()),
 
             ty::ty_param(_) => true,
 
-            // the user cannot implement traits for unboxed closures, so
-            // there's no point suggesting anything at all, local or not.
-            ty::ty_closure(..) => return Some(false),
-
             // everything else (primitive types etc.) is effectively
             // non-local (there are "edge" cases, e.g. (LocalType,), but
             // the noise from these sort of types is usually just really
             // annoying, rather than any sort of help).
             _ => false
-        };
-        if is_local {
-            Some(true)
+        }
+    }
+
+    // This occurs for UFCS desugaring of `T::method`, where there is no
+    // receiver expression for the method call, and thus no autoderef.
+    if rcvr_expr.is_none() {
+        return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty));
+    }
+
+    check::autoderef(fcx, span, rcvr_ty, None,
+                     check::UnresolvedTypeAction::Ignore, check::NoPreference,
+                     |ty, _| {
+        if is_local(ty) {
+            Some(())
         } else {
             None
         }
-    }).2.unwrap_or(false)
+    }).2.is_some()
 }
 
 #[derive(Copy)]
index e443b4d0e606abd082e45a8fdd9f8b4e8efec526..fd6ba79ec21bb87955d3c237fa1ca707edc1a5f4 100644 (file)
 use self::IsBinopAssignment::*;
 use self::TupleArgumentsFlag::*;
 
-use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
+use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
 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::infer;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::McResult;
 use middle::pat_util::{self, pat_id_map};
+use middle::privacy::{AllPublic, LastMod};
 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::{Disr, ParamTy, ParameterEnvironment};
-use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty};
+use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::liberate_late_bound_regions;
 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rscope::RegionScope;
 use session::Session;
-use {CrateCtxt, lookup_def_ccx, require_same_types};
+use {CrateCtxt, lookup_full_def, require_same_types};
 use TypeAndSubsts;
 use lint;
-use util::common::{block_query, indenter, loop_query};
+use util::common::{block_query, ErrorReported, indenter, loop_query};
 use util::ppaux::{self, Repr};
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
 use util::lev_distance::lev_distance;
 use std::slice;
 use syntax::{self, abi, attr};
 use syntax::attr::AttrMetaMethods;
-use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
+use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId, Visibility};
 use syntax::ast_util::{self, local_def, PostExpansionMethod};
 use syntax::codemap::{self, Span};
 use syntax::owned_slice::OwnedSlice;
@@ -615,7 +617,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
     let tcx = ccx.tcx;
     let err_count_on_creation = tcx.sess.err_count();
 
-    let arg_tys = &fn_sig.inputs[];
+    let arg_tys = &fn_sig.inputs;
     let ret_ty = fn_sig.output;
 
     debug!("check_fn(arg_tys={}, ret_ty={}, fn_id={})",
@@ -713,7 +715,7 @@ pub fn check_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
       ast::ItemEnum(ref enum_definition, _) => {
         check_enum_variants(ccx,
                             it.span,
-                            &enum_definition.variants[],
+                            &enum_definition.variants,
                             it.id);
       }
       ast::ItemFn(ref decl, _, _, _, ref body) => {
@@ -1204,18 +1206,48 @@ fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
 
-    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
-        ty::lookup_item_type(self.tcx(), id)
+    fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
+                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>
+    {
+        Ok(ty::lookup_item_type(self.tcx(), id))
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        ty::lookup_trait_def(self.tcx(), id)
+    fn get_trait_def(&self, _: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
+    {
+        Ok(ty::lookup_trait_def(self.tcx(), id))
     }
 
     fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
         Some(&self.inh.param_env.free_substs)
     }
 
+    fn get_type_parameter_bounds(&self,
+                                 _: Span,
+                                 node_id: ast::NodeId)
+                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
+    {
+        let def = self.tcx().type_parameter_def(node_id);
+        let r = self.inh.param_env.caller_bounds
+                                  .iter()
+                                  .filter_map(|predicate| {
+                                      match *predicate {
+                                          ty::Predicate::Trait(ref data) => {
+                                              if data.0.self_ty().is_param(def.space, def.index) {
+                                                  Some(data.to_poly_trait_ref())
+                                              } else {
+                                                  None
+                                              }
+                                          }
+                                          _ => {
+                                              None
+                                          }
+                                      }
+                                  })
+                                  .collect();
+        Ok(r)
+    }
+
     fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
         self.infcx().next_ty_var()
     }
@@ -1334,7 +1366,7 @@ pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
                 self.tcx().sess.span_bug(
                     span,
                     &format!("no type for local variable {}",
-                            nid)[]);
+                            nid));
             }
         }
     }
@@ -1598,23 +1630,11 @@ fn instantiate_struct_literal_ty(&self,
         let ty::TypeScheme { generics, ty: decl_ty } =
             ty::lookup_item_type(tcx, did);
 
-        let wants_params =
-            generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
-
-        let needs_defaults =
-            wants_params &&
-            path.segments.iter().all(|s| s.parameters.is_empty());
-
-        let substs = if needs_defaults {
-            let tps =
-                self.infcx().next_ty_vars(generics.types.len(TypeSpace));
-            let rps =
-                self.infcx().region_vars_for_defs(path.span,
-                                                  generics.regions.get_slice(TypeSpace));
-            Substs::new_type(tps, rps)
-        } else {
-            astconv::ast_path_substs_for_ty(self, self, &generics, path)
-        };
+        let substs = astconv::ast_path_substs_for_ty(self, self,
+                                                     path.span,
+                                                     PathParamMode::Optional,
+                                                     &generics,
+                                                     path.segments.last().unwrap());
 
         let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
 
@@ -1707,7 +1727,7 @@ pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
             Some(&t) => t,
             None => {
                 self.tcx().sess.bug(&format!("no type for expr in fcx {}",
-                                            self.tag())[]);
+                                            self.tag()));
             }
         }
     }
@@ -1739,7 +1759,7 @@ pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
                 self.tcx().sess.bug(
                     &format!("no type for node {}: {} in fcx {}",
                             id, self.tcx().map.node_to_string(id),
-                            self.tag())[]);
+                            self.tag()));
             }
         }
     }
@@ -2275,7 +2295,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         if arg_types.len() == 1 {""} else {"s"},
                         args.len(),
                         if args.len() == 1 {" was"} else {"s were"});
-                    expected_arg_tys = &[][];
+                    expected_arg_tys = &[];
                     err_args(fcx.tcx(), args.len())
                 } else {
                     expected_arg_tys = match expected_arg_tys.get(0) {
@@ -2292,7 +2312,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 span_err!(tcx.sess, sp, E0059,
                     "cannot use call notation; the first type parameter \
                      for the function trait is neither a tuple nor unit");
-                expected_arg_tys = &[][];
+                expected_arg_tys = &[];
                 err_args(fcx.tcx(), args.len())
             }
         }
@@ -2309,7 +2329,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 if expected_arg_count == 1 {""} else {"s"},
                 supplied_arg_count,
                 if supplied_arg_count == 1 {" was"} else {"s were"});
-            expected_arg_tys = &[][];
+            expected_arg_tys = &[];
             err_args(fcx.tcx(), supplied_arg_count)
         }
     } else {
@@ -2319,7 +2339,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             if expected_arg_count == 1 {""} else {"s"},
             supplied_arg_count,
             if supplied_arg_count == 1 {" was"} else {"s were"});
-        expected_arg_tys = &[][];
+        expected_arg_tys = &[];
         err_args(fcx.tcx(), supplied_arg_count)
     };
 
@@ -2698,7 +2718,7 @@ fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
             Err(error) => {
                 method::report_error(fcx, method_name.span, expr_t,
-                                     method_name.node.name, rcvr, error);
+                                     method_name.node.name, Some(rcvr), error);
                 fcx.write_error(expr.id);
                 fcx.tcx().types.err
             }
@@ -2809,7 +2829,7 @@ fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
         };
         let args = match rhs {
             Some(rhs) => slice::ref_slice(rhs),
-            None => &[][]
+            None => &[][..]
         };
         match method {
             Some(method) => {
@@ -3117,6 +3137,10 @@ fn suggest_field_names<'tcx>(id : DefId,
             if skip.iter().any(|&x| x == n) {
                 continue;
             }
+            // ignore private fields from non-local crates
+            if id.krate != ast::LOCAL_CRATE && elem.vis != Visibility::Public {
+                continue;
+            }
             let dist = lev_distance(n, name);
             if dist < best_dist {
                 best = Some(n);
@@ -3404,10 +3428,10 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
           let mut checked = false;
           opt_place.as_ref().map(|place| match place.node {
-              ast::ExprPath(ref path) => {
+              ast::ExprPath(None, ref path) => {
                   // FIXME(pcwalton): For now we hardcode the two permissible
                   // places: the exchange heap and the managed heap.
-                  let definition = lookup_def(fcx, path.span, place.id);
+                  let definition = lookup_full_def(tcx, path.span, place.id);
                   let def_id = definition.def_id();
                   let referent_ty = fcx.expr_ty(&**subexpr);
                   if tcx.lang_items.exchange_heap() == Some(def_id) {
@@ -3597,26 +3621,65 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         };
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprPath(ref path) => {
-          let defn = lookup_def(fcx, path.span, id);
-          let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
-          instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
+      ast::ExprPath(ref maybe_qself, ref path) => {
+          let opt_self_ty = maybe_qself.as_ref().map(|qself| {
+              fcx.to_ty(&qself.ty)
+          });
 
-          // We always require that the type provided as the value for
-          // a type parameter outlives the moment of instantiation.
-          constrain_path_type_parameters(fcx, expr);
-      }
-      ast::ExprQPath(ref qpath) => {
-          // Require explicit type params for the trait.
-          let self_ty = fcx.to_ty(&*qpath.self_type);
-          astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
-
-          let defn = lookup_def(fcx, expr.span, id);
-          let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
-          let mut path = qpath.trait_ref.path.clone();
-          path.segments.push(qpath.item_path.clone());
-          instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
-                           defn, expr.span, expr.id);
+          let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
+              d
+          } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
+                // Create some fake resolution that can't possibly be a type.
+                def::PathResolution {
+                    base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
+                    last_private: LastMod(AllPublic),
+                    depth: path.segments.len()
+                }
+            } else {
+              tcx.sess.span_bug(expr.span,
+                                &format!("unbound path {}", expr.repr(tcx)))
+          };
+
+          let mut def = path_res.base_def;
+          if path_res.depth == 0 {
+              let (scheme, predicates) =
+                  type_scheme_and_predicates_for_def(fcx, expr.span, def);
+              instantiate_path(fcx, &path.segments,
+                               scheme, &predicates,
+                               opt_self_ty, def, expr.span, id);
+          } 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,
+                                                           PathParamMode::Optional,
+                                                           &mut def,
+                                                           opt_self_ty,
+                                                           &ty_segments[..base_ty_end],
+                                                           &ty_segments[base_ty_end..]);
+              let method_segment = path.segments.last().unwrap();
+              let method_name = method_segment.identifier.name;
+              match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
+                  Ok((def, lp)) => {
+                      // Write back the new resolution.
+                      tcx.def_map.borrow_mut().insert(id, def::PathResolution {
+                          base_def: def,
+                          last_private: path_res.last_private.or(lp),
+                          depth: 0
+                      });
+
+                      let (scheme, predicates) =
+                          type_scheme_and_predicates_for_def(fcx, expr.span, def);
+                      instantiate_path(fcx, slice::ref_slice(method_segment),
+                                       scheme, &predicates,
+                                       Some(ty), def, expr.span, id);
+                  }
+                  Err(error) => {
+                      method::report_error(fcx, expr.span, ty,
+                                           method_name, None, error);
+                      fcx.write_error(id);
+                  }
+              }
+          }
 
           // We always require that the type provided as the value for
           // a type parameter outlives the moment of instantiation.
@@ -3851,14 +3914,14 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
       }
       ast::ExprStruct(ref path, ref fields, ref base_expr) => {
         // Resolve the path.
-        let def = tcx.def_map.borrow().get(&id).cloned();
+        let def = lookup_full_def(tcx, path.span, id);
         let struct_id = match def {
-            Some(def::DefVariant(enum_id, variant_id, true)) => {
+            def::DefVariant(enum_id, variant_id, true) => {
                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
                                           variant_id, &fields[..]);
                 enum_id
             }
-            Some(def::DefTrait(def_id)) => {
+            def::DefTrait(def_id) => {
                 span_err!(tcx.sess, path.span, E0159,
                     "use of trait `{}` as a struct constructor",
                     pprust::path_to_string(path));
@@ -3868,7 +3931,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                              base_expr);
                 def_id
             },
-            Some(def) => {
+            def => {
                 // Verify that this was actually a struct.
                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
                 match typ.ty.sty {
@@ -3893,10 +3956,6 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
                 def.def_id()
             }
-            _ => {
-                tcx.sess.span_bug(path.span,
-                                  "structure constructor wasn't resolved")
-            }
         };
 
         // Turn the path into a type and verify that that type unifies with
@@ -4584,7 +4643,7 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 
     let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
-        [].get(0).unwrap_or(&attr::ReprAny);
+        .get(0).unwrap_or(&attr::ReprAny);
 
     if hint != attr::ReprAny && vs.len() <= 1 {
         if vs.len() == 1 {
@@ -4610,10 +4669,6 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     check_instantiable(ccx.tcx, sp, id);
 }
 
-pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
-    lookup_def_ccx(fcx.ccx, sp, id)
-}
-
 // Returns the type parameter count and the type for the given definition.
 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 sp: Span,
@@ -4625,7 +4680,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
              ty::GenericPredicates::empty())
         }
-        def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
+        def::DefFn(id, _) | def::DefMethod(id, _) |
         def::DefStatic(id, _) | def::DefVariant(_, id, _) |
         def::DefStruct(id) | def::DefConst(id) => {
             (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
@@ -4633,14 +4688,12 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefTrait(_) |
         def::DefTy(..) |
         def::DefAssociatedTy(..) |
-        def::DefAssociatedPath(..) |
         def::DefPrimTy(_) |
         def::DefTyParam(..) |
         def::DefMod(..) |
         def::DefForeignMod(..) |
         def::DefUse(..) |
         def::DefRegion(..) |
-        def::DefTyParamBinder(..) |
         def::DefLabel(..) |
         def::DefSelfTy(..) => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
@@ -4651,15 +4704,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  path: &ast::Path,
+                                  segments: &[ast::PathSegment],
                                   type_scheme: TypeScheme<'tcx>,
                                   type_predicates: &ty::GenericPredicates<'tcx>,
                                   opt_self_ty: Option<Ty<'tcx>>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
-    debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
-           path.repr(fcx.tcx()),
+    debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
+           segments,
            def.repr(fcx.tcx()),
            node_id,
            type_scheme.repr(fcx.tcx()));
@@ -4723,23 +4776,23 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     //
     // The first step then is to categorize the segments appropriately.
 
-    assert!(path.segments.len() >= 1);
+    assert!(segments.len() >= 1);
+
+    let mut ufcs_method = None;
     let mut segment_spaces: Vec<_>;
     match def {
         // Case 1 and 1b. Reference to a *type* or *enum variant*.
         def::DefSelfTy(..) |
         def::DefStruct(..) |
         def::DefVariant(..) |
-        def::DefTyParamBinder(..) |
         def::DefTy(..) |
         def::DefAssociatedTy(..) |
-        def::DefAssociatedPath(..) |
         def::DefTrait(..) |
         def::DefPrimTy(..) |
         def::DefTyParam(..) => {
             // Everything but the final segment should have no
             // parameters at all.
-            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
+            segment_spaces = repeat(None).take(segments.len() - 1).collect();
             segment_spaces.push(Some(subst::TypeSpace));
         }
 
@@ -4747,25 +4800,29 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefFn(..) |
         def::DefConst(..) |
         def::DefStatic(..) => {
-            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
+            segment_spaces = repeat(None).take(segments.len() - 1).collect();
             segment_spaces.push(Some(subst::FnSpace));
         }
 
         // Case 3. Reference to a method.
-        def::DefStaticMethod(_, providence) |
-        def::DefMethod(_, _, providence) => {
-            assert!(path.segments.len() >= 2);
-
-            match providence {
+        def::DefMethod(_, provenance) => {
+            match provenance {
                 def::FromTrait(trait_did) => {
                     callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
                 }
                 def::FromImpl(_) => {}
             }
 
-            segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
-            segment_spaces.push(Some(subst::TypeSpace));
-            segment_spaces.push(Some(subst::FnSpace));
+            if segments.len() >= 2 {
+                segment_spaces = repeat(None).take(segments.len() - 2).collect();
+                segment_spaces.push(Some(subst::TypeSpace));
+                segment_spaces.push(Some(subst::FnSpace));
+            } else {
+                // `<T>::method` will end up here, and so can `T::method`.
+                let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
+                segment_spaces = vec![Some(subst::FnSpace)];
+                ufcs_method = Some((provenance, self_ty));
+            }
         }
 
         // Other cases. Various nonsense that really shouldn't show up
@@ -4778,10 +4835,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefRegion(..) |
         def::DefLabel(..) |
         def::DefUpvar(..) => {
-            segment_spaces = repeat(None).take(path.segments.len()).collect();
+            segment_spaces = repeat(None).take(segments.len()).collect();
         }
     }
-    assert_eq!(segment_spaces.len(), path.segments.len());
+    assert_eq!(segment_spaces.len(), segments.len());
+
+    // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
+    // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
+    // type parameters are not mandatory.
+    let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
 
     debug!("segment_spaces={:?}", segment_spaces);
 
@@ -4795,16 +4857,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // provided (if any) into their appropriate spaces. We'll also report
     // errors if type parameters are provided in an inappropriate place.
     let mut substs = Substs::empty();
-    for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
+    for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
         match *opt_space {
             None => {
-                report_error_if_segment_contains_type_parameters(fcx, segment);
+                check_path_args(fcx.tcx(), slice::ref_slice(segment),
+                                NO_TPS | NO_REGIONS);
             }
 
             Some(space) => {
                 push_explicit_parameters_from_segment_to_substs(fcx,
                                                                 space,
-                                                                path.span,
+                                                                span,
                                                                 type_defs,
                                                                 region_defs,
                                                                 segment,
@@ -4813,9 +4876,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
     }
     if let Some(self_ty) = opt_self_ty {
-        // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
-        assert_eq!(type_defs.len(subst::SelfSpace), 1);
-        substs.types.push(subst::SelfSpace, self_ty);
+        if type_defs.len(subst::SelfSpace) == 1 {
+            substs.types.push(subst::SelfSpace, self_ty);
+        }
     }
 
     // Now we have to compare the types that the user *actually*
@@ -4825,7 +4888,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // to add defaults. If the user provided *too many* types, that's
     // a problem.
     for &space in &ParamSpace::all() {
-        adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
+        adjust_type_parameters(fcx, span, space, type_defs,
+                               require_type_space, &mut substs);
         assert_eq!(substs.types.len(space), type_defs.len(space));
 
         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
@@ -4848,27 +4912,32 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // the referenced item.
     let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
 
-    fcx.write_ty(node_id, ty_substituted);
-    fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
-    return;
 
-    fn report_error_if_segment_contains_type_parameters(
-        fcx: &FnCtxt,
-        segment: &ast::PathSegment)
-    {
-        for typ in &segment.parameters.types() {
-            span_err!(fcx.tcx().sess, typ.span, E0085,
-                "type parameters may not appear here");
-            break;
-        }
+    if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
+        // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
+        // is inherent, there is no `Self` parameter, instead, the impl needs
+        // type parameters, which we can infer by unifying the provided `Self`
+        // with the substituted impl type.
+        let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
+        assert_eq!(substs.types.len(subst::TypeSpace),
+                   impl_scheme.generics.types.len(subst::TypeSpace));
+        assert_eq!(substs.regions().len(subst::TypeSpace),
+                   impl_scheme.generics.regions.len(subst::TypeSpace));
 
-        for lifetime in &segment.parameters.lifetimes() {
-            span_err!(fcx.tcx().sess, lifetime.span, E0086,
-                "lifetime parameters may not appear here");
-            break;
+        let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
+        if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
+            fcx.tcx().sess.span_bug(span,
+            &format!(
+                "instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
+                self_ty.repr(fcx.tcx()),
+                impl_ty.repr(fcx.tcx())));
         }
     }
 
+    fcx.write_ty(node_id, ty_substituted);
+    fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
+    return;
+
     /// Finds the parameters that the user provided and adds them to `substs`. If too many
     /// parameters are provided, then reports an error and clears the output vector.
     ///
@@ -5003,6 +5072,7 @@ fn adjust_type_parameters<'a, 'tcx>(
         span: Span,
         space: ParamSpace,
         defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
+        require_type_space: bool,
         substs: &mut Substs<'tcx>)
     {
         let provided_len = substs.types.len(space);
@@ -5025,9 +5095,8 @@ fn adjust_type_parameters<'a, 'tcx>(
 
         // Nothing specified at all: supply inference variables for
         // everything.
-        if provided_len == 0 {
-            substs.types.replace(space,
-                                 fcx.infcx().next_ty_vars(desired.len()));
+        if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
+            substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
             return;
         }
 
@@ -5149,18 +5218,15 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
             _ => false
         }
     })) ||
-   // Second: is there a labeled break with label
-   // <id> nested anywhere inside the loop?
+    // Second: is there a labeled break with label
+    // <id> nested anywhere inside the loop?
     (block_query(b, |e| {
-        match e.node {
-            ast::ExprBreak(Some(_)) => {
-                match cx.def_map.borrow().get(&e.id) {
-                    Some(&def::DefLabel(loop_id)) if id == loop_id => true,
-                    _ => false,
-                }
-            }
-            _ => false
-        }}))
+        if let ast::ExprBreak(Some(_)) = e.node {
+            lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
+        } else {
+            false
+        }
+    }))
 }
 
 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
index 82abff8c425f42c5aca7d2aa62f73ac9c85a78de..1518a09e7dc063656d2dba73782be746a686cbb7 100644 (file)
@@ -188,7 +188,7 @@ fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
         }
         _ => {
             tcx.sess.bug(&format!("unexpected def in region_of_def: {:?}",
-                                 def)[])
+                                 def))
         }
     }
 }
@@ -288,7 +288,7 @@ fn visit_fn_body(&mut self,
             Some(f) => f,
             None => {
                 self.tcx().sess.bug(
-                    &format!("No fn-sig entry for id={}", id)[]);
+                    &format!("No fn-sig entry for id={}", id));
             }
         };
 
@@ -554,8 +554,12 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
                                                                expr.span);
             }
             Err(..) => {
-                rcx.fcx.tcx().sess.span_note(expr.span,
-                                             "cat_expr_unadjusted Errd during dtor check");
+                let tcx = rcx.fcx.tcx();
+                if tcx.sess.has_errors() {
+                    // cannot run dropck; okay b/c in error state anyway.
+                } else {
+                    tcx.sess.span_bug(expr.span, "cat_expr_unadjusted Errd");
+                }
             }
         }
     }
@@ -571,8 +575,12 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             check_safety_of_rvalue_destructor_if_necessary(rcx, head_cmt, expr.span);
         }
         Err(..) => {
-            rcx.fcx.tcx().sess.span_note(expr.span,
-                                         "cat_expr Errd during dtor check");
+            let tcx = rcx.fcx.tcx();
+            if tcx.sess.has_errors() {
+                // cannot run dropck; okay b/c in error state anyway.
+            } else {
+                tcx.sess.span_bug(expr.span, "cat_expr Errd");
+            }
         }
     }
 
@@ -1013,7 +1021,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                         rcx.tcx().sess.span_bug(
                             deref_expr.span,
                             &format!("bad overloaded deref type {}",
-                                     method.ty.repr(rcx.tcx()))[])
+                                     method.ty.repr(rcx.tcx())))
                     }
                 };
 
@@ -1417,7 +1425,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                     rcx.tcx().sess.span_bug(
                         span,
                         &format!("Illegal upvar id: {}",
-                                upvar_id.repr(rcx.tcx()))[]);
+                                upvar_id.repr(rcx.tcx())));
                 }
             }
         }
@@ -1562,7 +1570,7 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
         GenericKind::Param(..) => { }
         GenericKind::Projection(ref projection_ty) => {
             param_bounds.push_all(
-                &projection_bounds(rcx, origin.span(), projection_ty)[]);
+                &projection_bounds(rcx, origin.span(), projection_ty));
         }
     }
 
index 3666b69d1c678ac4cc6a64d60118b794f4bdf449..630530cf11f841186dcb2e0c899e2b6d1ab28661 100644 (file)
@@ -133,14 +133,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                      in the supertrait listing");
             }
 
-            ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
-                tcx.sess.span_note(
-                    span,
-                    &format!("method `{}` has a receiver type of `Self`, \
-                              which cannot be used with a trait object",
-                             method.name.user_string(tcx)));
-            }
-
             ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
                 tcx.sess.span_note(
                     span,
index 2601c4d275291d144762ff46ac1484aee3e3b5eb..e024526d0016f7756c18baa0e2036f2379b0a213 100644 (file)
@@ -81,14 +81,17 @@ fn check_item_well_formed(&mut self, item: &ast::Item) {
             ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
                 self.check_impl(item);
             }
-            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
-                let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
+            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
+                let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
+                ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
                     Some(_) | None => {
-                        span_err!(ccx.tcx.sess, item.span, E0192,
-                            "negative impls are currently \
-                                     allowed just for `Send` and `Sync`")
+                        if !ty::trait_has_default_impl(ccx.tcx, trait_ref.def_id) {
+                            span_err!(ccx.tcx.sess, item.span, E0192,
+                                      "negative impls are only allowed for traits with \
+                                       default impls (e.g., `Send` and `Sync`)")
+                        }
                     }
                 }
             }
@@ -393,7 +396,7 @@ fn report_bivariance(&self,
         self.tcx().sess.span_err(
             span,
             &format!("parameter `{}` is never used",
-                     param_name.user_string(self.tcx()))[]);
+                     param_name.user_string(self.tcx())));
 
         match suggested_marker_id {
             Some(def_id) => {
index e535b86a7bfd1e0cfa72c2cb8e74ed84fcc3e261..e89c96b36e1a23887e2b52631945d2a2c99985dd 100644 (file)
@@ -28,8 +28,8 @@ struct ImplsChecker<'cx, 'tcx:'cx> {
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         match item.node {
-            ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => {
-                let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id);
+            ast::ItemImpl(_, _, _, Some(_), _, _) => {
+                let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id);
                 if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     match trait_ref.self_ty().sty {
                         ty::ty_struct(..) | ty::ty_enum(..) => {}
index 1542e74ff81672769a7fc68b8397bfe4f523b409..1913b55f1d8e69d03da3fc0b368345b055522ed5 100644 (file)
@@ -25,7 +25,7 @@
 use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
 use middle::ty::{ty_param, TypeScheme, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
-use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
+use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int};
 use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
 use middle::ty::{ty_projection};
 use middle::ty;
@@ -75,7 +75,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
 
         ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
         ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
-        ty_param(..) | ty_err | ty_open(..) |
+        ty_param(..) | ty_err |
         ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
             None
         }
@@ -86,7 +86,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
             inference_context.tcx.sess.span_bug(
                 span,
                 &format!("coherence encountered unexpected type searching for base type: {}",
-                        ty.repr(inference_context.tcx))[]);
+                        ty.repr(inference_context.tcx)));
         }
     }
 }
@@ -106,19 +106,9 @@ fn visit_item(&mut self, item: &Item) {
 
         //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
 
-        match item.node {
-            ItemImpl(_, _, _, ref opt_trait, _, _) => {
-                match opt_trait.clone() {
-                    Some(opt_trait) => {
-                        self.cc.check_implementation(item, &[opt_trait]);
-                    }
-                    None => self.cc.check_implementation(item, &[])
-                }
-            }
-            _ => {
-                // Nothing to do.
-            }
-        };
+        if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
+            self.cc.check_implementation(item, opt_trait.as_ref())
+        }
 
         visit::walk_item(self, item);
     }
@@ -155,9 +145,7 @@ fn check(&self, krate: &Crate) {
         self.check_implementations_of_copy();
     }
 
-    fn check_implementation(&self,
-                            item: &Item,
-                            associated_traits: &[TraitRef]) {
+    fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
         let tcx = self.crate_context.tcx;
         let impl_did = local_def(item.id);
         let self_type = ty::lookup_item_type(tcx, impl_did);
@@ -167,9 +155,8 @@ fn check_implementation(&self,
 
         let impl_items = self.create_impl_from_item(item);
 
-        for associated_trait in associated_traits {
-            let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx,
-                                                     associated_trait.ref_id);
+        if opt_trait.is_some() {
+            let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
             debug!("(checking implementation) adding impl for trait '{}', item '{}'",
                    trait_ref.repr(self.crate_context.tcx),
                    token::get_ident(item.ident));
@@ -191,7 +178,7 @@ fn check_implementation(&self,
             }
             Some(base_type_def_id) => {
                 // FIXME: Gather up default methods?
-                if associated_traits.len() == 0 {
+                if opt_trait.is_none() {
                     self.add_inherent_impl(base_type_def_id, impl_did);
                 }
             }
@@ -289,7 +276,7 @@ fn get_self_type_for_implementation(&self, impl_did: DefId)
     // Converts an implementation in the AST to a vector of items.
     fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
         match item.node {
-            ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => {
+            ItemImpl(_, _, _, ref opt_trait, _, ref ast_items) => {
                 let mut items: Vec<ImplOrTraitItemId> =
                         ast_items.iter()
                                  .map(|ast_item| {
@@ -304,13 +291,12 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
                             }
                         }).collect();
 
-                if let Some(ref trait_ref) = *trait_refs {
-                    let ty_trait_ref = ty::node_id_to_trait_ref(
-                        self.crate_context.tcx,
-                        trait_ref.ref_id);
+                if opt_trait.is_some() {
+                    let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
+                                                             item.id);
 
                     self.instantiate_default_methods(local_def(item.id),
-                                                     &*ty_trait_ref,
+                                                     &*trait_ref,
                                                      &mut items);
                 }
 
index f43469363cd81f435c03b018bac9cf8d606fd8a7..95dafccd866bf3369136c8f936b31edf362e7397 100644 (file)
@@ -16,7 +16,6 @@
 use syntax::ast::{Item, ItemImpl};
 use syntax::ast;
 use syntax::ast_util;
-use syntax::codemap::Span;
 use syntax::visit;
 use util::ppaux::{Repr, UserString};
 
@@ -30,9 +29,9 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
 }
 
 impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
-    fn check_def_id(&self, span: Span, def_id: ast::DefId) {
+    fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) {
         if def_id.krate != ast::LOCAL_CRATE {
-            span_err!(self.tcx.sess, span, E0116,
+            span_err!(self.tcx.sess, item.span, E0116,
                       "cannot associate methods with a type outside the \
                        crate the type is defined in; define and implement \
                        a trait or new type instead");
@@ -41,7 +40,7 @@ fn check_def_id(&self, span: Span, def_id: ast::DefId) {
 }
 
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &'v ast::Item) {
+    fn visit_item(&mut self, item: &ast::Item) {
         let def_id = ast_util::local_def(item.id);
         match item.node {
             ast::ItemImpl(_, _, _, None, _, _) => {
@@ -52,15 +51,13 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                 match self_ty.sty {
                     ty::ty_enum(def_id, _) |
                     ty::ty_struct(def_id, _) => {
-                        self.check_def_id(item.span, def_id);
+                        self.check_def_id(item, def_id);
                     }
                     ty::ty_trait(ref data) => {
-                        self.check_def_id(item.span, data.principal_def_id());
+                        self.check_def_id(item, data.principal_def_id());
                     }
                     ty::ty_uniq(..) => {
-                        self.check_def_id(item.span,
-                                          self.tcx.lang_items.owned_box()
-                                              .unwrap());
+                        self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
                     }
                     _ => {
                         span_err!(self.tcx.sess, item.span, E0118,
@@ -96,6 +93,16 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                     }
                 }
             }
+            ast::ItemDefaultImpl(..) => {
+                // "Trait" impl
+                debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx));
+                let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
+                if trait_ref.def_id.krate != ast::LOCAL_CRATE {
+                    span_err!(self.tcx.sess, item.span, E0318,
+                              "cannot create default implementations for traits outside the \
+                               crate they're defined in; define a new trait instead.");
+                }
+            }
             _ => {
                 // Not an impl
             }
index 403dcf1e25abaa52b4cefba4b6086aa2c413135a..a6ecafb6241316382fd516b7236ff6527b80571a 100644 (file)
 use syntax::ast::{DefId};
 use syntax::ast::{LOCAL_CRATE};
 use syntax::ast;
-use syntax::codemap::{Span};
+use syntax::ast_util;
+use syntax::visit;
+use syntax::codemap::Span;
 use util::ppaux::Repr;
 
 pub fn check(tcx: &ty::ctxt) {
-    let overlap = OverlapChecker { tcx: tcx };
+    let mut overlap = OverlapChecker { tcx: tcx };
     overlap.check_for_overlapping_impls();
+
+    // this secondary walk specifically checks for impls of defaulted
+    // traits, for which additional overlap rules exist
+    visit::walk_crate(&mut overlap, tcx.map.krate());
 }
 
 struct OverlapChecker<'cx, 'tcx:'cx> {
-    tcx: &'cx ty::ctxt<'tcx>
+    tcx: &'cx ty::ctxt<'tcx>,
 }
 
 impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
@@ -90,17 +96,28 @@ fn check_if_impls_overlap(&self,
             return;
         }
 
-        span_err!(self.tcx.sess, self.span_of_impl(impl1_def_id), E0119,
+        self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
+    }
+
+    fn report_overlap_error(&self, trait_def_id: ast::DefId,
+                            impl1: ast::DefId, impl2: ast::DefId) {
+
+        span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119,
                   "conflicting implementations for trait `{}`",
                   ty::item_path_str(self.tcx, trait_def_id));
 
-        if impl2_def_id.krate == ast::LOCAL_CRATE {
-            span_note!(self.tcx.sess, self.span_of_impl(impl2_def_id),
+        self.report_overlap_note(impl1, impl2);
+    }
+
+    fn report_overlap_note(&self, impl1: ast::DefId, impl2: ast::DefId) {
+
+        if impl2.krate == ast::LOCAL_CRATE {
+            span_note!(self.tcx.sess, self.span_of_impl(impl2),
                        "note conflicting implementation here");
         } else {
             let crate_store = &self.tcx.sess.cstore;
-            let cdata = crate_store.get_crate_data(impl2_def_id.krate);
-            span_note!(self.tcx.sess, self.span_of_impl(impl1_def_id),
+            let cdata = crate_store.get_crate_data(impl2.krate);
+            span_note!(self.tcx.sess, self.span_of_impl(impl1),
                        "conflicting implementation in crate `{}`",
                        cdata.name);
         }
@@ -111,3 +128,33 @@ fn span_of_impl(&self, impl_did: ast::DefId) -> Span {
         self.tcx.map.span(impl_did.node)
     }
 }
+
+
+impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
+    fn visit_item(&mut self, item: &'v ast::Item) {
+        match item.node {
+            ast::ItemDefaultImpl(_, _) => {
+                let impl_def_id = ast_util::local_def(item.id);
+                match ty::impl_trait_ref(self.tcx, impl_def_id) {
+                    Some(ref trait_ref) => {
+                        match ty::trait_default_impl(self.tcx, trait_ref.def_id) {
+                            Some(other_impl) if other_impl != impl_def_id => {
+                                self.report_overlap_error(trait_ref.def_id,
+                                                          other_impl,
+                                                          impl_def_id);
+                            }
+                            Some(_) => {}
+                            None => {
+                                self.tcx.sess.bug(
+                                          &format!("no default implementation recorded for `{:?}`",
+                                          item));
+                            }
+                        }
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+    }
+}
index 0b78af18e2617b2869bba2d8431488275e11f620..74fed6cbf3937364db6459f02cb83cd4b3975509 100644 (file)
@@ -91,19 +91,19 @@ trait hierarchy is only necessary for shorthands like `T::X` or
 use middle::lang_items::SizedTraitLangItem;
 use middle::region;
 use middle::resolve_lifetime;
-use middle::subst;
-use middle::subst::{Substs, SelfSpace, TypeSpace, VecPerParamSpace};
+use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
 use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
-use middle::ty::{self, RegionEscape, Ty, TypeScheme};
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::infer;
 use rscope::*;
-use util::common::memoized;
+use util::common::{ErrorReported, memoized};
 use util::nodemap::{FnvHashMap, FnvHashSet};
 use util::ppaux;
 use util::ppaux::{Repr,UserString};
 use write_ty_to_tcx;
 
+use std::cell::RefCell;
 use std::collections::HashSet;
 use std::rc::Rc;
 
@@ -121,7 +121,7 @@ trait hierarchy is only necessary for shorthands like `T::X` or
 // Main entry point
 
 pub fn collect_item_types(tcx: &ty::ctxt) {
-    let ccx = &CollectCtxt { tcx: tcx };
+    let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
 
     match ccx.tcx.lang_items.ty_desc() {
         Some(id) => { collect_intrinsic_type(ccx, id); }
@@ -141,17 +141,43 @@ pub fn collect_item_types(tcx: &ty::ctxt) {
 
 ///////////////////////////////////////////////////////////////////////////
 
-struct CollectCtxt<'a,'tcx:'a> {
+struct CrateCtxt<'a,'tcx:'a> {
     tcx: &'a ty::ctxt<'tcx>,
+
+    // This stack is used to identify cycles in the user's source.
+    // Note that these cycles can cross multiple items.
+    stack: RefCell<Vec<AstConvRequest>>,
+}
+
+/// Context specific to some particular item. This is what implements
+/// AstConv. It has information about the predicates that are defined
+/// on the trait. Unfortunately, this predicate information is
+/// available in various different forms at various points in the
+/// process. So we can't just store a pointer to e.g. the AST or the
+/// parsed ty form, we have to be more flexible. To this end, the
+/// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
+/// that it uses to satisfy `get_type_parameter_bounds` requests.
+/// This object might draw the information from the AST
+/// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
+/// or both (a tuple).
+struct ItemCtxt<'a,'tcx:'a> {
+    ccx: &'a CrateCtxt<'a,'tcx>,
+    param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
+}
+
+#[derive(Copy, PartialEq, Eq)]
+enum AstConvRequest {
+    GetItemTypeScheme(ast::DefId),
+    GetTraitDef(ast::DefId),
+    GetTypeParameterBounds(ast::NodeId),
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Zeroth phase: collect types of intrinsics
 
-fn collect_intrinsic_type(ccx: &CollectCtxt,
+fn collect_intrinsic_type(ccx: &CrateCtxt,
                           lang_item: ast::DefId) {
-    let ty::TypeScheme { ty, .. } =
-        ccx.get_item_type_scheme(lang_item);
+    let ty::TypeScheme { ty, .. } = type_scheme_of_def_id(ccx, lang_item);
     ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
 }
 
@@ -161,7 +187,7 @@ fn collect_intrinsic_type(ccx: &CollectCtxt,
 // know later when parsing field defs.
 
 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
-    ccx: &'a CollectCtxt<'a, 'tcx>
+    ccx: &'a CrateCtxt<'a, 'tcx>
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
@@ -182,7 +208,7 @@ fn visit_item(&mut self, i: &ast::Item) {
 // Second phase: collection proper.
 
 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
-    ccx: &'a CollectCtxt<'a, 'tcx>
+    ccx: &'a CrateCtxt<'a, 'tcx>
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
@@ -199,42 +225,143 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
 ///////////////////////////////////////////////////////////////////////////
 // Utility types and common code for the above passes.
 
-pub trait ToTy<'tcx> {
-    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
-}
+impl<'a,'tcx> CrateCtxt<'a,'tcx> {
+    fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
+        ItemCtxt { ccx: self, param_bounds: param_bounds }
+    }
 
-impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
-    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
-        ast_ty_to_ty(self, rs, ast_ty)
+    fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
+        let def_id = local_def(method_id);
+        match self.tcx.impl_or_trait_items.borrow()[def_id] {
+            ty::MethodTraitItem(ref mty) => mty.clone(),
+            ty::TypeTraitItem(..) => {
+                self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
+            }
+        }
     }
-}
 
-impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
+    fn cycle_check<F,R>(&self,
+                        span: Span,
+                        request: AstConvRequest,
+                        code: F)
+                        -> Result<R,ErrorReported>
+        where F: FnOnce() -> R
+    {
+        {
+            let mut stack = self.stack.borrow_mut();
+            match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
+                None => { }
+                Some((i, _)) => {
+                    let cycle = &stack[i..];
+                    self.report_cycle(span, cycle);
+                    return Err(ErrorReported);
+                }
+            }
+            stack.push(request);
+        }
+
+        let result = code();
 
-    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
-        if id.krate != ast::LOCAL_CRATE {
-            return ty::lookup_item_type(self.tcx, id);
+        self.stack.borrow_mut().pop();
+        Ok(result)
+    }
+
+    fn report_cycle(&self,
+                    span: Span,
+                    cycle: &[AstConvRequest])
+    {
+        assert!(!cycle.is_empty());
+        let tcx = self.tcx;
+
+        tcx.sess.span_err(
+            span,
+            &format!("unsupported cyclic reference between types/traits detected"));
+
+        match cycle[0] {
+            AstConvRequest::GetItemTypeScheme(def_id) |
+            AstConvRequest::GetTraitDef(def_id) => {
+                tcx.sess.note(
+                    &format!("the cycle begins when processing `{}`...",
+                             ty::item_path_str(tcx, def_id)));
+            }
+            AstConvRequest::GetTypeParameterBounds(id) => {
+                let def = tcx.type_parameter_def(id);
+                tcx.sess.note(
+                    &format!("the cycle begins when computing the bounds \
+                              for type parameter `{}`...",
+                             def.name.user_string(tcx)));
+            }
         }
 
-        match self.tcx.map.find(id.node) {
-            Some(ast_map::NodeItem(item)) => {
-                type_scheme_of_item(self, &*item)
+        for request in cycle[1..].iter() {
+            match *request {
+                AstConvRequest::GetItemTypeScheme(def_id) |
+                AstConvRequest::GetTraitDef(def_id) => {
+                    tcx.sess.note(
+                        &format!("...which then requires processing `{}`...",
+                                 ty::item_path_str(tcx, def_id)));
+                }
+                AstConvRequest::GetTypeParameterBounds(id) => {
+                    let def = tcx.type_parameter_def(id);
+                    tcx.sess.note(
+                        &format!("...which then requires computing the bounds \
+                                  for type parameter `{}`...",
+                                 def.name.user_string(tcx)));
+                }
             }
-            Some(ast_map::NodeForeignItem(foreign_item)) => {
-                let abi = self.tcx.map.get_foreign_abi(id.node);
-                type_scheme_of_foreign_item(self, &*foreign_item, abi)
+        }
+
+        match cycle[0] {
+            AstConvRequest::GetItemTypeScheme(def_id) |
+            AstConvRequest::GetTraitDef(def_id) => {
+                tcx.sess.note(
+                    &format!("...which then again requires processing `{}`, completing the cycle.",
+                             ty::item_path_str(tcx, def_id)));
             }
-            x => {
-                self.tcx.sess.bug(&format!("unexpected sort of node \
-                                            in get_item_type_scheme(): {:?}",
-                                           x));
+            AstConvRequest::GetTypeParameterBounds(id) => {
+                let def = tcx.type_parameter_def(id);
+                tcx.sess.note(
+                    &format!("...which then again requires computing the bounds \
+                              for type parameter `{}`, completing the cycle.",
+                             def.name.user_string(tcx)));
             }
         }
     }
+}
+
+impl<'a,'tcx> ItemCtxt<'a,'tcx> {
+    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
+        ast_ty_to_ty(self, rs, ast_ty)
+    }
+}
+
+impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
+    fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
+
+    fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
+                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>
+    {
+        self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
+            type_scheme_of_def_id(self.ccx, id)
+        })
+    }
+
+    fn get_trait_def(&self, span: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
+    {
+        self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
+            get_trait_def(self.ccx, id)
+        })
+    }
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        get_trait_def(self, id)
+    fn get_type_parameter_bounds(&self,
+                                 span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
+    {
+        self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
+            self.param_bounds.get_type_parameter_bounds(self, span, node_id)
+        })
     }
 
     fn ty_infer(&self, span: Span) -> Ty<'tcx> {
@@ -253,11 +380,147 @@ fn projected_ty(&self,
     }
 }
 
-fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+/// Interface used to find the bounds on a type parameter from within
+/// an `ItemCtxt`. This allows us to use multiple kinds of sources.
+trait GetTypeParameterBounds<'tcx> {
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>;
+}
+
+/// Find bounds from both elements of the tuple.
+impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
+    where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
+{
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
+        v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id).into_iter());
+        v
+    }
+}
+
+/// Empty set of bounds.
+impl<'tcx> GetTypeParameterBounds<'tcx> for () {
+    fn get_type_parameter_bounds(&self,
+                                 _astconv: &AstConv<'tcx>,
+                                 _span: Span,
+                                 _node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        Vec::new()
+    }
+}
+
+/// Find bounds from the parsed and converted predicates.  This is
+/// used when converting methods, because by that time the predicates
+/// from the trait/impl have been fully converted.
+impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 _span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        let def = astconv.tcx().type_parameter_def(node_id);
+
+        self.predicates
+            .iter()
+            .filter_map(|predicate| {
+                match *predicate {
+                    ty::Predicate::Trait(ref data) => {
+                        if data.0.self_ty().is_param(def.space, def.index) {
+                            Some(data.to_poly_trait_ref())
+                        } else {
+                            None
+                        }
+                    }
+                    ty::Predicate::Equate(..) |
+                    ty::Predicate::RegionOutlives(..) |
+                    ty::Predicate::TypeOutlives(..) |
+                    ty::Predicate::Projection(..) => {
+                        None
+                    }
+                }
+            })
+            .collect()
+    }
+}
+
+/// Find bounds from ast::Generics. This requires scanning through the
+/// AST. We do this to avoid having to convert *all* the bounds, which
+/// would create artificial cycles. Instead we can only convert the
+/// bounds for those a type parameter `X` if `X::Foo` is used.
+impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 _: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        // In the AST, bounds can derive from two places. Either
+        // written inline like `<T:Foo>` or in a where clause like
+        // `where T:Foo`.
+
+        let def = astconv.tcx().type_parameter_def(node_id);
+        let ty = ty::mk_param_from_def(astconv.tcx(), &def);
+
+        let from_ty_params =
+            self.ty_params
+                .iter()
+                .filter(|p| p.id == node_id)
+                .flat_map(|p| p.bounds.iter())
+                .filter_map(|b| poly_trait_ref_from_bound(astconv, ty, b, &mut Vec::new()));
+
+        let from_where_clauses =
+            self.where_clause
+                .predicates
+                .iter()
+                .filter_map(|wp| match *wp {
+                    ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
+                    _ => None
+                })
+                .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
+                .flat_map(|bp| bp.bounds.iter())
+                .filter_map(|b| poly_trait_ref_from_bound(astconv, ty, b, &mut Vec::new()));
+
+        from_ty_params.chain(from_where_clauses).collect()
+    }
+}
+
+/// Tests whether this is the AST for a reference to the type
+/// parameter with id `param_id`. We use this so as to avoid running
+/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
+/// conversion of the type to avoid inducing unnecessary cycles.
+fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
+                  ast_ty: &ast::Ty,
+                  param_id: ast::NodeId)
+                  -> bool
+{
+    if let ast::TyPath(None, _) = ast_ty.node {
+        let path_res = tcx.def_map.borrow()[ast_ty.id];
+        if let def::DefTyParam(_, _, def_id, _) = path_res.base_def {
+            path_res.depth == 0 && def_id == local_def(param_id)
+        } else {
+            false
+        }
+    } else {
+        false
+    }
+}
+
+fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     enum_scheme: ty::TypeScheme<'tcx>,
                                     enum_predicates: ty::GenericPredicates<'tcx>,
                                     variants: &[P<ast::Variant>]) {
     let tcx = ccx.tcx;
+    let icx = ccx.icx(&enum_predicates);
 
     // Create a set of parameter types shared among all the variants.
     for variant in variants {
@@ -268,8 +531,8 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         let result_ty = match variant.node.kind {
             ast::TupleVariantKind(ref args) if args.len() > 0 => {
                 let rs = ExplicitRscope;
-                let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
-                ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[..], enum_scheme.ty)
+                let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
+                ty::mk_ctor_fn(tcx, variant_def_id, &input_tys, enum_scheme.ty)
             }
 
             ast::TupleVariantKind(_) => {
@@ -294,7 +557,7 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
                                    trait_def: &ty::TraitDef<'tcx>,
                                    trait_predicates: &ty::GenericPredicates<'tcx>) {
@@ -393,7 +656,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         }
     }
 
-    fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
+    fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
         ccx.tcx.tcache.borrow_mut().insert(
             m.def_id,
             TypeScheme {
@@ -405,7 +668,7 @@ fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
             m.predicates.clone());
     }
 
-    fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                            trait_id: ast::NodeId,
                                            trait_generics: &ty::Generics<'tcx>,
                                            trait_bounds: &ty::GenericPredicates<'tcx>,
@@ -417,21 +680,17 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                            m_generics: &ast::Generics,
                                            m_unsafety: &ast::Unsafety,
                                            m_decl: &ast::FnDecl)
-                                           -> ty::Method<'tcx> {
+                                           -> ty::Method<'tcx>
+    {
         let ty_generics =
-            ty_generics_for_fn_or_method(ccx,
-                                         m_generics,
-                                         trait_generics.clone());
+            ty_generics_for_fn(ccx, m_generics, trait_generics);
 
-        let ty_bounds =
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               m_generics,
-                                               &ty_generics,
-                                               trait_bounds.clone());
+        let ty_generic_predicates =
+            ty_generic_predicates_for_fn(ccx, m_generics, trait_bounds);
 
         let (fty, explicit_self_category) = {
             let trait_self_ty = ty::mk_self_type(ccx.tcx);
-            astconv::ty_of_method(ccx,
+            astconv::ty_of_method(&ccx.icx(&(trait_bounds, m_generics)),
                                   *m_unsafety,
                                   trait_self_ty,
                                   m_explicit_self,
@@ -442,7 +701,7 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ty::Method::new(
             *m_name,
             ty_generics,
-            ty_bounds,
+            ty_generic_predicates,
             fty,
             explicit_self_category,
             // assume public, because this is only invoked on trait methods
@@ -454,12 +713,14 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
-                                struct_generics: &ty::Generics<'tcx>,
-                                struct_predicates: &ty::GenericPredicates<'tcx>,
-                                v: &ast::StructField,
-                                origin: ast::DefId) -> ty::field_ty {
-    let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
+fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                           struct_generics: &ty::Generics<'tcx>,
+                           struct_predicates: &ty::GenericPredicates<'tcx>,
+                           v: &ast::StructField,
+                           origin: ast::DefId)
+                           -> ty::field_ty
+{
+    let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
 
     /* add the field to the tcache */
@@ -491,7 +752,7 @@ fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      trait_def: &ty::TraitDef<'tcx>,
                                      associated_type: &ast::AssociatedType)
 {
@@ -504,18 +765,18 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     ccx.tcx
        .impl_or_trait_items
        .borrow_mut()
-       .insert(associated_type.def_id,
-               ty::TypeTraitItem(associated_type));
+       .insert(associated_type.def_id, ty::TypeTraitItem(associated_type));
 }
 
-fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                                  container: ImplOrTraitItemContainer,
                                  ms: I,
                                  untransformed_rcvr_ty: Ty<'tcx>,
                                  rcvr_ty_generics: &ty::Generics<'tcx>,
                                  rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,
                                  rcvr_visibility: ast::Visibility)
-                                 where I: Iterator<Item=&'i ast::Method> {
+                                 where I: Iterator<Item=&'i ast::Method>
+{
     debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
            untransformed_rcvr_ty.repr(ccx.tcx),
            rcvr_ty_generics.repr(ccx.tcx));
@@ -559,31 +820,28 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
            .insert(mty.def_id, ty::MethodTraitItem(mty));
     }
 
-    fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               container: ImplOrTraitItemContainer,
                               m: &ast::Method,
                               untransformed_rcvr_ty: Ty<'tcx>,
                               rcvr_ty_generics: &ty::Generics<'tcx>,
                               rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,
                               rcvr_visibility: ast::Visibility)
-                              -> ty::Method<'tcx> {
+                              -> ty::Method<'tcx>
+    {
         let m_ty_generics =
-            ty_generics_for_fn_or_method(ccx,
-                                         m.pe_generics(),
-                                         rcvr_ty_generics.clone());
-
-        let m_ty_bounds =
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               m.pe_generics(),
-                                               &m_ty_generics,
-                                               rcvr_ty_predicates.clone());
-
-        let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
-                                                                  m.pe_unsafety(),
-                                                                  untransformed_rcvr_ty,
-                                                                  m.pe_explicit_self(),
-                                                                  &*m.pe_fn_decl(),
-                                                                  m.pe_abi());
+            ty_generics_for_fn(ccx, m.pe_generics(), rcvr_ty_generics);
+
+        let m_ty_generic_predicates =
+            ty_generic_predicates_for_fn(ccx, m.pe_generics(), rcvr_ty_predicates);
+
+        let (fty, explicit_self_category) =
+            astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, m.pe_generics())),
+                                  m.pe_unsafety(),
+                                  untransformed_rcvr_ty,
+                                  m.pe_explicit_self(),
+                                  &*m.pe_fn_decl(),
+                                  m.pe_abi());
 
         // if the method specifies a visibility, use that, otherwise
         // inherit the visibility from the impl (so `foo` in `pub impl
@@ -593,7 +851,7 @@ fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 
         ty::Method::new(m.pe_ident().name,
                         m_ty_generics,
-                        m_ty_bounds,
+                        m_ty_generic_predicates,
                         fty,
                         explicit_self_category,
                         method_vis,
@@ -603,7 +861,7 @@ fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
+fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                                  span: Span,
                                  generics: &ast::Generics,
                                  thing: &'static str) {
@@ -632,7 +890,7 @@ fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
     }
 }
 
-fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
+fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
     let tcx = ccx.tcx;
     debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
     match it.node {
@@ -648,6 +906,16 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                                    predicates,
                                    &enum_definition.variants);
         },
+        ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
+            let trait_ref = astconv::instantiate_trait_ref(&ccx.icx(&()),
+                                                           &ExplicitRscope,
+                                                           ast_trait_ref,
+                                                           Some(it.id),
+                                                           None,
+                                                           None);
+
+            ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id))
+        }
         ast::ItemImpl(_, _,
                       ref generics,
                       ref opt_trait_ref,
@@ -657,11 +925,11 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
 
             debug!("convert: ast_generics={:?}", generics);
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
-            let ty_predicates = ty_generic_bounds_for_type_or_impl(ccx, &ty_generics, generics);
+            let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
 
             debug!("convert: impl_bounds={:?}", ty_predicates);
 
-            let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
+            let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
 
             tcx.tcache.borrow_mut().insert(local_def(it.id),
@@ -685,12 +953,6 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
             for impl_item in impl_items {
                 match *impl_item {
                     ast::MethodImplItem(ref method) => {
-                        let body_id = method.pe_body().id;
-                        check_method_self_type(ccx,
-                                               &BindingRscope::new(),
-                                               selfty,
-                                               method.pe_explicit_self(),
-                                               body_id);
                         methods.push(&**method);
                     }
                     ast::TypeImplItem(ref typedef) => {
@@ -699,7 +961,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                                               "associated items are not allowed in inherent impls");
                         }
 
-                        let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
+                        let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &*typedef.typ);
                         tcx.tcache.borrow_mut().insert(local_def(typedef.id),
                                                        TypeScheme {
                                                            generics: ty::Generics::empty(),
@@ -731,10 +993,26 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                             &ty_predicates,
                             parent_visibility);
 
+            for impl_item in impl_items {
+                match *impl_item {
+                    ast::MethodImplItem(ref method) => {
+                        let body_id = method.pe_body().id;
+                        check_method_self_type(ccx,
+                                               &BindingRscope::new(),
+                                               ccx.method_ty(method.id),
+                                               selfty,
+                                               method.pe_explicit_self(),
+                                               body_id);
+                    }
+                    ast::TypeImplItem(..) => { }
+                }
+            }
+
             if let Some(ref trait_ref) = *opt_trait_ref {
-                astconv::instantiate_trait_ref(ccx,
+                astconv::instantiate_trait_ref(&ccx.icx(&ty_predicates),
                                                &ExplicitRscope,
                                                trait_ref,
+                                               Some(it.id),
                                                Some(selfty),
                                                None);
             }
@@ -743,20 +1021,42 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                                                    generics,
                                                    local_def(it.id));
         },
-        ast::ItemTrait(_, _, _, ref trait_methods) => {
+        ast::ItemTrait(_, _, _, ref trait_items) => {
             let trait_def = trait_def_of_item(ccx, it);
             convert_trait_predicates(ccx, it);
             let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(it.id));
 
             debug!("convert: trait_bounds={:?}", trait_predicates);
 
-            for trait_method in trait_methods {
+            // Run convert_methods on the provided methods.
+            let untransformed_rcvr_ty = ty::mk_self_type(tcx);
+            convert_methods(ccx,
+                            TraitContainer(local_def(it.id)),
+                            trait_items.iter().filter_map(|m| match *m {
+                                ast::RequiredMethod(_) => None,
+                                ast::ProvidedMethod(ref m) => Some(&**m),
+                                ast::TypeTraitItem(_) => None,
+                            }),
+                            untransformed_rcvr_ty,
+                            &trait_def.generics,
+                            &trait_predicates,
+                            it.vis);
+
+            // We need to do this *after* converting methods, since
+            // convert_methods produces a tcache entry that is wrong for
+            // static trait methods. This is somewhat unfortunate.
+            collect_trait_methods(ccx, it.id, &*trait_def, &trait_predicates);
+
+            // This must be done after `collect_trait_methods` so that
+            // we have a method type stored for every method.
+            for trait_item in trait_items {
                 let self_type = ty::mk_self_type(tcx);
-                match *trait_method {
+                match *trait_item {
                     ast::RequiredMethod(ref type_method) => {
                         let rscope = BindingRscope::new();
                         check_method_self_type(ccx,
                                                &rscope,
+                                               ccx.method_ty(type_method.id),
                                                self_type,
                                                &type_method.explicit_self,
                                                it.id)
@@ -764,6 +1064,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                     ast::ProvidedMethod(ref method) => {
                         check_method_self_type(ccx,
                                                &BindingRscope::new(),
+                                               ccx.method_ty(method.id),
                                                self_type,
                                                method.pe_explicit_self(),
                                                it.id)
@@ -775,25 +1076,6 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                     }
                 }
             }
-
-            // Run convert_methods on the provided methods.
-            let untransformed_rcvr_ty = ty::mk_self_type(tcx);
-            convert_methods(ccx,
-                            TraitContainer(local_def(it.id)),
-                            trait_methods.iter().filter_map(|m| match *m {
-                                ast::RequiredMethod(_) => None,
-                                ast::ProvidedMethod(ref m) => Some(&**m),
-                                ast::TypeTraitItem(_) => None,
-                            }),
-                            untransformed_rcvr_ty,
-                            &trait_def.generics,
-                            &trait_predicates,
-                            it.vis);
-
-            // We need to do this *after* converting methods, since
-            // convert_methods produces a tcache entry that is wrong for
-            // static trait methods. This is somewhat unfortunate.
-            collect_trait_methods(ccx, it.id, &*trait_def, &trait_predicates);
         },
         ast::ItemStruct(ref struct_def, _) => {
             // Write the class type.
@@ -816,7 +1098,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
     }
 }
 
-fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             struct_def: &ast::StructDef,
                             scheme: ty::TypeScheme<'tcx>,
                             predicates: ty::GenericPredicates<'tcx>,
@@ -886,7 +1168,7 @@ fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            trait_id: ast::DefId)
                            -> Rc<ty::TraitDef<'tcx>> {
     let tcx = ccx.tcx;
@@ -899,12 +1181,12 @@ fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ast_map::NodeItem(item) => trait_def_of_item(ccx, &*item),
         _ => {
             tcx.sess.bug(&format!("get_trait_def({}): not an item",
-                                  trait_id.node)[])
+                                  trait_id.node))
         }
     }
 }
 
-fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                it: &ast::Item)
                                -> Rc<ty::TraitDef<'tcx>>
 {
@@ -925,7 +1207,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ref s => {
             tcx.sess.span_bug(
                 it.span,
-                &format!("trait_def_of_item invoked on {:?}", s)[]);
+                &format!("trait_def_of_item invoked on {:?}", s));
         }
     };
 
@@ -947,7 +1229,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     let self_param_ty = ty::ParamTy::for_self().to_ty(ccx.tcx);
 
     // supertraits:
-    let bounds = compute_bounds(ccx,
+    let bounds = compute_bounds(&ccx.icx(generics),
                                 self_param_ty,
                                 bounds,
                                 SizedByDefault::No,
@@ -981,9 +1263,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 
     return trait_def;
 
-    fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                  generics: &ast::Generics)
-                                 -> subst::Substs<'tcx>
+                                 -> Substs<'tcx>
     {
         let tcx = ccx.tcx;
 
@@ -993,7 +1275,7 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                     .iter()
                     .enumerate()
                     .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
-                                                     subst::TypeSpace,
+                                                     TypeSpace,
                                                      i as u32,
                                                      def.lifetime.name))
                     .collect();
@@ -1003,18 +1285,18 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
             generics.ty_params
                     .iter()
                     .enumerate()
-                    .map(|(i, def)| ty::mk_param(tcx, subst::TypeSpace,
+                    .map(|(i, def)| ty::mk_param(tcx, TypeSpace,
                                                  i as u32, def.ident.name))
                     .collect();
 
         // ...and also create the `Self` parameter.
         let self_ty = ty::mk_self_type(tcx);
 
-        subst::Substs::new_trait(types, regions, self_ty)
+        Substs::new_trait(types, regions, self_ty)
     }
 }
 
-fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item) {
+fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
     let tcx = ccx.tcx;
     let trait_def = trait_def_of_item(ccx, it);
 
@@ -1025,7 +1307,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Ite
         ref s => {
             tcx.sess.span_bug(
                 it.span,
-                &format!("trait_def_of_item invoked on {:?}", s)[]);
+                &format!("trait_def_of_item invoked on {:?}", s));
         }
     };
 
@@ -1033,9 +1315,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Ite
 
     let super_predicates = ty::predicates(ccx.tcx, self_param_ty, &trait_def.bounds);
 
-    let assoc_predicates = predicates_for_associated_types(ccx, &trait_def.trait_ref, items);
-
-    // `ty_generic_bounds` below will consider the bounds on the type
+    // `ty_generic_predicates` below will consider the bounds on the type
     // parameters (including `Self`) and the explicit where-clauses,
     // but to get the full set of predicates on a trait we need to add
     // in the supertrait bounds and anything declared on the
@@ -1044,27 +1324,31 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Ite
         ty::GenericPredicates {
             predicates: VecPerParamSpace::new(super_predicates, vec![], vec![])
         };
-    base_predicates.predicates.extend(subst::TypeSpace, assoc_predicates.into_iter());
 
-    let self_bounds = &trait_def.generics.types.get_self().unwrap().bounds;
-    base_predicates.predicates.extend(
-        subst::SelfSpace,
-        ty::predicates(ccx.tcx, self_param_ty, self_bounds).into_iter());
+    // Add in a predicate that `Self:Trait` (where `Trait` is the
+    // current trait).  This is needed for builtin bounds.
+    let self_predicate = trait_def.trait_ref.to_poly_trait_ref().as_predicate();
+    base_predicates.predicates.push(SelfSpace, self_predicate);
 
     // add in the explicit where-clauses
-    let trait_predicates =
-        ty_generic_bounds(ccx,
-                          subst::TypeSpace,
-                          &trait_def.generics,
-                          base_predicates,
-                          &generics.where_clause);
+    let mut trait_predicates =
+        ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
+
+    let assoc_predicates = predicates_for_associated_types(ccx,
+                                                           generics,
+                                                           &trait_predicates,
+                                                           &trait_def.trait_ref,
+                                                           items);
+    trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
 
     let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
     assert!(prev_predicates.is_none());
 
     return;
 
-    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                                 ast_generics: &ast::Generics,
+                                                 trait_predicates: &ty::GenericPredicates<'tcx>,
                                                  self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
                                                  trait_items: &[ast::TraitItem])
                                                  -> Vec<ty::Predicate<'tcx>>
@@ -1083,7 +1367,7 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                                  self_trait_ref.clone(),
                                                  assoc_type_def.ident.name);
 
-                let bounds = compute_bounds(ccx,
+                let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
                                             assoc_ty,
                                             &*assoc_type_def.bounds,
                                             SizedByDefault::Yes,
@@ -1095,7 +1379,31 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                  def_id: ast::DefId)
+                                  -> ty::TypeScheme<'tcx>
+{
+    if def_id.krate != ast::LOCAL_CRATE {
+        return ty::lookup_item_type(ccx.tcx, def_id);
+    }
+
+    match ccx.tcx.map.find(def_id.node) {
+        Some(ast_map::NodeItem(item)) => {
+            type_scheme_of_item(ccx, &*item)
+        }
+        Some(ast_map::NodeForeignItem(foreign_item)) => {
+            let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
+            type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
+        }
+        x => {
+            ccx.tcx.sess.bug(&format!("unexpected sort of node \
+                                            in get_item_type_scheme(): {:?}",
+                                       x));
+        }
+    }
+}
+
+fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                 it: &ast::Item)
                                 -> ty::TypeScheme<'tcx>
 {
@@ -1104,28 +1412,25 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
              |_| compute_type_scheme_of_item(ccx, it))
 }
 
-
-fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                              it: &ast::Item)
-                                              -> ty::TypeScheme<'tcx>
+fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                        it: &ast::Item)
+                                        -> ty::TypeScheme<'tcx>
 {
     let tcx = ccx.tcx;
     match it.node {
         ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
-            let ty = ccx.to_ty(&ExplicitRscope, &**t);
+            let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
         }
         ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
-            let ty_generics = ty_generics_for_fn_or_method(ccx,
-                                                           generics,
-                                                           ty::Generics::empty());
-            let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
+            let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
+            let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
             let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         ast::ItemTy(ref t, ref generics) => {
-            let ty = ccx.to_ty(&ExplicitRscope, &**t);
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
+            let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         ast::ItemEnum(_, ref generics) => {
@@ -1141,6 +1446,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
             let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
+        ast::ItemDefaultImpl(..) |
         ast::ItemTrait(..) |
         ast::ItemImpl(..) |
         ast::ItemMod(..) |
@@ -1156,7 +1462,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     }
 }
 
-fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 it: &ast::Item)
                                 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
 {
@@ -1169,20 +1475,18 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
             ty::GenericPredicates::empty()
         }
         ast::ItemFn(_, _, _, ref ast_generics, _) => {
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               ast_generics,
-                                               &scheme.generics,
-                                               ty::GenericPredicates::empty())
+            ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
         }
         ast::ItemTy(_, ref generics) => {
-            ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
+            ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
         ast::ItemEnum(_, ref generics) => {
-            ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
+            ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
         ast::ItemStruct(_, ref generics) => {
-            ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
+            ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
+        ast::ItemDefaultImpl(..) |
         ast::ItemTrait(..) |
         ast::ItemExternCrate(..) |
         ast::ItemUse(..) |
@@ -1192,8 +1496,8 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ast::ItemMac(..) => {
             tcx.sess.span_bug(
                 it.span,
-                format!("compute_type_scheme_of_item: unexpected item type: {:?}",
-                        it.node).as_slice());
+                &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
+                         it.node));
         }
     };
 
@@ -1209,7 +1513,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                      Some(ty::ObjectLifetimeDefault::Specific(r)) =>
                                          r.user_string(tcx),
                                      d =>
-                                         d.repr(ccx.tcx()),
+                                         d.repr(ccx.tcx),
                                  })
                                  .collect::<Vec<String>>()
                                  .connect(",");
@@ -1221,18 +1525,18 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 }
 
 fn type_scheme_of_foreign_item<'a, 'tcx>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     it: &ast::ForeignItem,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
-    memoized(&ccx.tcx().tcache,
+    memoized(&ccx.tcx.tcache,
              local_def(it.id),
              |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
 }
 
 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     it: &ast::ForeignItem,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
@@ -1244,13 +1548,13 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
         ast::ForeignItemStatic(ref t, _) => {
             ty::TypeScheme {
                 generics: ty::Generics::empty(),
-                ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
+                ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
             }
         }
     }
 }
 
-fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                   it: &ast::ForeignItem)
 {
     // For reasons I cannot fully articulate, I do so hate the AST
@@ -1265,10 +1569,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 
     let predicates = match it.node {
         ast::ForeignItemFn(_, ref generics) => {
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               generics,
-                                               &scheme.generics,
-                                               ty::GenericPredicates::empty())
+            ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
         }
         ast::ForeignItemStatic(..) => {
             ty::GenericPredicates::empty()
@@ -1279,45 +1580,29 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     assert!(prev_predicates.is_none());
 }
 
-fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                           generics: &ast::Generics)
                                           -> ty::Generics<'tcx> {
-    ty_generics(ccx,
-                subst::TypeSpace,
-                &generics.lifetimes[],
-                &generics.ty_params[],
-                &generics.where_clause,
-                ty::Generics::empty())
+    ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
 }
 
-fn ty_generic_bounds_for_type_or_impl<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                               ty_generics: &ty::Generics<'tcx>,
-                                               generics: &ast::Generics)
-                                               -> ty::GenericPredicates<'tcx>
+fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                                   generics: &ast::Generics)
+                                                   -> ty::GenericPredicates<'tcx>
 {
-    ty_generic_bounds(ccx,
-                      subst::TypeSpace,
-                      ty_generics,
-                      ty::GenericPredicates::empty(),
-                      &generics.where_clause)
+    ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
 }
 
-fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
-                                   substs: &'tcx subst::Substs<'tcx>,
+                                   substs: &'tcx Substs<'tcx>,
                                    ast_generics: &ast::Generics)
                                    -> ty::Generics<'tcx>
 {
     debug!("ty_generics_for_trait(trait_id={}, substs={})",
            local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
 
-    let mut generics =
-        ty_generics(ccx,
-                    subst::TypeSpace,
-                    &ast_generics.lifetimes[],
-                    &ast_generics.ty_params[],
-                    &ast_generics.where_clause,
-                    ty::Generics::empty());
+    let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
 
     // Add in the self type parameter.
     //
@@ -1325,65 +1610,46 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     // the node id for the Self type parameter.
     let param_id = trait_id;
 
-    let self_trait_ref =
-        Rc::new(ty::TraitRef { def_id: local_def(trait_id),
-                               substs: substs });
-
     let def = ty::TypeParameterDef {
-        space: subst::SelfSpace,
+        space: SelfSpace,
         index: 0,
         name: special_idents::type_self.name,
         def_id: local_def(param_id),
-        bounds: ty::ParamBounds {
-            region_bounds: vec!(),
-            builtin_bounds: ty::empty_builtin_bounds(),
-            trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
-            projection_bounds: vec!(),
-        },
         default: None,
         object_lifetime_default: None,
     };
 
     ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
 
-    generics.types.push(subst::SelfSpace, def);
+    generics.types.push(SelfSpace, def);
 
     return generics;
 }
 
-fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                         generics: &ast::Generics,
-                                         base_generics: ty::Generics<'tcx>)
-                                         -> ty::Generics<'tcx>
+fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                               generics: &ast::Generics,
+                               base_generics: &ty::Generics<'tcx>)
+                               -> ty::Generics<'tcx>
 {
-    let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
-    ty_generics(ccx,
-                subst::FnSpace,
-                &early_lifetimes[..],
-                &generics.ty_params[],
-                &generics.where_clause,
-                base_generics)
+    ty_generics(ccx, FnSpace, generics, base_generics)
 }
 
-fn ty_generic_bounds_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                               generics: &ast::Generics,
-                                               ty_generics: &ty::Generics<'tcx>,
-                                               base: ty::GenericPredicates<'tcx>)
-                                               -> ty::GenericPredicates<'tcx>
+fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                         generics: &ast::Generics,
+                                         base_predicates: &ty::GenericPredicates<'tcx>)
+                                         -> ty::GenericPredicates<'tcx>
 {
-    ty_generic_bounds(ccx,
-                      subst::FnSpace,
-                      ty_generics,
-                      base,
-                      &generics.where_clause)
+    ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                              bounds: &mut ty::BuiltinBounds,
-                              ast_bounds: &[ast::TyParamBound],
-                              span: Span)
+fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
+                           bounds: &mut ty::BuiltinBounds,
+                           ast_bounds: &[ast::TyParamBound],
+                           span: Span)
 {
+    let tcx = astconv.tcx();
+
     // Try to find an unbound in bounds.
     let mut unbound = None;
     for ab in ast_bounds {
@@ -1392,80 +1658,108 @@ fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                 assert!(ptr.bound_lifetimes.is_empty());
                 unbound = Some(ptr.trait_ref.clone());
             } else {
-                span_err!(ccx.tcx.sess, span, E0203,
+                span_err!(tcx.sess, span, E0203,
                           "type parameter has more than one relaxed default \
                                                 bound, only one is supported");
             }
         }
     }
 
-    let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
+    let kind_id = tcx.lang_items.require(SizedTraitLangItem);
     match unbound {
         Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
-            let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
+            let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb);
             match kind_id {
                 Ok(kind_id) if trait_def_id != kind_id => {
-                    ccx.tcx.sess.span_warn(span,
-                                              "default bound relaxed for a type parameter, but \
-                                               this does nothing because the given bound is not \
-                                               a default. Only `?Sized` is supported");
-                    ty::try_add_builtin_trait(ccx.tcx,
-                                              kind_id,
-                                              bounds);
+                    tcx.sess.span_warn(span,
+                                       "default bound relaxed for a type parameter, but \
+                                       this does nothing because the given bound is not \
+                                       a default. Only `?Sized` is supported");
+                    ty::try_add_builtin_trait(tcx, kind_id, bounds);
                 }
                 _ => {}
             }
         }
         _ if kind_id.is_ok() => {
-            ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
+            ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds);
         }
         // No lang item for Sized, so we can't add it as a bound.
         None => {}
     }
 }
 
-fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                              space: subst::ParamSpace,
-                              generics: &ty::Generics<'tcx>,
-                              base: ty::GenericPredicates<'tcx>,
-                              where_clause: &ast::WhereClause)
-                              -> ty::GenericPredicates<'tcx>
+/// Returns the early-bound lifetimes declared in this generics
+/// listing.  For anything other than fns/methods, this is just all
+/// the lifetimes that are declared. For fns or methods, we have to
+/// screen out those that do not appear in any where-clauses etc using
+/// `resolve_lifetime::early_bound_lifetimes`.
+fn early_bound_lifetimes_from_generics(space: ParamSpace,
+                                       ast_generics: &ast::Generics)
+                                       -> Vec<ast::LifetimeDef>
+{
+    match space {
+        SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
+        FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
+    }
+}
+
+fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                  space: ParamSpace,
+                                  ast_generics: &ast::Generics,
+                                  base_predicates: &ty::GenericPredicates<'tcx>)
+                                  -> ty::GenericPredicates<'tcx>
 {
     let tcx = ccx.tcx;
-    let mut result = base;
-
-    // For now, scrape the bounds out of parameters from Generics. This is not great.
-    for def in generics.regions.get_slice(space) {
-        let r_a = def.to_early_bound_region();
-        for &r_b in &def.bounds {
-            let outlives = ty::Binder(ty::OutlivesPredicate(r_a, r_b));
-            result.predicates.push(def.space, ty::Predicate::RegionOutlives(outlives));
-        }
+    let mut result = base_predicates.clone();
+
+    // Collect the predicates that were written inline by the user on each
+    // type parameter (e.g., `<T:Foo>`).
+    for (index, param) in ast_generics.ty_params.iter().enumerate() {
+        let index = index as u32;
+        let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
+        let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
+                                    param_ty,
+                                    &param.bounds,
+                                    SizedByDefault::Yes,
+                                    param.span);
+        let predicates = ty::predicates(ccx.tcx, param_ty, &bounds);
+        result.predicates.extend(space, predicates.into_iter());
     }
-    for def in generics.types.get_slice(space) {
-        let t = ty::mk_param_from_def(ccx.tcx, def);
-        result.predicates.extend(def.space, ty::predicates(ccx.tcx, t, &def.bounds).into_iter());
+
+    // Collect the region predicates that were declared inline as
+    // well. In the case of parameters declared on a fn or method, we
+    // have to be careful to only iterate over early-bound regions.
+    let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
+    for (index, param) in early_lifetimes.iter().enumerate() {
+        let index = index as u32;
+        let region = ty::ReEarlyBound(param.lifetime.id, space, index, param.lifetime.name);
+        for bound in &param.bounds {
+            let bound_region = ast_region_to_region(ccx.tcx, bound);
+            let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
+            result.predicates.push(space, outlives.as_predicate());
+        }
     }
 
-    // Add the bounds not associated with a type parameter
+    // Add in the bounds that appear in the where-clause
+    let where_clause = &ast_generics.where_clause;
     for predicate in &where_clause.predicates {
         match predicate {
             &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
+                let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
+                                      &ExplicitRscope,
+                                      &*bound_pred.bounded_ty);
 
                 for bound in &*bound_pred.bounds {
                     match bound {
                         &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
                             let mut projections = Vec::new();
 
-                            let trait_ref = astconv::instantiate_poly_trait_ref(
-                                ccx,
-                                &ExplicitRscope,
-                                poly_trait_ref,
-                                Some(ty),
-                                &mut projections,
-                            );
+                            let trait_ref =
+                                conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
+                                                    ty,
+                                                    poly_trait_ref,
+                                                    &mut projections);
 
                             result.predicates.push(space, trait_ref.as_predicate());
 
@@ -1504,18 +1798,17 @@ fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     return result;
 }
 
-fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                        space: subst::ParamSpace,
-                        lifetime_defs: &[ast::LifetimeDef],
-                        types: &[ast::TyParam],
-                        where_clause: &ast::WhereClause,
-                        base_generics: ty::Generics<'tcx>)
+fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                        space: ParamSpace,
+                        ast_generics: &ast::Generics,
+                        base_generics: &ty::Generics<'tcx>)
                         -> ty::Generics<'tcx>
 {
     let tcx = ccx.tcx;
-    let mut result = base_generics;
+    let mut result = base_generics.clone();
 
-    for (i, l) in lifetime_defs.iter().enumerate() {
+    let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
+    for (i, l) in early_lifetimes.iter().enumerate() {
         let bounds = l.bounds.iter()
                              .map(|l| ast_region_to_region(tcx, l))
                              .collect();
@@ -1524,16 +1817,14 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                                            index: i as u32,
                                            def_id: local_def(l.lifetime.id),
                                            bounds: bounds };
-        // debug!("ty_generics: def for region param: {:?}",
-        //        def.repr(tcx));
         result.regions.push(space, def);
     }
 
     assert!(result.types.is_empty_in(space));
 
     // Now create the real type parameters.
-    for (i, param) in types.iter().enumerate() {
-        let def = get_or_create_type_parameter_def(ccx, space, param, i as u32, where_clause);
+    for i in 0..ast_generics.ty_params.len() {
+        let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
         debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
         result.types.push(space, def);
     }
@@ -1541,29 +1832,24 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     result
 }
 
-fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                             space: subst::ParamSpace,
-                                             param: &ast::TyParam,
-                                             index: u32,
-                                             where_clause: &ast::WhereClause)
+fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                             ast_generics: &ast::Generics,
+                                             space: ParamSpace,
+                                             index: u32)
                                              -> ty::TypeParameterDef<'tcx>
 {
+    let param = &ast_generics.ty_params[index as usize];
+
     let tcx = ccx.tcx;
     match tcx.ty_param_defs.borrow().get(&param.id) {
         Some(d) => { return d.clone(); }
         None => { }
     }
 
-    let param_ty = ty::ParamTy::new(space, index, param.ident.name);
-    let bounds = compute_bounds(ccx,
-                                param_ty.to_ty(ccx.tcx),
-                                &param.bounds[],
-                                SizedByDefault::Yes,
-                                param.span);
     let default = match param.default {
         None => None,
         Some(ref path) => {
-            let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
+            let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path);
             let cur_idx = index;
 
             ty::walk_ty(ty, |t| {
@@ -1582,14 +1868,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     };
 
     let object_lifetime_default =
-        compute_object_lifetime_default(ccx, space, index, &param.bounds, where_clause);
+        compute_object_lifetime_default(ccx, param.id,
+                                        &param.bounds, &ast_generics.where_clause);
 
     let def = ty::TypeParameterDef {
         space: space,
         index: index,
         name: param.ident.name,
         def_id: local_def(param.id),
-        bounds: bounds,
         default: default,
         object_lifetime_default: object_lifetime_default,
     };
@@ -1605,15 +1891,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
 /// intentionally avoid just asking astconv to convert all the where
 /// clauses into a `ty::Predicate`. This is because that could induce
 /// artificial cycles.
-fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                            space: subst::ParamSpace,
-                                            index: u32,
+fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                            param_id: ast::NodeId,
                                             param_bounds: &[ast::TyParamBound],
                                             where_clause: &ast::WhereClause)
                                             -> Option<ty::ObjectLifetimeDefault>
 {
     let inline_bounds = from_bounds(ccx, param_bounds);
-    let where_bounds = from_predicates(ccx, space, index, &where_clause.predicates);
+    let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
     let all_bounds: HashSet<_> = inline_bounds.into_iter()
                                               .chain(where_bounds.into_iter())
                                               .collect();
@@ -1625,7 +1910,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                   .map(ty::ObjectLifetimeDefault::Specific)
     };
 
-    fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+    fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                             bounds: &[ast::TyParamBound])
                             -> Vec<ty::Region>
     {
@@ -1635,15 +1920,14 @@ fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                       ast::TraitTyParamBound(..) =>
                           None,
                       ast::RegionTyParamBound(ref lifetime) =>
-                          Some(astconv::ast_region_to_region(ccx.tcx(), lifetime)),
+                          Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
                   }
               })
               .collect()
     }
 
-    fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                space: subst::ParamSpace,
-                                index: u32,
+    fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                param_id: ast::NodeId,
                                 predicates: &[ast::WherePredicate])
                                 -> Vec<ty::Region>
     {
@@ -1652,7 +1936,7 @@ fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                       match *predicate {
                           ast::WherePredicate::BoundPredicate(ref data) => {
                               if data.bound_lifetimes.len() == 0 &&
-                                  is_param(ccx, &data.bounded_ty, space, index)
+                                  is_param(ccx.tcx, &data.bounded_ty, param_id)
                               {
                                   from_bounds(ccx, &data.bounds).into_iter()
                               } else {
@@ -1667,29 +1951,6 @@ fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                   })
                   .collect()
     }
-
-    fn is_param(ccx: &CollectCtxt,
-                ast_ty: &ast::Ty,
-                space: subst::ParamSpace,
-                index: u32)
-                -> bool
-    {
-        match ast_ty.node {
-            ast::TyPath(_, id) => {
-                match ccx.tcx.def_map.borrow()[id] {
-                    def::DefTyParam(s, i, _, _) => {
-                        space == s && index == i
-                    }
-                    _ => {
-                        false
-                    }
-                }
-            }
-            _ => {
-                false
-            }
-        }
-    }
 }
 
 enum SizedByDefault { Yes, No }
@@ -1697,25 +1958,25 @@ enum SizedByDefault { Yes, No }
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                           param_ty: ty::Ty<'tcx>,
-                           ast_bounds: &[ast::TyParamBound],
-                           sized_by_default: SizedByDefault,
-                           span: Span)
-                           -> ty::ParamBounds<'tcx>
+fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
+                        param_ty: ty::Ty<'tcx>,
+                        ast_bounds: &[ast::TyParamBound],
+                        sized_by_default: SizedByDefault,
+                        span: Span)
+                        -> ty::ParamBounds<'tcx>
 {
-    let mut param_bounds = conv_param_bounds(ccx,
+    let mut param_bounds = conv_param_bounds(astconv,
                                              span,
                                              param_ty,
                                              ast_bounds);
 
     if let SizedByDefault::Yes = sized_by_default {
-        add_unsized_bound(ccx,
+        add_unsized_bound(astconv,
                           &mut param_bounds.builtin_bounds,
                           ast_bounds,
                           span);
 
-        check_bounds_compatible(ccx,
+        check_bounds_compatible(astconv,
                                 param_ty,
                                 &param_bounds,
                                 span);
@@ -1726,35 +1987,72 @@ fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     param_bounds
 }
 
-fn check_bounds_compatible<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                    param_ty: Ty<'tcx>,
-                                    param_bounds: &ty::ParamBounds<'tcx>,
-                                    span: Span) {
+fn check_bounds_compatible<'tcx>(astconv: &AstConv<'tcx>,
+                                 param_ty: Ty<'tcx>,
+                                 param_bounds: &ty::ParamBounds<'tcx>,
+                                 span: Span) {
+    let tcx = astconv.tcx();
     if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
         ty::each_bound_trait_and_supertraits(
-            ccx.tcx,
-            &param_bounds.trait_bounds[],
+            tcx,
+            &param_bounds.trait_bounds,
             |trait_ref| {
-                let trait_def = ccx.get_trait_def(trait_ref.def_id());
-                if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
-                    span_err!(ccx.tcx.sess, span, E0129,
-                              "incompatible bounds on `{}`, \
-                               bound `{}` does not allow unsized type",
-                              param_ty.user_string(ccx.tcx),
-                              trait_ref.user_string(ccx.tcx));
+                match astconv.get_trait_def(span, trait_ref.def_id()) {
+                    Ok(trait_def) => {
+                        if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
+                            span_err!(tcx.sess, span, E0129,
+                                      "incompatible bounds on `{}`, \
+                                        bound `{}` does not allow unsized type",
+                                      param_ty.user_string(tcx),
+                                      trait_ref.user_string(tcx));
+                        }
+                    }
+                    Err(ErrorReported) => { }
                 }
                 true
             });
     }
 }
 
-fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+/// Converts a specific TyParamBound from the AST into the
+/// appropriate poly-trait-reference.
+fn poly_trait_ref_from_bound<'tcx>(astconv: &AstConv<'tcx>,
+                                   param_ty: Ty<'tcx>,
+                                   bound: &ast::TyParamBound,
+                                   projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+                                   -> Option<ty::PolyTraitRef<'tcx>>
+{
+    match *bound {
+        ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
+            Some(conv_poly_trait_ref(astconv, param_ty, tr, projections))
+        }
+        ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) |
+        ast::RegionTyParamBound(_) => {
+            None
+        }
+    }
+}
+
+fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
+                             param_ty: Ty<'tcx>,
+                             trait_ref: &ast::PolyTraitRef,
+                             projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+                             -> ty::PolyTraitRef<'tcx>
+{
+    astconv::instantiate_poly_trait_ref(astconv,
+                                        &ExplicitRscope,
+                                        trait_ref,
+                                        Some(param_ty),
+                                        projections)
+}
+
+fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[ast::TyParamBound])
                               -> ty::ParamBounds<'tcx>
 {
-    let tcx = ccx.tcx;
+    let tcx = astconv.tcx();
     let astconv::PartitionedBounds {
         builtin_bounds,
         trait_bounds,
@@ -1764,19 +2062,16 @@ fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     let mut projection_bounds = Vec::new();
 
     let trait_bounds: Vec<ty::PolyTraitRef> =
-        trait_bounds.into_iter()
-        .map(|bound| {
-            astconv::instantiate_poly_trait_ref(ccx,
-                                                &ExplicitRscope,
-                                                bound,
-                                                Some(param_ty),
-                                                &mut projection_bounds)
-        })
-    .collect();
+        trait_bounds.iter()
+                    .map(|bound| conv_poly_trait_ref(astconv,
+                                                     param_ty,
+                                                     *bound,
+                                                     &mut projection_bounds))
+                    .collect();
 
     let region_bounds: Vec<ty::Region> =
         region_bounds.into_iter()
-                     .map(|r| ast_region_to_region(ccx.tcx, r))
+                     .map(|r| ast_region_to_region(tcx, r))
                      .collect();
 
     ty::ParamBounds {
@@ -1788,7 +2083,7 @@ fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
 }
 
 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     decl: &ast::FnDecl,
     ast_generics: &ast::Generics,
     abi: abi::Abi)
@@ -1805,17 +2100,17 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
         }
     }
 
-    let ty_generics = ty_generics_for_fn_or_method(ccx, ast_generics, ty::Generics::empty());
+    let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
 
     let rb = BindingRscope::new();
     let input_tys = decl.inputs
                         .iter()
-                        .map(|a| ty_of_arg(ccx, &rb, a, None))
+                        .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
                         .collect();
 
     let output = match decl.output {
         ast::Return(ref ty) =>
-            ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
+            ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
         ast::DefaultReturn(..) =>
             ty::FnConverging(ty::mk_nil(ccx.tcx)),
         ast::NoReturn(..) =>
@@ -1839,9 +2134,9 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     }
 }
 
-fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             ty_generics: &ty::Generics<'tcx>)
-                            -> subst::Substs<'tcx>
+                            -> Substs<'tcx>
 {
     let types =
         ty_generics.types.map(
@@ -1851,7 +2146,7 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ty_generics.regions.map(
             |def| def.to_early_bound_region());
 
-    subst::Substs::new(types, regions)
+    Substs::new(types, regions)
 }
 
 /// Verifies that the explicit self type of a method matches the impl
@@ -1861,15 +2156,16 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 /// comes back to check after the fact that explicit type the user
 /// wrote actually matches what the pre-defined option said.
 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     rs: &RS,
+    method_type: Rc<ty::Method<'tcx>>,
     required_type: Ty<'tcx>,
     explicit_self: &ast::ExplicitSelf,
     body_id: ast::NodeId)
 {
     let tcx = ccx.tcx;
     if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
-        let typ = ccx.to_ty(rs, &**ast_type);
+        let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
         let base_type = match typ.sty {
             ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
             ty::ty_uniq(typ) => typ,
index 17cf92d39d8f542d332f7fab010e401280c7f3fd..7b43a9fef06dcd36d604f5b42425fd42b3cecf72 100644 (file)
@@ -80,6 +80,7 @@
     E0120,
     E0121,
     E0122,
+    E0123,
     E0124,
     E0127,
     E0128,
     E0247, // found module name used as a type
     E0248, // found value name used as a type
     E0249, // expected constant expr for array length
-    E0250  // expected constant expr for array length
+    E0250, // expected constant expr for array length
+    E0318, // can't create default impls for traits outside their crates
+    E0319  // trait impls for defaulted traits allowed just for structs/enums
 }
 
 __build_diagnostic_array! { DIAGNOSTICS }
index b5dca0bd4f6f42348e2981d23bf079541b91986b..78dd66c8e7dbbd02e80bc8f197f2d014a2bf990e 100644 (file)
@@ -163,20 +163,16 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
         tcx.item_substs.borrow_mut().insert(node_id, item_substs);
     }
 }
-fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
+
+fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
     match tcx.def_map.borrow().get(&id) {
-        Some(x) => x.clone(),
-        _ => {
+        Some(x) => x.full_def(),
+        None => {
             span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
         }
     }
 }
 
-fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
-                   -> def::Def {
-    lookup_def_tcx(ccx.tcx, sp, id)
-}
-
 fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
                                    maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
                                    t1_is_expected: bool,
@@ -253,7 +249,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                               &format!("main has a non-function type: found \
                                        `{}`",
                                       ppaux::ty_to_string(tcx,
-                                                       main_t))[]);
+                                                       main_t)));
         }
     }
 }
@@ -304,7 +300,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
             tcx.sess.span_bug(start_span,
                               &format!("start has a non-function type: found \
                                        `{}`",
-                                      ppaux::ty_to_string(tcx, start_t))[]);
+                                      ppaux::ty_to_string(tcx, start_t)));
         }
     }
 }
index 1adcf133bf3e0788490204a73c62a4e120497526..1fba4a21ccd376a61ab08fbc52609e1cb9b32b50 100644 (file)
 //! failure, but rather because the target type `Foo<Y>` is itself just
 //! not well-formed. Basically we get to assume well-formedness of all
 //! types involved before considering variance.
+//!
+//! ### Associated types
+//!
+//! Any trait with an associated type is invariant with respect to all
+//! of its inputs. To see why this makes sense, consider what
+//! subtyping for a trait reference means:
+//!
+//!    <T as Trait> <: <U as Trait>
+//!
+//! means that if I know that `T as Trait`,
+//! I also know that `U as
+//! Trait`. Moreover, if you think of it as
+//! dictionary passing style, it means that
+//! a dictionary for `<T as Trait>` is safe
+//! to use where a dictionary for `<U as
+//! Trait>` is expected.
+//!
+//! The problem is that when you can
+//! project types out from `<T as Trait>`,
+//! the relationship to types projected out
+//! of `<U as Trait>` is completely unknown
+//! unless `T==U` (see #21726 for more
+//! details). Making `Trait` invariant
+//! ensures that this is true.
+//!
+//! *Historical note: we used to preserve this invariant another way,
+//! by tweaking the subtyping rules and requiring that when a type `T`
+//! appeared as part of a projection, that was considered an invariant
+//! location, but this version does away with the need for those
+//! somewhat "special-case-feeling" rules.*
+//!
+//! Another related reason is that if we didn't make traits with
+//! associated types invariant, then projection is no longer a
+//! function with a single result. Consider:
+//!
+//! ```
+//! trait Identity { type Out; fn foo(&self); }
+//! impl<T> Identity for T { type Out = T; ... }
+//! ```
+//!
+//! Now if I have `<&'static () as Identity>::Out`, this can be
+//! validly derived as `&'a ()` for any `'a`:
+//!
+//!    <&'a () as Identity> <: <&'static () as Identity>
+//!    if &'static () < : &'a ()   -- Identity is contravariant in Self
+//!    if 'static : 'a             -- Subtyping rules for relations
+//!
+//! This change otoh means that `<'static () as Identity>::Out` is
+//! always `&'static ()` (which might then be upcast to `'a ()`,
+//! separately). This was helpful in solving #21750.
 
 use self::VarianceTerm::*;
 use self::ParamKind::*;
@@ -476,6 +526,7 @@ fn visit_item(&mut self, item: &ast::Item) {
 
             ast::ItemExternCrate(_) |
             ast::ItemUse(_) |
+            ast::ItemDefaultImpl(..) |
             ast::ItemImpl(..) |
             ast::ItemStatic(..) |
             ast::ItemConst(..) |
@@ -595,7 +646,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                 let trait_def = ty::lookup_trait_def(tcx, did);
                 let predicates = ty::predicates(tcx, ty::mk_self_type(tcx), &trait_def.bounds);
                 self.add_constraints_from_predicates(&trait_def.generics,
-                                                     &predicates[],
+                                                     &predicates,
                                                      self.covariant);
 
                 let trait_items = ty::trait_items(tcx, did);
@@ -612,7 +663,18 @@ fn visit_item(&mut self, item: &ast::Item) {
                                 &method.fty.sig,
                                 self.covariant);
                         }
-                        ty::TypeTraitItem(_) => {}
+                        ty::TypeTraitItem(ref data) => {
+                            // Any trait with an associated type is
+                            // invariant with respect to all of its
+                            // inputs. See length discussion in the comment
+                            // on this module.
+                            let projection_ty = ty::mk_projection(tcx,
+                                                                  trait_def.trait_ref.clone(),
+                                                                  data.name);
+                            self.add_constraints_from_ty(&trait_def.generics,
+                                                         projection_ty,
+                                                         self.invariant);
+                        }
                     }
                 }
             }
@@ -626,6 +688,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemForeignMod(..) |
             ast::ItemTy(..) |
             ast::ItemImpl(..) |
+            ast::ItemDefaultImpl(..) |
             ast::ItemMac(..) => {
             }
         }
@@ -652,7 +715,7 @@ fn inferred_index(&self, param_id: ast::NodeId) -> InferredIndex {
             None => {
                 self.tcx().sess.bug(&format!(
                         "no inferred index entry for {}",
-                        self.tcx().map.node_to_string(param_id))[]);
+                        self.tcx().map.node_to_string(param_id)));
             }
         }
     }
@@ -847,7 +910,7 @@ fn add_constraints_from_ty(&mut self,
                 self.add_constraints_from_mt(generics, mt, variance);
             }
 
-            ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
+            ty::ty_uniq(typ) | ty::ty_vec(typ, _) => {
                 self.add_constraints_from_ty(generics, typ, variance);
             }
 
@@ -891,7 +954,7 @@ fn add_constraints_from_ty(&mut self,
                     trait_def.generics.types.as_slice(),
                     trait_def.generics.regions.as_slice(),
                     trait_ref.substs,
-                    self.invariant);
+                    variance);
             }
 
             ty::ty_trait(ref data) => {
@@ -941,7 +1004,7 @@ fn add_constraints_from_ty(&mut self,
                 self.tcx().sess.bug(
                     &format!("unexpected type encountered in \
                             variance inference: {}",
-                            ty.repr(self.tcx()))[]);
+                            ty.repr(self.tcx())));
             }
         }
     }
@@ -1071,7 +1134,7 @@ fn add_constraints_from_region(&mut self,
                     .sess
                     .bug(&format!("unexpected region encountered in variance \
                                   inference: {}",
-                                 region.repr(self.tcx()))[]);
+                                 region.repr(self.tcx())));
             }
         }
     }
index d1283d6f46bd842ed3a945f5ef3668df9af1e2d8..2bb4424822a4749c5b58b3537fee5d09cb860823 100644 (file)
@@ -46,7 +46,7 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Ident>)
         None => return None,
     };
     let def = match tcx.def_map.borrow().get(&id) {
-        Some(def) => *def,
+        Some(d) => d.full_def(),
         None => return None,
     };
     let did = def.def_id();
@@ -308,6 +308,9 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
                 if method.vis != ast::Public && associated_trait.is_none() {
                     return None
                 }
+                if method.provided_source.is_some() {
+                    return None
+                }
                 let mut item = method.clean(cx);
                 item.inner = match item.inner.clone() {
                     clean::TyMethodItem(clean::TyMethod {
index 7ef48378af183415d595255c30b3541896a698b3..36d39fa58ba7e5ec7e23a8bcc5cc2c595e59f341 100644 (file)
@@ -479,11 +479,10 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParam {
         cx.external_typarams.borrow_mut().as_mut().unwrap()
           .insert(self.def_id, self.name.clean(cx));
-        let bounds = self.bounds.clean(cx);
         TyParam {
             name: self.name.clean(cx),
             did: self.def_id,
-            bounds: bounds,
+            bounds: vec![], // these are filled in from the where-clauses
             default: self.default.clean(cx),
         }
     }
@@ -892,9 +891,7 @@ fn has_sized_bound(bounds: &[TyParamBound], cx: &DocContext) -> bool {
         // Bounds in the type_params and lifetimes fields are repeated in the predicates
         // field (see rustc_typeck::collect::ty_generics), so remove them.
         let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
-            let mut stp = tp.clone();
-            stp.bounds = ty::ParamBounds::empty();
-            stp.clean(cx)
+            tp.clean(cx)
         }).collect::<Vec<_>>();
         let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
             let mut srp = rp.clone();
@@ -1344,8 +1341,6 @@ pub enum Type {
         typarams: Option<Vec<TyParamBound>>,
         did: ast::DefId,
     },
-    // I have no idea how to usefully use this.
-    TyParamBinder(ast::NodeId),
     /// For parameterized types, so the consumer of the JSON don't go
     /// looking for types which don't exist anywhere.
     Generic(String),
@@ -1496,8 +1491,17 @@ fn clean(&self, cx: &DocContext) -> Type {
             TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
                                                            e.span.to_src(cx)),
             TyTup(ref tys) => Tuple(tys.clean(cx)),
-            TyPath(ref p, id) => {
-                resolve_type(cx, p.clean(cx), id)
+            TyPath(None, ref p) => {
+                resolve_type(cx, p.clean(cx), self.id)
+            }
+            TyPath(Some(ref qself), ref p) => {
+                let mut trait_path = p.clone();
+                trait_path.segments.pop();
+                Type::QPath {
+                    name: p.segments.last().unwrap().identifier.clean(cx),
+                    self_type: box qself.ty.clean(cx),
+                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
+                }
             }
             TyObjectSum(ref lhs, ref bounds) => {
                 let lhs_ty = lhs.clean(cx);
@@ -1512,7 +1516,6 @@ fn clean(&self, cx: &DocContext) -> Type {
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyParen(ref ty) => ty.clean(cx),
-            TyQPath(ref qp) => qp.clean(cx),
             TyPolyTraitRef(ref bounds) => {
                 PolyTraitRef(bounds.clean(cx))
             },
@@ -1619,22 +1622,11 @@ fn clean(&self, cx: &DocContext) -> Type {
             ty::ty_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::ty_infer(..) => panic!("ty_infer"),
-            ty::ty_open(..) => panic!("ty_open"),
             ty::ty_err => panic!("ty_err"),
         }
     }
 }
 
-impl Clean<Type> for ast::QPath {
-    fn clean(&self, cx: &DocContext) -> Type {
-        Type::QPath {
-            name: self.item_path.identifier.clean(cx),
-            self_type: box self.self_type.clean(cx),
-            trait_: box self.trait_ref.clean(cx)
-        }
-    }
-}
-
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum StructField {
     HiddenStructField, // inserted later by strip passes
@@ -2169,7 +2161,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
         let denied = self.vis != ast::Public || self.attrs.iter().any(|a| {
-            &a.name()[] == "doc" && match a.meta_item_list() {
+            &a.name()[..] == "doc" && match a.meta_item_list() {
                 Some(l) => attr::contains_name(l, "no_inline"),
                 None => false,
             }
@@ -2393,7 +2385,7 @@ fn resolve_type(cx: &DocContext,
     };
     debug!("searching for {} in defmap", id);
     let def = match tcx.def_map.borrow().get(&id) {
-        Some(&k) => k,
+        Some(k) => k.full_def(),
         None => panic!("unresolved id not in defmap")
     };
 
@@ -2419,7 +2411,6 @@ fn resolve_type(cx: &DocContext,
             ast::TyFloat(ast::TyF64) => return Primitive(F64),
         },
         def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()),
-        def::DefTyParamBinder(i) => return TyParamBinder(i),
         _ => {}
     };
     let did = register_def(&*cx, def);
@@ -2460,7 +2451,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
 
 fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
     cx.tcx_opt().and_then(|tcx| {
-        tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def))
+        tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
     })
 }
 
index ba5df56f4fb5655d44762548fe8f53eaf83db88c..8143926982f0168988bc92d27e08101cf1a46582 100644 (file)
@@ -39,6 +39,7 @@ pub struct Module {
     pub vis: ast::Visibility,
     pub stab: Option<attr::Stability>,
     pub impls: Vec<Impl>,
+    pub def_traits: Vec<DefaultImpl>,
     pub foreigns: Vec<ast::ForeignMod>,
     pub macros: Vec<Macro>,
     pub is_crate: bool,
@@ -65,6 +66,7 @@ pub fn new(name: Option<Ident>) -> Module {
             constants  : Vec::new(),
             traits     : Vec::new(),
             impls      : Vec::new(),
+            def_traits : Vec::new(),
             foreigns   : Vec::new(),
             macros     : Vec::new(),
             is_crate   : false,
@@ -196,6 +198,12 @@ pub struct Impl {
     pub id: ast::NodeId,
 }
 
+pub struct DefaultImpl {
+    pub unsafety: ast::Unsafety,
+    pub trait_: ast::TraitRef,
+    pub id: ast::NodeId,
+}
+
 pub struct Macro {
     pub name: Ident,
     pub id: ast::NodeId,
index ad91c3cb2c35b60e4b023c655ef8486403ebfd12..6b2676eca3d026ef4061ca442ab265236c7f7402 100644 (file)
@@ -64,7 +64,9 @@ pub struct flock {
         pub const F_SETLKW: libc::c_int = 13;
     }
 
-    #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
+    #[cfg(any(target_os = "dragonfly",
+              target_os = "bitrig",
+              target_os = "openbsd"))]
     mod os {
         use libc;
 
index ed7f051408c45894303ab703902b7d49a155d1a6..03a2d708ee43aa5b742c2efc9c19aacdf4764ecf 100644 (file)
@@ -25,6 +25,7 @@
 use stability_summary::ModuleSummary;
 use html::item_type::ItemType;
 use html::render;
+use html::escape::Escape;
 use html::render::{cache, CURRENT_LOCATION_KEY};
 
 /// Helper to render an optional visibility with a space after it (if the
@@ -453,9 +454,6 @@ fn tybounds(w: &mut fmt::Formatter,
 impl fmt::Display for clean::Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            clean::TyParamBinder(id) => {
-                f.write_str(&cache().typarams[ast_util::local_def(id)])
-            }
             clean::Generic(ref name) => {
                 f.write_str(name)
             }
@@ -710,13 +708,14 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let Stability(stab) = *self;
         match *stab {
             Some(ref stability) => {
+                let lvl = if stability.deprecated_since.is_empty() {
+                    format!("{}", stability.level)
+                } else {
+                    "Deprecated".to_string()
+                };
                 write!(f, "<a class='stability {lvl}' title='{reason}'>{lvl}</a>",
-                       lvl = if stability.deprecated_since.is_empty() {
-                           format!("{}", stability.level)
-                       } else {
-                           "Deprecated".to_string()
-                       },
-                       reason = stability.reason)
+                       lvl = Escape(&*lvl),
+                       reason = Escape(&*stability.reason))
             }
             None => Ok(())
         }
@@ -728,14 +727,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         let ConciseStability(stab) = *self;
         match *stab {
             Some(ref stability) => {
+                let lvl = if stability.deprecated_since.is_empty() {
+                    format!("{}", stability.level)
+                } else {
+                    "Deprecated".to_string()
+                };
                 write!(f, "<a class='stability {lvl}' title='{lvl}{colon}{reason}'></a>",
-                       lvl = if stability.deprecated_since.is_empty() {
-                           format!("{}", stability.level)
-                       } else {
-                           "Deprecated".to_string()
-                       },
+                       lvl = Escape(&*lvl),
                        colon = if stability.reason.len() > 0 { ": " } else { "" },
-                       reason = stability.reason)
+                       reason = Escape(&*stability.reason))
             }
             None => {
                 write!(f, "<a class='stability Unmarked' title='No stability level'></a>")
index 44c0acda66fba8e8c3c0384ae763d970b488fadd..b88e5065b4f9c82b77f2801a82529010b039e446 100644 (file)
@@ -142,7 +142,7 @@ fn doit(sess: &parse::ParseSess, mut lexer: lexer::StringReader,
 
             // keywords are also included in the identifier set
             token::Ident(ident, _is_mod_sep) => {
-                match &token::get_ident(ident)[] {
+                match &token::get_ident(ident)[..] {
                     "ref" | "mut" => "kw-2",
 
                     "self" => "self",
index fc3c87389917abebacff1d984cebd20078a43e3a..735487611dc50d522a13a2ae0ebf4b67e0fc50e6 100644 (file)
@@ -1469,7 +1469,7 @@ fn full_path(cx: &Context, item: &clean::Item) -> String {
 
 fn shorter<'a>(s: Option<&'a str>) -> &'a str {
     match s {
-        Some(s) => match s.find_str("\n\n") {
+        Some(s) => match s.find("\n\n") {
             Some(pos) => &s[..pos],
             None => s,
         },
index 2f0755ecb898a0bf17b04cdd9b3641eb6b21f752..21b7de9ff7c821ab6f68c9439b5c9371a4369d8e 100644 (file)
@@ -374,8 +374,14 @@ a {
     color: #000;
     background: transparent;
 }
-.docblock a { color: #4e8bca; }
-.docblock a:hover { text-decoration: underline; }
+
+.docblock a {
+    color: #4e8bca;
+}
+
+.docblock a:hover {
+    text-decoration: underline;
+}
 
 .content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; }
 .content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
@@ -529,10 +535,19 @@ pre.rust { position: relative; }
     margin: 0 0 -5px;
     padding: 0;
 }
+
 .section-header:hover a:after {
     content: '\2002\00a7\2002';
 }
 
+.section-header:hover a {
+    text-decoration: none;
+}
+
+.section-header a {
+    color: inherit;
+}
+
 .collapse-toggle {
     font-weight: 300;
     position: absolute;
index bf14b86ebd1e39e21189cd0097dff9072a15fcd7..78f126dcf6a827d438057e6cd074c2a7a47e853e 100644 (file)
@@ -13,7 +13,7 @@
 use std::dynamic_lib::DynamicLibrary;
 use std::old_io::{Command, TempDir};
 use std::old_io;
-use std::env;
+use std::os;
 use std::str;
 use std::thread;
 use std::thunk::Thunk;
@@ -46,7 +46,7 @@ pub fn run(input: &str,
     let input = config::Input::File(input_path.clone());
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
+        maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()),
         search_paths: libs.clone(),
         crate_types: vec!(config::CrateTypeDylib),
         externs: externs.clone(),
@@ -113,7 +113,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
     let input = config::Input::Str(test.to_string());
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
+        maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()),
         search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
         output_types: vec!(config::OutputTypeExe),
index c52b0bab1fa8b800129e3688e7423bca40dba82d..3e998166397bc5deb38e2a30bb6497c0da82e63c 100644 (file)
@@ -196,7 +196,7 @@ fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>,
             Some(tcx) => tcx,
             None => return false
         };
-        let def = (*tcx.def_map.borrow())[id].def_id();
+        let def = tcx.def_map.borrow()[id].def_id();
         if !ast_util::is_local(def) { return false }
         let analysis = match self.analysis {
             Some(analysis) => analysis, None => return false
@@ -253,7 +253,7 @@ pub fn visit_item(&mut self, item: &ast::Item,
                     let please_inline = item.attrs.iter().any(|item| {
                         match item.meta_item_list() {
                             Some(list) => {
-                                list.iter().any(|i| &i.name()[] == "inline")
+                                list.iter().any(|i| &i.name()[..] == "inline")
                             }
                             None => false,
                         }
@@ -358,6 +358,14 @@ pub fn visit_item(&mut self, item: &ast::Item,
                 };
                 om.impls.push(i);
             },
+            ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
+                let i = DefaultImpl {
+                    unsafety: unsafety,
+                    trait_: trait_ref.clone(),
+                    id: item.id
+                };
+                om.def_traits.push(i);
+            }
             ast::ItemForeignMod(ref fm) => {
                 om.foreigns.push(fm.clone());
             }
index 10cf02f85e818579e5ed811acaa424ee4e65b251..e7430f698e9c962e5bdec559d7a18ec3ba70004b 100644 (file)
@@ -13,7 +13,6 @@
 use std::usize;
 use std::default::Default;
 use std::hash::Hash;
-#[cfg(stage0)] use std::hash::Hasher;
 use std::collections::hash_state::HashState;
 
 use {Decodable, Encodable, Decoder, Encoder};
@@ -158,26 +157,6 @@ fn decode<D: Decoder>(d: &mut D) -> Result<EnumSet<T>, D::Error> {
     }
 }
 
-#[cfg(stage0)]
-impl<K, V, S> Encodable for HashMap<K, V, S>
-    where K: Encodable + Hash< <S as HashState>::Hasher> + Eq,
-          V: Encodable,
-          S: HashState,
-          <S as HashState>::Hasher: Hasher<Output=u64>
-{
-    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
-        e.emit_map(self.len(), |e| {
-            let mut i = 0;
-            for (key, val) in self {
-                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
-                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
-                i += 1;
-            }
-            Ok(())
-        })
-    }
-}
-#[cfg(not(stage0))]
 impl<K, V, S> Encodable for HashMap<K, V, S>
     where K: Encodable + Hash + Eq,
           V: Encodable,
@@ -196,27 +175,6 @@ fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
     }
 }
 
-#[cfg(stage0)]
-impl<K, V, S> Decodable for HashMap<K, V, S>
-    where K: Decodable + Hash< <S as HashState>::Hasher> + Eq,
-          V: Decodable,
-          S: HashState + Default,
-          <S as HashState>::Hasher: Hasher<Output=u64>
-{
-    fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
-        d.read_map(|d, len| {
-            let state = Default::default();
-            let mut map = HashMap::with_capacity_and_hash_state(len, state);
-            for i in 0..len {
-                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
-                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
-                map.insert(key, val);
-            }
-            Ok(map)
-        })
-    }
-}
-#[cfg(not(stage0))]
 impl<K, V, S> Decodable for HashMap<K, V, S>
     where K: Decodable + Hash + Eq,
           V: Decodable,
@@ -236,24 +194,6 @@ fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
     }
 }
 
-#[cfg(stage0)]
-impl<T, S> Encodable for HashSet<T, S>
-    where T: Encodable + Hash< <S as HashState>::Hasher> + Eq,
-          S: HashState,
-          <S as HashState>::Hasher: Hasher<Output=u64>
-{
-    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
-        s.emit_seq(self.len(), |s| {
-            let mut i = 0;
-            for e in self {
-                try!(s.emit_seq_elt(i, |s| e.encode(s)));
-                i += 1;
-            }
-            Ok(())
-        })
-    }
-}
-#[cfg(not(stage0))]
 impl<T, S> Encodable for HashSet<T, S>
     where T: Encodable + Hash + Eq,
           S: HashState,
@@ -270,24 +210,6 @@ fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
     }
 }
 
-#[cfg(stage0)]
-impl<T, S> Decodable for HashSet<T, S>
-    where T: Decodable + Hash< <S as HashState>::Hasher> + Eq,
-          S: HashState + Default,
-          <S as HashState>::Hasher: Hasher<Output=u64>
-{
-    fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
-        d.read_seq(|d, len| {
-            let state = Default::default();
-            let mut set = HashSet::with_capacity_and_hash_state(len, state);
-            for i in 0..len {
-                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
-            }
-            Ok(set)
-        })
-    }
-}
-#[cfg(not(stage0))]
 impl<T, S> Decodable for HashSet<T, S>
     where T: Decodable + Hash + Eq,
           S: HashState + Default,
index a0f42815b439611b61fd1e07a748b69adaa2cef4..05d4e0f59fefc4d1732c83ec6ff588deda10df5d 100644 (file)
@@ -3074,19 +3074,19 @@ fn test_read_array() {
     #[test]
     fn test_decode_array() {
         let v: Vec<()> = super::decode("[]").unwrap();
-        assert_eq!(v, vec![]);
+        assert_eq!(v, []);
 
         let v: Vec<()> = super::decode("[null]").unwrap();
-        assert_eq!(v, vec![()]);
+        assert_eq!(v, [()]);
 
         let v: Vec<bool> = super::decode("[true]").unwrap();
-        assert_eq!(v, vec![true]);
+        assert_eq!(v, [true]);
 
         let v: Vec<int> = super::decode("[3, 1]").unwrap();
-        assert_eq!(v, vec![3, 1]);
+        assert_eq!(v, [3, 1]);
 
         let v: Vec<Vec<uint>> = super::decode("[[3], [1, 2]]").unwrap();
-        assert_eq!(v, vec![vec![3], vec![1, 2]]);
+        assert_eq!(v, [vec![3], vec![1, 2]]);
     }
 
     #[test]
index 4d38d17576ddb2a15ee7fe13624ff1a993a979e6..94457a5d71441b784dc52e9969f6d5e77703ea60 100644 (file)
@@ -37,6 +37,7 @@ pub trait OwnedAsciiExt {
 /// Extension methods for ASCII-subset only operations on string slices
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsciiExt {
+    /// Container type for copied ASCII characters.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Owned;
 
index ade4f1f0533ee73abdb388bab488ac4a9a2d0452..faddbba50590f9ce1a87499ef7db2a299e21b038 100644 (file)
@@ -88,7 +88,6 @@ fn usable_capacity(&self, cap: usize) -> usize {
 
 #[test]
 fn test_resize_policy() {
-    use prelude::v1::*;
     let rp = DefaultResizePolicy;
     for n in 0..1000 {
         assert!(rp.min_capacity(rp.usable_capacity(n)) <= n);
@@ -204,7 +203,7 @@ fn test_resize_policy() {
 // produces identical results to a linear naive reinsertion from the same
 // element.
 //
-// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs
+// FIXME(Gankro, pczarn): review the proof and put it all in a separate README.md
 
 /// A hash map implementation which uses linear probing with Robin
 /// Hood bucket stealing.
@@ -1213,7 +1212,7 @@ impl<K, V, S> Debug for HashMap<K, V, S>
     where K: Eq + Hash + Debug, V: Debug, S: HashState
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "HashMap {{"));
+        try!(write!(f, "{{"));
 
         for (i, (k, v)) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -2000,9 +1999,9 @@ fn test_show() {
 
         let map_str = format!("{:?}", map);
 
-        assert!(map_str == "HashMap {1: 2, 3: 4}" ||
-                map_str == "HashMap {3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "HashMap {}");
+        assert!(map_str == "{1: 2, 3: 4}" ||
+                map_str == "{3: 4, 1: 2}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
@@ -2256,6 +2255,7 @@ fn test_entry(){
 
     #[test]
     fn test_entry_take_doesnt_corrupt() {
+        #![allow(deprecated)] //rand
         // Test for #19292
         fn check(m: &HashMap<isize, ()>) {
             for k in m.keys() {
diff --git a/src/libstd/collections/hash/map_stage0.rs b/src/libstd/collections/hash/map_stage0.rs
deleted file mode 100644 (file)
index f9e5044..0000000
+++ /dev/null
@@ -1,2330 +0,0 @@
-// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-// ignore-lexer-test FIXME #15883
-
-use self::Entry::*;
-use self::SearchResult::*;
-use self::VacantEntryState::*;
-
-use borrow::Borrow;
-use clone::Clone;
-use cmp::{max, Eq, PartialEq};
-use default::Default;
-use fmt::{self, Debug};
-use hash::{self, Hash, SipHasher};
-use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
-use marker::Sized;
-use mem::{self, replace};
-use num::{Int, UnsignedInt};
-use ops::{Deref, FnMut, Index, IndexMut};
-use option::Option::{self, Some, None};
-use rand::{self, Rng};
-use result::Result::{self, Ok, Err};
-
-use super::table::{
-    self,
-    Bucket,
-    EmptyBucket,
-    FullBucket,
-    FullBucketImm,
-    FullBucketMut,
-    RawTable,
-    SafeHash
-};
-use super::table::BucketState::{
-    Empty,
-    Full,
-};
-use super::state::HashState;
-
-const INITIAL_LOG2_CAP: usize = 5;
-#[unstable(feature = "std_misc")]
-pub const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5
-
-/// The default behavior of HashMap implements a load factor of 90.9%.
-/// This behavior is characterized by the following condition:
-///
-/// - if size > 0.909 * capacity: grow the map
-#[derive(Clone)]
-struct DefaultResizePolicy;
-
-impl DefaultResizePolicy {
-    fn new() -> DefaultResizePolicy {
-        DefaultResizePolicy
-    }
-
-    #[inline]
-    fn min_capacity(&self, usable_size: usize) -> usize {
-        // Here, we are rephrasing the logic by specifying the lower limit
-        // on capacity:
-        //
-        // - if `cap < size * 1.1`: grow the map
-        usable_size * 11 / 10
-    }
-
-    /// An inverse of `min_capacity`, approximately.
-    #[inline]
-    fn usable_capacity(&self, cap: usize) -> usize {
-        // As the number of entries approaches usable capacity,
-        // min_capacity(size) must be smaller than the internal capacity,
-        // so that the map is not resized:
-        // `min_capacity(usable_capacity(x)) <= x`.
-        // The left-hand side can only be smaller due to flooring by integer
-        // division.
-        //
-        // This doesn't have to be checked for overflow since allocation size
-        // in bytes will overflow earlier than multiplication by 10.
-        cap * 10 / 11
-    }
-}
-
-#[test]
-fn test_resize_policy() {
-    use prelude::v1::*;
-    let rp = DefaultResizePolicy;
-    for n in 0..1000 {
-        assert!(rp.min_capacity(rp.usable_capacity(n)) <= n);
-        assert!(rp.usable_capacity(rp.min_capacity(n)) <= n);
-    }
-}
-
-// The main performance trick in this hashmap is called Robin Hood Hashing.
-// It gains its excellent performance from one essential operation:
-//
-//    If an insertion collides with an existing element, and that element's
-//    "probe distance" (how far away the element is from its ideal location)
-//    is higher than how far we've already probed, swap the elements.
-//
-// This massively lowers variance in probe distance, and allows us to get very
-// high load factors with good performance. The 90% load factor I use is rather
-// conservative.
-//
-// > Why a load factor of approximately 90%?
-//
-// In general, all the distances to initial buckets will converge on the mean.
-// At a load factor of α, the odds of finding the target bucket after k
-// probes is approximately 1-α^k. If we set this equal to 50% (since we converge
-// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round
-// this down to make the math easier on the CPU and avoid its FPU.
-// Since on average we start the probing in the middle of a cache line, this
-// strategy pulls in two cache lines of hashes on every lookup. I think that's
-// pretty good, but if you want to trade off some space, it could go down to one
-// cache line on average with an α of 0.84.
-//
-// > Wait, what? Where did you get 1-α^k from?
-//
-// On the first probe, your odds of a collision with an existing element is α.
-// The odds of doing this twice in a row is approximately α^2. For three times,
-// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT
-// colliding after k tries is 1-α^k.
-//
-// The paper from 1986 cited below mentions an implementation which keeps track
-// of the distance-to-initial-bucket histogram. This approach is not suitable
-// for modern architectures because it requires maintaining an internal data
-// structure. This allows very good first guesses, but we are most concerned
-// with guessing entire cache lines, not individual indexes. Furthermore, array
-// accesses are no longer linear and in one direction, as we have now. There
-// is also memory and cache pressure that this would entail that would be very
-// difficult to properly see in a microbenchmark.
-//
-// ## Future Improvements (FIXME!)
-//
-// Allow the load factor to be changed dynamically and/or at initialization.
-//
-// Also, would it be possible for us to reuse storage when growing the
-// underlying table? This is exactly the use case for 'realloc', and may
-// be worth exploring.
-//
-// ## Future Optimizations (FIXME!)
-//
-// Another possible design choice that I made without any real reason is
-// parameterizing the raw table over keys and values. Technically, all we need
-// is the size and alignment of keys and values, and the code should be just as
-// efficient (well, we might need one for power-of-two size and one for not...).
-// This has the potential to reduce code bloat in rust executables, without
-// really losing anything except 4 words (key size, key alignment, val size,
-// val alignment) which can be passed in to every call of a `RawTable` function.
-// This would definitely be an avenue worth exploring if people start complaining
-// about the size of rust executables.
-//
-// Annotate exceedingly likely branches in `table::make_hash`
-// and `search_hashed` to reduce instruction cache pressure
-// and mispredictions once it becomes possible (blocked on issue #11092).
-//
-// Shrinking the table could simply reallocate in place after moving buckets
-// to the first half.
-//
-// The growth algorithm (fragment of the Proof of Correctness)
-// --------------------
-//
-// The growth algorithm is basically a fast path of the naive reinsertion-
-// during-resize algorithm. Other paths should never be taken.
-//
-// Consider growing a robin hood hashtable of capacity n. Normally, we do this
-// by allocating a new table of capacity `2n`, and then individually reinsert
-// each element in the old table into the new one. This guarantees that the
-// new table is a valid robin hood hashtable with all the desired statistical
-// properties. Remark that the order we reinsert the elements in should not
-// matter. For simplicity and efficiency, we will consider only linear
-// reinsertions, which consist of reinserting all elements in the old table
-// into the new one by increasing order of index. However we will not be
-// starting our reinsertions from index 0 in general. If we start from index
-// i, for the purpose of reinsertion we will consider all elements with real
-// index j < i to have virtual index n + j.
-//
-// Our hash generation scheme consists of generating a 64-bit hash and
-// truncating the most significant bits. When moving to the new table, we
-// simply introduce a new bit to the front of the hash. Therefore, if an
-// elements has ideal index i in the old table, it can have one of two ideal
-// locations in the new table. If the new bit is 0, then the new ideal index
-// is i. If the new bit is 1, then the new ideal index is n + i. Intuitively,
-// we are producing two independent tables of size n, and for each element we
-// independently choose which table to insert it into with equal probability.
-// However the rather than wrapping around themselves on overflowing their
-// indexes, the first table overflows into the first, and the first into the
-// second. Visually, our new table will look something like:
-//
-// [yy_xxx_xxxx_xxx|xx_yyy_yyyy_yyy]
-//
-// Where x's are elements inserted into the first table, y's are elements
-// inserted into the second, and _'s are empty sections. We now define a few
-// key concepts that we will use later. Note that this is a very abstract
-// perspective of the table. A real resized table would be at least half
-// empty.
-//
-// Theorem: A linear robin hood reinsertion from the first ideal element
-// produces identical results to a linear naive reinsertion from the same
-// element.
-//
-// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs
-
-/// A hash map implementation which uses linear probing with Robin
-/// Hood bucket stealing.
-///
-/// The hashes are all keyed by the task-local random number generator
-/// on creation by default. This means that the ordering of the keys is
-/// randomized, but makes the tables more resistant to
-/// denial-of-service attacks (Hash DoS). This behaviour can be
-/// overridden with one of the constructors.
-///
-/// It is required that the keys implement the `Eq` and `Hash` traits, although
-/// this can frequently be achieved by using `#[derive(Eq, Hash)]`.
-///
-/// Relevant papers/articles:
-///
-/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
-/// 2. Emmanuel Goossaert. ["Robin Hood
-///    hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/)
-/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift
-///    deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
-///
-/// # Example
-///
-/// ```
-/// use std::collections::HashMap;
-///
-/// // type inference lets us omit an explicit type signature (which
-/// // would be `HashMap<&str, &str>` in this example).
-/// let mut book_reviews = HashMap::new();
-///
-/// // review some books.
-/// book_reviews.insert("Adventures of Huckleberry Finn",    "My favorite book.");
-/// book_reviews.insert("Grimms' Fairy Tales",               "Masterpiece.");
-/// book_reviews.insert("Pride and Prejudice",               "Very enjoyable.");
-/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
-///
-/// // check for a specific one.
-/// if !book_reviews.contains_key(&("Les Misérables")) {
-///     println!("We've got {} reviews, but Les Misérables ain't one.",
-///              book_reviews.len());
-/// }
-///
-/// // oops, this review has a lot of spelling mistakes, let's delete it.
-/// book_reviews.remove(&("The Adventures of Sherlock Holmes"));
-///
-/// // look up the values associated with some keys.
-/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
-/// for book in to_find.iter() {
-///     match book_reviews.get(book) {
-///         Some(review) => println!("{}: {}", *book, *review),
-///         None => println!("{} is unreviewed.", *book)
-///     }
-/// }
-///
-/// // iterate over everything.
-/// for (book, review) in book_reviews.iter() {
-///     println!("{}: \"{}\"", *book, *review);
-/// }
-/// ```
-///
-/// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`.
-/// We must also derive `PartialEq`.
-///
-/// ```
-/// use std::collections::HashMap;
-///
-/// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking {
-///     name: String,
-///     country: String,
-/// }
-///
-/// impl Viking {
-///     /// Create a new Viking.
-///     fn new(name: &str, country: &str) -> Viking {
-///         Viking { name: name.to_string(), country: country.to_string() }
-///     }
-/// }
-///
-/// // Use a HashMap to store the vikings' health points.
-/// let mut vikings = HashMap::new();
-///
-/// vikings.insert(Viking::new("Einar", "Norway"), 25);
-/// vikings.insert(Viking::new("Olaf", "Denmark"), 24);
-/// vikings.insert(Viking::new("Harald", "Iceland"), 12);
-///
-/// // Use derived implementation to print the status of the vikings.
-/// for (viking, health) in vikings.iter() {
-///     println!("{:?} has {} hp", viking, health);
-/// }
-/// ```
-#[derive(Clone)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct HashMap<K, V, S = RandomState> {
-    // All hashes are keyed on these values, to prevent hash collision attacks.
-    hash_state: S,
-
-    table: RawTable<K, V>,
-
-    resize_policy: DefaultResizePolicy,
-}
-
-/// Search for a pre-hashed key.
-fn search_hashed<K, V, M, F>(table: M,
-                             hash: SafeHash,
-                             mut is_match: F)
-                             -> SearchResult<K, V, M> where
-    M: Deref<Target=RawTable<K, V>>,
-    F: FnMut(&K) -> bool,
-{
-    let size = table.size();
-    let mut probe = Bucket::new(table, hash);
-    let ib = probe.index();
-
-    while probe.index() != ib + size {
-        let full = match probe.peek() {
-            Empty(b) => return TableRef(b.into_table()), // hit an empty bucket
-            Full(b) => b
-        };
-
-        if full.distance() + ib < full.index() {
-            // We can finish the search early if we hit any bucket
-            // with a lower distance to initial bucket than we've probed.
-            return TableRef(full.into_table());
-        }
-
-        // If the hash doesn't match, it can't be this one..
-        if hash == full.hash() {
-            // If the key doesn't match, it can't be this one..
-            if is_match(full.read().0) {
-                return FoundExisting(full);
-            }
-        }
-
-        probe = full.next();
-    }
-
-    TableRef(probe.into_table())
-}
-
-fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
-    let (empty, retkey, retval) = starting_bucket.take();
-    let mut gap = match empty.gap_peek() {
-        Some(b) => b,
-        None => return (retkey, retval)
-    };
-
-    while gap.full().distance() != 0 {
-        gap = match gap.shift() {
-            Some(b) => b,
-            None => break
-        };
-    }
-
-    // Now we've done all our shifting. Return the value we grabbed earlier.
-    (retkey, retval)
-}
-
-/// Perform robin hood bucket stealing at the given `bucket`. You must
-/// also pass the position of that bucket's initial bucket so we don't have
-/// to recalculate it.
-///
-/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
-fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
-                        mut ib: usize,
-                        mut hash: SafeHash,
-                        mut k: K,
-                        mut v: V)
-                        -> &'a mut V {
-    let starting_index = bucket.index();
-    let size = {
-        let table = bucket.table(); // FIXME "lifetime too short".
-        table.size()
-    };
-    // There can be at most `size - dib` buckets to displace, because
-    // in the worst case, there are `size` elements and we already are
-    // `distance` buckets away from the initial one.
-    let idx_end = starting_index + size - bucket.distance();
-
-    loop {
-        let (old_hash, old_key, old_val) = bucket.replace(hash, k, v);
-        loop {
-            let probe = bucket.next();
-            assert!(probe.index() != idx_end);
-
-            let full_bucket = match probe.peek() {
-                Empty(bucket) => {
-                    // Found a hole!
-                    let b = bucket.put(old_hash, old_key, old_val);
-                    // Now that it's stolen, just read the value's pointer
-                    // right out of the table!
-                    return Bucket::at_index(b.into_table(), starting_index)
-                               .peek()
-                               .expect_full()
-                               .into_mut_refs()
-                               .1;
-                },
-                Full(bucket) => bucket
-            };
-
-            let probe_ib = full_bucket.index() - full_bucket.distance();
-
-            bucket = full_bucket;
-
-            // Robin hood! Steal the spot.
-            if ib < probe_ib {
-                ib = probe_ib;
-                hash = old_hash;
-                k = old_key;
-                v = old_val;
-                break;
-            }
-        }
-    }
-}
-
-/// A result that works like Option<FullBucket<..>> but preserves
-/// the reference that grants us access to the table in any case.
-enum SearchResult<K, V, M> {
-    // This is an entry that holds the given key:
-    FoundExisting(FullBucket<K, V, M>),
-
-    // There was no such entry. The reference is given back:
-    TableRef(M)
-}
-
-impl<K, V, M> SearchResult<K, V, M> {
-    fn into_option(self) -> Option<FullBucket<K, V, M>> {
-        match self {
-            FoundExisting(bucket) => Some(bucket),
-            TableRef(_) => None
-        }
-    }
-}
-
-impl<K, V, S, H> HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash<H> {
-        table::make_hash(&self.hash_state, x)
-    }
-
-    /// Search for a key, yielding the index if it's found in the hashtable.
-    /// If you already have the hash for the key lying around, use
-    /// search_hashed.
-    fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
-        where K: Borrow<Q>, Q: Eq + Hash<H>
-    {
-        let hash = self.make_hash(q);
-        search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
-            .into_option()
-    }
-
-    fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
-        where K: Borrow<Q>, Q: Eq + Hash<H>
-    {
-        let hash = self.make_hash(q);
-        search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
-            .into_option()
-    }
-
-    // The caller should ensure that invariants by Robin Hood Hashing hold.
-    fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
-        let cap = self.table.capacity();
-        let mut buckets = Bucket::new(&mut self.table, hash);
-        let ib = buckets.index();
-
-        while buckets.index() != ib + cap {
-            // We don't need to compare hashes for value swap.
-            // Not even DIBs for Robin Hood.
-            buckets = match buckets.peek() {
-                Empty(empty) => {
-                    empty.put(hash, k, v);
-                    return;
-                }
-                Full(b) => b.into_bucket()
-            };
-            buckets.next();
-        }
-        panic!("Internal HashMap error: Out of space.");
-    }
-}
-
-impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
-    /// Create an empty HashMap.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// let mut map: HashMap<&str, int> = HashMap::new();
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> HashMap<K, V, RandomState> {
-        Default::default()
-    }
-
-    /// Creates an empty hash map with the given initial capacity.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(capacity: usize) -> HashMap<K, V, RandomState> {
-        HashMap::with_capacity_and_hash_state(capacity, Default::default())
-    }
-}
-
-impl<K, V, S, H> HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    /// Creates an empty hashmap which will use the given hasher to hash keys.
-    ///
-    /// The creates map has the default initial capacity.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// use std::collections::hash_map::RandomState;
-    ///
-    /// let s = RandomState::new();
-    /// let mut map = HashMap::with_hash_state(s);
-    /// map.insert(1, 2);
-    /// ```
-    #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
-    pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
-        HashMap {
-            hash_state:    hash_state,
-            resize_policy: DefaultResizePolicy::new(),
-            table:         RawTable::new(0),
-        }
-    }
-
-    /// Create an empty HashMap with space for at least `capacity`
-    /// elements, using `hasher` to hash the keys.
-    ///
-    /// Warning: `hasher` is normally randomly generated, and
-    /// is designed to allow HashMaps to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// use std::collections::hash_map::RandomState;
-    ///
-    /// let s = RandomState::new();
-    /// let mut map = HashMap::with_capacity_and_hash_state(10, s);
-    /// map.insert(1, 2);
-    /// ```
-    #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
-    pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
-                                        -> HashMap<K, V, S> {
-        let resize_policy = DefaultResizePolicy::new();
-        let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
-        let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow");
-        assert!(internal_cap >= capacity, "capacity overflow");
-        HashMap {
-            hash_state:    hash_state,
-            resize_policy: resize_policy,
-            table:         RawTable::new(internal_cap),
-        }
-    }
-
-    /// Returns the number of elements the map can hold without reallocating.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// let map: HashMap<int, int> = HashMap::with_capacity(100);
-    /// assert!(map.capacity() >= 100);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn capacity(&self) -> usize {
-        self.resize_policy.usable_capacity(self.table.capacity())
-    }
-
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashMap`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new allocation size overflows `usize`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    /// let mut map: HashMap<&str, int> = HashMap::new();
-    /// map.reserve(10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn reserve(&mut self, additional: usize) {
-        let new_size = self.len().checked_add(additional).expect("capacity overflow");
-        let min_cap = self.resize_policy.min_capacity(new_size);
-
-        // An invalid value shouldn't make us run out of space. This includes
-        // an overflow check.
-        assert!(new_size <= min_cap);
-
-        if self.table.capacity() < min_cap {
-            let new_capacity = max(min_cap.next_power_of_two(), INITIAL_CAPACITY);
-            self.resize(new_capacity);
-        }
-    }
-
-    /// Resizes the internal vectors to a new capacity. It's your responsibility to:
-    ///   1) Make sure the new capacity is enough for all the elements, accounting
-    ///      for the load factor.
-    ///   2) Ensure new_capacity is a power of two or zero.
-    fn resize(&mut self, new_capacity: usize) {
-        assert!(self.table.size() <= new_capacity);
-        assert!(new_capacity.is_power_of_two() || new_capacity == 0);
-
-        let mut old_table = replace(&mut self.table, RawTable::new(new_capacity));
-        let old_size = old_table.size();
-
-        if old_table.capacity() == 0 || old_table.size() == 0 {
-            return;
-        }
-
-        // Grow the table.
-        // Specialization of the other branch.
-        let mut bucket = Bucket::first(&mut old_table);
-
-        // "So a few of the first shall be last: for many be called,
-        // but few chosen."
-        //
-        // We'll most likely encounter a few buckets at the beginning that
-        // have their initial buckets near the end of the table. They were
-        // placed at the beginning as the probe wrapped around the table
-        // during insertion. We must skip forward to a bucket that won't
-        // get reinserted too early and won't unfairly steal others spot.
-        // This eliminates the need for robin hood.
-        loop {
-            bucket = match bucket.peek() {
-                Full(full) => {
-                    if full.distance() == 0 {
-                        // This bucket occupies its ideal spot.
-                        // It indicates the start of another "cluster".
-                        bucket = full.into_bucket();
-                        break;
-                    }
-                    // Leaving this bucket in the last cluster for later.
-                    full.into_bucket()
-                }
-                Empty(b) => {
-                    // Encountered a hole between clusters.
-                    b.into_bucket()
-                }
-            };
-            bucket.next();
-        }
-
-        // This is how the buckets might be laid out in memory:
-        // ($ marks an initialized bucket)
-        //  ________________
-        // |$$$_$$$$$$_$$$$$|
-        //
-        // But we've skipped the entire initial cluster of buckets
-        // and will continue iteration in this order:
-        //  ________________
-        //     |$$$$$$_$$$$$
-        //                  ^ wrap around once end is reached
-        //  ________________
-        //  $$$_____________|
-        //    ^ exit once table.size == 0
-        loop {
-            bucket = match bucket.peek() {
-                Full(bucket) => {
-                    let h = bucket.hash();
-                    let (b, k, v) = bucket.take();
-                    self.insert_hashed_ordered(h, k, v);
-                    {
-                        let t = b.table(); // FIXME "lifetime too short".
-                        if t.size() == 0 { break }
-                    };
-                    b.into_bucket()
-                }
-                Empty(b) => b.into_bucket()
-            };
-            bucket.next();
-        }
-
-        assert_eq!(self.table.size(), old_size);
-    }
-
-    /// Shrinks the capacity of the map as much as possible. It will drop
-    /// down as much as possible while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map: HashMap<int, int> = HashMap::with_capacity(100);
-    /// map.insert(1, 2);
-    /// map.insert(3, 4);
-    /// assert!(map.capacity() >= 100);
-    /// map.shrink_to_fit();
-    /// assert!(map.capacity() >= 2);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn shrink_to_fit(&mut self) {
-        let min_capacity = self.resize_policy.min_capacity(self.len());
-        let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY);
-
-        // An invalid value shouldn't make us run out of space.
-        debug_assert!(self.len() <= min_capacity);
-
-        if self.table.capacity() != min_capacity {
-            let old_table = replace(&mut self.table, RawTable::new(min_capacity));
-            let old_size = old_table.size();
-
-            // Shrink the table. Naive algorithm for resizing:
-            for (h, k, v) in old_table.into_iter() {
-                self.insert_hashed_nocheck(h, k, v);
-            }
-
-            debug_assert_eq!(self.table.size(), old_size);
-        }
-    }
-
-    /// Insert a pre-hashed key-value pair, without first checking
-    /// that there's enough room in the buckets. Returns a reference to the
-    /// newly insert value.
-    ///
-    /// If the key already exists, the hashtable will be returned untouched
-    /// and a reference to the existing element will be returned.
-    fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> &mut V {
-        self.insert_or_replace_with(hash, k, v, |_, _, _| ())
-    }
-
-    fn insert_or_replace_with<'a, F>(&'a mut self,
-                                     hash: SafeHash,
-                                     k: K,
-                                     v: V,
-                                     mut found_existing: F)
-                                     -> &'a mut V where
-        F: FnMut(&mut K, &mut V, V),
-    {
-        // Worst case, we'll find one empty bucket among `size + 1` buckets.
-        let size = self.table.size();
-        let mut probe = Bucket::new(&mut self.table, hash);
-        let ib = probe.index();
-
-        loop {
-            let mut bucket = match probe.peek() {
-                Empty(bucket) => {
-                    // Found a hole!
-                    return bucket.put(hash, k, v).into_mut_refs().1;
-                }
-                Full(bucket) => bucket
-            };
-
-            // hash matches?
-            if bucket.hash() == hash {
-                // key matches?
-                if k == *bucket.read_mut().0 {
-                    let (bucket_k, bucket_v) = bucket.into_mut_refs();
-                    debug_assert!(k == *bucket_k);
-                    // Key already exists. Get its reference.
-                    found_existing(bucket_k, bucket_v, v);
-                    return bucket_v;
-                }
-            }
-
-            let robin_ib = bucket.index() as int - bucket.distance() as int;
-
-            if (ib as int) < robin_ib {
-                // Found a luckier bucket than me. Better steal his spot.
-                return robin_hood(bucket, robin_ib as usize, hash, k, v);
-            }
-
-            probe = bucket.next();
-            assert!(probe.index() != ib + size + 1);
-        }
-    }
-
-    /// An iterator visiting all keys in arbitrary order.
-    /// Iterator element type is `&'a K`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for key in map.keys() {
-    ///     println!("{}", key);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
-        fn first<A, B>((a, _): (A, B)) -> A { a }
-        let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr
-
-        Keys { inner: self.iter().map(first) }
-    }
-
-    /// An iterator visiting all values in arbitrary order.
-    /// Iterator element type is `&'a V`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for val in map.values() {
-    ///     println!("{}", val);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
-        fn second<A, B>((_, b): (A, B)) -> B { b }
-        let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr
-
-        Values { inner: self.iter().map(second) }
-    }
-
-    /// An iterator visiting all key-value pairs in arbitrary order.
-    /// Iterator element type is `(&'a K, &'a V)`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// for (key, val) in map.iter() {
-    ///     println!("key: {} val: {}", key, val);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<K, V> {
-        Iter { inner: self.table.iter() }
-    }
-
-    /// An iterator visiting all key-value pairs in arbitrary order,
-    /// with mutable references to the values.
-    /// Iterator element type is `(&'a K, &'a mut V)`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// // Update all values
-    /// for (_, val) in map.iter_mut() {
-    ///     *val *= 2;
-    /// }
-    ///
-    /// for (key, val) in map.iter() {
-    ///     println!("key: {} val: {}", key, val);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter_mut(&mut self) -> IterMut<K, V> {
-        IterMut { inner: self.table.iter_mut() }
-    }
-
-    /// Creates a consuming iterator, that is, one that moves each key-value
-    /// pair out of the map in arbitrary order. The map cannot be used after
-    /// calling this.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert("a", 1);
-    /// map.insert("b", 2);
-    /// map.insert("c", 3);
-    ///
-    /// // Not possible with .iter()
-    /// let vec: Vec<(&str, int)> = map.into_iter().collect();
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_iter(self) -> IntoIter<K, V> {
-        fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
-        let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
-
-        IntoIter {
-            inner: self.table.into_iter().map(last_two)
-        }
-    }
-
-    /// Gets the given key's corresponding entry in the map for in-place manipulation.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn entry(&mut self, key: K) -> Entry<K, V> {
-        // Gotta resize now.
-        self.reserve(1);
-
-        let hash = self.make_hash(&key);
-        search_entry_hashed(&mut self.table, hash, key)
-    }
-
-    /// Returns the number of elements in the map.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// assert_eq!(a.len(), 0);
-    /// a.insert(1, "a");
-    /// assert_eq!(a.len(), 1);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn len(&self) -> usize { self.table.size() }
-
-    /// Returns true if the map contains no elements.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// assert!(a.is_empty());
-    /// a.insert(1, "a");
-    /// assert!(!a.is_empty());
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool { self.len() == 0 }
-
-    /// Clears the map, returning all key-value pairs as an iterator. Keeps the
-    /// allocated memory for reuse.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// a.insert(1, "a");
-    /// a.insert(2, "b");
-    ///
-    /// for (k, v) in a.drain().take(1) {
-    ///     assert!(k == 1 || k == 2);
-    ///     assert!(v == "a" || v == "b");
-    /// }
-    ///
-    /// assert!(a.is_empty());
-    /// ```
-    #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "matches collection reform specification, waiting for dust to settle")]
-    pub fn drain(&mut self) -> Drain<K, V> {
-        fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
-        let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer
-
-        Drain {
-            inner: self.table.drain().map(last_two),
-        }
-    }
-
-    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
-    /// for reuse.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut a = HashMap::new();
-    /// a.insert(1, "a");
-    /// a.clear();
-    /// assert!(a.is_empty());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[inline]
-    pub fn clear(&mut self) {
-        self.drain();
-    }
-
-    /// Returns a reference to the value corresponding to the key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// `Hash` and `Eq` on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.get(&1), Some(&"a"));
-    /// assert_eq!(map.get(&2), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
-        where K: Borrow<Q>, Q: Hash<H> + Eq
-    {
-        self.search(k).map(|bucket| bucket.into_refs().1)
-    }
-
-    /// Returns true if the map contains a value for the specified key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// `Hash` and `Eq` on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.contains_key(&1), true);
-    /// assert_eq!(map.contains_key(&2), false);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
-        where K: Borrow<Q>, Q: Hash<H> + Eq
-    {
-        self.search(k).is_some()
-    }
-
-    /// Returns a mutable reference to the value corresponding to the key.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// `Hash` and `Eq` on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// match map.get_mut(&1) {
-    ///     Some(x) => *x = "b",
-    ///     None => (),
-    /// }
-    /// assert_eq!(map[1], "b");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
-        where K: Borrow<Q>, Q: Hash<H> + Eq
-    {
-        self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
-    }
-
-    /// Inserts a key-value pair from the map. If the key already had a value
-    /// present in the map, that value is returned. Otherwise, `None` is returned.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// assert_eq!(map.insert(37, "a"), None);
-    /// assert_eq!(map.is_empty(), false);
-    ///
-    /// map.insert(37, "b");
-    /// assert_eq!(map.insert(37, "c"), Some("b"));
-    /// assert_eq!(map[37], "c");
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
-        let hash = self.make_hash(&k);
-        self.reserve(1);
-
-        let mut retval = None;
-        self.insert_or_replace_with(hash, k, v, |_, val_ref, val| {
-            retval = Some(replace(val_ref, val));
-        });
-        retval
-    }
-
-    /// Removes a key from the map, returning the value at the key if the key
-    /// was previously in the map.
-    ///
-    /// The key may be any borrowed form of the map's key type, but
-    /// `Hash` and `Eq` on the borrowed form *must* match those for
-    /// the key type.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashMap;
-    ///
-    /// let mut map = HashMap::new();
-    /// map.insert(1, "a");
-    /// assert_eq!(map.remove(&1), Some("a"));
-    /// assert_eq!(map.remove(&1), None);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
-        where K: Borrow<Q>, Q: Hash<H> + Eq
-    {
-        if self.table.size() == 0 {
-            return None
-        }
-
-        self.search_mut(k).map(|bucket| pop_internal(bucket).1)
-    }
-}
-
-fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: K)
-        -> Entry<'a, K, V>
-{
-    // Worst case, we'll find one empty bucket among `size + 1` buckets.
-    let size = table.size();
-    let mut probe = Bucket::new(table, hash);
-    let ib = probe.index();
-
-    loop {
-        let bucket = match probe.peek() {
-            Empty(bucket) => {
-                // Found a hole!
-                return Vacant(VacantEntry {
-                    hash: hash,
-                    key: k,
-                    elem: NoElem(bucket),
-                });
-            },
-            Full(bucket) => bucket
-        };
-
-        // hash matches?
-        if bucket.hash() == hash {
-            // key matches?
-            if k == *bucket.read().0 {
-                return Occupied(OccupiedEntry{
-                    elem: bucket,
-                });
-            }
-        }
-
-        let robin_ib = bucket.index() as int - bucket.distance() as int;
-
-        if (ib as int) < robin_ib {
-            // Found a luckier bucket than me. Better steal his spot.
-            return Vacant(VacantEntry {
-                hash: hash,
-                key: k,
-                elem: NeqElem(bucket, robin_ib as usize),
-            });
-        }
-
-        probe = bucket.next();
-        assert!(probe.index() != ib + size + 1);
-    }
-}
-
-impl<K, V, S, H> PartialEq for HashMap<K, V, S>
-    where K: Eq + Hash<H>, V: PartialEq,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn eq(&self, other: &HashMap<K, V, S>) -> bool {
-        if self.len() != other.len() { return false; }
-
-        self.iter().all(|(key, value)|
-            other.get(key).map_or(false, |v| *value == *v)
-        )
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Eq for HashMap<K, V, S>
-    where K: Eq + Hash<H>, V: Eq,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Debug for HashMap<K, V, S>
-    where K: Eq + Hash<H> + Debug, V: Debug,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "HashMap {{"));
-
-        for (i, (k, v)) in self.iter().enumerate() {
-            if i != 0 { try!(write!(f, ", ")); }
-            try!(write!(f, "{:?}: {:?}", *k, *v));
-        }
-
-        write!(f, "}}")
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Default for HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    fn default() -> HashMap<K, V, S> {
-        HashMap::with_hash_state(Default::default())
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
-    where K: Eq + Hash<H> + Borrow<Q>,
-          Q: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Output = V;
-
-    #[inline]
-    fn index<'a>(&'a self, index: &Q) -> &'a V {
-        self.get(index).expect("no entry found for key")
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
-    where K: Eq + Hash<H> + Borrow<Q>,
-          Q: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    #[inline]
-    fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
-        self.get_mut(index).expect("no entry found for key")
-    }
-}
-
-/// HashMap iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, K: 'a, V: 'a> {
-    inner: table::Iter<'a, K, V>
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-impl<'a, K, V> Clone for Iter<'a, K, V> {
-    fn clone(&self) -> Iter<'a, K, V> {
-        Iter {
-            inner: self.inner.clone()
-        }
-    }
-}
-
-/// HashMap mutable values iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IterMut<'a, K: 'a, V: 'a> {
-    inner: table::IterMut<'a, K, V>
-}
-
-/// HashMap move iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<K, V> {
-    inner: iter::Map<table::IntoIter<K, V>, fn((SafeHash, K, V)) -> (K, V)>
-}
-
-/// HashMap keys iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Keys<'a, K: 'a, V: 'a> {
-    inner: Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-impl<'a, K, V> Clone for Keys<'a, K, V> {
-    fn clone(&self) -> Keys<'a, K, V> {
-        Keys {
-            inner: self.inner.clone()
-        }
-    }
-}
-
-/// HashMap values iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Values<'a, K: 'a, V: 'a> {
-    inner: Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-impl<'a, K, V> Clone for Values<'a, K, V> {
-    fn clone(&self) -> Values<'a, K, V> {
-        Values {
-            inner: self.inner.clone()
-        }
-    }
-}
-
-/// HashMap drain iterator.
-#[unstable(feature = "std_misc",
-           reason = "matches collection reform specification, waiting for dust to settle")]
-pub struct Drain<'a, K: 'a, V: 'a> {
-    inner: iter::Map<table::Drain<'a, K, V>, fn((SafeHash, K, V)) -> (K, V)>
-}
-
-/// A view into a single occupied location in a HashMap.
-#[unstable(feature = "std_misc",
-           reason = "precise API still being fleshed out")]
-pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
-    elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
-}
-
-/// A view into a single empty location in a HashMap.
-#[unstable(feature = "std_misc",
-           reason = "precise API still being fleshed out")]
-pub struct VacantEntry<'a, K: 'a, V: 'a> {
-    hash: SafeHash,
-    key: K,
-    elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
-}
-
-/// A view into a single location in a map, which may be vacant or occupied.
-#[unstable(feature = "std_misc",
-           reason = "precise API still being fleshed out")]
-pub enum Entry<'a, K: 'a, V: 'a> {
-    /// An occupied Entry.
-    Occupied(OccupiedEntry<'a, K, V>),
-    /// A vacant Entry.
-    Vacant(VacantEntry<'a, K, V>),
-}
-
-/// Possible states of a VacantEntry.
-enum VacantEntryState<K, V, M> {
-    /// The index is occupied, but the key to insert has precedence,
-    /// and will kick the current one out on insertion.
-    NeqElem(FullBucket<K, V, M>, usize),
-    /// The index is genuinely vacant.
-    NoElem(EmptyBucket<K, V, M>),
-}
-
-impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = (&'a K, &'a V);
-    type IntoIter = Iter<'a, K, V>;
-
-    fn into_iter(self) -> Iter<'a, K, V> {
-        self.iter()
-    }
-}
-
-impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = (&'a K, &'a mut V);
-    type IntoIter = IterMut<'a, K, V>;
-
-    fn into_iter(mut self) -> IterMut<'a, K, V> {
-        self.iter_mut()
-    }
-}
-
-impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = (K, V);
-    type IntoIter = IntoIter<K, V>;
-
-    fn into_iter(self) -> IntoIter<K, V> {
-        self.into_iter()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> Iterator for Iter<'a, K, V> {
-    type Item = (&'a K, &'a V);
-
-    #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> Iterator for IterMut<'a, K, V> {
-    type Item = (&'a K, &'a mut V);
-
-    #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V> Iterator for IntoIter<K, V> {
-    type Item = (K, V);
-
-    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V> ExactSizeIterator for IntoIter<K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> Iterator for Keys<'a, K, V> {
-    type Item = &'a K;
-
-    #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> Iterator for Values<'a, K, V> {
-    type Item = &'a V;
-
-    #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> Iterator for Drain<'a, K, V> {
-    type Item = (K, V);
-
-    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
-    #[inline] fn len(&self) -> usize { self.inner.len() }
-}
-
-#[unstable(feature = "std_misc",
-           reason = "matches collection reform v2 specification, waiting for dust to settle")]
-impl<'a, K, V> Entry<'a, K, V> {
-    /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant.
-    pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
-        match self {
-            Occupied(entry) => Ok(entry.into_mut()),
-            Vacant(entry) => Err(entry),
-        }
-    }
-}
-
-impl<'a, K, V> OccupiedEntry<'a, K, V> {
-    /// Gets a reference to the value in the entry.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get(&self) -> &V {
-        self.elem.read().1
-    }
-
-    /// Gets a mutable reference to the value in the entry.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get_mut(&mut self) -> &mut V {
-        self.elem.read_mut().1
-    }
-
-    /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_mut(self) -> &'a mut V {
-        self.elem.into_mut_refs().1
-    }
-
-    /// Sets the value of the entry, and returns the entry's old value
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(&mut self, mut value: V) -> V {
-        let old_value = self.get_mut();
-        mem::swap(&mut value, old_value);
-        value
-    }
-
-    /// Takes the value out of the entry, and returns it
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn remove(self) -> V {
-        pop_internal(self.elem).1
-    }
-}
-
-impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
-    /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(self, value: V) -> &'a mut V {
-        match self.elem {
-            NeqElem(bucket, ib) => {
-                robin_hood(bucket, ib, self.hash, self.key, value)
-            }
-            NoElem(bucket) => {
-                bucket.put(self.hash, self.key, value).into_mut_refs().1
-            }
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, S> {
-        let iter = iter.into_iter();
-        let lower = iter.size_hint().0;
-        let mut map = HashMap::with_capacity_and_hash_state(lower,
-                                                            Default::default());
-        map.extend(iter);
-        map
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
-    where K: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
-        for (k, v) in iter {
-            self.insert(k, v);
-        }
-    }
-}
-
-
-/// `RandomState` is the default state for `HashMap` types.
-///
-/// A particular instance `RandomState` will create the same instances of
-/// `Hasher`, but the hashers created by two different `RandomState`
-/// instances are unlikely to produce the same result for the same values.
-#[derive(Clone)]
-#[unstable(feature = "std_misc",
-           reason = "hashing an hash maps may be altered")]
-pub struct RandomState {
-    k0: u64,
-    k1: u64,
-}
-
-#[unstable(feature = "std_misc",
-           reason = "hashing an hash maps may be altered")]
-impl RandomState {
-    /// Construct a new `RandomState` that is initialized with random keys.
-    #[inline]
-    #[allow(deprecated)]
-    pub fn new() -> RandomState {
-        let mut r = rand::thread_rng();
-        RandomState { k0: r.gen(), k1: r.gen() }
-    }
-}
-
-#[unstable(feature = "std_misc",
-           reason = "hashing an hash maps may be altered")]
-impl HashState for RandomState {
-    type Hasher = Hasher;
-    fn hasher(&self) -> Hasher {
-        Hasher { inner: SipHasher::new_with_keys(self.k0, self.k1) }
-    }
-}
-
-#[unstable(feature = "std_misc",
-           reason = "hashing an hash maps may be altered")]
-impl Default for RandomState {
-    #[inline]
-    fn default() -> RandomState {
-        RandomState::new()
-    }
-}
-
-/// A hasher implementation which is generated from `RandomState` instances.
-///
-/// This is the default hasher used in a `HashMap` to hash keys. Types do not
-/// typically declare an ability to explicitly hash into this particular type,
-/// but rather in a `H: hash::Writer` type parameter.
-#[unstable(feature = "std_misc",
-           reason = "hashing an hash maps may be altered")]
-pub struct Hasher { inner: SipHasher }
-
-impl hash::Writer for Hasher {
-    fn write(&mut self, data: &[u8]) {
-        hash::Writer::write(&mut self.inner, data)
-    }
-}
-
-impl hash::Hasher for Hasher {
-    type Output = u64;
-    fn reset(&mut self) { hash::Hasher::reset(&mut self.inner) }
-    fn finish(&self) -> u64 { self.inner.finish() }
-}
-
-#[cfg(test)]
-mod test_map {
-    use prelude::v1::*;
-
-    use super::HashMap;
-    use super::Entry::{Occupied, Vacant};
-    use iter::{range_inclusive, range_step_inclusive, repeat};
-    use cell::RefCell;
-    use rand::{weak_rng, Rng};
-
-    #[test]
-    fn test_create_capacity_zero() {
-        let mut m = HashMap::with_capacity(0);
-
-        assert!(m.insert(1, 1).is_none());
-
-        assert!(m.contains_key(&1));
-        assert!(!m.contains_key(&0));
-    }
-
-    #[test]
-    fn test_insert() {
-        let mut m = HashMap::new();
-        assert_eq!(m.len(), 0);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(2, 4).is_none());
-        assert_eq!(m.len(), 2);
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&2).unwrap(), 4);
-    }
-
-    thread_local! { static DROP_VECTOR: RefCell<Vec<int>> = RefCell::new(Vec::new()) }
-
-    #[derive(Hash, PartialEq, Eq)]
-    struct Dropable {
-        k: usize
-    }
-
-    impl Dropable {
-        fn new(k: usize) -> Dropable {
-            DROP_VECTOR.with(|slot| {
-                slot.borrow_mut()[k] += 1;
-            });
-
-            Dropable { k: k }
-        }
-    }
-
-    impl Drop for Dropable {
-        fn drop(&mut self) {
-            DROP_VECTOR.with(|slot| {
-                slot.borrow_mut()[self.k] -= 1;
-            });
-        }
-    }
-
-    impl Clone for Dropable {
-        fn clone(&self) -> Dropable {
-            Dropable::new(self.k)
-        }
-    }
-
-    #[test]
-    fn test_drops() {
-        DROP_VECTOR.with(|slot| {
-            *slot.borrow_mut() = repeat(0).take(200).collect();
-        });
-
-        {
-            let mut m = HashMap::new();
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 0);
-                }
-            });
-
-            for i in 0..100 {
-                let d1 = Dropable::new(i);
-                let d2 = Dropable::new(i+100);
-                m.insert(d1, d2);
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            for i in 0..50 {
-                let k = Dropable::new(i);
-                let v = m.remove(&k);
-
-                assert!(v.is_some());
-
-                DROP_VECTOR.with(|v| {
-                    assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i+100], 1);
-                });
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..50 {
-                    assert_eq!(v.borrow()[i], 0);
-                    assert_eq!(v.borrow()[i+100], 0);
-                }
-
-                for i in 50..100 {
-                    assert_eq!(v.borrow()[i], 1);
-                    assert_eq!(v.borrow()[i+100], 1);
-                }
-            });
-        }
-
-        DROP_VECTOR.with(|v| {
-            for i in 0..200 {
-                assert_eq!(v.borrow()[i], 0);
-            }
-        });
-    }
-
-    #[test]
-    fn test_move_iter_drops() {
-        DROP_VECTOR.with(|v| {
-            *v.borrow_mut() = repeat(0).take(200).collect();
-        });
-
-        let hm = {
-            let mut hm = HashMap::new();
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 0);
-                }
-            });
-
-            for i in 0..100 {
-                let d1 = Dropable::new(i);
-                let d2 = Dropable::new(i+100);
-                hm.insert(d1, d2);
-            }
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            hm
-        };
-
-        // By the way, ensure that cloning doesn't screw up the dropping.
-        drop(hm.clone());
-
-        {
-            let mut half = hm.into_iter().take(50);
-
-            DROP_VECTOR.with(|v| {
-                for i in 0..200 {
-                    assert_eq!(v.borrow()[i], 1);
-                }
-            });
-
-            for _ in half.by_ref() {}
-
-            DROP_VECTOR.with(|v| {
-                let nk = (0..100).filter(|&i| {
-                    v.borrow()[i] == 1
-                }).count();
-
-                let nv = (0..100).filter(|&i| {
-                    v.borrow()[i+100] == 1
-                }).count();
-
-                assert_eq!(nk, 50);
-                assert_eq!(nv, 50);
-            });
-        };
-
-        DROP_VECTOR.with(|v| {
-            for i in 0..200 {
-                assert_eq!(v.borrow()[i], 0);
-            }
-        });
-    }
-
-    #[test]
-    fn test_empty_pop() {
-        let mut m: HashMap<int, bool> = HashMap::new();
-        assert_eq!(m.remove(&0), None);
-    }
-
-    #[test]
-    fn test_lots_of_insertions() {
-        let mut m = HashMap::new();
-
-        // Try this a few times to make sure we never screw up the hashmap's
-        // internal state.
-        for _ in 0..10 {
-            assert!(m.is_empty());
-
-            for i in range_inclusive(1, 1000) {
-                assert!(m.insert(i, i).is_none());
-
-                for j in range_inclusive(1, i) {
-                    let r = m.get(&j);
-                    assert_eq!(r, Some(&j));
-                }
-
-                for j in range_inclusive(i+1, 1000) {
-                    let r = m.get(&j);
-                    assert_eq!(r, None);
-                }
-            }
-
-            for i in range_inclusive(1001, 2000) {
-                assert!(!m.contains_key(&i));
-            }
-
-            // remove forwards
-            for i in range_inclusive(1, 1000) {
-                assert!(m.remove(&i).is_some());
-
-                for j in range_inclusive(1, i) {
-                    assert!(!m.contains_key(&j));
-                }
-
-                for j in range_inclusive(i+1, 1000) {
-                    assert!(m.contains_key(&j));
-                }
-            }
-
-            for i in range_inclusive(1, 1000) {
-                assert!(!m.contains_key(&i));
-            }
-
-            for i in range_inclusive(1, 1000) {
-                assert!(m.insert(i, i).is_none());
-            }
-
-            // remove backwards
-            for i in range_step_inclusive(1000, 1, -1) {
-                assert!(m.remove(&i).is_some());
-
-                for j in range_inclusive(i, 1000) {
-                    assert!(!m.contains_key(&j));
-                }
-
-                for j in range_inclusive(1, i-1) {
-                    assert!(m.contains_key(&j));
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn test_find_mut() {
-        let mut m = HashMap::new();
-        assert!(m.insert(1, 12).is_none());
-        assert!(m.insert(2, 8).is_none());
-        assert!(m.insert(5, 14).is_none());
-        let new = 100;
-        match m.get_mut(&5) {
-            None => panic!(), Some(x) => *x = new
-        }
-        assert_eq!(m.get(&5), Some(&new));
-    }
-
-    #[test]
-    fn test_insert_overwrite() {
-        let mut m = HashMap::new();
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert!(!m.insert(1, 3).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 3);
-    }
-
-    #[test]
-    fn test_insert_conflicts() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert!(m.insert(5, 3).is_none());
-        assert!(m.insert(9, 4).is_none());
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert_eq!(*m.get(&1).unwrap(), 2);
-    }
-
-    #[test]
-    fn test_conflict_remove() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert!(m.insert(5, 3).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert!(m.insert(9, 4).is_none());
-        assert_eq!(*m.get(&1).unwrap(), 2);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert!(m.remove(&1).is_some());
-        assert_eq!(*m.get(&9).unwrap(), 4);
-        assert_eq!(*m.get(&5).unwrap(), 3);
-    }
-
-    #[test]
-    fn test_is_empty() {
-        let mut m = HashMap::with_capacity(4);
-        assert!(m.insert(1, 2).is_none());
-        assert!(!m.is_empty());
-        assert!(m.remove(&1).is_some());
-        assert!(m.is_empty());
-    }
-
-    #[test]
-    fn test_pop() {
-        let mut m = HashMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.remove(&1), Some(2));
-        assert_eq!(m.remove(&1), None);
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut m = HashMap::with_capacity(4);
-        for i in 0..32 {
-            assert!(m.insert(i, i*2).is_none());
-        }
-        assert_eq!(m.len(), 32);
-
-        let mut observed: u32 = 0;
-
-        for (k, v) in &m {
-            assert_eq!(*v, *k * 2);
-            observed |= 1 << *k;
-        }
-        assert_eq!(observed, 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_keys() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_iter().collect();
-        let keys: Vec<_> = map.keys().cloned().collect();
-        assert_eq!(keys.len(), 3);
-        assert!(keys.contains(&1));
-        assert!(keys.contains(&2));
-        assert!(keys.contains(&3));
-    }
-
-    #[test]
-    fn test_values() {
-        let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
-        let map: HashMap<_, _> = vec.into_iter().collect();
-        let values: Vec<_> = map.values().cloned().collect();
-        assert_eq!(values.len(), 3);
-        assert!(values.contains(&'a'));
-        assert!(values.contains(&'b'));
-        assert!(values.contains(&'c'));
-    }
-
-    #[test]
-    fn test_find() {
-        let mut m = HashMap::new();
-        assert!(m.get(&1).is_none());
-        m.insert(1, 2);
-        match m.get(&1) {
-            None => panic!(),
-            Some(v) => assert_eq!(*v, 2)
-        }
-    }
-
-    #[test]
-    fn test_eq() {
-        let mut m1 = HashMap::new();
-        m1.insert(1, 2);
-        m1.insert(2, 3);
-        m1.insert(3, 4);
-
-        let mut m2 = HashMap::new();
-        m2.insert(1, 2);
-        m2.insert(2, 3);
-
-        assert!(m1 != m2);
-
-        m2.insert(3, 4);
-
-        assert_eq!(m1, m2);
-    }
-
-    #[test]
-    fn test_show() {
-        let mut map = HashMap::new();
-        let empty: HashMap<i32, i32> = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(3, 4);
-
-        let map_str = format!("{:?}", map);
-
-        assert!(map_str == "HashMap {1: 2, 3: 4}" ||
-                map_str == "HashMap {3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "HashMap {}");
-    }
-
-    #[test]
-    fn test_expand() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert!(m.is_empty());
-
-        let mut i = 0;
-        let old_cap = m.table.capacity();
-        while old_cap == m.table.capacity() {
-            m.insert(i, i);
-            i += 1;
-        }
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-    }
-
-    #[test]
-    fn test_behavior_resize_policy() {
-        let mut m = HashMap::new();
-
-        assert_eq!(m.len(), 0);
-        assert_eq!(m.table.capacity(), 0);
-        assert!(m.is_empty());
-
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.is_empty());
-        let initial_cap = m.table.capacity();
-        m.reserve(initial_cap);
-        let cap = m.table.capacity();
-
-        assert_eq!(cap, initial_cap * 2);
-
-        let mut i = 0;
-        for _ in 0..cap * 3 / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // three quarters full
-
-        assert_eq!(m.len(), i);
-        assert_eq!(m.table.capacity(), cap);
-
-        for _ in 0..cap / 4 {
-            m.insert(i, i);
-            i += 1;
-        }
-        // half full
-
-        let new_cap = m.table.capacity();
-        assert_eq!(new_cap, cap * 2);
-
-        for _ in 0..cap / 2 - 1 {
-            i -= 1;
-            m.remove(&i);
-            assert_eq!(m.table.capacity(), new_cap);
-        }
-        // A little more than one quarter full.
-        m.shrink_to_fit();
-        assert_eq!(m.table.capacity(), cap);
-        // again, a little more than half full
-        for _ in 0..cap / 2 - 1 {
-            i -= 1;
-            m.remove(&i);
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), i);
-        assert!(!m.is_empty());
-        assert_eq!(m.table.capacity(), initial_cap);
-    }
-
-    #[test]
-    fn test_reserve_shrink_to_fit() {
-        let mut m = HashMap::new();
-        m.insert(0, 0);
-        m.remove(&0);
-        assert!(m.capacity() >= m.len());
-        for i in 0..128 {
-            m.insert(i, i);
-        }
-        m.reserve(256);
-
-        let usable_cap = m.capacity();
-        for i in 128..(128 + 256) {
-            m.insert(i, i);
-            assert_eq!(m.capacity(), usable_cap);
-        }
-
-        for i in 100..(128 + 256) {
-            assert_eq!(m.remove(&i), Some(i));
-        }
-        m.shrink_to_fit();
-
-        assert_eq!(m.len(), 100);
-        assert!(!m.is_empty());
-        assert!(m.capacity() >= m.len());
-
-        for i in 0..100 {
-            assert_eq!(m.remove(&i), Some(i));
-        }
-        m.shrink_to_fit();
-        m.insert(0, 0);
-
-        assert_eq!(m.len(), 1);
-        assert!(m.capacity() >= m.len());
-        assert_eq!(m.remove(&0), Some(0));
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        for &(k, v) in &xs {
-            assert_eq!(map.get(&k), Some(&v));
-        }
-    }
-
-    #[test]
-    fn test_size_hint() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _>  = xs.iter().cloned().collect();
-
-        let mut iter = map.iter();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.size_hint(), (3, Some(3)));
-    }
-
-    #[test]
-    fn test_iter_len() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let map: HashMap<_, _>  = xs.iter().cloned().collect();
-
-        let mut iter = map.iter();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.len(), 3);
-    }
-
-    #[test]
-    fn test_mut_size_hint() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let mut map: HashMap<_, _>  = xs.iter().cloned().collect();
-
-        let mut iter = map.iter_mut();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.size_hint(), (3, Some(3)));
-    }
-
-    #[test]
-    fn test_iter_mut_len() {
-        let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
-
-        let mut map: HashMap<_, _>  = xs.iter().cloned().collect();
-
-        let mut iter = map.iter_mut();
-
-        for _ in iter.by_ref().take(3) {}
-
-        assert_eq!(iter.len(), 3);
-    }
-
-    #[test]
-    fn test_index() {
-        let mut map = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(2, 1);
-        map.insert(3, 4);
-
-        assert_eq!(map[2], 1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_index_nonexistent() {
-        let mut map = HashMap::new();
-
-        map.insert(1, 2);
-        map.insert(2, 1);
-        map.insert(3, 4);
-
-        map[4];
-    }
-
-    #[test]
-    fn test_entry(){
-        let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
-
-        let mut map: HashMap<_, _> = xs.iter().cloned().collect();
-
-        // Existing key (insert)
-        match map.entry(1) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                assert_eq!(view.get(), &10);
-                assert_eq!(view.insert(100), 10);
-            }
-        }
-        assert_eq!(map.get(&1).unwrap(), &100);
-        assert_eq!(map.len(), 6);
-
-
-        // Existing key (update)
-        match map.entry(2) {
-            Vacant(_) => unreachable!(),
-            Occupied(mut view) => {
-                let v = view.get_mut();
-                let new_v = (*v) * 10;
-                *v = new_v;
-            }
-        }
-        assert_eq!(map.get(&2).unwrap(), &200);
-        assert_eq!(map.len(), 6);
-
-        // Existing key (take)
-        match map.entry(3) {
-            Vacant(_) => unreachable!(),
-            Occupied(view) => {
-                assert_eq!(view.remove(), 30);
-            }
-        }
-        assert_eq!(map.get(&3), None);
-        assert_eq!(map.len(), 5);
-
-
-        // Inexistent key (insert)
-        match map.entry(10) {
-            Occupied(_) => unreachable!(),
-            Vacant(view) => {
-                assert_eq!(*view.insert(1000), 1000);
-            }
-        }
-        assert_eq!(map.get(&10).unwrap(), &1000);
-        assert_eq!(map.len(), 6);
-    }
-
-    #[test]
-    fn test_entry_take_doesnt_corrupt() {
-        // Test for #19292
-        fn check(m: &HashMap<isize, ()>) {
-            for k in m.keys() {
-                assert!(m.contains_key(k),
-                        "{} is in keys() but not in the map?", k);
-            }
-        }
-
-        let mut m = HashMap::new();
-        let mut rng = weak_rng();
-
-        // Populate the map with some items.
-        for _ in 0..50 {
-            let x = rng.gen_range(-10, 10);
-            m.insert(x, ());
-        }
-
-        for i in 0..1000 {
-            let x = rng.gen_range(-10, 10);
-            match m.entry(x) {
-                Vacant(_) => {},
-                Occupied(e) => {
-                    println!("{}: remove {}", i, x);
-                    e.remove();
-                },
-            }
-
-            check(&m);
-        }
-    }
-}
index 39c1458b720019cd84f52245f7e7204f085cfe88..47e300af26981da7cd395a6b361bf63704358cb6 100644 (file)
 
 mod bench;
 mod table;
-#[cfg(stage0)]
-#[path = "map_stage0.rs"]
 pub mod map;
-#[cfg(not(stage0))]
-pub mod map;
-#[cfg(stage0)]
-#[path = "set_stage0.rs"]
-pub mod set;
-#[cfg(not(stage0))]
 pub mod set;
 pub mod state;
index e0631a64d44b127048402f0667195daed7e4ffc6..cdc0ebd76aada5d823709363e9c96203211cf0dd 100644 (file)
@@ -598,7 +598,7 @@ impl<T, S> fmt::Debug for HashSet<T, S>
           S: HashState
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "HashSet {{"));
+        try!(write!(f, "{{"));
 
         for (i, x) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1186,8 +1186,8 @@ fn test_show() {
 
         let set_str = format!("{:?}", set);
 
-        assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}");
-        assert_eq!(format!("{:?}", empty), "HashSet {}");
+        assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
diff --git a/src/libstd/collections/hash/set_stage0.rs b/src/libstd/collections/hash/set_stage0.rs
deleted file mode 100644 (file)
index 68c9e02..0000000
+++ /dev/null
@@ -1,1252 +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.
-//
-// ignore-lexer-test FIXME #15883
-
-use borrow::Borrow;
-use clone::Clone;
-use cmp::{Eq, PartialEq};
-use core::marker::Sized;
-use default::Default;
-use fmt::Debug;
-use fmt;
-use hash::{self, Hash};
-use iter::{
-    Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend,
-};
-use ops::{BitOr, BitAnd, BitXor, Sub};
-use option::Option::{Some, None, self};
-
-use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState, Hasher};
-use super::state::HashState;
-
-// Future Optimization (FIXME!)
-// =============================
-//
-// Iteration over zero sized values is a noop. There is no need
-// for `bucket.val` in the case of HashSet. I suppose we would need HKT
-// to get rid of it properly.
-
-/// An implementation of a hash set using the underlying representation of a
-/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
-/// requires that the elements implement the `Eq` and `Hash` traits.
-///
-/// # Example
-///
-/// ```
-/// use std::collections::HashSet;
-/// // Type inference lets us omit an explicit type signature (which
-/// // would be `HashSet<&str>` in this example).
-/// let mut books = HashSet::new();
-///
-/// // Add some books.
-/// books.insert("A Dance With Dragons");
-/// books.insert("To Kill a Mockingbird");
-/// books.insert("The Odyssey");
-/// books.insert("The Great Gatsby");
-///
-/// // Check for a specific one.
-/// if !books.contains(&("The Winds of Winter")) {
-///     println!("We have {} books, but The Winds of Winter ain't one.",
-///              books.len());
-/// }
-///
-/// // Remove a book.
-/// books.remove(&"The Odyssey");
-///
-/// // Iterate over everything.
-/// for book in books.iter() {
-///     println!("{}", *book);
-/// }
-/// ```
-///
-/// The easiest way to use `HashSet` with a custom type is to derive
-/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the
-/// future be implied by `Eq`.
-///
-/// ```
-/// use std::collections::HashSet;
-/// #[derive(Hash, Eq, PartialEq, Debug)]
-/// struct Viking<'a> {
-///     name: &'a str,
-///     power: usize,
-/// }
-///
-/// let mut vikings = HashSet::new();
-///
-/// vikings.insert(Viking { name: "Einar", power: 9 });
-/// vikings.insert(Viking { name: "Einar", power: 9 });
-/// vikings.insert(Viking { name: "Olaf", power: 4 });
-/// vikings.insert(Viking { name: "Harald", power: 8 });
-///
-/// // Use derived implementation to print the vikings.
-/// for x in vikings.iter() {
-///     println!("{:?}", x);
-/// }
-/// ```
-#[derive(Clone)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct HashSet<T, S = RandomState> {
-    map: HashMap<T, (), S>
-}
-
-impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
-    /// Create an empty HashSet.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let mut set: HashSet<int> = HashSet::new();
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new() -> HashSet<T, RandomState> {
-        HashSet::with_capacity(INITIAL_CAPACITY)
-    }
-
-    /// Create an empty HashSet with space for at least `n` elements in
-    /// the hash table.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let mut set: HashSet<int> = HashSet::with_capacity(10);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn with_capacity(capacity: usize) -> HashSet<T, RandomState> {
-        HashSet { map: HashMap::with_capacity(capacity) }
-    }
-}
-
-impl<T, S, H> HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    /// Creates a new empty hash set which will use the given hasher to hash
-    /// keys.
-    ///
-    /// The hash set is also created with the default initial capacity.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// use std::collections::hash_map::RandomState;
-    ///
-    /// let s = RandomState::new();
-    /// let mut set = HashSet::with_hash_state(s);
-    /// set.insert(2);
-    /// ```
-    #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
-    pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
-        HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
-    }
-
-    /// Create an empty HashSet with space for at least `capacity`
-    /// elements in the hash table, using `hasher` to hash the keys.
-    ///
-    /// Warning: `hasher` is normally randomly generated, and
-    /// is designed to allow `HashSet`s to be resistant to attacks that
-    /// cause many collisions and very poor performance. Setting it
-    /// manually using this function can expose a DoS attack vector.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// use std::collections::hash_map::RandomState;
-    ///
-    /// let s = RandomState::new();
-    /// let mut set = HashSet::with_capacity_and_hash_state(10, s);
-    /// set.insert(1);
-    /// ```
-    #[inline]
-    #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
-    pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
-                                        -> HashSet<T, S> {
-        HashSet {
-            map: HashMap::with_capacity_and_hash_state(capacity, hash_state),
-        }
-    }
-
-    /// Returns the number of elements the set can hold without reallocating.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let set: HashSet<int> = HashSet::with_capacity(100);
-    /// assert!(set.capacity() >= 100);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn capacity(&self) -> usize {
-        self.map.capacity()
-    }
-
-    /// Reserves capacity for at least `additional` more elements to be inserted
-    /// in the `HashSet`. The collection may reserve more space to avoid
-    /// frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new allocation size overflows `usize`.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let mut set: HashSet<int> = HashSet::new();
-    /// set.reserve(10);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn reserve(&mut self, additional: usize) {
-        self.map.reserve(additional)
-    }
-
-    /// Shrinks the capacity of the set as much as possible. It will drop
-    /// down as much as possible while maintaining the internal rules
-    /// and possibly leaving some space in accordance with the resize policy.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let mut set: HashSet<int> = HashSet::with_capacity(100);
-    /// set.insert(1);
-    /// set.insert(2);
-    /// assert!(set.capacity() >= 100);
-    /// set.shrink_to_fit();
-    /// assert!(set.capacity() >= 2);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn shrink_to_fit(&mut self) {
-        self.map.shrink_to_fit()
-    }
-
-    /// An iterator visiting all elements in arbitrary order.
-    /// Iterator element type is &'a T.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let mut set = HashSet::new();
-    /// set.insert("a");
-    /// set.insert("b");
-    ///
-    /// // Will print in an arbitrary order.
-    /// for x in set.iter() {
-    ///     println!("{}", x);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn iter(&self) -> Iter<T> {
-        Iter { iter: self.map.keys() }
-    }
-
-    /// Creates a consuming iterator, that is, one that moves each value out
-    /// of the set in arbitrary order. The set cannot be used after calling
-    /// this.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let mut set = HashSet::new();
-    /// set.insert("a".to_string());
-    /// set.insert("b".to_string());
-    ///
-    /// // Not possible to collect to a Vec<String> with a regular `.iter()`.
-    /// let v: Vec<String> = set.into_iter().collect();
-    ///
-    /// // Will print in an arbitrary order.
-    /// for x in v.iter() {
-    ///     println!("{}", x);
-    /// }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn into_iter(self) -> IntoIter<T> {
-        fn first<A, B>((a, _): (A, B)) -> A { a }
-        let first: fn((T, ())) -> T = first;
-
-        IntoIter { iter: self.map.into_iter().map(first) }
-    }
-
-    /// Visit the values representing the difference.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
-    ///
-    /// // Can be seen as `a - b`.
-    /// for x in a.difference(&b) {
-    ///     println!("{}", x); // Print 1
-    /// }
-    ///
-    /// let diff: HashSet<int> = a.difference(&b).map(|&x| x).collect();
-    /// assert_eq!(diff, [1].iter().map(|&x| x).collect());
-    ///
-    /// // Note that difference is not symmetric,
-    /// // and `b - a` means something else:
-    /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect();
-    /// assert_eq!(diff, [4].iter().map(|&x| x).collect());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
-        Difference {
-            iter: self.iter(),
-            other: other,
-        }
-    }
-
-    /// Visit the values representing the symmetric difference.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
-    ///
-    /// // Print 1, 4 in arbitrary order.
-    /// for x in a.symmetric_difference(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let diff1: HashSet<int> = a.symmetric_difference(&b).map(|&x| x).collect();
-    /// let diff2: HashSet<int> = b.symmetric_difference(&a).map(|&x| x).collect();
-    ///
-    /// assert_eq!(diff1, diff2);
-    /// assert_eq!(diff1, [1, 4].iter().map(|&x| x).collect());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>)
-        -> SymmetricDifference<'a, T, S> {
-        SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
-    }
-
-    /// Visit the values representing the intersection.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
-    ///
-    /// // Print 2, 3 in arbitrary order.
-    /// for x in a.intersection(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect();
-    /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
-        Intersection {
-            iter: self.iter(),
-            other: other,
-        }
-    }
-
-    /// Visit the values representing the union.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
-    /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
-    ///
-    /// // Print 1, 2, 3, 4 in arbitrary order.
-    /// for x in a.union(&b) {
-    ///     println!("{}", x);
-    /// }
-    ///
-    /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect();
-    /// assert_eq!(diff, [1, 2, 3, 4].iter().map(|&x| x).collect());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
-        Union { iter: self.iter().chain(other.difference(self)) }
-    }
-
-    /// Return the number of elements in the set
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// assert_eq!(v.len(), 0);
-    /// v.insert(1);
-    /// assert_eq!(v.len(), 1);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn len(&self) -> usize { self.map.len() }
-
-    /// Returns true if the set contains no elements
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// assert!(v.is_empty());
-    /// v.insert(1);
-    /// assert!(!v.is_empty());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_empty(&self) -> bool { self.map.len() == 0 }
-
-    /// Clears the set, returning all elements in an iterator.
-    #[inline]
-    #[unstable(feature = "std_misc",
-               reason = "matches collection reform specification, waiting for dust to settle")]
-    pub fn drain(&mut self) -> Drain<T> {
-        fn first<A, B>((a, _): (A, B)) -> A { a }
-        let first: fn((T, ())) -> T = first; // coerce to fn pointer
-
-        Drain { iter: self.map.drain().map(first) }
-    }
-
-    /// Clears the set, removing all values.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let mut v = HashSet::new();
-    /// v.insert(1);
-    /// v.clear();
-    /// assert!(v.is_empty());
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn clear(&mut self) { self.map.clear() }
-
-    /// Returns `true` if the set contains a value.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// `Hash` and `Eq` on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// assert_eq!(set.contains(&1), true);
-    /// assert_eq!(set.contains(&4), false);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
-        where T: Borrow<Q>, Q: Hash<H> + Eq
-    {
-        self.map.contains_key(value)
-    }
-
-    /// Returns `true` if the set has no elements in common with `other`.
-    /// This is equivalent to checking for an empty intersection.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let mut b = HashSet::new();
-    ///
-    /// assert_eq!(a.is_disjoint(&b), true);
-    /// b.insert(4);
-    /// assert_eq!(a.is_disjoint(&b), true);
-    /// b.insert(1);
-    /// assert_eq!(a.is_disjoint(&b), false);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool {
-        self.iter().all(|v| !other.contains(v))
-    }
-
-    /// Returns `true` if the set is a subset of another.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect();
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.is_subset(&sup), true);
-    /// set.insert(2);
-    /// assert_eq!(set.is_subset(&sup), true);
-    /// set.insert(4);
-    /// assert_eq!(set.is_subset(&sup), false);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
-        self.iter().all(|v| other.contains(v))
-    }
-
-    /// Returns `true` if the set is a superset of another.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let sub: HashSet<_> = [1, 2].iter().cloned().collect();
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.is_superset(&sub), false);
-    ///
-    /// set.insert(0);
-    /// set.insert(1);
-    /// assert_eq!(set.is_superset(&sub), false);
-    ///
-    /// set.insert(2);
-    /// assert_eq!(set.is_superset(&sub), true);
-    /// ```
-    #[inline]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_superset(&self, other: &HashSet<T, S>) -> bool {
-        other.is_subset(self)
-    }
-
-    /// Adds a value to the set. Returns `true` if the value was not already
-    /// present in the set.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    ///
-    /// assert_eq!(set.insert(2), true);
-    /// assert_eq!(set.insert(2), false);
-    /// assert_eq!(set.len(), 1);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() }
-
-    /// Removes a value from the set. Returns `true` if the value was
-    /// present in the set.
-    ///
-    /// The value may be any borrowed form of the set's value type, but
-    /// `Hash` and `Eq` on the borrowed form *must* match those for
-    /// the value type.
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let mut set = HashSet::new();
-    ///
-    /// set.insert(2);
-    /// assert_eq!(set.remove(&2), true);
-    /// assert_eq!(set.remove(&2), false);
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
-        where T: Borrow<Q>, Q: Hash<H> + Eq
-    {
-        self.map.remove(value).is_some()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> PartialEq for HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn eq(&self, other: &HashSet<T, S>) -> bool {
-        if self.len() != other.len() { return false; }
-
-        self.iter().all(|key| other.contains(key))
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> Eq for HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> fmt::Debug for HashSet<T, S>
-    where T: Eq + Hash<H> + fmt::Debug,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "HashSet {{"));
-
-        for (i, x) in self.iter().enumerate() {
-            if i != 0 { try!(write!(f, ", ")); }
-            try!(write!(f, "{:?}", *x));
-        }
-
-        write!(f, "}}")
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> FromIterator<T> for HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> HashSet<T, S> {
-        let iter = iter.into_iter();
-        let lower = iter.size_hint().0;
-        let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default());
-        set.extend(iter);
-        set
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> Extend<T> for HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
-        for k in iter {
-            self.insert(k);
-        }
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> Default for HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn default() -> HashSet<T, S> {
-        HashSet::with_hash_state(Default::default())
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
-    where T: Eq + Hash<H> + Clone,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a | &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2, 3, 4, 5];
-    /// for x in set.iter() {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.union(rhs).cloned().collect()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
-    where T: Eq + Hash<H> + Clone,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
-    ///
-    /// let set = &a & &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [2, 3];
-    /// for x in set.iter() {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.intersection(rhs).cloned().collect()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
-    where T: Eq + Hash<H> + Clone,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a ^ &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2, 4, 5];
-    /// for x in set.iter() {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.symmetric_difference(rhs).cloned().collect()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
-    where T: Eq + Hash<H> + Clone,
-          S: HashState<Hasher=H> + Default,
-          H: hash::Hasher<Output=u64>
-{
-    type Output = HashSet<T, S>;
-
-    /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::collections::HashSet;
-    ///
-    /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
-    /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
-    ///
-    /// let set = &a - &b;
-    ///
-    /// let mut i = 0;
-    /// let expected = [1, 2];
-    /// for x in set.iter() {
-    ///     assert!(expected.contains(x));
-    ///     i += 1;
-    /// }
-    /// assert_eq!(i, expected.len());
-    /// ```
-    fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
-        self.difference(rhs).cloned().collect()
-    }
-}
-
-/// HashSet iterator
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, K: 'a> {
-    iter: Keys<'a, K, ()>
-}
-
-/// HashSet move iterator
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<K> {
-    iter: Map<map::IntoIter<K, ()>, fn((K, ())) -> K>
-}
-
-/// HashSet drain iterator
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Drain<'a, K: 'a> {
-    iter: Map<map::Drain<'a, K, ()>, fn((K, ())) -> K>,
-}
-
-/// Intersection iterator
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Intersection<'a, T: 'a, S: 'a> {
-    // iterator of the first set
-    iter: Iter<'a, T>,
-    // the second set
-    other: &'a HashSet<T, S>,
-}
-
-/// Difference iterator
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Difference<'a, T: 'a, S: 'a> {
-    // iterator of the first set
-    iter: Iter<'a, T>,
-    // the second set
-    other: &'a HashSet<T, S>,
-}
-
-/// Symmetric difference iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
-    iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>
-}
-
-/// Set union iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Union<'a, T: 'a, S: 'a> {
-    iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
-}
-
-impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = &'a T;
-    type IntoIter = Iter<'a, T>;
-
-    fn into_iter(self) -> Iter<'a, T> {
-        self.iter()
-    }
-}
-
-impl<T, S, H> IntoIterator for HashSet<T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = T;
-    type IntoIter = IntoIter<T>;
-
-    fn into_iter(self) -> IntoIter<T> {
-        self.into_iter()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K> Iterator for Iter<'a, K> {
-    type Item = &'a K;
-
-    fn next(&mut self) -> Option<&'a K> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K> ExactSizeIterator for Iter<'a, K> {
-    fn len(&self) -> usize { self.iter.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K> Iterator for IntoIter<K> {
-    type Item = K;
-
-    fn next(&mut self) -> Option<K> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<K> ExactSizeIterator for IntoIter<K> {
-    fn len(&self) -> usize { self.iter.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K> Iterator for Drain<'a, K> {
-    type Item = K;
-
-    fn next(&mut self) -> Option<K> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K> ExactSizeIterator for Drain<'a, K> {
-    fn len(&self) -> usize { self.iter.len() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = &'a T;
-
-    fn next(&mut self) -> Option<&'a T> {
-        loop {
-            match self.iter.next() {
-                None => return None,
-                Some(elt) => if self.other.contains(elt) {
-                    return Some(elt)
-                },
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for Difference<'a, T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = &'a T;
-
-    fn next(&mut self) -> Option<&'a T> {
-        loop {
-            match self.iter.next() {
-                None => return None,
-                Some(elt) => if !self.other.contains(elt) {
-                    return Some(elt)
-                },
-            }
-        }
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (_, upper) = self.iter.size_hint();
-        (0, upper)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = &'a T;
-
-    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for Union<'a, T, S>
-    where T: Eq + Hash<H>,
-          S: HashState<Hasher=H>,
-          H: hash::Hasher<Output=u64>
-{
-    type Item = &'a T;
-
-    fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
-}
-
-#[cfg(test)]
-mod test_set {
-    use prelude::v1::*;
-
-    use super::HashSet;
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = HashSet::new();
-        let mut ys = HashSet::new();
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(ys.insert(-11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.is_disjoint(&ys));
-        assert!(!ys.is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = HashSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = HashSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(!b.is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(b.is_superset(&a));
-    }
-
-    #[test]
-    fn test_iterate() {
-        let mut a = HashSet::new();
-        for i in 0..32 {
-            assert!(a.insert(i));
-        }
-        let mut observed: u32 = 0;
-        for k in &a {
-            observed |= 1 << *k;
-        }
-        assert_eq!(observed, 0xFFFF_FFFF);
-    }
-
-    #[test]
-    fn test_intersection() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-        assert!(a.insert(-5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(-9));
-        assert!(b.insert(-42));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let mut i = 0;
-        let expected = [3, 5, 11, 77];
-        for x in a.intersection(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-
-        let mut i = 0;
-        let expected = [1, 5, 11];
-        for x in a.difference(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(22));
-
-        let mut i = 0;
-        let expected = [-2, 1, 5, 11, 14, 22];
-        for x in a.symmetric_difference(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_union() {
-        let mut a = HashSet::new();
-        let mut b = HashSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(16));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(-2));
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let mut i = 0;
-        let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
-        for x in a.union(&b) {
-            assert!(expected.contains(x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_from_iter() {
-        let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
-
-        let set: HashSet<_> = xs.iter().cloned().collect();
-
-        for x in &xs {
-            assert!(set.contains(x));
-        }
-    }
-
-    #[test]
-    fn test_move_iter() {
-        let hs = {
-            let mut hs = HashSet::new();
-
-            hs.insert('a');
-            hs.insert('b');
-
-            hs
-        };
-
-        let v = hs.into_iter().collect::<Vec<char>>();
-        assert!(['a', 'b'] == v || ['b', 'a'] == v);
-    }
-
-    #[test]
-    fn test_eq() {
-        // These constants once happened to expose a bug in insert().
-        // I'm keeping them around to prevent a regression.
-        let mut s1 = HashSet::new();
-
-        s1.insert(1);
-        s1.insert(2);
-        s1.insert(3);
-
-        let mut s2 = HashSet::new();
-
-        s2.insert(1);
-        s2.insert(2);
-
-        assert!(s1 != s2);
-
-        s2.insert(3);
-
-        assert_eq!(s1, s2);
-    }
-
-    #[test]
-    fn test_show() {
-        let mut set = HashSet::new();
-        let empty = HashSet::<i32>::new();
-
-        set.insert(1);
-        set.insert(2);
-
-        let set_str = format!("{:?}", set);
-
-        assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}");
-        assert_eq!(format!("{:?}", empty), "HashSet {}");
-    }
-
-    #[test]
-    fn test_trivial_drain() {
-        let mut s = HashSet::<i32>::new();
-        for _ in s.drain() {}
-        assert!(s.is_empty());
-        drop(s);
-
-        let mut s = HashSet::<i32>::new();
-        drop(s.drain());
-        assert!(s.is_empty());
-    }
-
-    #[test]
-    fn test_drain() {
-        let mut s: HashSet<_> = (1..100).collect();
-
-        // try this a bunch of times to make sure we don't screw up internal state.
-        for _ in 0..20 {
-            assert_eq!(s.len(), 99);
-
-            {
-                let mut last_i = 0;
-                let mut d = s.drain();
-                for (i, x) in d.by_ref().take(50).enumerate() {
-                    last_i = i;
-                    assert!(x != 0);
-                }
-                assert_eq!(last_i, 49);
-            }
-
-            for _ in &s { panic!("s should be empty!"); }
-
-            // reset to try again.
-            s.extend(1..100);
-        }
-    }
-}
index 7e6dd45b51e48f69f553388787dc490f1f843e03..3a06d2d03bf3f7046ec7c74479f9936abb704be8 100644 (file)
@@ -27,6 +27,7 @@
 /// to `Default` when asked to create a hasher.
 #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
 pub trait HashState {
+    /// Type of the hasher that will be created.
     type Hasher: hash::Hasher;
 
     /// Creates a new hasher based on the given state of this object.
index f301f6db92f96a7bf96d2ee545128212db7c9de7..4c03d8915eb8a04ca0909e022739eb6c38ade22a 100644 (file)
@@ -23,7 +23,7 @@
 use ops::{Deref, DerefMut, Drop};
 use option::Option;
 use option::Option::{Some, None};
-use ptr::{self, PtrExt, copy_nonoverlapping_memory, Unique, zero_memory};
+use ptr::{self, PtrExt, Unique};
 use rt::heap::{allocate, deallocate, EMPTY};
 use collections::hash_state::HashState;
 
@@ -143,25 +143,6 @@ pub fn inspect(&self) -> u64 { self.hash }
 /// We need to remove hashes of 0. That's reserved for empty buckets.
 /// This function wraps up `hash_keyed` to be the only way outside this
 /// module to generate a SafeHash.
-#[cfg(stage0)]
-pub fn make_hash<T: ?Sized, S, H>(hash_state: &S, t: &T) -> SafeHash
-    where T: Hash<H>,
-          S: HashState<Hasher=H>,
-          H: Hasher<Output=u64>
-{
-    let mut state = hash_state.hasher();
-    t.hash(&mut state);
-    // We need to avoid 0u64 in order to prevent collisions with
-    // EMPTY_HASH. We can maintain our precious uniform distribution
-    // of initial indexes by unconditionally setting the MSB,
-    // effectively reducing 64-bits hashes to 63 bits.
-    SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
-}
-
-/// We need to remove hashes of 0. That's reserved for empty buckets.
-/// This function wraps up `hash_keyed` to be the only way outside this
-/// module to generate a SafeHash.
-#[cfg(not(stage0))]
 pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
     where T: Hash, S: HashState
 {
@@ -496,8 +477,8 @@ pub fn full(&self) -> &FullBucket<K, V, M> {
     pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
         unsafe {
             *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
-            copy_nonoverlapping_memory(self.gap.raw.key, self.full.raw.key, 1);
-            copy_nonoverlapping_memory(self.gap.raw.val, self.full.raw.val, 1);
+            ptr::copy_nonoverlapping(self.gap.raw.key, self.full.raw.key, 1);
+            ptr::copy_nonoverlapping(self.gap.raw.val, self.full.raw.val, 1);
         }
 
         let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
@@ -656,7 +637,7 @@ fn first_bucket_raw(&self) -> RawBucket<K, V> {
     pub fn new(capacity: usize) -> RawTable<K, V> {
         unsafe {
             let ret = RawTable::new_uninitialized(capacity);
-            zero_memory(*ret.hashes, capacity);
+            ptr::write_bytes(*ret.hashes, 0, capacity);
             ret
         }
     }
index 0e64370df60ecbdc8b24ff51abc1a506ba83b8a2..100d3e6ed4aa9c5c6afb095c293b3e1c6ee8fe7e 100644 (file)
@@ -23,9 +23,9 @@
 //!
 //! Rust's collections can be grouped into four major categories:
 //!
-//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitV`
+//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitVec`
 //! * Maps: `HashMap`, `BTreeMap`, `VecMap`
-//! * Sets: `HashSet`, `BTreeSet`, `BitVSet`
+//! * Sets: `HashSet`, `BTreeSet`, `BitSet`
 //! * Misc: `BinaryHeap`
 //!
 //! # When Should You Use Which Collection?
 //! * There is no meaningful value to associate with your keys.
 //! * You just want a set.
 //!
-//! ### Use a `BitV` when:
+//! ### Use a `BitVec` when:
 //! * You want to store an unbounded number of booleans in a small space.
 //! * You want a bit vector.
 //!
-//! ### Use a `BitVSet` when:
+//! ### Use a `BitSet` when:
 //! * You want a `VecSet`.
 //!
 //! ### Use a `BinaryHeap` when:
index b0fb9c29403511d13e42b274030523c50efbbf67..babae3b3019ec18c33d01b2749c4395d4ae7bd13 100644 (file)
@@ -21,6 +21,7 @@
 use mem;
 use env;
 use str;
+use os;
 
 pub struct DynamicLibrary {
     handle: *mut u8
@@ -102,7 +103,7 @@ fn separator() -> u8 {
     /// process
     pub fn search_path() -> Vec<Path> {
         match env::var_os(DynamicLibrary::envvar()) {
-            Some(var) => env::split_paths(&var).collect(),
+            Some(var) => os::split_paths(var.to_str().unwrap()),
             None => Vec::new(),
         }
     }
@@ -165,6 +166,7 @@ fn test_loading_cosine() {
               target_os = "macos",
               target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     fn test_errors_do_not_crash() {
         // Open /dev/null as a library to get an error, and make sure
@@ -183,6 +185,7 @@ fn test_errors_do_not_crash() {
           target_os = "ios",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 mod dl {
     use prelude::v1::*;
index 8676586e7dc2a7e32971773e026af9537bdbea25..e2849ec92e08835f007cdbaba0e1901b84a3f477 100644 (file)
@@ -21,7 +21,8 @@
 use error::Error;
 use ffi::{OsString, AsOsStr};
 use fmt;
-use old_io::IoResult;
+use io;
+use path::{AsPath, PathBuf};
 use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
 use sync::{StaticMutex, MUTEX_INIT};
 use sys::os as os_imp;
@@ -46,7 +47,7 @@
 /// let p = env::current_dir().unwrap();
 /// println!("The current directory is {}", p.display());
 /// ```
-pub fn current_dir() -> IoResult<Path> {
+pub fn current_dir() -> io::Result<PathBuf> {
     os_imp::getcwd()
 }
 
@@ -57,14 +58,14 @@ pub fn current_dir() -> IoResult<Path> {
 ///
 /// ```rust
 /// use std::env;
-/// use std::old_path::Path;
+/// use std::path::Path;
 ///
 /// let root = Path::new("/");
 /// assert!(env::set_current_dir(&root).is_ok());
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
-pub fn set_current_dir(p: &Path) -> IoResult<()> {
-    os_imp::chdir(p)
+pub fn set_current_dir<P: AsPath + ?Sized>(p: &P) -> io::Result<()> {
+    os_imp::chdir(p.as_path())
 }
 
 static ENV_LOCK: StaticMutex = MUTEX_INIT;
@@ -280,8 +281,8 @@ pub fn split_paths<T: AsOsStr + ?Sized>(unparsed: &T) -> SplitPaths {
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
-    type Item = Path;
-    fn next(&mut self) -> Option<Path> { self.inner.next() }
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
@@ -305,10 +306,11 @@ pub struct JoinPathsError {
 ///
 /// ```rust
 /// use std::env;
+/// use std::path::PathBuf;
 ///
 /// if let Some(path) = env::var_os("PATH") {
 ///     let mut paths = env::split_paths(&path).collect::<Vec<_>>();
-///     paths.push(Path::new("/home/xyz/bin"));
+///     paths.push(PathBuf::new("/home/xyz/bin"));
 ///     let new_path = env::join_paths(paths.iter()).unwrap();
 ///     env::set_var("PATH", &new_path);
 /// }
@@ -355,7 +357,7 @@ fn description(&self) -> &str { self.inner.description() }
 ///     None => println!("Impossible to get your home dir!")
 /// }
 /// ```
-pub fn home_dir() -> Option<Path> {
+pub fn home_dir() -> Option<PathBuf> {
     os_imp::home_dir()
 }
 
@@ -369,7 +371,7 @@ pub fn home_dir() -> Option<Path> {
 /// 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.
-pub fn temp_dir() -> Path {
+pub fn temp_dir() -> PathBuf {
     os_imp::temp_dir()
 }
 
@@ -396,7 +398,7 @@ pub fn temp_dir() -> Path {
 ///     Err(e) => println!("failed to get current exe path: {}", e),
 /// };
 /// ```
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     os_imp::current_exe()
 }
 
@@ -655,6 +657,38 @@ pub mod consts {
     pub const EXE_EXTENSION: &'static str = "";
 }
 
+/// Constants associated with the current target
+#[cfg(target_os = "bitrig")]
+pub mod consts {
+    pub use super::arch_consts::ARCH;
+
+    pub const FAMILY: &'static str = "unix";
+
+    /// A string describing the specific operating system in use: in this
+    /// case, `bitrig`.
+    pub const OS: &'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 = "";
+}
+
 /// Constants associated with the current target
 #[cfg(target_os = "openbsd")]
 pub mod consts {
@@ -663,7 +697,7 @@ pub mod consts {
     pub const FAMILY: &'static str = "unix";
 
     /// A string describing the specific operating system in use: in this
-    /// case, `dragonfly`.
+    /// case, `openbsd`.
     pub const OS: &'static str = "openbsd";
 
     /// Specifies the filename prefix used for shared libraries on this
@@ -793,6 +827,7 @@ mod tests {
     use iter::repeat;
     use rand::{self, Rng};
     use ffi::{OsString, OsStr};
+    use path::PathBuf;
 
     fn make_rand_name() -> OsString {
         let mut rng = rand::thread_rng();
@@ -892,7 +927,7 @@ fn test() {
     fn split_paths_windows() {
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
-                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
+                parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
         }
 
         assert!(check_parse("", &mut [""]));
@@ -912,7 +947,7 @@ fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
     fn split_paths_unix() {
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
-                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
+                parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
         }
 
         assert!(check_parse("", &mut [""]));
index 8976813d3f91e9681a84f48d8ca552733319ff6c..69bcc82f6827570f61226dc0e241a0b4de023d5c 100644 (file)
@@ -224,7 +224,7 @@ pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
     /// Returns the contents of this `CString` as a slice of bytes.
     ///
     /// The returned slice does **not** contain the trailing nul separator and
-    /// it is guaranteet to not have any interior nul bytes.
+    /// it is guaranteed to not have any interior nul bytes.
     pub fn as_bytes(&self) -> &[u8] {
         &self.inner[..self.inner.len() - 1]
     }
@@ -333,7 +333,7 @@ pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
     /// Return the inner pointer to this C string.
     ///
     /// The returned pointer will be valid for as long as `self` is and points
-    /// to a continguous region of memory terminated with a 0 byte to represent
+    /// to a contiguous region of memory terminated with a 0 byte to represent
     /// the end of the string.
     pub fn as_ptr(&self) -> *const libc::c_char {
         self.inner.as_ptr()
@@ -371,7 +371,7 @@ pub fn to_bytes_with_nul(&self) -> &[u8] {
 
 impl PartialEq for CStr {
     fn eq(&self, other: &CStr) -> bool {
-        self.to_bytes().eq(&other.to_bytes())
+        self.to_bytes().eq(other.to_bytes())
     }
 }
 impl Eq for CStr {}
index 84149a2eb8e43353a1d9857c8a19cdecd65f379e..fe0df1728efc0bd34559941d394346acc3d0a63d 100644 (file)
@@ -41,7 +41,6 @@
 use ops;
 use cmp;
 use hash::{Hash, Hasher};
-#[cfg(stage0)] use hash::Writer;
 use old_path::{Path, GenericPath};
 
 use sys::os_str::{Buf, Slice};
@@ -163,14 +162,6 @@ fn cmp(&self, other: &OsString) -> cmp::Ordering {
     }
 }
 
-#[cfg(stage0)]
-impl<'a, S: Hasher + Writer> Hash<S> for OsString {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        (&**self).hash(state)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Hash for OsString {
     #[inline]
@@ -263,14 +254,6 @@ impl Ord for OsStr {
     fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
 }
 
-#[cfg(stage0)]
-impl<'a, S: Hasher + Writer> Hash<S> for OsStr {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.bytes().hash(state)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Hash for OsStr {
     #[inline]
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
deleted file mode 100644 (file)
index 6979108..0000000
+++ /dev/null
@@ -1,1501 +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`.
-
-#![unstable(feature = "fs")]
-
-use core::prelude::*;
-
-use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
-use path::{AsPath, 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.
-///
-/// # Example
-///
-/// ```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(())
-/// # }
-/// ```
-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.
-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.
-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.
-pub struct DirEntry(fs_imp::DirEntry);
-
-/// An iterator that recursively walks over the contents of a directory.
-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)]
-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)]
-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`.
-    pub fn open<P: AsPath + ?Sized>(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.
-    pub fn create<P: AsPath + ?Sized>(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.
-    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.
-    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`.
-    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.
-    pub fn set_len(&self, size: u64) -> io::Result<()> {
-        self.inner.truncate(size)
-    }
-
-    /// Queries information about the underlying file.
-    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 Read for File {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
-    }
-}
-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() }
-}
-impl Seek for File {
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.inner.seek(pos)
-    }
-}
-impl<'a> Read for &'a File {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
-    }
-}
-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() }
-}
-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`.
-    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.
-    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.
-    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.
-    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.
-    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.
-    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)
-    pub fn open<P: AsPath + ?Sized>(&self, path: &P) -> io::Result<File> {
-        let path = path.as_path();
-        let inner = try!(fs_imp::File::open(path, &self.0));
-
-        // On *BSD systems, we can open a directory as a file and read from
-        // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old
-        // tradition before the introduction of opendir(3).  We explicitly
-        // reject it because there are few use cases.
-        if cfg!(not(any(target_os = "linux", target_os = "android"))) &&
-           try!(inner.file_attr()).is_dir() {
-            Err(Error::new(ErrorKind::InvalidInput, "is a directory", None))
-        } else {
-            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.
-    pub fn is_dir(&self) -> bool { self.0.is_dir() }
-
-    /// Returns whether this metadata is for a regular file.
-    pub fn is_file(&self) -> bool { self.0.is_file() }
-
-    /// Returns the size of the file, in bytes, this metadata is for.
-    pub fn len(&self) -> u64 { self.0.size() }
-
-    /// Returns the permissions of the file this metadata is for.
-    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.
-    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.
-    pub fn modified(&self) -> u64 { self.0.modified() }
-}
-
-impl Permissions {
-    /// Returns whether these permissions describe a readonly file.
-    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.
-    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 Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        self.0.next().map(|entry| entry.map(DirEntry))
-    }
-}
-
-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.
-    pub fn path(&self) -> PathBuf { self.0.path() }
-}
-
-/// Remove a file from the underlying filesystem.
-///
-/// # Example
-///
-/// ```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.
-pub fn remove_file<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    let path = path.as_path();
-    let e = match fs_imp::unlink(path) {
-        Ok(()) => return Ok(()),
-        Err(e) => e,
-    };
-    if !cfg!(windows) { return Err(e) }
-
-    // On unix, a readonly file can be successfully removed. On windows,
-    // however, it cannot. To keep the two platforms in line with
-    // respect to their behavior, catch this case on windows, attempt to
-    // change it to read-write, and then remove the file.
-    if e.kind() != ErrorKind::PermissionDenied { return Err(e) }
-
-    let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) };
-    let mut perms = attr.permissions();
-    if !perms.readonly() { return Err(e) }
-    perms.set_readonly(false);
-
-    if set_permissions(path, perms).is_err() { return Err(e) }
-    if fs_imp::unlink(path).is_ok() { return Ok(()) }
-
-    // Oops, try to put things back the way we found it
-    let _ = set_permissions(path, attr.permissions());
-    Err(e)
-}
-
-/// 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.
-///
-/// # Example
-///
-/// ```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.
-pub fn metadata<P: AsPath + ?Sized>(path: &P) -> io::Result<Metadata> {
-    fs_imp::stat(path.as_path()).map(Metadata)
-}
-
-/// Rename a file or directory to a new name.
-///
-/// # Example
-///
-/// ```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.
-pub fn rename<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
-                                                      -> io::Result<()> {
-    fs_imp::rename(from.as_path(), to.as_path())
-}
-
-/// 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.
-///
-/// # Example
-///
-/// ```rust
-/// 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`
-pub fn copy<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
-                                                    -> io::Result<u64> {
-    let from = from.as_path();
-    if !from.is_file() {
-        return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
-                              "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.
-pub fn hard_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
-                                                         -> io::Result<()> {
-    fs_imp::link(src.as_path(), dst.as_path())
-}
-
-/// Creates a new soft link on the filesystem.
-///
-/// The `dst` path will be a soft link pointing to the `src` path.
-pub fn soft_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
-                                                         -> io::Result<()> {
-    fs_imp::symlink(src.as_path(), dst.as_path())
-}
-
-/// 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.
-pub fn read_link<P: AsPath + ?Sized>(path: &P) -> io::Result<PathBuf> {
-    fs_imp::readlink(path.as_path())
-}
-
-/// Create a new, empty directory at the provided path
-///
-/// # Example
-///
-/// ```rust
-/// 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.
-pub fn create_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    fs_imp::mkdir(path.as_path())
-}
-
-/// 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`.
-pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    let path = path.as_path();
-    if path.is_dir() { return Ok(()) }
-    match path.parent() {
-        Some(p) if p != path => try!(create_dir_all(p)),
-        _ => {}
-    }
-    create_dir(path)
-}
-
-/// Remove an existing, empty directory
-///
-/// # Example
-///
-/// ```rust
-/// 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.
-pub fn remove_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    fs_imp::rmdir(path.as_path())
-}
-
-/// 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`
-pub fn remove_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    let path = path.as_path();
-    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.
-///
-/// # Example
-///
-/// ```rust
-/// 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
-pub fn read_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<ReadDir> {
-    fs_imp::readdir(path.as_path()).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.
-pub fn walk_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<WalkDir> {
-    let start = try!(read_dir(path));
-    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
-}
-
-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.
-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.
-pub fn set_file_times<P: AsPath + ?Sized>(path: &P, accessed: u64,
-                                          modified: u64) -> io::Result<()> {
-    fs_imp::utimes(path.as_path(), accessed, modified)
-}
-
-/// Changes the permissions found on a file or a directory.
-///
-/// # Example
-///
-/// ```
-/// # 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.
-pub fn set_permissions<P: AsPath + ?Sized>(path: &P, perm: Permissions)
-                                           -> io::Result<()> {
-    fs_imp::set_perm(path.as_path(), perm.0)
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-    use io::prelude::*;
-
-    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.as_slice()),
-                                    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 s = os::tmpdir();
-        let p = Path2::new(s.as_str().unwrap());
-        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.as_slice(), 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 range(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 mut files = check!(fs::read_dir(dir));
-        let mut mem = [0u8; 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.as_slice(), 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 mut files = check!(fs::walk_dir(dir));
-        let mut cur = [0u8; 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::PathAlreadyExists);
-    }
-
-    #[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());
-    }
-
-    #[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) {
-            Ok(..) => panic!("wanted a panic"),
-            Err(..) => {}
-        }
-    }
-
-    #[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're seeked
-        // 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().ok().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]
-    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));
-    }
-}
diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs
new file mode 100644 (file)
index 0000000..64ec025
--- /dev/null
@@ -0,0 +1,1525 @@
+// 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`.
+
+#![unstable(feature = "fs")]
+
+use core::prelude::*;
+
+use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
+use path::{AsPath, Path, PathBuf};
+use sys::fs2 as fs_imp;
+use sys_common::{AsInnerMut, FromInner, AsInner};
+use vec::Vec;
+
+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.
+///
+/// # Example
+///
+/// ```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(())
+/// # }
+/// ```
+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.
+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.
+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.
+pub struct DirEntry(fs_imp::DirEntry);
+
+/// An iterator that recursively walks over the contents of a directory.
+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)]
+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)]
+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`.
+    pub fn open<P: AsPath + ?Sized>(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.
+    pub fn create<P: AsPath + ?Sized>(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.
+    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.
+    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`.
+    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.
+    pub fn set_len(&self, size: u64) -> io::Result<()> {
+        self.inner.truncate(size)
+    }
+
+    /// Queries information about the underlying file.
+    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 Read for File {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.read(buf)
+    }
+}
+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() }
+}
+impl Seek for File {
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        self.inner.seek(pos)
+    }
+}
+impl<'a> Read for &'a File {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.read(buf)
+    }
+}
+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() }
+}
+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`.
+    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.
+    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.
+    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.
+    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.
+    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.
+    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)
+    pub fn open<P: AsPath + ?Sized>(&self, path: &P) -> io::Result<File> {
+        let path = path.as_path();
+        let inner = try!(fs_imp::File::open(path, &self.0));
+
+        // On *BSD systems, we can open a directory as a file and read from
+        // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old
+        // tradition before the introduction of opendir(3).  We explicitly
+        // reject it because there are few use cases.
+        if cfg!(not(any(target_os = "linux", target_os = "android"))) &&
+           try!(inner.file_attr()).is_dir() {
+            Err(Error::new(ErrorKind::InvalidInput, "is a directory", None))
+        } else {
+            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.
+    pub fn is_dir(&self) -> bool { self.0.is_dir() }
+
+    /// Returns whether this metadata is for a regular file.
+    pub fn is_file(&self) -> bool { self.0.is_file() }
+
+    /// Returns the size of the file, in bytes, this metadata is for.
+    pub fn len(&self) -> u64 { self.0.size() }
+
+    /// Returns the permissions of the file this metadata is for.
+    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.
+    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.
+    pub fn modified(&self) -> u64 { self.0.modified() }
+}
+
+impl Permissions {
+    /// Returns whether these permissions describe a readonly file.
+    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.
+    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 }
+}
+
+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))
+    }
+}
+
+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.
+    pub fn path(&self) -> PathBuf { self.0.path() }
+}
+
+/// Remove a file from the underlying filesystem.
+///
+/// # Example
+///
+/// ```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.
+pub fn remove_file<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    let path = path.as_path();
+    let e = match fs_imp::unlink(path) {
+        Ok(()) => return Ok(()),
+        Err(e) => e,
+    };
+    if !cfg!(windows) { return Err(e) }
+
+    // On unix, a readonly file can be successfully removed. On windows,
+    // however, it cannot. To keep the two platforms in line with
+    // respect to their behavior, catch this case on windows, attempt to
+    // change it to read-write, and then remove the file.
+    if e.kind() != ErrorKind::PermissionDenied { return Err(e) }
+
+    let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) };
+    let mut perms = attr.permissions();
+    if !perms.readonly() { return Err(e) }
+    perms.set_readonly(false);
+
+    if set_permissions(path, perms).is_err() { return Err(e) }
+    if fs_imp::unlink(path).is_ok() { return Ok(()) }
+
+    // Oops, try to put things back the way we found it
+    let _ = set_permissions(path, attr.permissions());
+    Err(e)
+}
+
+/// 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.
+///
+/// # Example
+///
+/// ```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.
+pub fn metadata<P: AsPath + ?Sized>(path: &P) -> io::Result<Metadata> {
+    fs_imp::stat(path.as_path()).map(Metadata)
+}
+
+/// Rename a file or directory to a new name.
+///
+/// # Example
+///
+/// ```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.
+pub fn rename<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
+                                                      -> io::Result<()> {
+    fs_imp::rename(from.as_path(), to.as_path())
+}
+
+/// 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.
+///
+/// # Example
+///
+/// ```rust
+/// 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`
+pub fn copy<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
+                                                    -> io::Result<u64> {
+    let from = from.as_path();
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
+                              "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.
+pub fn hard_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
+                                                         -> io::Result<()> {
+    fs_imp::link(src.as_path(), dst.as_path())
+}
+
+/// Creates a new soft link on the filesystem.
+///
+/// The `dst` path will be a soft link pointing to the `src` path.
+pub fn soft_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
+                                                         -> io::Result<()> {
+    fs_imp::symlink(src.as_path(), dst.as_path())
+}
+
+/// 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.
+pub fn read_link<P: AsPath + ?Sized>(path: &P) -> io::Result<PathBuf> {
+    fs_imp::readlink(path.as_path())
+}
+
+/// Create a new, empty directory at the provided path
+///
+/// # Example
+///
+/// ```rust
+/// 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.
+pub fn create_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    fs_imp::mkdir(path.as_path())
+}
+
+/// 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`.
+pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    let path = path.as_path();
+    if path.is_dir() { return Ok(()) }
+    match path.parent() {
+        Some(p) if p != path => try!(create_dir_all(p)),
+        _ => {}
+    }
+    // If the file name of the given `path` is blank then the creation of the
+    // parent directory will have taken care of the whole path for us, so we're
+    // good to go.
+    if path.file_name().is_none() {
+        Ok(())
+    } else {
+        create_dir(path)
+    }
+}
+
+/// Remove an existing, empty directory
+///
+/// # Example
+///
+/// ```rust
+/// 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.
+pub fn remove_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    fs_imp::rmdir(path.as_path())
+}
+
+/// 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`
+pub fn remove_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    let path = path.as_path();
+    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.
+///
+/// # Example
+///
+/// ```rust
+/// 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
+pub fn read_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<ReadDir> {
+    fs_imp::readdir(path.as_path()).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.
+pub fn walk_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<WalkDir> {
+    let start = try!(read_dir(path));
+    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
+}
+
+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.
+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.
+pub fn set_file_times<P: AsPath + ?Sized>(path: &P, accessed: u64,
+                                          modified: u64) -> io::Result<()> {
+    fs_imp::utimes(path.as_path(), accessed, modified)
+}
+
+/// Changes the permissions found on a file or a directory.
+///
+/// # Example
+///
+/// ```
+/// # 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.
+pub fn set_permissions<P: AsPath + ?Sized>(path: &P, perm: Permissions)
+                                           -> io::Result<()> {
+    fs_imp::set_perm(path.as_path(), perm.0)
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(deprecated)] //rand
+
+    use prelude::v1::*;
+    use io::prelude::*;
+
+    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.as_slice()),
+                                    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 s = os::tmpdir();
+        let p = Path2::new(s.as_str().unwrap());
+        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.as_slice(), 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 range(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 = [0u8; 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.as_slice(), 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 = [0u8; 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::PathAlreadyExists);
+    }
+
+    #[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());
+    }
+
+    #[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) {
+            Ok(..) => panic!("wanted a panic"),
+            Err(..) => {}
+        }
+    }
+
+    #[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're seeked
+        // 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().ok().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]
+    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
new file mode 100644 (file)
index 0000000..79bdb35
--- /dev/null
@@ -0,0 +1,125 @@
+// 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")]
+
+use prelude::v1::*;
+
+use env;
+use io::{self, Error, ErrorKind};
+use fs;
+use path::{self, PathBuf, AsPath};
+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: uint = 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: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
+                                      -> io::Result<TempDir> {
+        let storage;
+        let mut tmpdir = tmpdir.as_path();
+        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::PathAlreadyExists => {}
+                Err(e) => return Err(e)
+            }
+        }
+
+        Err(Error::new(ErrorKind::PathAlreadyExists,
+                       "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 e9a8dbb4098afb3f15340725b35894ae409cf20b..1135609959015d2fbee5d2565a0dd18affd69b7f 100644 (file)
@@ -48,7 +48,7 @@ pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
     }
 
     /// Gets a reference to the underlying reader.
-    pub fn get_ref<'a>(&self) -> &R { &self.inner }
+    pub fn get_ref(&self) -> &R { &self.inner }
 
     /// Gets a mutable reference to the underlying reader.
     ///
@@ -155,9 +155,9 @@ fn flush_buf(&mut self) -> io::Result<()> {
         if written > 0 {
             // NB: would be better expressed as .remove(0..n) if it existed
             unsafe {
-                ptr::copy_memory(self.buf.as_mut_ptr(),
-                                 self.buf.as_ptr().offset(written as isize),
-                                 len - written);
+                ptr::copy(self.buf.as_mut_ptr(),
+                          self.buf.as_ptr().offset(written as isize),
+                          len - written);
             }
         }
         self.buf.truncate(len - written);
@@ -497,7 +497,6 @@ fn test_buffered_writer() {
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8]);
 
         writer.write(&[9, 10, 11]).unwrap();
-        let a: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
         assert_eq!(*writer.get_ref(), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
 
         writer.flush().unwrap();
@@ -593,7 +592,7 @@ fn test_read_line() {
     #[test]
     fn test_lines() {
         let in_buf = b"a\nb\nc";
-        let mut reader = BufReader::with_capacity(2, in_buf);
+        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())));
@@ -618,14 +617,14 @@ fn test_short_reads() {
     #[test]
     fn read_char_buffered() {
         let buf = [195u8, 159u8];
-        let mut reader = BufReader::with_capacity(1, &buf[..]);
+        let reader = BufReader::with_capacity(1, &buf[..]);
         assert_eq!(reader.chars().next(), Some(Ok('ß')));
     }
 
     #[test]
     fn test_chars() {
         let buf = [195u8, 159u8, b'a'];
-        let mut reader = BufReader::with_capacity(1, &buf[..]);
+        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')));
index 7f3ce7924c1caaa0fe8bfefdcf4968c80e95d201..82b69ddebff68630fcf70bf1da0d61c342ed754b 100644 (file)
 
 use boxed::Box;
 use cmp;
-use io::{self, SeekFrom, Read, Write, Seek, BufRead};
+use io::{self, SeekFrom, Read, Write, Seek, BufRead, Error, ErrorKind};
+use fmt;
 use mem;
 use slice;
+use string::String;
 use vec::Vec;
 
 // =============================================================================
 
 impl<'a, R: Read + ?Sized> Read for &'a mut R {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> { (**self).read_to_end(buf) }
+
+    fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
+        (**self).read_to_string(buf)
+    }
 }
 impl<'a, W: Write + ?Sized> Write for &'a mut W {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
+
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) }
+
+    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) }
+
     fn flush(&mut self) -> io::Result<()> { (**self).flush() }
 }
 impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
@@ -32,7 +45,14 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
 }
 impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
     fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
+
     fn consume(&mut self, amt: usize) { (**self).consume(amt) }
+
+    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> {
+        (**self).read_until(byte, buf)
+    }
+
+    fn read_line(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_line(buf) }
 }
 
 impl<R: Read + ?Sized> Read for Box<R> {
@@ -76,6 +96,15 @@ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         *self = b;
         Ok(amt)
     }
+
+    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))
+        }
+    }
+
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
@@ -84,5 +113,11 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.push_all(buf);
         Ok(buf.len())
     }
+
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        try!(self.write(buf));
+        Ok(())
+    }
+
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
index c38d52161c96e8484ab8e656b224d29f7f9595e8..3b4e15953c4613958adfea8d2015625ae32e0017 100644 (file)
@@ -15,7 +15,7 @@
 //! > module while the details of this module shake out.
 
 #![unstable(feature = "io",
-            reason = "this new I/O module is still under active deveopment and \
+            reason = "this new I/O module is still under active development and \
                       APIs are subject to tweaks fairly regularly")]
 
 use cmp;
@@ -669,6 +669,11 @@ pub fn limit(&self) -> u64 { self.limit }
 
 impl<T: Read> Read for Take<T> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+        // Don't call into inner reader at all at EOF because it may still block
+        if self.limit == 0 {
+            return Ok(0);
+        }
+
         let max = cmp::min(buf.len() as u64, self.limit) as usize;
         let n = try!(self.inner.read(&mut buf[..max]));
         self.limit -= n as u64;
@@ -676,6 +681,21 @@ fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
     }
 }
 
+impl<T: BufRead> BufRead for Take<T> {
+    fn fill_buf(&mut self) -> Result<&[u8]> {
+        let buf = try!(self.inner.fill_buf());
+        let cap = cmp::min(buf.len() as u64, self.limit) as usize;
+        Ok(&buf[..cap])
+    }
+
+    fn consume(&mut self, amt: usize) {
+        // Don't let callers reset the limit by passing an overlarge value
+        let amt = cmp::min(amt as u64, self.limit) as usize;
+        self.limit -= amt as u64;
+        self.inner.consume(amt);
+    }
+}
+
 /// An adaptor which will emit all read data to a specified writer as well.
 ///
 /// For more information see `ReadExt::tee`
@@ -846,6 +866,7 @@ fn next(&mut self) -> Option<Result<String>> {
 mod tests {
     use prelude::v1::*;
     use io::prelude::*;
+    use io;
     use super::Cursor;
 
     #[test]
@@ -869,12 +890,12 @@ fn read_until() {
 
     #[test]
     fn split() {
-        let mut buf = Cursor::new(b"12");
+        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);
 
-        let mut buf = Cursor::new(b"1233");
+        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![])));
@@ -902,12 +923,12 @@ fn read_line() {
 
     #[test]
     fn lines() {
-        let mut buf = Cursor::new(b"12");
+        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);
 
-        let mut buf = Cursor::new(b"12\n\n");
+        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())));
@@ -943,4 +964,18 @@ fn read_to_string() {
         let mut v = String::new();
         assert!(c.read_to_string(&mut v).is_err());
     }
+
+    #[test]
+    fn take_eof() {
+        struct R;
+
+        impl Read for R {
+            fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+                Err(io::Error::new(io::ErrorKind::Other, "", None))
+            }
+        }
+
+        let mut buf = [0; 1];
+        assert_eq!(Ok(0), R.take(0).read(&mut buf));
+    }
 }
index fbd403ea593b8a970b0218f876a193d4cc71f778..b5bdeb7f181b0ddab0bebb3c25491c619d385ddc 100644 (file)
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(core)]
-#![feature(hash)]
 #![feature(int_uint)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(unsafe_destructor)]
 #![feature(unsafe_no_drop_flag)]
 #![feature(macro_reexport)]
-#![cfg_attr(test, feature(test))]
+#![feature(hash)]
+#![feature(unique)]
+#![cfg_attr(test, feature(test, rustc_private, env))]
 
 // Don't link to std. We are std.
 #![feature(no_std)]
 #[macro_use]
 mod uint_macros;
 
-#[path = "num/int.rs"]  pub mod int;
 #[path = "num/isize.rs"]  pub mod isize;
+pub use isize as int;
 #[path = "num/i8.rs"]   pub mod i8;
 #[path = "num/i16.rs"]  pub mod i16;
 #[path = "num/i32.rs"]  pub mod i32;
 #[path = "num/i64.rs"]  pub mod i64;
 
-#[path = "num/uint.rs"] pub mod uint;
 #[path = "num/usize.rs"] pub mod usize;
+pub use usize as uint;
 #[path = "num/u8.rs"]   pub mod u8;
 #[path = "num/u16.rs"]  pub mod u16;
 #[path = "num/u32.rs"]  pub mod u32;
index 00bb7f86b170cf47b536ed5bdfac11b0405dd590..abdcca59c58f31a850d55476b3f0a7a9b8de96dd 100644 (file)
@@ -44,7 +44,7 @@ macro_rules! panic {
     ($msg:expr) => ({
         $crate::rt::begin_unwind($msg, {
             // static requires less code at runtime, more constant data
-            static _FILE_LINE: (&'static str, usize) = (file!(), line!());
+            static _FILE_LINE: (&'static str, usize) = (file!(), line!() as usize);
             &_FILE_LINE
         })
     });
@@ -54,7 +54,7 @@ macro_rules! panic {
             // used inside a dead function. Just `#[allow(dead_code)]` is
             // insufficient, since the user may have
             // `#[forbid(dead_code)]` and which cannot be overridden.
-            static _FILE_LINE: (&'static str, usize) = (file!(), line!());
+            static _FILE_LINE: (&'static str, usize) = (file!(), line!() as usize);
             &_FILE_LINE
         })
     });
index 51944adf3b40395f7adb88b57943ce2fb21a5b3d..f16f501c46a19006ff789b01839a71f054684528 100644 (file)
@@ -147,21 +147,6 @@ fn eq(&self, other: &Repr) -> bool {
 }
 impl Eq for Repr {}
 
-#[cfg(stage0)]
-impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Repr {
-    fn hash(&self, s: &mut S) {
-        match *self {
-            Repr::V4(ref a) => {
-                (a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s)
-            }
-            Repr::V6(ref a) => {
-                (a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr,
-                 a.sin6_flowinfo, a.sin6_scope_id).hash(s)
-            }
-        }
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Repr {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
index 571a1b03ef07fbd879a1e98c7caafe1838506d87..d699886e57747dbbf2ca041d9f94271564f6a72c 100644 (file)
@@ -189,13 +189,6 @@ fn eq(&self, other: &Ipv4Addr) -> bool {
 }
 impl Eq for Ipv4Addr {}
 
-#[cfg(stage0)]
-impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Ipv4Addr {
-    fn hash(&self, s: &mut S) {
-        self.inner.s_addr.hash(s)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Ipv4Addr {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
@@ -429,13 +422,6 @@ fn eq(&self, other: &Ipv6Addr) -> bool {
 }
 impl Eq for Ipv6Addr {}
 
-#[cfg(stage0)]
-impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Ipv6Addr {
-    fn hash(&self, s: &mut S) {
-        self.inner.s6_addr.hash(s)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Ipv6Addr {
     fn hash<H: hash::Hasher>(&self, s: &mut H) {
index b861b74947eeb20961995bc8a48450ccc3efe25c..f99cd2b1d1be9eeb59887f081817a4787236af95 100644 (file)
@@ -456,12 +456,6 @@ fn connect(i: usize, addr: SocketAddr) {
         }
     }
 
-    pub fn socket_name(addr: SocketAddr) {
-    }
-
-    pub fn peer_name(addr: SocketAddr) {
-    }
-
     #[test]
     fn socket_and_peer_name_ip4() {
         each_ip(&mut |addr| {
index 971fb4b69c8ef5ee6df1cd5ef3700d2c248f2ebf..dbebede9f50e42881c627dec9aa41dac14f842d4 100644 (file)
 use net::{SocketAddr, IpAddr};
 use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
+static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
+
 pub fn next_test_ip4() -> SocketAddr {
-    static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
     SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1),
                     PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port())
 }
 
 pub fn next_test_ip6() -> SocketAddr {
-    static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
     SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0, 1),
                     PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port())
 }
@@ -33,7 +33,7 @@ fn base_port() -> u16 {
     let cwd = env::current_dir().unwrap();
     let dirs = ["32-opt", "32-nopt", "64-opt", "64-nopt", "64-opt-vg",
                 "all-opt", "snap3", "dist"];
-    dirs.iter().enumerate().find(|&(i, dir)| {
-        cwd.as_str().unwrap().contains(dir)
+    dirs.iter().enumerate().find(|&(_, dir)| {
+        cwd.to_str().unwrap().contains(dir)
     }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
 }
diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs
deleted file mode 100644 (file)
index 669952e..0000000
+++ /dev/null
@@ -1,22 +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.
-
-//! Deprecated: replaced by `isize`.
-//!
-//! The rollout of the new type will gradually take place over the
-//! alpha cycle along with the development of clearer conventions
-//! around integer types.
-
-#![unstable(feature = "std_misc")]
-#![deprecated(since = "1.0.0", reason = "replaced by isize")]
-
-pub use core::int::{BITS, BYTES, MIN, MAX};
-
-int_module! { int }
index c94c16498332924e2fd5348fc12e317983c792e3..15ae8b027e128a20451ebc5c8a408ae008f5b42e 100644 (file)
@@ -11,7 +11,7 @@
 //! Numeric traits and functions for generic mathematics
 //!
 //! These are implemented for the primitive numeric types in `std::{u8, u16,
-//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64}`.
+//! u32, u64, usize, i8, i16, i32, i64, isize, f32, f64}`.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
@@ -146,12 +146,12 @@ pub trait Float
     #[deprecated(since = "1.0.0",
                  reason = "use `std::f32::MANTISSA_DIGITS` or \
                            `std::f64::MANTISSA_DIGITS` as appropriate")]
-    fn mantissa_digits(unused_self: Option<Self>) -> uint;
+    fn mantissa_digits(unused_self: Option<Self>) -> usize;
     /// Deprecated: use `std::f32::DIGITS` or `std::f64::DIGITS` instead.
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
                  reason = "use `std::f32::DIGITS` or `std::f64::DIGITS` as appropriate")]
-    fn digits(unused_self: Option<Self>) -> uint;
+    fn digits(unused_self: Option<Self>) -> usize;
     /// Deprecated: use `std::f32::EPSILON` or `std::f64::EPSILON` instead.
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
@@ -161,22 +161,22 @@ pub trait Float
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
                  reason = "use `std::f32::MIN_EXP` or `std::f64::MIN_EXP` as appropriate")]
-    fn min_exp(unused_self: Option<Self>) -> int;
+    fn min_exp(unused_self: Option<Self>) -> isize;
     /// Deprecated: use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` instead.
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
                  reason = "use `std::f32::MAX_EXP` or `std::f64::MAX_EXP` as appropriate")]
-    fn max_exp(unused_self: Option<Self>) -> int;
+    fn max_exp(unused_self: Option<Self>) -> isize;
     /// Deprecated: use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` instead.
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
                  reason = "use `std::f32::MIN_10_EXP` or `std::f64::MIN_10_EXP` as appropriate")]
-    fn min_10_exp(unused_self: Option<Self>) -> int;
+    fn min_10_exp(unused_self: Option<Self>) -> isize;
     /// Deprecated: use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` instead.
     #[unstable(feature = "std_misc")]
     #[deprecated(since = "1.0.0",
                  reason = "use `std::f32::MAX_10_EXP` or `std::f64::MAX_10_EXP` as appropriate")]
-    fn max_10_exp(unused_self: Option<Self>) -> int;
+    fn max_10_exp(unused_self: Option<Self>) -> isize;
 
     /// Returns the smallest finite value that this type can represent.
     ///
@@ -698,7 +698,7 @@ pub trait Float
     /// ```
     #[unstable(feature = "std_misc",
                reason = "pending integer conventions")]
-    fn ldexp(x: Self, exp: int) -> Self;
+    fn ldexp(x: Self, exp: isize) -> Self;
     /// Breaks the number into a normalized fraction and a base-2 exponent,
     /// satisfying:
     ///
@@ -720,7 +720,7 @@ pub trait Float
     /// ```
     #[unstable(feature = "std_misc",
                reason = "pending integer conventions")]
-    fn frexp(self) -> (Self, int);
+    fn frexp(self) -> (Self, isize);
     /// Returns the next representable floating-point value in the direction of
     /// `other`.
     ///
@@ -1112,12 +1112,12 @@ mod tests {
     use i16;
     use i32;
     use i64;
-    use int;
+    use isize;
     use u8;
     use u16;
     use u32;
     use u64;
-    use uint;
+    use usize;
 
     macro_rules! test_cast_20 {
         ($_20:expr) => ({
@@ -1179,25 +1179,25 @@ macro_rules! test_cast_20 {
 
     #[test]
     fn test_cast_range_int_min() {
-        assert_eq!(int::MIN.to_int(),  Some(int::MIN as int));
-        assert_eq!(int::MIN.to_i8(),   None);
-        assert_eq!(int::MIN.to_i16(),  None);
-        // int::MIN.to_i32() is word-size specific
-        assert_eq!(int::MIN.to_i64(),  Some(int::MIN as i64));
-        assert_eq!(int::MIN.to_uint(), None);
-        assert_eq!(int::MIN.to_u8(),   None);
-        assert_eq!(int::MIN.to_u16(),  None);
-        assert_eq!(int::MIN.to_u32(),  None);
-        assert_eq!(int::MIN.to_u64(),  None);
+        assert_eq!(isize::MIN.to_int(),  Some(isize::MIN as isize));
+        assert_eq!(isize::MIN.to_i8(),   None);
+        assert_eq!(isize::MIN.to_i16(),  None);
+        // isize::MIN.to_i32() is word-size specific
+        assert_eq!(isize::MIN.to_i64(),  Some(isize::MIN as i64));
+        assert_eq!(isize::MIN.to_uint(), None);
+        assert_eq!(isize::MIN.to_u8(),   None);
+        assert_eq!(isize::MIN.to_u16(),  None);
+        assert_eq!(isize::MIN.to_u32(),  None);
+        assert_eq!(isize::MIN.to_u64(),  None);
 
         #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
-            assert_eq!(int::MIN.to_i32(), Some(int::MIN as i32));
+            assert_eq!(isize::MIN.to_i32(), Some(isize::MIN as i32));
         }
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(int::MIN.to_i32(), None);
+            assert_eq!(isize::MIN.to_i32(), None);
         }
 
         check_word_size();
@@ -1205,7 +1205,7 @@ fn check_word_size() {
 
     #[test]
     fn test_cast_range_i8_min() {
-        assert_eq!(i8::MIN.to_int(),  Some(i8::MIN as int));
+        assert_eq!(i8::MIN.to_int(),  Some(i8::MIN as isize));
         assert_eq!(i8::MIN.to_i8(),   Some(i8::MIN as i8));
         assert_eq!(i8::MIN.to_i16(),  Some(i8::MIN as i16));
         assert_eq!(i8::MIN.to_i32(),  Some(i8::MIN as i32));
@@ -1219,7 +1219,7 @@ fn test_cast_range_i8_min() {
 
     #[test]
     fn test_cast_range_i16_min() {
-        assert_eq!(i16::MIN.to_int(),  Some(i16::MIN as int));
+        assert_eq!(i16::MIN.to_int(),  Some(i16::MIN as isize));
         assert_eq!(i16::MIN.to_i8(),   None);
         assert_eq!(i16::MIN.to_i16(),  Some(i16::MIN as i16));
         assert_eq!(i16::MIN.to_i32(),  Some(i16::MIN as i32));
@@ -1233,7 +1233,7 @@ fn test_cast_range_i16_min() {
 
     #[test]
     fn test_cast_range_i32_min() {
-        assert_eq!(i32::MIN.to_int(),  Some(i32::MIN as int));
+        assert_eq!(i32::MIN.to_int(),  Some(i32::MIN as isize));
         assert_eq!(i32::MIN.to_i8(),   None);
         assert_eq!(i32::MIN.to_i16(),  None);
         assert_eq!(i32::MIN.to_i32(),  Some(i32::MIN as i32));
@@ -1265,7 +1265,7 @@ fn check_word_size() {
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(i64::MIN.to_int(), Some(i64::MIN as int));
+            assert_eq!(i64::MIN.to_int(), Some(i64::MIN as isize));
         }
 
         check_word_size();
@@ -1273,26 +1273,26 @@ fn check_word_size() {
 
     #[test]
     fn test_cast_range_int_max() {
-        assert_eq!(int::MAX.to_int(),  Some(int::MAX as int));
-        assert_eq!(int::MAX.to_i8(),   None);
-        assert_eq!(int::MAX.to_i16(),  None);
-        // int::MAX.to_i32() is word-size specific
-        assert_eq!(int::MAX.to_i64(),  Some(int::MAX as i64));
-        assert_eq!(int::MAX.to_u8(),   None);
-        assert_eq!(int::MAX.to_u16(),  None);
-        // int::MAX.to_u32() is word-size specific
-        assert_eq!(int::MAX.to_u64(),  Some(int::MAX as u64));
+        assert_eq!(isize::MAX.to_int(),  Some(isize::MAX as isize));
+        assert_eq!(isize::MAX.to_i8(),   None);
+        assert_eq!(isize::MAX.to_i16(),  None);
+        // isize::MAX.to_i32() is word-size specific
+        assert_eq!(isize::MAX.to_i64(),  Some(isize::MAX as i64));
+        assert_eq!(isize::MAX.to_u8(),   None);
+        assert_eq!(isize::MAX.to_u16(),  None);
+        // isize::MAX.to_u32() is word-size specific
+        assert_eq!(isize::MAX.to_u64(),  Some(isize::MAX as u64));
 
         #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
-            assert_eq!(int::MAX.to_i32(), Some(int::MAX as i32));
-            assert_eq!(int::MAX.to_u32(), Some(int::MAX as u32));
+            assert_eq!(isize::MAX.to_i32(), Some(isize::MAX as i32));
+            assert_eq!(isize::MAX.to_u32(), Some(isize::MAX as u32));
         }
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(int::MAX.to_i32(), None);
-            assert_eq!(int::MAX.to_u32(), None);
+            assert_eq!(isize::MAX.to_i32(), None);
+            assert_eq!(isize::MAX.to_u32(), None);
         }
 
         check_word_size();
@@ -1300,12 +1300,12 @@ fn check_word_size() {
 
     #[test]
     fn test_cast_range_i8_max() {
-        assert_eq!(i8::MAX.to_int(),  Some(i8::MAX as int));
+        assert_eq!(i8::MAX.to_int(),  Some(i8::MAX as isize));
         assert_eq!(i8::MAX.to_i8(),   Some(i8::MAX as i8));
         assert_eq!(i8::MAX.to_i16(),  Some(i8::MAX as i16));
         assert_eq!(i8::MAX.to_i32(),  Some(i8::MAX as i32));
         assert_eq!(i8::MAX.to_i64(),  Some(i8::MAX as i64));
-        assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as uint));
+        assert_eq!(i8::MAX.to_uint(), Some(i8::MAX as usize));
         assert_eq!(i8::MAX.to_u8(),   Some(i8::MAX as u8));
         assert_eq!(i8::MAX.to_u16(),  Some(i8::MAX as u16));
         assert_eq!(i8::MAX.to_u32(),  Some(i8::MAX as u32));
@@ -1314,12 +1314,12 @@ fn test_cast_range_i8_max() {
 
     #[test]
     fn test_cast_range_i16_max() {
-        assert_eq!(i16::MAX.to_int(),  Some(i16::MAX as int));
+        assert_eq!(i16::MAX.to_int(),  Some(i16::MAX as isize));
         assert_eq!(i16::MAX.to_i8(),   None);
         assert_eq!(i16::MAX.to_i16(),  Some(i16::MAX as i16));
         assert_eq!(i16::MAX.to_i32(),  Some(i16::MAX as i32));
         assert_eq!(i16::MAX.to_i64(),  Some(i16::MAX as i64));
-        assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as uint));
+        assert_eq!(i16::MAX.to_uint(), Some(i16::MAX as usize));
         assert_eq!(i16::MAX.to_u8(),   None);
         assert_eq!(i16::MAX.to_u16(),  Some(i16::MAX as u16));
         assert_eq!(i16::MAX.to_u32(),  Some(i16::MAX as u32));
@@ -1328,12 +1328,12 @@ fn test_cast_range_i16_max() {
 
     #[test]
     fn test_cast_range_i32_max() {
-        assert_eq!(i32::MAX.to_int(),  Some(i32::MAX as int));
+        assert_eq!(i32::MAX.to_int(),  Some(i32::MAX as isize));
         assert_eq!(i32::MAX.to_i8(),   None);
         assert_eq!(i32::MAX.to_i16(),  None);
         assert_eq!(i32::MAX.to_i32(),  Some(i32::MAX as i32));
         assert_eq!(i32::MAX.to_i64(),  Some(i32::MAX as i64));
-        assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as uint));
+        assert_eq!(i32::MAX.to_uint(), Some(i32::MAX as usize));
         assert_eq!(i32::MAX.to_u8(),   None);
         assert_eq!(i32::MAX.to_u16(),  None);
         assert_eq!(i32::MAX.to_u32(),  Some(i32::MAX as u32));
@@ -1361,8 +1361,8 @@ fn check_word_size() {
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(i64::MAX.to_int(),  Some(i64::MAX as int));
-            assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as uint));
+            assert_eq!(i64::MAX.to_int(),  Some(i64::MAX as isize));
+            assert_eq!(i64::MAX.to_uint(), Some(i64::MAX as usize));
         }
 
         check_word_size();
@@ -1370,26 +1370,26 @@ fn check_word_size() {
 
     #[test]
     fn test_cast_range_uint_min() {
-        assert_eq!(uint::MIN.to_int(),  Some(uint::MIN as int));
-        assert_eq!(uint::MIN.to_i8(),   Some(uint::MIN as i8));
-        assert_eq!(uint::MIN.to_i16(),  Some(uint::MIN as i16));
-        assert_eq!(uint::MIN.to_i32(),  Some(uint::MIN as i32));
-        assert_eq!(uint::MIN.to_i64(),  Some(uint::MIN as i64));
-        assert_eq!(uint::MIN.to_uint(), Some(uint::MIN as uint));
-        assert_eq!(uint::MIN.to_u8(),   Some(uint::MIN as u8));
-        assert_eq!(uint::MIN.to_u16(),  Some(uint::MIN as u16));
-        assert_eq!(uint::MIN.to_u32(),  Some(uint::MIN as u32));
-        assert_eq!(uint::MIN.to_u64(),  Some(uint::MIN as u64));
+        assert_eq!(usize::MIN.to_int(),  Some(usize::MIN as isize));
+        assert_eq!(usize::MIN.to_i8(),   Some(usize::MIN as i8));
+        assert_eq!(usize::MIN.to_i16(),  Some(usize::MIN as i16));
+        assert_eq!(usize::MIN.to_i32(),  Some(usize::MIN as i32));
+        assert_eq!(usize::MIN.to_i64(),  Some(usize::MIN as i64));
+        assert_eq!(usize::MIN.to_uint(), Some(usize::MIN as usize));
+        assert_eq!(usize::MIN.to_u8(),   Some(usize::MIN as u8));
+        assert_eq!(usize::MIN.to_u16(),  Some(usize::MIN as u16));
+        assert_eq!(usize::MIN.to_u32(),  Some(usize::MIN as u32));
+        assert_eq!(usize::MIN.to_u64(),  Some(usize::MIN as u64));
     }
 
     #[test]
     fn test_cast_range_u8_min() {
-        assert_eq!(u8::MIN.to_int(),  Some(u8::MIN as int));
+        assert_eq!(u8::MIN.to_int(),  Some(u8::MIN as isize));
         assert_eq!(u8::MIN.to_i8(),   Some(u8::MIN as i8));
         assert_eq!(u8::MIN.to_i16(),  Some(u8::MIN as i16));
         assert_eq!(u8::MIN.to_i32(),  Some(u8::MIN as i32));
         assert_eq!(u8::MIN.to_i64(),  Some(u8::MIN as i64));
-        assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as uint));
+        assert_eq!(u8::MIN.to_uint(), Some(u8::MIN as usize));
         assert_eq!(u8::MIN.to_u8(),   Some(u8::MIN as u8));
         assert_eq!(u8::MIN.to_u16(),  Some(u8::MIN as u16));
         assert_eq!(u8::MIN.to_u32(),  Some(u8::MIN as u32));
@@ -1398,12 +1398,12 @@ fn test_cast_range_u8_min() {
 
     #[test]
     fn test_cast_range_u16_min() {
-        assert_eq!(u16::MIN.to_int(),  Some(u16::MIN as int));
+        assert_eq!(u16::MIN.to_int(),  Some(u16::MIN as isize));
         assert_eq!(u16::MIN.to_i8(),   Some(u16::MIN as i8));
         assert_eq!(u16::MIN.to_i16(),  Some(u16::MIN as i16));
         assert_eq!(u16::MIN.to_i32(),  Some(u16::MIN as i32));
         assert_eq!(u16::MIN.to_i64(),  Some(u16::MIN as i64));
-        assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as uint));
+        assert_eq!(u16::MIN.to_uint(), Some(u16::MIN as usize));
         assert_eq!(u16::MIN.to_u8(),   Some(u16::MIN as u8));
         assert_eq!(u16::MIN.to_u16(),  Some(u16::MIN as u16));
         assert_eq!(u16::MIN.to_u32(),  Some(u16::MIN as u32));
@@ -1412,12 +1412,12 @@ fn test_cast_range_u16_min() {
 
     #[test]
     fn test_cast_range_u32_min() {
-        assert_eq!(u32::MIN.to_int(),  Some(u32::MIN as int));
+        assert_eq!(u32::MIN.to_int(),  Some(u32::MIN as isize));
         assert_eq!(u32::MIN.to_i8(),   Some(u32::MIN as i8));
         assert_eq!(u32::MIN.to_i16(),  Some(u32::MIN as i16));
         assert_eq!(u32::MIN.to_i32(),  Some(u32::MIN as i32));
         assert_eq!(u32::MIN.to_i64(),  Some(u32::MIN as i64));
-        assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as uint));
+        assert_eq!(u32::MIN.to_uint(), Some(u32::MIN as usize));
         assert_eq!(u32::MIN.to_u8(),   Some(u32::MIN as u8));
         assert_eq!(u32::MIN.to_u16(),  Some(u32::MIN as u16));
         assert_eq!(u32::MIN.to_u32(),  Some(u32::MIN as u32));
@@ -1426,12 +1426,12 @@ fn test_cast_range_u32_min() {
 
     #[test]
     fn test_cast_range_u64_min() {
-        assert_eq!(u64::MIN.to_int(),  Some(u64::MIN as int));
+        assert_eq!(u64::MIN.to_int(),  Some(u64::MIN as isize));
         assert_eq!(u64::MIN.to_i8(),   Some(u64::MIN as i8));
         assert_eq!(u64::MIN.to_i16(),  Some(u64::MIN as i16));
         assert_eq!(u64::MIN.to_i32(),  Some(u64::MIN as i32));
         assert_eq!(u64::MIN.to_i64(),  Some(u64::MIN as i64));
-        assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as uint));
+        assert_eq!(u64::MIN.to_uint(), Some(u64::MIN as usize));
         assert_eq!(u64::MIN.to_u8(),   Some(u64::MIN as u8));
         assert_eq!(u64::MIN.to_u16(),  Some(u64::MIN as u16));
         assert_eq!(u64::MIN.to_u32(),  Some(u64::MIN as u32));
@@ -1440,26 +1440,26 @@ fn test_cast_range_u64_min() {
 
     #[test]
     fn test_cast_range_uint_max() {
-        assert_eq!(uint::MAX.to_int(),  None);
-        assert_eq!(uint::MAX.to_i8(),   None);
-        assert_eq!(uint::MAX.to_i16(),  None);
-        assert_eq!(uint::MAX.to_i32(),  None);
-        // uint::MAX.to_i64() is word-size specific
-        assert_eq!(uint::MAX.to_u8(),   None);
-        assert_eq!(uint::MAX.to_u16(),  None);
-        // uint::MAX.to_u32() is word-size specific
-        assert_eq!(uint::MAX.to_u64(),  Some(uint::MAX as u64));
+        assert_eq!(usize::MAX.to_int(),  None);
+        assert_eq!(usize::MAX.to_i8(),   None);
+        assert_eq!(usize::MAX.to_i16(),  None);
+        assert_eq!(usize::MAX.to_i32(),  None);
+        // usize::MAX.to_i64() is word-size specific
+        assert_eq!(usize::MAX.to_u8(),   None);
+        assert_eq!(usize::MAX.to_u16(),  None);
+        // usize::MAX.to_u32() is word-size specific
+        assert_eq!(usize::MAX.to_u64(),  Some(usize::MAX as u64));
 
         #[cfg(target_pointer_width = "32")]
         fn check_word_size() {
-            assert_eq!(uint::MAX.to_u32(), Some(uint::MAX as u32));
-            assert_eq!(uint::MAX.to_i64(), Some(uint::MAX as i64));
+            assert_eq!(usize::MAX.to_u32(), Some(usize::MAX as u32));
+            assert_eq!(usize::MAX.to_i64(), Some(usize::MAX as i64));
         }
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(uint::MAX.to_u32(), None);
-            assert_eq!(uint::MAX.to_i64(), None);
+            assert_eq!(usize::MAX.to_u32(), None);
+            assert_eq!(usize::MAX.to_i64(), None);
         }
 
         check_word_size();
@@ -1467,12 +1467,12 @@ fn check_word_size() {
 
     #[test]
     fn test_cast_range_u8_max() {
-        assert_eq!(u8::MAX.to_int(),  Some(u8::MAX as int));
+        assert_eq!(u8::MAX.to_int(),  Some(u8::MAX as isize));
         assert_eq!(u8::MAX.to_i8(),   None);
         assert_eq!(u8::MAX.to_i16(),  Some(u8::MAX as i16));
         assert_eq!(u8::MAX.to_i32(),  Some(u8::MAX as i32));
         assert_eq!(u8::MAX.to_i64(),  Some(u8::MAX as i64));
-        assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as uint));
+        assert_eq!(u8::MAX.to_uint(), Some(u8::MAX as usize));
         assert_eq!(u8::MAX.to_u8(),   Some(u8::MAX as u8));
         assert_eq!(u8::MAX.to_u16(),  Some(u8::MAX as u16));
         assert_eq!(u8::MAX.to_u32(),  Some(u8::MAX as u32));
@@ -1481,12 +1481,12 @@ fn test_cast_range_u8_max() {
 
     #[test]
     fn test_cast_range_u16_max() {
-        assert_eq!(u16::MAX.to_int(),  Some(u16::MAX as int));
+        assert_eq!(u16::MAX.to_int(),  Some(u16::MAX as isize));
         assert_eq!(u16::MAX.to_i8(),   None);
         assert_eq!(u16::MAX.to_i16(),  None);
         assert_eq!(u16::MAX.to_i32(),  Some(u16::MAX as i32));
         assert_eq!(u16::MAX.to_i64(),  Some(u16::MAX as i64));
-        assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as uint));
+        assert_eq!(u16::MAX.to_uint(), Some(u16::MAX as usize));
         assert_eq!(u16::MAX.to_u8(),   None);
         assert_eq!(u16::MAX.to_u16(),  Some(u16::MAX as u16));
         assert_eq!(u16::MAX.to_u32(),  Some(u16::MAX as u32));
@@ -1500,7 +1500,7 @@ fn test_cast_range_u32_max() {
         assert_eq!(u32::MAX.to_i16(),  None);
         assert_eq!(u32::MAX.to_i32(),  None);
         assert_eq!(u32::MAX.to_i64(),  Some(u32::MAX as i64));
-        assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as uint));
+        assert_eq!(u32::MAX.to_uint(), Some(u32::MAX as usize));
         assert_eq!(u32::MAX.to_u8(),   None);
         assert_eq!(u32::MAX.to_u16(),  None);
         assert_eq!(u32::MAX.to_u32(),  Some(u32::MAX as u32));
@@ -1513,7 +1513,7 @@ fn check_word_size() {
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(u32::MAX.to_int(),  Some(u32::MAX as int));
+            assert_eq!(u32::MAX.to_int(),  Some(u32::MAX as isize));
         }
 
         check_word_size();
@@ -1539,7 +1539,7 @@ fn check_word_size() {
 
         #[cfg(target_pointer_width = "64")]
         fn check_word_size() {
-            assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as uint));
+            assert_eq!(u64::MAX.to_uint(), Some(u64::MAX as usize));
         }
 
         check_word_size();
@@ -1547,7 +1547,7 @@ fn check_word_size() {
 
     #[test]
     fn test_saturating_add_uint() {
-        use uint::MAX;
+        use usize::MAX;
         assert_eq!(3_usize.saturating_add(5_usize), 8_usize);
         assert_eq!(3_usize.saturating_add(MAX-1), MAX);
         assert_eq!(MAX.saturating_add(MAX), MAX);
@@ -1556,7 +1556,7 @@ fn test_saturating_add_uint() {
 
     #[test]
     fn test_saturating_sub_uint() {
-        use uint::MAX;
+        use usize::MAX;
         assert_eq!(5_usize.saturating_sub(3_usize), 2_usize);
         assert_eq!(3_usize.saturating_sub(5_usize), 0_usize);
         assert_eq!(0_usize.saturating_sub(1_usize), 0_usize);
@@ -1565,7 +1565,7 @@ fn test_saturating_sub_uint() {
 
     #[test]
     fn test_saturating_add_int() {
-        use int::{MIN,MAX};
+        use isize::{MIN,MAX};
         assert_eq!(3.saturating_add(5), 8);
         assert_eq!(3.saturating_add(MAX-1), MAX);
         assert_eq!(MAX.saturating_add(MAX), MAX);
@@ -1577,7 +1577,7 @@ fn test_saturating_add_int() {
 
     #[test]
     fn test_saturating_sub_int() {
-        use int::{MIN,MAX};
+        use isize::{MIN,MAX};
         assert_eq!(3.saturating_sub(5), -2);
         assert_eq!(MIN.saturating_sub(1), MIN);
         assert_eq!((-2).saturating_sub(MAX), MIN);
@@ -1589,13 +1589,13 @@ fn test_saturating_sub_int() {
 
     #[test]
     fn test_checked_add() {
-        let five_less = uint::MAX - 5;
-        assert_eq!(five_less.checked_add(0), Some(uint::MAX - 5));
-        assert_eq!(five_less.checked_add(1), Some(uint::MAX - 4));
-        assert_eq!(five_less.checked_add(2), Some(uint::MAX - 3));
-        assert_eq!(five_less.checked_add(3), Some(uint::MAX - 2));
-        assert_eq!(five_less.checked_add(4), Some(uint::MAX - 1));
-        assert_eq!(five_less.checked_add(5), Some(uint::MAX));
+        let five_less = usize::MAX - 5;
+        assert_eq!(five_less.checked_add(0), Some(usize::MAX - 5));
+        assert_eq!(five_less.checked_add(1), Some(usize::MAX - 4));
+        assert_eq!(five_less.checked_add(2), Some(usize::MAX - 3));
+        assert_eq!(five_less.checked_add(3), Some(usize::MAX - 2));
+        assert_eq!(five_less.checked_add(4), Some(usize::MAX - 1));
+        assert_eq!(five_less.checked_add(5), Some(usize::MAX));
         assert_eq!(five_less.checked_add(6), None);
         assert_eq!(five_less.checked_add(7), None);
     }
@@ -1614,7 +1614,7 @@ fn test_checked_sub() {
 
     #[test]
     fn test_checked_mul() {
-        let third = uint::MAX / 3;
+        let third = usize::MAX / 3;
         assert_eq!(third.checked_mul(0), Some(0));
         assert_eq!(third.checked_mul(1), Some(third));
         assert_eq!(third.checked_mul(2), Some(third * 2));
@@ -1641,7 +1641,7 @@ fn $test_name() {
     test_is_power_of_two!{ test_is_power_of_two_u16, u16 }
     test_is_power_of_two!{ test_is_power_of_two_u32, u32 }
     test_is_power_of_two!{ test_is_power_of_two_u64, u64 }
-    test_is_power_of_two!{ test_is_power_of_two_uint, uint }
+    test_is_power_of_two!{ test_is_power_of_two_uint, usize }
 
     macro_rules! test_next_power_of_two {
         ($test_name:ident, $T:ident) => (
@@ -1661,7 +1661,7 @@ fn $test_name() {
     test_next_power_of_two! { test_next_power_of_two_u16, u16 }
     test_next_power_of_two! { test_next_power_of_two_u32, u32 }
     test_next_power_of_two! { test_next_power_of_two_u64, u64 }
-    test_next_power_of_two! { test_next_power_of_two_uint, uint }
+    test_next_power_of_two! { test_next_power_of_two_uint, usize }
 
     macro_rules! test_checked_next_power_of_two {
         ($test_name:ident, $T:ident) => (
@@ -1684,10 +1684,10 @@ fn $test_name() {
     test_checked_next_power_of_two! { test_checked_next_power_of_two_u16, u16 }
     test_checked_next_power_of_two! { test_checked_next_power_of_two_u32, u32 }
     test_checked_next_power_of_two! { test_checked_next_power_of_two_u64, u64 }
-    test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, uint }
+    test_checked_next_power_of_two! { test_checked_next_power_of_two_uint, usize }
 
     #[derive(PartialEq, Debug)]
-    struct Value { x: int }
+    struct Value { x: isize }
 
     impl ToPrimitive for Value {
         fn to_i64(&self) -> Option<i64> { self.x.to_i64() }
@@ -1695,8 +1695,8 @@ fn to_u64(&self) -> Option<u64> { self.x.to_u64() }
     }
 
     impl FromPrimitive for Value {
-        fn from_i64(n: i64) -> Option<Value> { Some(Value { x: n as int }) }
-        fn from_u64(n: u64) -> Option<Value> { Some(Value { x: n as int }) }
+        fn from_i64(n: i64) -> Option<Value> { Some(Value { x: n as isize }) }
+        fn from_u64(n: u64) -> Option<Value> { Some(Value { x: n as isize }) }
     }
 
     #[test]
@@ -1734,7 +1734,7 @@ fn test_from_primitive() {
 
     #[test]
     fn test_pow() {
-        fn naive_pow<T: Int>(base: T, exp: uint) -> T {
+        fn naive_pow<T: Int>(base: T, exp: usize) -> T {
             let one: T = Int::one();
             (0..exp).fold(one, |acc, _| acc * base)
         }
@@ -1751,6 +1751,72 @@ macro_rules! assert_pow {
         assert_pow!((8,     3 ) => 512);
         assert_pow!((2u64,   50) => 1125899906842624);
     }
+
+    #[test]
+    fn test_uint_to_str_overflow() {
+        let mut u8_val: u8 = 255_u8;
+        assert_eq!(u8_val.to_string(), "255");
+
+        u8_val += 1 as u8;
+        assert_eq!(u8_val.to_string(), "0");
+
+        let mut u16_val: u16 = 65_535_u16;
+        assert_eq!(u16_val.to_string(), "65535");
+
+        u16_val += 1 as u16;
+        assert_eq!(u16_val.to_string(), "0");
+
+        let mut u32_val: u32 = 4_294_967_295_u32;
+        assert_eq!(u32_val.to_string(), "4294967295");
+
+        u32_val += 1 as u32;
+        assert_eq!(u32_val.to_string(), "0");
+
+        let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
+        assert_eq!(u64_val.to_string(), "18446744073709551615");
+
+        u64_val += 1 as u64;
+        assert_eq!(u64_val.to_string(), "0");
+    }
+
+    fn from_str<T: ::str::FromStr>(t: &str) -> Option<T> {
+        ::str::FromStr::from_str(t).ok()
+    }
+
+    #[test]
+    fn test_uint_from_str_overflow() {
+        let mut u8_val: u8 = 255_u8;
+        assert_eq!(from_str::<u8>("255"), Some(u8_val));
+        assert_eq!(from_str::<u8>("256"), None);
+
+        u8_val += 1 as u8;
+        assert_eq!(from_str::<u8>("0"), Some(u8_val));
+        assert_eq!(from_str::<u8>("-1"), None);
+
+        let mut u16_val: u16 = 65_535_u16;
+        assert_eq!(from_str::<u16>("65535"), Some(u16_val));
+        assert_eq!(from_str::<u16>("65536"), None);
+
+        u16_val += 1 as u16;
+        assert_eq!(from_str::<u16>("0"), Some(u16_val));
+        assert_eq!(from_str::<u16>("-1"), None);
+
+        let mut u32_val: u32 = 4_294_967_295_u32;
+        assert_eq!(from_str::<u32>("4294967295"), Some(u32_val));
+        assert_eq!(from_str::<u32>("4294967296"), None);
+
+        u32_val += 1 as u32;
+        assert_eq!(from_str::<u32>("0"), Some(u32_val));
+        assert_eq!(from_str::<u32>("-1"), None);
+
+        let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
+        assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val));
+        assert_eq!(from_str::<u64>("18446744073709551616"), None);
+
+        u64_val += 1 as u64;
+        assert_eq!(from_str::<u64>("0"), Some(u64_val));
+        assert_eq!(from_str::<u64>("-1"), None);
+    }
 }
 
 
diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs
deleted file mode 100644 (file)
index c7b4913..0000000
+++ /dev/null
@@ -1,22 +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.
-
-//! Deprecated: replaced by `usize`.
-//!
-//! The rollout of the new type will gradually take place over the
-//! alpha cycle along with the development of clearer conventions
-//! around integer types.
-
-#![unstable(feature = "std_misc")]
-#![deprecated(since = "1.0.0", reason = "replaced by usize")]
-
-pub use core::uint::{BITS, BYTES, MIN, MAX};
-
-uint_module! { uint }
index 8d4f0344beb62b767bc92927bceb3306ce63708f..c9e6a8f66d1d25cb01e50a4a67c9f20873cdfbbb 100644 (file)
@@ -48,68 +48,6 @@ pub fn test_parse_bytes() {
         assert_eq!(FromStrRadix::from_str_radix("Z", 10).ok(), None::<$T>);
         assert_eq!(FromStrRadix::from_str_radix("_", 2).ok(), None::<$T>);
     }
-
-    #[test]
-    fn test_uint_to_str_overflow() {
-        let mut u8_val: u8 = 255_u8;
-        assert_eq!(u8_val.to_string(), "255");
-
-        u8_val += 1 as u8;
-        assert_eq!(u8_val.to_string(), "0");
-
-        let mut u16_val: u16 = 65_535_u16;
-        assert_eq!(u16_val.to_string(), "65535");
-
-        u16_val += 1 as u16;
-        assert_eq!(u16_val.to_string(), "0");
-
-        let mut u32_val: u32 = 4_294_967_295_u32;
-        assert_eq!(u32_val.to_string(), "4294967295");
-
-        u32_val += 1 as u32;
-        assert_eq!(u32_val.to_string(), "0");
-
-        let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
-        assert_eq!(u64_val.to_string(), "18446744073709551615");
-
-        u64_val += 1 as u64;
-        assert_eq!(u64_val.to_string(), "0");
-    }
-
-    #[test]
-    fn test_uint_from_str_overflow() {
-        let mut u8_val: u8 = 255_u8;
-        assert_eq!(from_str::<u8>("255"), Some(u8_val));
-        assert_eq!(from_str::<u8>("256"), None);
-
-        u8_val += 1 as u8;
-        assert_eq!(from_str::<u8>("0"), Some(u8_val));
-        assert_eq!(from_str::<u8>("-1"), None);
-
-        let mut u16_val: u16 = 65_535_u16;
-        assert_eq!(from_str::<u16>("65535"), Some(u16_val));
-        assert_eq!(from_str::<u16>("65536"), None);
-
-        u16_val += 1 as u16;
-        assert_eq!(from_str::<u16>("0"), Some(u16_val));
-        assert_eq!(from_str::<u16>("-1"), None);
-
-        let mut u32_val: u32 = 4_294_967_295_u32;
-        assert_eq!(from_str::<u32>("4294967295"), Some(u32_val));
-        assert_eq!(from_str::<u32>("4294967296"), None);
-
-        u32_val += 1 as u32;
-        assert_eq!(from_str::<u32>("0"), Some(u32_val));
-        assert_eq!(from_str::<u32>("-1"), None);
-
-        let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
-        assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val));
-        assert_eq!(from_str::<u64>("18446744073709551616"), None);
-
-        u64_val += 1 as u64;
-        assert_eq!(from_str::<u64>("0"), Some(u64_val));
-        assert_eq!(from_str::<u64>("-1"), None);
-    }
 }
 
 ) }
index c2a6c515acc70b2978fdcd1f494884127549bc25..8bd19f063f0300c51cc9256b70f6c7f0d1aa5fba 100644 (file)
@@ -328,7 +328,7 @@ fn bytes_error() {
     fn read_bytes() {
         let mut reader = MemReader::new(vec!(10, 11, 12, 13));
         let bytes = reader.read_exact(4).unwrap();
-        assert!(bytes == vec!(10, 11, 12, 13));
+        assert_eq!(bytes, [10, 11, 12, 13]);
     }
 
     #[test]
@@ -337,7 +337,7 @@ fn read_bytes_partial() {
             count: 0,
         };
         let bytes = reader.read_exact(4).unwrap();
-        assert!(bytes == vec!(10, 11, 12, 13));
+        assert_eq!(bytes, [10, 11, 12, 13]);
     }
 
     #[test]
@@ -351,7 +351,7 @@ fn push_at_least() {
         let mut reader = MemReader::new(vec![10, 11, 12, 13]);
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
-        assert!(buf == vec![8, 9, 10, 11, 12, 13]);
+        assert_eq!(buf, [8, 9, 10, 11, 12, 13]);
     }
 
     #[test]
@@ -361,7 +361,7 @@ fn push_at_least_partial() {
         };
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
-        assert!(buf == vec![8, 9, 10, 11, 12, 13]);
+        assert_eq!(buf, [8, 9, 10, 11, 12, 13]);
     }
 
     #[test]
@@ -369,7 +369,7 @@ fn push_at_least_eof() {
         let mut reader = MemReader::new(vec![10, 11]);
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_err());
-        assert!(buf == vec![8, 9, 10, 11]);
+        assert_eq!(buf, [8, 9, 10, 11]);
     }
 
     #[test]
@@ -379,7 +379,7 @@ fn push_at_least_error() {
         };
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_err());
-        assert!(buf == vec![8, 9, 10]);
+        assert_eq!(buf, [8, 9, 10]);
     }
 
     #[test]
@@ -388,7 +388,7 @@ fn read_to_end() {
             count: 0,
         };
         let buf = reader.read_to_end().unwrap();
-        assert!(buf == vec!(10, 11, 12, 13));
+        assert_eq!(buf, [10, 11, 12, 13]);
     }
 
     #[test]
@@ -398,7 +398,7 @@ fn read_to_end_error() {
             count: 0,
         };
         let buf = reader.read_to_end().unwrap();
-        assert!(buf == vec!(10, 11));
+        assert_eq!(buf, [10, 11]);
     }
 
     #[test]
index 1fd527014a3d62d4e6fcdac2a6df7b20c26c424d..c08a2c1f477b3ea6017fffbaff6e739d301af081 100644 (file)
@@ -60,7 +60,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 /// let mut w = MemWriter::new();
 /// w.write(&[0, 1, 2]);
 ///
-/// assert_eq!(w.into_inner(), vec!(0, 1, 2));
+/// assert_eq!(w.into_inner(), [0, 1, 2]);
 /// ```
 #[unstable(feature = "io")]
 #[deprecated(since = "1.0.0",
@@ -118,7 +118,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 ///
 /// let mut r = MemReader::new(vec!(0, 1, 2));
 ///
-/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2));
+/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]);
 /// ```
 pub struct MemReader {
     buf: Vec<u8>,
@@ -321,7 +321,7 @@ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
 /// let buf = [0, 1, 2, 3];
 /// let mut r = BufReader::new(&buf);
 ///
-/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]);
+/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]);
 /// ```
 pub struct BufReader<'a> {
     buf: &'a [u8],
@@ -504,8 +504,8 @@ fn test_mem_reader() {
         assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
+        assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
         assert!(reader.read(&mut buf).is_err());
     }
 
@@ -530,8 +530,8 @@ fn test_slice_reader() {
         assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = &mut &*in_buf;
-        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
+        assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
         assert!(reader.read(&mut buf).is_err());
     }
 
@@ -557,8 +557,8 @@ fn test_buf_reader() {
         assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = BufReader::new(&in_buf);
-        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
+        assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
         assert!(reader.read(&mut buf).is_err());
     }
 
index fc3deb67f41ec97148e6a2639964129193006150..b82572fc08957380c68f439b2ae1919d7ccca064 100644 (file)
 
 #![unstable(feature = "old_io")]
 #![deny(unused_must_use)]
+#![allow(deprecated)] // seriously this is all deprecated
+#![allow(unused_imports)]
 
 pub use self::SeekStyle::*;
 pub use self::FileMode::*;
index c803cfbcb7d85db2b9a77b33955b1ebce56c67a8..a13295b1ccb5014ea8137156559b628cca769547 100644 (file)
@@ -104,19 +104,7 @@ pub struct Process {
 #[derive(Eq, Clone, Debug)]
 struct EnvKey(CString);
 
-#[cfg(all(windows, stage0))]
-impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for EnvKey {
-    fn hash(&self, state: &mut H) {
-        let &EnvKey(ref x) = self;
-        match str::from_utf8(x.as_bytes()) {
-            Ok(s) => for ch in s.chars() {
-                (ch as u8 as char).to_lowercase().hash(state);
-            },
-            Err(..) => x.hash(state)
-        }
-    }
-}
-#[cfg(all(windows, not(stage0)))]
+#[cfg(windows)]
 impl hash::Hash for EnvKey {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         let &EnvKey(ref x) = self;
index f42cb6ce8c97bf4d9c9f93d1b5ef9a2b5273945a..cdf2bae1cbad3c260e28e36b682b1db6b1a4a201 100644 (file)
@@ -87,7 +87,7 @@ fn test_option_writer() {
         let mut writer: old_io::IoResult<Vec<u8>> = Ok(Vec::new());
         writer.write_all(&[0, 1, 2]).unwrap();
         writer.flush().unwrap();
-        assert_eq!(writer.unwrap(), vec!(0, 1, 2));
+        assert_eq!(writer.unwrap(), [0, 1, 2]);
     }
 
     #[test]
index e3d0232684fcc3a9b57c25735973550c8a00b607..56a707c24a6c9789c5c8b751e31759d91c7fef5f 100644 (file)
@@ -27,6 +27,7 @@
 
 use self::StdSource::*;
 
+use boxed;
 use boxed::Box;
 use cell::RefCell;
 use clone::Clone;
@@ -218,7 +219,7 @@ fn read_be_uint_n(&mut self, nbytes: uint) -> IoResult<u64> {
 /// See `stdout()` for more notes about this function.
 pub fn stdin() -> StdinReader {
     // We're following the same strategy as kimundi's lazy_static library
-    static mut STDIN: *const StdinReader = 0 as *const StdinReader;
+    static mut STDIN: *mut StdinReader = 0 as *mut StdinReader;
     static ONCE: Once = ONCE_INIT;
 
     unsafe {
@@ -235,12 +236,12 @@ pub fn stdin() -> StdinReader {
             let stdin = StdinReader {
                 inner: Arc::new(Mutex::new(RaceBox(stdin)))
             };
-            STDIN = mem::transmute(box stdin);
+            STDIN = boxed::into_raw(box stdin);
 
             // Make sure to free it at exit
             rt::at_exit(|| {
-                mem::transmute::<_, Box<StdinReader>>(STDIN);
-                STDIN = ptr::null();
+                Box::from_raw(STDIN);
+                STDIN = ptr::null_mut();
             });
         });
 
index 42317c7a2d4316be452817d5b0988bc00a667cad..76753dca52e1eec4dfdad70d862723c3b5e88427 100644 (file)
@@ -96,9 +96,10 @@ impl TempDir {
     /// deleted once the returned wrapper is destroyed.
     ///
     /// If no directory can be created, `Err` is returned.
+    #[allow(deprecated)]
     pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
         if !tmpdir.is_absolute() {
-            let cur_dir = try!(env::current_dir());
+            let cur_dir = try!(::os::getcwd());
             return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
         }
 
@@ -132,8 +133,9 @@ pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
     /// deleted once the returned wrapper is destroyed.
     ///
     /// If no directory can be created, `Err` is returned.
+    #[allow(deprecated)]
     pub fn new(prefix: &str) -> IoResult<TempDir> {
-        TempDir::new_in(&env::temp_dir(), prefix)
+        TempDir::new_in(&::os::tmpdir(), prefix)
     }
 
     /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
index ee72beccfa8488f61fa0f997809ea11b8bc8c3fa..43c0b9268a242d065cc90b9c53c0a71a3207cb9c 100644 (file)
@@ -38,10 +38,11 @@ fn next_test_unix_socket() -> String {
 
 /// Get a temporary path which could be the location of a unix socket
 #[cfg(not(target_os = "ios"))]
+#[allow(deprecated)]
 pub fn next_test_unix() -> Path {
     let string = next_test_unix_socket();
     if cfg!(unix) {
-        env::temp_dir().join(string)
+        ::os::tmpdir().join(string)
     } else {
         Path::new(format!("{}{}", r"\\.\pipe\", string))
     }
@@ -88,7 +89,7 @@ fn base_port() -> u16 {
 
     // FIXME (#9639): This needs to handle non-utf8 paths
     let path = env::current_dir().unwrap();
-    let path_s = path.as_str().unwrap();
+    let path_s = path.to_str().unwrap();
 
     let mut final_base = base;
 
index 5ae239014d188145e55a2014b36be610b3f03dba..8e49335ed5469e110114ab9823866d113903e071 100644 (file)
@@ -284,7 +284,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!(vec!(0, 1, 2), r.read_to_end().unwrap());
+            assert_eq!([0, 1, 2], r.read_to_end().unwrap());
         }
     }
 
@@ -293,9 +293,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!(vec!(0, 1), r.read_to_end().unwrap());
+            assert_eq!([0, 1], r.read_to_end().unwrap());
         }
-        assert_eq!(vec!(2), r.read_to_end().unwrap());
+        assert_eq!([2], r.read_to_end().unwrap());
     }
 
     #[test]
@@ -305,7 +305,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!(vec!(1, 2), r.read_to_end().unwrap());
+        assert_eq!([1, 2], r.read_to_end().unwrap());
         assert_eq!(0, r.limit());
     }
 
@@ -314,7 +314,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!(vec![], r.read_to_end().unwrap());
+        assert_eq!([], r.read_to_end().unwrap());
     }
 
     #[test]
@@ -330,7 +330,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!(vec![0, 0, 0], buf);
+        assert_eq!([0, 0, 0], buf);
     }
 
     #[test]
@@ -373,16 +373,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!(vec!(0, 1, 2, 3), r.read_to_end().unwrap());
+        assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap());
     }
 
     #[test]
     fn test_tee_reader() {
         let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
                                    Vec::new());
-        assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
+        assert_eq!([0, 1, 2], r.read_to_end().unwrap());
         let (_, w) = r.into_inner();
-        assert_eq!(vec!(0, 1, 2), w);
+        assert_eq!([0, 1, 2], w);
     }
 
     #[test]
@@ -390,7 +390,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!(vec!(0, 1, 2, 3, 4), w);
+        assert_eq!([0, 1, 2, 3, 4], w);
     }
 
     #[test]
index e9005aa22bcfbebc37cbb051a1bcde0c412d3180..4f8976fb2ecda2e18faf75c8f5098e9929d43a17 100644 (file)
@@ -60,6 +60,8 @@
 //! ```
 
 #![unstable(feature = "old_path")]
+#![allow(deprecated)] // seriously this is all deprecated
+#![allow(unused_imports)]
 
 use core::marker::Sized;
 use ffi::CString;
index 15eee9e4a0c02d3c2fa0360319a9cab81dec737c..8d5765e1ffe5e929f3c386e62d54d11d97fc053e 100644 (file)
@@ -100,14 +100,6 @@ fn from_str(s: &str) -> Result<Path, ParsePathError> {
 #[derive(Debug, Clone, PartialEq, Copy)]
 pub struct ParsePathError;
 
-#[cfg(stage0)]
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.repr.hash(state)
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Path {
     #[inline]
index 887dc804c7af3da57949f4ea87c1fa249c46e751..31a8cbe572a0318d60d8c0afb8f2c710d205cd11 100644 (file)
@@ -127,21 +127,6 @@ fn from_str(s: &str) -> Result<Path, ParsePathError> {
 #[derive(Debug, Clone, PartialEq, Copy)]
 pub struct ParsePathError;
 
-#[cfg(stage0)]
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
-    #[cfg(not(test))]
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.repr.hash(state)
-    }
-
-    #[cfg(test)]
-    #[inline]
-    fn hash(&self, _: &mut S) {
-        // No-op because the `hash` implementation will be wrong.
-    }
-}
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl hash::Hash for Path {
     #[cfg(not(test))]
@@ -522,7 +507,7 @@ fn is_ancestor_of(&self, other: &Path) -> bool {
 
     fn path_relative_from(&self, base: &Path) -> Option<Path> {
         fn comp_requires_verbatim(s: &str) -> bool {
-            s == "." || s == ".." || s.contains_char(SEP2)
+            s == "." || s == ".." || s.contains(SEP2)
         }
 
         if !self.equiv_prefix(base) {
index f181fc5df5759b557ae5f9099ff12fd6061754b7..9c42d1be77ee1c009ead6a37df39ebbaeda03878 100644 (file)
@@ -49,6 +49,7 @@
 use option::Option::{Some, None};
 use option::Option;
 use old_path::{Path, GenericPath, BytesContainer};
+use path::{self, PathBuf};
 use ptr::PtrExt;
 use ptr;
 use result::Result::{Err, Ok};
 #[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::new(path.as_str().unwrap())
+}
+#[cfg(unix)]
+fn path2new(path: &Path) -> PathBuf {
+    use os::unix::prelude::*;
+    PathBuf::new(<OsStr as OsStrExt>::from_bytes(path.as_vec()))
+}
+
+#[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() -> uint {
     unsafe {
@@ -100,10 +130,9 @@ pub fn num_cpus() -> uint {
 /// let current_working_directory = os::getcwd().unwrap();
 /// println!("The current directory is {:?}", current_working_directory.display());
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")]
 #[unstable(feature = "os")]
 pub fn getcwd() -> IoResult<Path> {
-    env::current_dir()
+    env::current_dir().map_err(err2old).map(|s| path2old(&s))
 }
 
 /// Returns a vector of (variable, value) pairs, for all the environment
@@ -245,12 +274,11 @@ pub fn unsetenv(n: &str) {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")]
 #[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).collect()
+    env::split_paths(s).map(|s| path2old(&s)).collect()
 }
 
 /// Joins a collection of `Path`s appropriately for the `PATH`
@@ -274,7 +302,6 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
 /// paths.push(Path::new("/home/xyz/bin"));
 /// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")]
 #[unstable(feature = "os")]
 pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
     env::join_paths(paths.iter().map(|s| {
@@ -335,10 +362,9 @@ pub fn dll_filename(base: &str) -> String {
 ///     None => println!("Unable to get the path of this executable!")
 /// };
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")]
 #[unstable(feature = "os")]
 pub fn self_exe_name() -> Option<Path> {
-    env::current_exe().ok()
+    env::current_exe().ok().map(|p| path2old(&p))
 }
 
 /// Optionally returns the filesystem path to the current executable which is
@@ -356,10 +382,9 @@ pub fn self_exe_name() -> Option<Path> {
 ///     None => println!("Impossible to fetch the path of this executable.")
 /// };
 /// ```
-#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")]
 #[unstable(feature = "os")]
 pub fn self_exe_path() -> Option<Path> {
-    env::current_exe().ok().map(|mut p| { p.pop(); p })
+    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.
@@ -386,9 +411,8 @@ pub fn self_exe_path() -> Option<Path> {
 ///     None => println!("Impossible to get your home dir!")
 /// }
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")]
-#[allow(deprecated)]
 #[unstable(feature = "os")]
+#[allow(deprecated)]
 pub fn homedir() -> Option<Path> {
     #[inline]
     #[cfg(unix)]
@@ -424,9 +448,8 @@ fn aux_homedir(home_name: &str) -> Option<Path> {
 /// 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.
-#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")]
-#[allow(deprecated)]
 #[unstable(feature = "os")]
+#[allow(deprecated)]
 pub fn tmpdir() -> Path {
     return lookup();
 
@@ -488,7 +511,8 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
     if p.is_absolute() {
         Ok(p.clone())
     } else {
-        env::current_dir().map(|mut cwd| {
+        env::current_dir().map_err(err2old).map(|cwd| {
+            let mut cwd = path2old(&cwd);
             cwd.push(p);
             cwd
         })
@@ -507,10 +531,9 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
 /// assert!(os::change_dir(&root).is_ok());
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")]
 #[unstable(feature = "os")]
 pub fn change_dir(p: &Path) -> IoResult<()> {
-    return sys::os::chdir(p);
+    sys::os::chdir(&path2new(p)).map_err(err2old)
 }
 
 /// Returns the platform-specific value of errno
@@ -595,7 +618,7 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
 // res
 #[cfg(target_os = "ios")]
 fn real_args_as_bytes() -> Vec<Vec<u8>> {
-    use ffi::c_str_to_bytes;
+    use ffi::CStr;
     use iter::range;
     use mem;
 
@@ -630,7 +653,7 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
             let tmp = objc_msgSend(args, objectAtSel, i);
             let utf_c_str: *const libc::c_char =
                 mem::transmute(objc_msgSend(tmp, utf8Sel));
-            res.push(c_str_to_bytes(&utf_c_str).to_vec());
+            res.push(CStr::from_ptr(utf_c_str).to_bytes().to_vec());
         }
     }
 
@@ -641,6 +664,7 @@ fn real_args_as_bytes() -> Vec<Vec<u8>> {
           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;
@@ -1289,6 +1313,39 @@ pub mod consts {
     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")]
index 49a5efec7c2e48095a9bdc282b5274d7b24a5410..b85a0dcec81805cb0a844a926531e5b2501c15dd 100755 (executable)
 use core::prelude::*;
 
 use ascii::*;
-use borrow::{Borrow, ToOwned, Cow};
+use borrow::{Borrow, IntoCow, ToOwned, Cow};
 use cmp;
 use iter::{self, IntoIterator};
 use mem;
@@ -987,6 +987,18 @@ fn borrow(&self) -> &Path {
     }
 }
 
+impl IntoCow<'static, Path> for PathBuf {
+    fn into_cow(self) -> Cow<'static, Path> {
+        Cow::Owned(self)
+    }
+}
+
+impl<'a> IntoCow<'a, Path> for &'a Path {
+    fn into_cow(self) -> Cow<'a, Path> {
+        Cow::Borrowed(self)
+    }
+}
+
 impl ToOwned for Path {
     type Owned = PathBuf;
     fn to_owned(&self) -> PathBuf { self.to_path_buf() }
@@ -1324,7 +1336,6 @@ fn as_path(&self) -> &Path { Path::new(self.as_os_str()) }
 #[cfg(test)]
 mod tests {
     use super::*;
-    use ffi::OsStr;
     use core::prelude::*;
     use string::{ToString, String};
     use vec::Vec;
@@ -1412,6 +1423,26 @@ macro_rules! t(
         );
     );
 
+    #[test]
+    fn into_cow() {
+        use borrow::{Cow, IntoCow};
+
+        let static_path = Path::new("/home/foo");
+        let static_cow_path: Cow<'static, Path> = static_path.into_cow();
+        let pathbuf = PathBuf::new("/home/foo");
+
+        {
+            let path: &Path = &pathbuf;
+            let borrowed_cow_path: Cow<Path> = path.into_cow();
+
+            assert_eq!(static_cow_path, borrowed_cow_path);
+        }
+
+        let owned_cow_path: Cow<'static, Path> = pathbuf.into_cow();
+
+        assert_eq!(static_cow_path, owned_cow_path);
+    }
+
     #[test]
     #[cfg(unix)]
     pub fn test_decompositions_unix() {
index d2dc33451200f5f866973f03939eecf2523613c5..dad0ff0a15e299424d265b076d15f20f229c525b 100644 (file)
@@ -23,7 +23,6 @@
 #[doc(no_inline)] pub use mem::drop;
 
 // Reexported types and traits
-
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use boxed::Box;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -45,9 +44,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use result::Result::{self, Ok, Err};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use slice::AsSlice;
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt};
+#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt, AsSlice};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use str::{Str, StrExt};
 #[stable(feature = "rust1", since = "1.0.0")]
index 5baa095d35985c7b44aed14c10f4d49359f113ce..c24b08deec2dc482d8395a7038214f22fc7762c9 100644 (file)
@@ -355,11 +355,11 @@ impl Stdio {
     pub fn capture() -> Stdio { Stdio(StdioImp::Capture) }
 
     /// The child inherits from the corresponding parent descriptor.
-    pub fn inherit() -> Stdio { Stdio(StdioImp::Capture) }
+    pub fn inherit() -> Stdio { Stdio(StdioImp::Inherit) }
 
     /// This stream will be ignored. This is the equivalent of attaching the
     /// stream to `/dev/null`
-    pub fn null() -> Stdio { Stdio(StdioImp::Capture) }
+    pub fn null() -> Stdio { Stdio(StdioImp::Null) }
 }
 
 /// Describes the result of a process after it has terminated.
@@ -489,18 +489,14 @@ fn read<T: Read + Send + 'static>(stream: Option<T>) -> Receiver<io::Result<Vec<
 mod tests {
     use io::ErrorKind;
     use io::prelude::*;
-    use prelude::v1::{Ok, Err, range, drop, Some, None, Vec};
+    use prelude::v1::{Ok, Err, drop, Some, Vec};
     use prelude::v1::{String, Clone};
     use prelude::v1::{SliceExt, Str, StrExt, AsSlice, ToString, GenericPath};
-    use path::Path;
     use old_path;
     use old_io::fs::PathExtensions;
     use rt::running_on_valgrind;
     use str;
-    use super::{Child, Command, Output, ExitStatus, Stdio};
-    use sync::mpsc::channel;
-    use thread;
-    use time::Duration;
+    use super::{Command, Output, Stdio};
 
     // FIXME(#10380) these tests should not all be ignored on android.
 
index 0e2766f3889441331b0ec73c3ecad0ddfb25c8ca..1a13405633d2ede6f2218e4caa596c67baf7d4e1 100644 (file)
@@ -188,7 +188,6 @@ mod imp {
     extern crate libc;
 
     use old_io::{IoResult};
-    use marker::Sync;
     use mem;
     use os;
     use rand::Rng;
@@ -214,10 +213,8 @@ pub struct OsRng {
     #[repr(C)]
     struct SecRandom;
 
-    unsafe impl Sync for *const SecRandom {}
-
     #[allow(non_upper_case_globals)]
-    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
+    const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
 
     #[link(name = "Security", kind = "framework")]
     extern "C" {
index 61f5bd0f013606f37f2e4476acf3b155c5f7f6af..9da63405346e8470af85431ab163989ae475c499 100644 (file)
@@ -43,6 +43,7 @@ pub fn clone() -> Option<Vec<Vec<u8>>> { imp::clone() }
           target_os = "android",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 mod imp {
     use prelude::v1::*;
index 72486fc55d48ee91ef09c3e4a73b3908c9d395d0..08755ba829f8f9af3958b4a18ff1fb2d31bfda23 100644 (file)
@@ -14,9 +14,9 @@
 
 use core::prelude::*;
 
+use boxed;
 use boxed::Box;
 use vec::Vec;
-use mem;
 use thunk::Thunk;
 use sys_common::mutex::{Mutex, MUTEX_INIT};
 
@@ -32,7 +32,7 @@
 unsafe fn init() {
     if QUEUE.is_null() {
         let state: Box<Queue> = box Vec::new();
-        QUEUE = mem::transmute(state);
+        QUEUE = boxed::into_raw(state);
     } else {
         // can't re-init after a cleanup
         rtassert!(QUEUE as uint != 1);
@@ -57,7 +57,7 @@ pub fn cleanup() {
 
         // If we never called init, not need to cleanup!
         if queue as uint != 0 {
-            let queue: Box<Queue> = mem::transmute(queue);
+            let queue: Box<Queue> = Box::from_raw(queue);
             for to_run in *queue {
                 to_run.invoke(());
             }
index 43e3a43f56d3632ce38017ebf3df9511aed42709..3063d9d942a28c3c3a8edd3b23ec2f1c431dadf4 100644 (file)
@@ -109,6 +109,10 @@ pub enum _Unwind_Context {}
 #[link(name = "gcc_pic")]
 extern {}
 
+#[cfg(target_os = "bitrig")]
+#[link(name = "c++abi")]
+extern {}
+
 extern "C" {
     // iOS on armv7 uses SjLj exceptions and requires to link
     // against corresponding routine (..._SjLj_...)
index 1f5eb3af695be8e09040c92463db3ce950031e97..4dda3ea8c998800e94cde11c237296ab2ee502da 100644 (file)
@@ -60,6 +60,7 @@
 use prelude::v1::*;
 
 use any::Any;
+use boxed;
 use cell::Cell;
 use cmp;
 use panicking;
@@ -173,7 +174,8 @@ fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
             },
             cause: Some(cause),
         };
-        let error = uw::_Unwind_RaiseException(mem::transmute(exception));
+        let exception_param = boxed::into_raw(exception) as *mut uw::_Unwind_Exception;
+        let error = uw::_Unwind_RaiseException(exception_param);
         rtabort!("Could not unwind stack, error = {}", error as int)
     }
 
@@ -181,7 +183,7 @@ fn rust_panic(cause: Box<Any + Send + 'static>) -> ! {
                                 exception: *mut uw::_Unwind_Exception) {
         rtdebug!("exception_cleanup()");
         unsafe {
-            let _: Box<Exception> = mem::transmute(exception);
+            let _: Box<Exception> = Box::from_raw(exception as *mut Exception);
         }
     }
 }
index 1392bc815c4f9d68d31a93aa47ae87e3a72af478..96c4bcec853dc28d8d687eae95b3b1e64f9f5a22 100644 (file)
@@ -39,7 +39,9 @@
 #[link(name = "pthread")]
 extern {}
 
-#[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
+#[cfg(any(target_os = "dragonfly",
+          target_os = "bitrig",
+          target_os = "openbsd"))]
 #[link(name = "pthread")]
 extern {}
 
index b036177af153a50da6ff9f4951ae7ea69d4cdffa..f697d10d5dfab14ad5f85ee1db0a45569f89fc52 100644 (file)
 pub struct Barrier {
     lock: Mutex<BarrierState>,
     cvar: Condvar,
-    num_threads: uint,
+    num_threads: usize,
 }
 
 // The inner state of a double barrier
 struct BarrierState {
-    count: uint,
-    generation_id: uint,
+    count: usize,
+    generation_id: usize,
 }
 
 /// A result returned from wait.
@@ -54,7 +54,7 @@ impl Barrier {
     /// A barrier will block `n`-1 threads which call `wait` and then wake up
     /// all threads at once when the `n`th thread calls `wait`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(n: uint) -> Barrier {
+    pub fn new(n: usize) -> Barrier {
         Barrier {
             lock: Mutex::new(BarrierState {
                 count: 0,
@@ -115,7 +115,7 @@ mod tests {
 
     #[test]
     fn test_barrier() {
-        const N: uint = 10;
+        const N: usize = 10;
 
         let barrier = Arc::new(Barrier::new(N));
         let (tx, rx) = channel();
index 52561d482c39dcc4b5acf9a05de030865870b91d..e7ee9bd2066514f4e47a04b3bf2eb102de874fc6 100644 (file)
@@ -61,9 +61,6 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Condvar { inner: Box<StaticCondvar> }
 
-unsafe impl Send for Condvar {}
-unsafe impl Sync for Condvar {}
-
 /// Statically allocated condition variables.
 ///
 /// This structure is identical to `Condvar` except that it is suitable for use
@@ -83,9 +80,6 @@ pub struct StaticCondvar {
     mutex: AtomicUsize,
 }
 
-unsafe impl Send for StaticCondvar {}
-unsafe impl Sync for StaticCondvar {}
-
 /// Constant initializer for a statically allocated condition variable.
 #[unstable(feature = "std_misc",
            reason = "may be merged with Condvar in the future")]
@@ -327,7 +321,7 @@ pub unsafe fn destroy(&'static self) {
     }
 
     fn verify(&self, mutex: &sys_mutex::Mutex) {
-        let addr = mutex as *const _ as uint;
+        let addr = mutex as *const _ as usize;
         match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
             // If we got out 0, then we have successfully bound the mutex to
             // this cvar.
@@ -388,7 +382,7 @@ fn notify_one() {
 
     #[test]
     fn notify_all() {
-        const N: uint = 10;
+        const N: usize = 10;
 
         let data = Arc::new((Mutex::new(0), Condvar::new()));
         let (tx, rx) = channel();
index f3b721438d807a2872f2fa706e441ebc2df3a3f2..68137601c405c84876ee746a0b8d302300cd2b03 100644 (file)
@@ -31,6 +31,7 @@
 pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
 
 pub use self::future::Future;
+#[allow(deprecated)]
 pub use self::task_pool::TaskPool;
 
 pub mod mpsc;
index 69b1e242b154d472857c032aab0ff00cdec3366c..2e4155ea35128d070c7854e304a40b58a30a87ac 100644 (file)
@@ -61,17 +61,17 @@ pub fn signal(&self) -> bool {
         wake
     }
 
-    /// Convert to an unsafe uint value. Useful for storing in a pipe's state
+    /// Convert to an unsafe usize value. Useful for storing in a pipe's state
     /// flag.
     #[inline]
-    pub unsafe fn cast_to_uint(self) -> uint {
+    pub unsafe fn cast_to_usize(self) -> usize {
         mem::transmute(self.inner)
     }
 
-    /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
+    /// Convert from an unsafe usize value. Useful for retrieving a pipe's state
     /// flag.
     #[inline]
-    pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
+    pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken {
         SignalToken { inner: mem::transmute(signal_ptr) }
     }
 
index 21993e51669d359789f04767c4911391c36350cb..7bd1f3542eb13828ca4a2806e53a623bc8c68e45 100644 (file)
@@ -94,7 +94,7 @@
 //!
 //! // The call to recv() will return an error because the channel has already
 //! // hung up (or been deallocated)
-//! let (tx, rx) = channel::<int>();
+//! let (tx, rx) = channel::<i32>();
 //! drop(tx);
 //! assert!(rx.recv().is_err());
 //! ```
 //! use std::thread;
 //! use std::sync::mpsc::sync_channel;
 //!
-//! let (tx, rx) = sync_channel::<int>(0);
+//! let (tx, rx) = sync_channel::<i32>(0);
 //! thread::spawn(move|| {
 //!     // This will wait for the parent task to start receiving
 //!     tx.send(53).unwrap();
 //! use std::old_io::timer::Timer;
 //! use std::time::Duration;
 //!
-//! let (tx, rx) = channel::<int>();
+//! let (tx, rx) = channel::<i32>();
 //! let mut timer = Timer::new().unwrap();
 //! let timeout = timer.oneshot(Duration::seconds(10));
 //!
 //! use std::old_io::timer::Timer;
 //! use std::time::Duration;
 //!
-//! let (tx, rx) = channel::<int>();
+//! let (tx, rx) = channel::<i32>();
 //! let mut timer = Timer::new().unwrap();
 //!
 //! loop {
@@ -345,7 +345,7 @@ pub struct Receiver<T> {
 
 // The receiver port can be sent from place to place, so long as it
 // is not used to receive non-sendable things.
-unsafe impl<T: Send + 'static> Send for Receiver<T> { }
+unsafe impl<T: Send> Send for Receiver<T> { }
 
 /// An iterator over messages on a receiver, this iterator will block
 /// whenever `next` is called, waiting for a new message, and `None` will be
@@ -364,7 +364,7 @@ pub struct Sender<T> {
 
 // The send port can be sent from place to place, so long as it
 // is not used to send non-sendable things.
-unsafe impl<T: Send + 'static> Send for Sender<T> { }
+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.
@@ -373,7 +373,7 @@ pub struct SyncSender<T> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
 }
 
-unsafe impl<T: Send + 'static> Send for SyncSender<T> {}
+unsafe impl<T: Send> Send for SyncSender<T> {}
 
 impl<T> !Sync for SyncSender<T> {}
 
@@ -485,7 +485,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 + 'static>() -> (Sender<T>, Receiver<T>) {
+pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
     (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
 }
@@ -525,7 +525,7 @@ pub fn channel<T: Send + 'static>() -> (Sender<T>, Receiver<T>) {
 /// assert_eq!(rx.recv().unwrap(), 2);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn sync_channel<T: Send + 'static>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
+pub fn sync_channel<T: Send>(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)))
 }
@@ -534,7 +534,7 @@ pub fn sync_channel<T: Send + 'static>(bound: uint) -> (SyncSender<T>, Receiver<
 // Sender
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send + 'static> Sender<T> {
+impl<T: Send> Sender<T> {
     fn new(inner: Flavor<T>) -> Sender<T> {
         Sender {
             inner: UnsafeCell::new(inner),
@@ -616,7 +616,7 @@ pub fn send(&self, t: T) -> Result<(), SendError<T>> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Clone for Sender<T> {
+impl<T: Send> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
         let (packet, sleeper, guard) = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
@@ -662,7 +662,7 @@ fn clone(&self) -> Sender<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Sender<T> {
+impl<T: Send> Drop for Sender<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
             Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
@@ -677,7 +677,7 @@ fn drop(&mut self) {
 // SyncSender
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send + 'static> SyncSender<T> {
+impl<T: Send> SyncSender<T> {
     fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
         SyncSender { inner: inner }
     }
@@ -717,7 +717,7 @@ pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Clone for SyncSender<T> {
+impl<T: Send> Clone for SyncSender<T> {
     fn clone(&self) -> SyncSender<T> {
         unsafe { (*self.inner.get()).clone_chan(); }
         return SyncSender::new(self.inner.clone());
@@ -726,7 +726,7 @@ fn clone(&self) -> SyncSender<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for SyncSender<T> {
+impl<T: Send> Drop for SyncSender<T> {
     fn drop(&mut self) {
         unsafe { (*self.inner.get()).drop_chan(); }
     }
@@ -736,7 +736,7 @@ fn drop(&mut self) {
 // Receiver
 ////////////////////////////////////////////////////////////////////////////////
 
-impl<T: Send + 'static> Receiver<T> {
+impl<T: Send> Receiver<T> {
     fn new(inner: Flavor<T>) -> Receiver<T> {
         Receiver { inner: UnsafeCell::new(inner) }
     }
@@ -855,7 +855,7 @@ pub fn iter(&self) -> Iter<T> {
     }
 }
 
-impl<T: Send + 'static> select::Packet for Receiver<T> {
+impl<T: Send> select::Packet for Receiver<T> {
     fn can_recv(&self) -> bool {
         loop {
             let new_port = match *unsafe { self.inner() } {
@@ -942,7 +942,7 @@ fn abort_selection(&self) -> bool {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: Send + 'static> Iterator for Iter<'a, T> {
+impl<'a, T: Send> Iterator for Iter<'a, T> {
     type Item = T;
 
     fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
@@ -950,7 +950,7 @@ fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Receiver<T> {
+impl<T: Send> Drop for Receiver<T> {
     fn drop(&mut self) {
         match *unsafe { self.inner_mut() } {
             Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
@@ -1028,7 +1028,7 @@ mod test {
     use super::*;
     use thread;
 
-    pub fn stress_factor() -> uint {
+    pub fn stress_factor() -> usize {
         match env::var("RUST_TEST_STRESS") {
             Ok(val) => val.parse().unwrap(),
             Err(..) => 1,
@@ -1037,7 +1037,7 @@ pub fn stress_factor() -> uint {
 
     #[test]
     fn smoke() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
     }
@@ -1058,7 +1058,7 @@ fn drop_full_shared() {
 
     #[test]
     fn smoke_shared() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
         let tx = tx.clone();
@@ -1068,7 +1068,7 @@ fn smoke_shared() {
 
     #[test]
     fn smoke_threads() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let _t = thread::spawn(move|| {
             tx.send(1).unwrap();
         });
@@ -1077,21 +1077,21 @@ fn smoke_threads() {
 
     #[test]
     fn smoke_port_gone() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         assert!(tx.send(1).is_err());
     }
 
     #[test]
     fn smoke_shared_port_gone() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         assert!(tx.send(1).is_err())
     }
 
     #[test]
     fn smoke_shared_port_gone2() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         let tx2 = tx.clone();
         drop(tx);
@@ -1100,7 +1100,7 @@ fn smoke_shared_port_gone2() {
 
     #[test]
     fn port_gone_concurrent() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
         });
@@ -1109,7 +1109,7 @@ fn port_gone_concurrent() {
 
     #[test]
     fn port_gone_concurrent_shared() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let tx2 = tx.clone();
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
@@ -1119,7 +1119,7 @@ fn port_gone_concurrent_shared() {
 
     #[test]
     fn smoke_chan_gone() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(tx);
         assert!(rx.recv().is_err());
     }
@@ -1135,7 +1135,7 @@ fn smoke_chan_gone_shared() {
 
     #[test]
     fn chan_gone_concurrent() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let _t = thread::spawn(move|| {
             tx.send(1).unwrap();
             tx.send(1).unwrap();
@@ -1145,7 +1145,7 @@ fn chan_gone_concurrent() {
 
     #[test]
     fn stress() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let t = thread::spawn(move|| {
             for _ in 0..10000 { tx.send(1).unwrap(); }
         });
@@ -1157,9 +1157,9 @@ fn stress() {
 
     #[test]
     fn stress_shared() {
-        static AMT: uint = 10000;
-        static NTHREADS: uint = 8;
-        let (tx, rx) = channel::<int>();
+        static AMT: u32 = 10000;
+        static NTHREADS: u32 = 8;
+        let (tx, rx) = channel::<i32>();
 
         let t = thread::spawn(move|| {
             for _ in 0..AMT * NTHREADS {
@@ -1184,7 +1184,7 @@ fn stress_shared() {
     #[test]
     fn send_from_outside_runtime() {
         let (tx1, rx1) = channel::<()>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx2, rx2) = channel::<i32>();
         let t1 = thread::spawn(move|| {
             tx1.send(()).unwrap();
             for _ in 0..40 {
@@ -1203,7 +1203,7 @@ fn send_from_outside_runtime() {
 
     #[test]
     fn recv_from_outside_runtime() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let t = thread::spawn(move|| {
             for _ in 0..40 {
                 assert_eq!(rx.recv().unwrap(), 1);
@@ -1217,8 +1217,8 @@ fn recv_from_outside_runtime() {
 
     #[test]
     fn no_runtime() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         let t1 = thread::spawn(move|| {
             assert_eq!(rx1.recv().unwrap(), 1);
             tx2.send(2).unwrap();
@@ -1234,21 +1234,21 @@ fn no_runtime() {
     #[test]
     fn oneshot_single_thread_close_port_first() {
         // Simple test of closing without sending
-        let (_tx, rx) = channel::<int>();
+        let (_tx, rx) = channel::<i32>();
         drop(rx);
     }
 
     #[test]
     fn oneshot_single_thread_close_chan_first() {
         // Simple test of closing without sending
-        let (tx, _rx) = channel::<int>();
+        let (tx, _rx) = channel::<i32>();
         drop(tx);
     }
 
     #[test]
     fn oneshot_single_thread_send_port_close() {
         // Testing that the sender cleans up the payload if receiver is closed
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         drop(rx);
         assert!(tx.send(box 0).is_err());
     }
@@ -1257,7 +1257,7 @@ fn oneshot_single_thread_send_port_close() {
     fn oneshot_single_thread_recv_chan_close() {
         // Receiving on a closed chan will panic
         let res = thread::spawn(move|| {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             drop(tx);
             rx.recv().unwrap();
         }).join();
@@ -1267,42 +1267,42 @@ fn oneshot_single_thread_recv_chan_close() {
 
     #[test]
     fn oneshot_single_thread_send_then_recv() {
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         tx.send(box 10).unwrap();
         assert!(rx.recv().unwrap() == box 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_open() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         assert!(tx.send(10).is_ok());
         assert!(rx.recv().unwrap() == 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_closed() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         assert!(tx.send(10).is_err());
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_open() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         tx.send(10).unwrap();
         assert!(rx.recv() == Ok(10));
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_closed() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(tx);
         assert!(rx.recv().is_err());
     }
 
     #[test]
     fn oneshot_single_thread_peek_data() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
         tx.send(10).unwrap();
         assert_eq!(rx.try_recv(), Ok(10));
@@ -1310,7 +1310,7 @@ fn oneshot_single_thread_peek_data() {
 
     #[test]
     fn oneshot_single_thread_peek_close() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(tx);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
@@ -1318,13 +1318,13 @@ fn oneshot_single_thread_peek_close() {
 
     #[test]
     fn oneshot_single_thread_peek_open() {
-        let (_tx, rx) = channel::<int>();
+        let (_tx, rx) = channel::<i32>();
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
     }
 
     #[test]
     fn oneshot_multi_task_recv_then_send() {
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         let _t = thread::spawn(move|| {
             assert!(rx.recv().unwrap() == box 10);
         });
@@ -1334,7 +1334,7 @@ fn oneshot_multi_task_recv_then_send() {
 
     #[test]
     fn oneshot_multi_task_recv_then_close() {
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         let _t = thread::spawn(move|| {
             drop(tx);
         });
@@ -1347,7 +1347,7 @@ fn oneshot_multi_task_recv_then_close() {
     #[test]
     fn oneshot_multi_thread_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1358,7 +1358,7 @@ fn oneshot_multi_thread_close_stress() {
     #[test]
     fn oneshot_multi_thread_send_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1371,7 +1371,7 @@ fn oneshot_multi_thread_send_close_stress() {
     #[test]
     fn oneshot_multi_thread_recv_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             thread::spawn(move|| {
                 let res = thread::spawn(move|| {
                     rx.recv().unwrap();
@@ -1405,7 +1405,7 @@ fn stream_send_recv_stress() {
             send(tx, 0);
             recv(rx, 0);
 
-            fn send(tx: Sender<Box<int>>, i: int) {
+            fn send(tx: Sender<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1414,7 +1414,7 @@ fn send(tx: Sender<Box<int>>, i: int) {
                 });
             }
 
-            fn recv(rx: Receiver<Box<int>>, i: int) {
+            fn recv(rx: Receiver<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1451,8 +1451,8 @@ fn shared_chan_stress() {
 
     #[test]
     fn test_nested_recv_iter() {
-        let (tx, rx) = channel::<int>();
-        let (total_tx, total_rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
+        let (total_tx, total_rx) = channel::<i32>();
 
         let _t = thread::spawn(move|| {
             let mut acc = 0;
@@ -1471,7 +1471,7 @@ fn test_nested_recv_iter() {
 
     #[test]
     fn test_recv_iter_break() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let (count_tx, count_rx) = channel();
 
         let _t = thread::spawn(move|| {
@@ -1496,7 +1496,7 @@ fn test_recv_iter_break() {
 
     #[test]
     fn try_recv_states() {
-        let (tx1, rx1) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
         let (tx2, rx2) = channel::<()>();
         let (tx3, rx3) = channel::<()>();
         let _t = thread::spawn(move|| {
@@ -1550,7 +1550,7 @@ mod sync_tests {
     use thread;
     use super::*;
 
-    pub fn stress_factor() -> uint {
+    pub fn stress_factor() -> usize {
         match env::var("RUST_TEST_STRESS") {
             Ok(val) => val.parse().unwrap(),
             Err(..) => 1,
@@ -1559,7 +1559,7 @@ pub fn stress_factor() -> uint {
 
     #[test]
     fn smoke() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
     }
@@ -1572,7 +1572,7 @@ fn drop_full() {
 
     #[test]
     fn smoke_shared() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
         let tx = tx.clone();
@@ -1582,7 +1582,7 @@ fn smoke_shared() {
 
     #[test]
     fn smoke_threads() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| {
             tx.send(1).unwrap();
         });
@@ -1591,14 +1591,14 @@ fn smoke_threads() {
 
     #[test]
     fn smoke_port_gone() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(rx);
         assert!(tx.send(1).is_err());
     }
 
     #[test]
     fn smoke_shared_port_gone2() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(rx);
         let tx2 = tx.clone();
         drop(tx);
@@ -1607,7 +1607,7 @@ fn smoke_shared_port_gone2() {
 
     #[test]
     fn port_gone_concurrent() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
         });
@@ -1616,7 +1616,7 @@ fn port_gone_concurrent() {
 
     #[test]
     fn port_gone_concurrent_shared() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let tx2 = tx.clone();
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
@@ -1626,7 +1626,7 @@ fn port_gone_concurrent_shared() {
 
     #[test]
     fn smoke_chan_gone() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(tx);
         assert!(rx.recv().is_err());
     }
@@ -1642,7 +1642,7 @@ fn smoke_chan_gone_shared() {
 
     #[test]
     fn chan_gone_concurrent() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         thread::spawn(move|| {
             tx.send(1).unwrap();
             tx.send(1).unwrap();
@@ -1652,7 +1652,7 @@ fn chan_gone_concurrent() {
 
     #[test]
     fn stress() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         thread::spawn(move|| {
             for _ in 0..10000 { tx.send(1).unwrap(); }
         });
@@ -1663,9 +1663,9 @@ fn stress() {
 
     #[test]
     fn stress_shared() {
-        static AMT: uint = 1000;
-        static NTHREADS: uint = 8;
-        let (tx, rx) = sync_channel::<int>(0);
+        static AMT: u32 = 1000;
+        static NTHREADS: u32 = 8;
+        let (tx, rx) = sync_channel::<i32>(0);
         let (dtx, drx) = sync_channel::<()>(0);
 
         thread::spawn(move|| {
@@ -1692,21 +1692,21 @@ fn stress_shared() {
     #[test]
     fn oneshot_single_thread_close_port_first() {
         // Simple test of closing without sending
-        let (_tx, rx) = sync_channel::<int>(0);
+        let (_tx, rx) = sync_channel::<i32>(0);
         drop(rx);
     }
 
     #[test]
     fn oneshot_single_thread_close_chan_first() {
         // Simple test of closing without sending
-        let (tx, _rx) = sync_channel::<int>(0);
+        let (tx, _rx) = sync_channel::<i32>(0);
         drop(tx);
     }
 
     #[test]
     fn oneshot_single_thread_send_port_close() {
         // Testing that the sender cleans up the payload if receiver is closed
-        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let (tx, rx) = sync_channel::<Box<i32>>(0);
         drop(rx);
         assert!(tx.send(box 0).is_err());
     }
@@ -1715,7 +1715,7 @@ fn oneshot_single_thread_send_port_close() {
     fn oneshot_single_thread_recv_chan_close() {
         // Receiving on a closed chan will panic
         let res = thread::spawn(move|| {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             drop(tx);
             rx.recv().unwrap();
         }).join();
@@ -1725,48 +1725,48 @@ fn oneshot_single_thread_recv_chan_close() {
 
     #[test]
     fn oneshot_single_thread_send_then_recv() {
-        let (tx, rx) = sync_channel::<Box<int>>(1);
+        let (tx, rx) = sync_channel::<Box<i32>>(1);
         tx.send(box 10).unwrap();
         assert!(rx.recv().unwrap() == box 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_open() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(tx.try_send(10), Ok(()));
         assert!(rx.recv().unwrap() == 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_closed() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(rx);
         assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10)));
     }
 
     #[test]
     fn oneshot_single_thread_try_send_closed2() {
-        let (tx, _rx) = sync_channel::<int>(0);
+        let (tx, _rx) = sync_channel::<i32>(0);
         assert_eq!(tx.try_send(10), Err(TrySendError::Full(10)));
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_open() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(10).unwrap();
         assert!(rx.recv() == Ok(10));
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_closed() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(tx);
         assert!(rx.recv().is_err());
     }
 
     #[test]
     fn oneshot_single_thread_peek_data() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
         tx.send(10).unwrap();
         assert_eq!(rx.try_recv(), Ok(10));
@@ -1774,7 +1774,7 @@ fn oneshot_single_thread_peek_data() {
 
     #[test]
     fn oneshot_single_thread_peek_close() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(tx);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
@@ -1782,13 +1782,13 @@ fn oneshot_single_thread_peek_close() {
 
     #[test]
     fn oneshot_single_thread_peek_open() {
-        let (_tx, rx) = sync_channel::<int>(0);
+        let (_tx, rx) = sync_channel::<i32>(0);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
     }
 
     #[test]
     fn oneshot_multi_task_recv_then_send() {
-        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let (tx, rx) = sync_channel::<Box<i32>>(0);
         let _t = thread::spawn(move|| {
             assert!(rx.recv().unwrap() == box 10);
         });
@@ -1798,7 +1798,7 @@ fn oneshot_multi_task_recv_then_send() {
 
     #[test]
     fn oneshot_multi_task_recv_then_close() {
-        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let (tx, rx) = sync_channel::<Box<i32>>(0);
         let _t = thread::spawn(move|| {
             drop(tx);
         });
@@ -1811,7 +1811,7 @@ fn oneshot_multi_task_recv_then_close() {
     #[test]
     fn oneshot_multi_thread_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1822,7 +1822,7 @@ fn oneshot_multi_thread_close_stress() {
     #[test]
     fn oneshot_multi_thread_send_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1835,7 +1835,7 @@ fn oneshot_multi_thread_send_close_stress() {
     #[test]
     fn oneshot_multi_thread_recv_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             let _t = thread::spawn(move|| {
                 let res = thread::spawn(move|| {
                     rx.recv().unwrap();
@@ -1853,7 +1853,7 @@ fn oneshot_multi_thread_recv_close_stress() {
     #[test]
     fn oneshot_multi_thread_send_recv_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<Box<int>>(0);
+            let (tx, rx) = sync_channel::<Box<i32>>(0);
             let _t = thread::spawn(move|| {
                 tx.send(box 10).unwrap();
             });
@@ -1864,12 +1864,12 @@ fn oneshot_multi_thread_send_recv_stress() {
     #[test]
     fn stream_send_recv_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<Box<int>>(0);
+            let (tx, rx) = sync_channel::<Box<i32>>(0);
 
             send(tx, 0);
             recv(rx, 0);
 
-            fn send(tx: SyncSender<Box<int>>, i: int) {
+            fn send(tx: SyncSender<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1878,7 +1878,7 @@ fn send(tx: SyncSender<Box<int>>, i: int) {
                 });
             }
 
-            fn recv(rx: Receiver<Box<int>>, i: int) {
+            fn recv(rx: Receiver<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1915,8 +1915,8 @@ fn shared_chan_stress() {
 
     #[test]
     fn test_nested_recv_iter() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let (total_tx, total_rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
+        let (total_tx, total_rx) = sync_channel::<i32>(0);
 
         let _t = thread::spawn(move|| {
             let mut acc = 0;
@@ -1935,7 +1935,7 @@ fn test_nested_recv_iter() {
 
     #[test]
     fn test_recv_iter_break() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let (count_tx, count_rx) = sync_channel(0);
 
         let _t = thread::spawn(move|| {
@@ -1960,7 +1960,7 @@ fn test_recv_iter_break() {
 
     #[test]
     fn try_recv_states() {
-        let (tx1, rx1) = sync_channel::<int>(1);
+        let (tx1, rx1) = sync_channel::<i32>(1);
         let (tx2, rx2) = sync_channel::<()>(1);
         let (tx3, rx3) = sync_channel::<()>(1);
         let _t = thread::spawn(move|| {
@@ -2007,21 +2007,21 @@ fn destroy_upgraded_shared_port_when_sender_still_active() {
 
     #[test]
     fn send1() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| { rx.recv().unwrap(); });
         assert_eq!(tx.send(1), Ok(()));
     }
 
     #[test]
     fn send2() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| { drop(rx); });
         assert!(tx.send(1).is_err());
     }
 
     #[test]
     fn send3() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(tx.send(1), Ok(()));
         let _t =thread::spawn(move|| { drop(rx); });
         assert!(tx.send(1).is_err());
@@ -2029,7 +2029,7 @@ fn send3() {
 
     #[test]
     fn send4() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let tx2 = tx.clone();
         let (done, donerx) = channel();
         let done2 = done.clone();
@@ -2048,20 +2048,20 @@ fn send4() {
 
     #[test]
     fn try_send1() {
-        let (tx, _rx) = sync_channel::<int>(0);
+        let (tx, _rx) = sync_channel::<i32>(0);
         assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
     }
 
     #[test]
     fn try_send2() {
-        let (tx, _rx) = sync_channel::<int>(1);
+        let (tx, _rx) = sync_channel::<i32>(1);
         assert_eq!(tx.try_send(1), Ok(()));
         assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
     }
 
     #[test]
     fn try_send3() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(tx.try_send(1), Ok(()));
         drop(rx);
         assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1)));
index a2accb128c310c2298ca6c277bee6792ad57b57d..59fa2e6bc9a91c31dc28cc60f8e3ad8b0dfd9861 100644 (file)
@@ -44,8 +44,8 @@
 
 use core::prelude::*;
 
+use alloc::boxed;
 use alloc::boxed::Box;
-use core::mem;
 use core::ptr;
 use core::cell::UnsafeCell;
 
@@ -78,18 +78,18 @@ pub struct Queue<T> {
 }
 
 unsafe impl<T:Send> Send for Queue<T> { }
-unsafe impl<T: Send + 'static> Sync for Queue<T> { }
+unsafe impl<T: Send> Sync for Queue<T> { }
 
 impl<T> Node<T> {
     unsafe fn new(v: Option<T>) -> *mut Node<T> {
-        mem::transmute(box Node {
+        boxed::into_raw(box Node {
             next: AtomicPtr::new(ptr::null_mut()),
             value: v,
         })
     }
 }
 
-impl<T: Send + 'static> Queue<T> {
+impl<T: Send> Queue<T> {
     /// Creates a new queue that is safe to share among multiple producers and
     /// one consumer.
     pub fn new() -> Queue<T> {
@@ -129,7 +129,7 @@ pub fn pop(&self) -> PopResult<T> {
                 assert!((*tail).value.is_none());
                 assert!((*next).value.is_some());
                 let ret = (*next).value.take().unwrap();
-                let _: Box<Node<T>> = mem::transmute(tail);
+                let _: Box<Node<T>> = Box::from_raw(tail);
                 return Data(ret);
             }
 
@@ -140,13 +140,13 @@ pub fn pop(&self) -> PopResult<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Queue<T> {
+impl<T: Send> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
             let mut cur = *self.tail.get();
             while !cur.is_null() {
                 let next = (*cur).next.load(Ordering::Relaxed);
-                let _: Box<Node<T>> = mem::transmute(cur);
+                let _: Box<Node<T>> = Box::from_raw(cur);
                 cur = next;
             }
         }
index 55b2caf7c6d4cccea53aa2331ea3defaf0113524..f287712d9d45d59bdc2eb7745ed4ddd468092fe0 100644 (file)
@@ -22,7 +22,7 @@
 ///
 /// # Implementation
 ///
-/// Oneshots are implemented around one atomic uint variable. This variable
+/// Oneshots are implemented around one atomic usize variable. This variable
 /// indicates both the state of the port/chan but also contains any tasks
 /// blocked on the port. All atomic operations happen on this one word.
 ///
@@ -45,9 +45,9 @@
 use sync::atomic::{AtomicUsize, Ordering};
 
 // Various states you can find a port in.
-const EMPTY: uint = 0;          // initial state: no data, no blocked receiver
-const DATA: uint = 1;           // data ready for receiver to take
-const DISCONNECTED: uint = 2;   // channel is disconnected OR upgraded
+const EMPTY: usize = 0;          // initial state: no data, no blocked receiver
+const DATA: usize = 1;           // data ready for receiver to take
+const DISCONNECTED: usize = 2;   // channel is disconnected OR upgraded
 // Any other value represents a pointer to a SignalToken value. The
 // protocol ensures that when the state moves *to* a pointer,
 // ownership of the token is given to the packet, and when the state
@@ -88,7 +88,7 @@ enum MyUpgrade<T> {
     GoUp(Receiver<T>),
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
             data: None,
@@ -123,7 +123,7 @@ pub fn send(&mut self, t: T) -> Result<(), T> {
             // There is a thread waiting on the other end. We leave the 'DATA'
             // state inside so it'll pick it up on the other end.
             ptr => unsafe {
-                SignalToken::cast_from_uint(ptr).signal();
+                SignalToken::cast_from_usize(ptr).signal();
                 Ok(())
             }
         }
@@ -143,7 +143,7 @@ pub fn recv(&mut self) -> Result<T, Failure<T>> {
         // like we're not empty, then immediately go through to `try_recv`.
         if self.state.load(Ordering::SeqCst) == EMPTY {
             let (wait_token, signal_token) = blocking::tokens();
-            let ptr = unsafe { signal_token.cast_to_uint() };
+            let ptr = unsafe { signal_token.cast_to_usize() };
 
             // race with senders to enter the blocking state
             if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY {
@@ -151,7 +151,7 @@ pub fn recv(&mut self) -> Result<T, Failure<T>> {
                 debug_assert!(self.state.load(Ordering::SeqCst) != EMPTY);
             } else {
                 // drop the signal token, since we never blocked
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                drop(unsafe { SignalToken::cast_from_usize(ptr) });
             }
         }
 
@@ -220,7 +220,7 @@ pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
             DISCONNECTED => { self.upgrade = prev; UpDisconnected }
 
             // If someone's waiting, we gotta wake them up
-            ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) })
+            ptr => UpWoke(unsafe { SignalToken::cast_from_usize(ptr) })
         }
     }
 
@@ -230,7 +230,7 @@ pub fn drop_chan(&mut self) {
 
             // If someone's waiting, we gotta wake them up
             ptr => unsafe {
-                SignalToken::cast_from_uint(ptr).signal();
+                SignalToken::cast_from_usize(ptr).signal();
             }
         }
     }
@@ -283,15 +283,15 @@ pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
     // Attempts to start selection on this port. This can either succeed, fail
     // because there is data, or fail because there is an upgrade pending.
     pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
-        let ptr = unsafe { token.cast_to_uint() };
+        let ptr = unsafe { token.cast_to_usize() };
         match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
             EMPTY => SelSuccess,
             DATA => {
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                drop(unsafe { SignalToken::cast_from_usize(ptr) });
                 SelCanceled
             }
             DISCONNECTED if self.data.is_some() => {
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                drop(unsafe { SignalToken::cast_from_usize(ptr) });
                 SelCanceled
             }
             DISCONNECTED => {
@@ -300,7 +300,7 @@ pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
                     // propagate upwards whether the upgrade can receive
                     // data
                     GoUp(upgrade) => {
-                        SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade)
+                        SelUpgraded(unsafe { SignalToken::cast_from_usize(ptr) }, upgrade)
                     }
 
                     // If the other end disconnected without sending an
@@ -308,7 +308,7 @@ pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
                     // disconnected).
                     up => {
                         self.upgrade = up;
-                        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                        drop(unsafe { SignalToken::cast_from_usize(ptr) });
                         SelCanceled
                     }
                 }
@@ -360,7 +360,7 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
 
             // We woke ourselves up from select.
             ptr => unsafe {
-                drop(SignalToken::cast_from_uint(ptr));
+                drop(SignalToken::cast_from_usize(ptr));
                 Ok(false)
             }
         }
@@ -368,7 +368,7 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
     }
index 8fcedd2ab5796cbd0d955ec65c73257c01186a80..8de5bbc6206658c10d740bc67974e19edb00434f 100644 (file)
@@ -71,7 +71,7 @@
 pub struct Select {
     head: *mut Handle<'static, ()>,
     tail: *mut Handle<'static, ()>,
-    next_id: Cell<uint>,
+    next_id: Cell<usize>,
 }
 
 impl !marker::Send for Select {}
@@ -82,7 +82,7 @@ impl !marker::Send for Select {}
 pub struct Handle<'rx, T:'rx> {
     /// The ID of this handle, used to compare against the return value of
     /// `Select::wait()`
-    id: uint,
+    id: usize,
     selector: &'rx Select,
     next: *mut Handle<'static, ()>,
     prev: *mut Handle<'static, ()>,
@@ -134,7 +134,7 @@ pub fn new() -> Select {
     /// Creates a new handle into this receiver set for a new receiver. Note
     /// that this does *not* add the receiver to the receiver set, for that you
     /// must call the `add` method on the handle itself.
-    pub fn handle<'a, T: Send + 'static>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
+    pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
         let id = self.next_id.get();
         self.next_id.set(id + 1);
         Handle {
@@ -154,12 +154,12 @@ pub fn handle<'a, T: Send + 'static>(&'a self, rx: &'a Receiver<T>) -> Handle<'a
     /// the matching `id` will have some sort of event available on it. The
     /// event could either be that data is available or the corresponding
     /// channel has been closed.
-    pub fn wait(&self) -> uint {
+    pub fn wait(&self) -> usize {
         self.wait2(true)
     }
 
     /// Helper method for skipping the preflight checks during testing
-    fn wait2(&self, do_preflight_checks: bool) -> uint {
+    fn wait2(&self, do_preflight_checks: bool) -> usize {
         // Note that this is currently an inefficient implementation. We in
         // theory have knowledge about all receivers in the set ahead of time,
         // so this method shouldn't really have to iterate over all of them yet
@@ -251,10 +251,10 @@ fn wait2(&self, do_preflight_checks: bool) -> uint {
     fn iter(&self) -> Packets { Packets { cur: self.head } }
 }
 
-impl<'rx, T: Send + 'static> Handle<'rx, T> {
+impl<'rx, T: Send> Handle<'rx, T> {
     /// Retrieve the id of this handle.
     #[inline]
-    pub fn id(&self) -> uint { self.id }
+    pub fn id(&self) -> usize { self.id }
 
     /// Block to receive a value on the underlying receiver, returning `Some` on
     /// success or `None` if the channel disconnects. This function has the same
@@ -322,7 +322,7 @@ fn drop(&mut self) {
 }
 
 #[unsafe_destructor]
-impl<'rx, T: Send + 'static> Drop for Handle<'rx, T> {
+impl<'rx, T: Send> Drop for Handle<'rx, T> {
     fn drop(&mut self) {
         unsafe { self.remove() }
     }
@@ -369,8 +369,8 @@ macro_rules! select {
 
     #[test]
     fn smoke() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         tx1.send(1).unwrap();
         select! {
             foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); },
@@ -394,11 +394,11 @@ fn smoke() {
 
     #[test]
     fn smoke2() {
-        let (_tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (_tx3, rx3) = channel::<int>();
-        let (_tx4, rx4) = channel::<int>();
-        let (tx5, rx5) = channel::<int>();
+        let (_tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
+        let (_tx3, rx3) = channel::<i32>();
+        let (_tx4, rx4) = channel::<i32>();
+        let (tx5, rx5) = channel::<i32>();
         tx5.send(4).unwrap();
         select! {
             _foo = rx1.recv() => { panic!("1") },
@@ -411,8 +411,8 @@ fn smoke2() {
 
     #[test]
     fn closed() {
-        let (_tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (_tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         drop(tx2);
 
         select! {
@@ -423,9 +423,9 @@ fn closed() {
 
     #[test]
     fn unblocks() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
+        let (tx3, rx3) = channel::<i32>();
 
         let _t = thread::spawn(move|| {
             for _ in 0..20 { thread::yield_now(); }
@@ -447,8 +447,8 @@ fn unblocks() {
 
     #[test]
     fn both_ready() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -473,9 +473,9 @@ fn both_ready() {
 
     #[test]
     fn stress() {
-        static AMT: int = 10000;
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        static AMT: i32 = 10000;
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -500,8 +500,8 @@ fn stress() {
 
     #[test]
     fn cloning() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -522,8 +522,8 @@ fn cloning() {
 
     #[test]
     fn cloning2() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -716,7 +716,7 @@ fn shared_data_waiting() {
 
     #[test]
     fn sync1() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(1).unwrap();
         select! {
             n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
@@ -725,7 +725,7 @@ fn sync1() {
 
     #[test]
     fn sync2() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| {
             for _ in 0..100 { thread::yield_now() }
             tx.send(1).unwrap();
@@ -737,8 +737,8 @@ fn sync2() {
 
     #[test]
     fn sync3() {
-        let (tx1, rx1) = sync_channel::<int>(0);
-        let (tx2, rx2): (Sender<int>, Receiver<int>) = channel();
+        let (tx1, rx1) = sync_channel::<i32>(0);
+        let (tx2, rx2): (Sender<i32>, Receiver<i32>) = channel();
         let _t = thread::spawn(move|| { tx1.send(1).unwrap(); });
         let _t = thread::spawn(move|| { tx2.send(2).unwrap(); });
         select! {
index bc9c73585c21fe86ff9ec4e5630191f6330289e9..8d14824d37feed09e3e0c9916b2b2431b8897b4b 100644 (file)
@@ -64,7 +64,7 @@ pub enum Failure {
     Disconnected,
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> 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> {
@@ -101,7 +101,7 @@ pub fn inherit_blocker(&mut self,
         token.map(|token| {
             assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
             assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-            self.to_wake.store(unsafe { token.cast_to_uint() }, Ordering::SeqCst);
+            self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst);
             self.cnt.store(-1, Ordering::SeqCst);
 
             // This store is a little sketchy. What's happening here is that
@@ -241,7 +241,7 @@ pub fn recv(&mut self) -> Result<T, Failure> {
     // Returns true if blocking should proceed.
     fn decrement(&mut self, token: SignalToken) -> StartResult {
         assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_uint() };
+        let ptr = unsafe { token.cast_to_usize() };
         self.to_wake.store(ptr, Ordering::SeqCst);
 
         let steals = self.steals;
@@ -258,7 +258,7 @@ fn decrement(&mut self, token: SignalToken) -> StartResult {
         }
 
         self.to_wake.store(0, Ordering::SeqCst);
-        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+        drop(unsafe { SignalToken::cast_from_usize(ptr) });
         Abort
     }
 
@@ -380,7 +380,7 @@ fn take_to_wake(&mut self) -> SignalToken {
         let ptr = self.to_wake.load(Ordering::SeqCst);
         self.to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
-        unsafe { SignalToken::cast_from_uint(ptr) }
+        unsafe { SignalToken::cast_from_usize(ptr) }
     }
 
     ////////////////////////////////////////////////////////////////////////////
@@ -474,7 +474,7 @@ pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> 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 e1a897065092af2ca1485b6354a70c355561b78e..ce40fa2672ab32555339aca56e87deed24dbf4a9 100644 (file)
@@ -37,8 +37,8 @@
 
 use core::prelude::*;
 
+use alloc::boxed;
 use alloc::boxed::Box;
-use core::mem;
 use core::ptr;
 use core::cell::UnsafeCell;
 
@@ -69,19 +69,19 @@ pub struct Queue<T> {
 
     // Cache maintenance fields. Additions and subtractions are stored
     // separately in order to allow them to use nonatomic addition/subtraction.
-    cache_bound: uint,
+    cache_bound: usize,
     cache_additions: AtomicUsize,
     cache_subtractions: AtomicUsize,
 }
 
-unsafe impl<T: Send + 'static> Send for Queue<T> { }
+unsafe impl<T: Send> Send for Queue<T> { }
 
-unsafe impl<T: Send + 'static> Sync for Queue<T> { }
+unsafe impl<T: Send> Sync for Queue<T> { }
 
-impl<T: Send + 'static> Node<T> {
+impl<T: Send> Node<T> {
     fn new() -> *mut Node<T> {
         unsafe {
-            mem::transmute(box Node {
+            boxed::into_raw(box Node {
                 value: None,
                 next: AtomicPtr::new(ptr::null_mut::<Node<T>>()),
             })
@@ -89,7 +89,7 @@ fn new() -> *mut Node<T> {
     }
 }
 
-impl<T: Send + 'static> Queue<T> {
+impl<T: Send> Queue<T> {
     /// Creates a new queue.
     ///
     /// This is unsafe as the type system doesn't enforce a single
@@ -107,7 +107,7 @@ impl<T: Send + 'static> Queue<T> {
     ///               cache (if desired). If the value is 0, then the cache has
     ///               no bound. Otherwise, the cache will never grow larger than
     ///               `bound` (although the queue itself could be much larger.
-    pub unsafe fn new(bound: uint) -> Queue<T> {
+    pub unsafe fn new(bound: usize) -> Queue<T> {
         let n1 = Node::new();
         let n2 = Node::new();
         (*n1).next.store(n2, Ordering::Relaxed);
@@ -200,7 +200,7 @@ pub fn pop(&self) -> Option<T> {
                           .next.store(next, Ordering::Relaxed);
                     // We have successfully erased all references to 'tail', so
                     // now we can safely drop it.
-                    let _: Box<Node<T>> = mem::transmute(tail);
+                    let _: Box<Node<T>> = Box::from_raw(tail);
                 }
             }
             return ret;
@@ -227,13 +227,13 @@ pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Queue<T> {
+impl<T: Send> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
             let mut cur = *self.first.get();
             while !cur.is_null() {
                 let next = (*cur).next.load(Ordering::Relaxed);
-                let _n: Box<Node<T>> = mem::transmute(cur);
+                let _n: Box<Node<T>> = Box::from_raw(cur);
                 cur = next;
             }
         }
@@ -319,7 +319,7 @@ fn stress() {
             stress_bound(1);
         }
 
-        unsafe fn stress_bound(bound: uint) {
+        unsafe fn stress_bound(bound: usize) {
             let q = Arc::new(Queue::new(bound));
 
             let (tx, rx) = channel();
index a194c99669263e356e1ad1bf46f160a6c212f8cf..5a1e05f9c1565e1e28512f51685cc5b59849b20a 100644 (file)
@@ -43,7 +43,7 @@ pub struct Packet<T> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
     cnt: AtomicIsize, // How many items are on this channel
-    steals: int, // How many times has a port received without blocking?
+    steals: isize, // How many times has a port received without blocking?
     to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
 
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
@@ -74,7 +74,7 @@ enum Message<T> {
     GoUp(Receiver<T>),
 }
 
-impl<T: Send + 'static> Packet<T> {
+impl<T: Send> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
             queue: unsafe { spsc::Queue::new(128) },
@@ -146,7 +146,7 @@ fn take_to_wake(&mut self) -> SignalToken {
         let ptr = self.to_wake.load(Ordering::SeqCst);
         self.to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
-        unsafe { SignalToken::cast_from_uint(ptr) }
+        unsafe { SignalToken::cast_from_usize(ptr) }
     }
 
     // Decrements the count on the channel for a sleeper, returning the sleeper
@@ -154,7 +154,7 @@ fn take_to_wake(&mut self) -> SignalToken {
     // steals into account.
     fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
         assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_uint() };
+        let ptr = unsafe { token.cast_to_usize() };
         self.to_wake.store(ptr, Ordering::SeqCst);
 
         let steals = self.steals;
@@ -171,7 +171,7 @@ fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
         }
 
         self.to_wake.store(0, Ordering::SeqCst);
-        Err(unsafe { SignalToken::cast_from_uint(ptr) })
+        Err(unsafe { SignalToken::cast_from_usize(ptr) })
     }
 
     pub fn recv(&mut self) -> Result<T, Failure<T>> {
@@ -350,7 +350,7 @@ pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
     }
 
     // increment the count on the channel (used for selection)
-    fn bump(&mut self, amt: int) -> int {
+    fn bump(&mut self, amt: isize) -> isize {
         match self.cnt.fetch_add(amt, Ordering::SeqCst) {
             DISCONNECTED => {
                 self.cnt.store(DISCONNECTED, Ordering::SeqCst);
@@ -472,7 +472,7 @@ pub fn abort_selection(&mut self,
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> 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 ae96a2491dc267ee06066c369ee6cfb838e3c204..33c1614e1b297dfe7037782d6533c6c6fe19a943 100644 (file)
@@ -55,16 +55,16 @@ pub struct Packet<T> {
     lock: Mutex<State<T>>,
 }
 
-unsafe impl<T: Send + 'static> Send for Packet<T> { }
+unsafe impl<T: Send> Send for Packet<T> { }
 
-unsafe impl<T: Send + 'static> Sync for Packet<T> { }
+unsafe impl<T: Send> Sync for Packet<T> { }
 
 struct State<T> {
     disconnected: bool, // Is the channel disconnected yet?
     queue: Queue,       // queue of senders waiting to send data
     blocker: Blocker,   // currently blocked task on this channel
     buf: Buffer<T>,     // storage for buffered messages
-    cap: uint,          // capacity of this channel
+    cap: usize,         // capacity of this channel
 
     /// A curious flag used to indicate whether a sender failed or succeeded in
     /// blocking. This is used to transmit information back to the task that it
@@ -75,7 +75,7 @@ struct State<T> {
     canceled: Option<&'static mut bool>,
 }
 
-unsafe impl<T: Send + 'static> Send for State<T> {}
+unsafe impl<T: Send> Send for State<T> {}
 
 /// Possible flavors of threads who can be blocked on this channel.
 enum Blocker {
@@ -101,8 +101,8 @@ unsafe impl Send for Node {}
 /// A simple ring-buffer
 struct Buffer<T> {
     buf: Vec<Option<T>>,
-    start: uint,
-    size: uint,
+    start: usize,
+    size: usize,
 }
 
 #[derive(Debug)]
@@ -113,7 +113,7 @@ 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 + 'static>(lock: &'a Mutex<State<T>>,
+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>>
@@ -136,8 +136,8 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
     token.signal();
 }
 
-impl<T: Send + 'static> Packet<T> {
-    pub fn new(cap: uint) -> Packet<T> {
+impl<T: Send> Packet<T> {
+    pub fn new(cap: usize) -> Packet<T> {
         Packet {
             channels: AtomicUsize::new(1),
             lock: Mutex::new(State {
@@ -412,7 +412,7 @@ pub fn abort_selection(&self) -> bool {
 }
 
 #[unsafe_destructor]
-impl<T: Send + 'static> Drop for Packet<T> {
+impl<T: Send> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.channels.load(Ordering::SeqCst), 0);
         let mut guard = self.lock.lock().unwrap();
@@ -442,8 +442,8 @@ fn dequeue(&mut self) -> T {
         result.take().unwrap()
     }
 
-    fn size(&self) -> uint { self.size }
-    fn cap(&self) -> uint { self.buf.len() }
+    fn size(&self) -> usize { self.size }
+    fn cap(&self) -> usize { self.buf.len() }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index e875bab5d911971d976aa88b7e6831a7f830c2fc..4c3b5d98a3cb172e13673201c2296d49b27f1c54 100644 (file)
@@ -51,7 +51,7 @@
 /// use std::thread;
 /// use std::sync::mpsc::channel;
 ///
-/// const N: uint = 10;
+/// const N: usize = 10;
 ///
 /// // Spawn a few threads to increment a shared variable (non-atomically), and
 /// // let the main thread know once all increments are done.
@@ -121,9 +121,9 @@ pub struct Mutex<T> {
     data: UnsafeCell<T>,
 }
 
-unsafe impl<T: Send + 'static> Send for Mutex<T> { }
+unsafe impl<T: Send> Send for Mutex<T> { }
 
-unsafe impl<T: Send + 'static> Sync for Mutex<T> { }
+unsafe impl<T: Send> Sync for Mutex<T> { }
 
 /// The static mutex type is provided to allow for static allocation of mutexes.
 ///
@@ -153,8 +153,6 @@ pub struct StaticMutex {
     poison: poison::Flag,
 }
 
-unsafe impl Sync for StaticMutex {}
-
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
 ///
@@ -181,7 +179,7 @@ impl<'a, T> !marker::Send for MutexGuard<'a, T> {}
     poison: poison::FLAG_INIT,
 };
 
-impl<T: Send + 'static> Mutex<T> {
+impl<T: Send> 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 +242,7 @@ pub fn is_poisoned(&self) -> bool {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Send + 'static> Drop for Mutex<T> {
+impl<T: Send> 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
@@ -368,7 +366,7 @@ mod test {
 
     struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
 
-    unsafe impl<T:'static+Send> Send for Packet<T> {}
+    unsafe impl<T: Send> Send for Packet<T> {}
     unsafe impl<T> Sync for Packet<T> {}
 
     #[test]
@@ -391,9 +389,9 @@ fn smoke_static() {
     #[test]
     fn lots_and_lots() {
         static M: StaticMutex = MUTEX_INIT;
-        static mut CNT: uint = 0;
-        static J: uint = 1000;
-        static K: uint = 3;
+        static mut CNT: u32 = 0;
+        static J: u32 = 1000;
+        static K: u32 = 3;
 
         fn inc() {
             for _ in 0..J {
@@ -515,7 +513,7 @@ fn test_mutex_arc_access_in_unwind() {
         let arc2 = arc.clone();
         let _ = thread::spawn(move|| -> () {
             struct Unwinder {
-                i: Arc<Mutex<int>>,
+                i: Arc<Mutex<i32>>,
             }
             impl Drop for Unwinder {
                 fn drop(&mut self) {
index 97f985e21e8aba0bbc5068d55db1e2e6432695ea..d2054a1e819ab377d5204799f8e33e77e7bad937 100644 (file)
 //! This primitive is meant to be used to run one-time initialization. An
 //! example use case would be for initializing an FFI library.
 
+use prelude::v1::*;
+
 use isize;
-use marker::Sync;
-use mem::drop;
-use ops::FnOnce;
 use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
 use sync::{StaticMutex, MUTEX_INIT};
 
@@ -43,8 +42,6 @@ pub struct Once {
     lock_cnt: AtomicIsize,
 }
 
-unsafe impl Sync for Once {}
-
 /// Initialization value for static `Once` values.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const ONCE_INIT: Once = Once {
index 32c8150ba4070172473cfe7d7602dca56a8c09de..2587ff5238ea7b86eb29d107856be5ed31629198 100644 (file)
 use thread;
 
 pub struct Flag { failed: UnsafeCell<bool> }
+
+// This flag is only ever accessed with a lock previously held. Note that this
+// a totally private structure.
+unsafe impl Send for Flag {}
+unsafe impl Sync for Flag {}
+
 pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } };
 
 impl Flag {
index 672ea1b1f6238294215db4abe5787d2c12a770f9..454c5b4f0cf7b20eb6bca82ca9cc7d9d3a73a89f 100644 (file)
@@ -65,8 +65,8 @@ pub struct RwLock<T> {
     data: UnsafeCell<T>,
 }
 
-unsafe impl<T:'static+Send> Send for RwLock<T> {}
-unsafe impl<T> Sync for RwLock<T> {}
+unsafe impl<T: Send + Sync> Send for RwLock<T> {}
+unsafe impl<T: Send + Sync> Sync for RwLock<T> {}
 
 /// Structure representing a statically allocated RwLock.
 ///
@@ -98,9 +98,6 @@ pub struct StaticRwLock {
     poison: poison::Flag,
 }
 
-unsafe impl Send for StaticRwLock {}
-unsafe impl Sync for StaticRwLock {}
-
 /// Constant initialization for a statically-initialized rwlock.
 #[unstable(feature = "std_misc",
            reason = "may be merged with RwLock in the future")]
index a45048be24c06a9e0eb37cba43cb7af6ab2b7017..efb6689e7855a40da3f9d374ead25439b9bee138 100644 (file)
 
 //! Abstraction of a thread pool for basic parallelism.
 
-#![unstable(feature = "std_misc",
-            reason = "the semantics of a failing task and whether a thread is \
-                      re-attached to a thread pool are somewhat unclear, and the \
-                      utility of this type in `std::sync` is questionable with \
-                      respect to the jobs of other primitives")]
+#![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::*;
 
@@ -89,7 +91,7 @@ impl TaskPool {
     /// # Panics
     ///
     /// This function will panic if `threads` is 0.
-    pub fn new(threads: uint) -> TaskPool {
+    pub fn new(threads: usize) -> TaskPool {
         assert!(threads >= 1);
 
         let (tx, rx) = channel::<Thunk>();
@@ -142,7 +144,7 @@ mod test {
     use super::*;
     use sync::mpsc::channel;
 
-    const TEST_TASKS: uint = 4;
+    const TEST_TASKS: usize = 4;
 
     #[test]
     fn test_works() {
index dc1ae85efe03395660f9e63fd82b0a398e5a969e..5faaa928ee973893d345e29aab91b8446f1947a1 100644 (file)
@@ -22,8 +22,8 @@
 
 use prelude::v1::*;
 
+use boxed;
 use cell::UnsafeCell;
-use mem;
 use ptr;
 use rt;
 use sync::{StaticMutex, StaticCondvar};
@@ -88,7 +88,7 @@ pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receive
             let _guard = self.lock.lock().unwrap();
             if !*self.initialized.get() {
                 let (tx, rx) = channel();
-                *self.chan.get() = mem::transmute(box tx);
+                *self.chan.get() = boxed::into_raw(box tx);
                 let (receive, send) = helper_signal::new();
                 *self.signal.get() = send as uint;
 
@@ -132,7 +132,7 @@ fn shutdown(&'static self) {
             let mut guard = self.lock.lock().unwrap();
 
             // Close the channel by destroying it
-            let chan: Box<Sender<M>> = mem::transmute(*self.chan.get());
+            let chan: Box<Sender<M>> = Box::from_raw(*self.chan.get());
             *self.chan.get() = ptr::null_mut();
             drop(chan);
             helper_signal::signal(*self.signal.get() as helper_signal::signal);
index e2ac5ac24f89ec01269f0eb545a58d381e296b46..228362e3d62ae2450ed349fae0b518f02db651b6 100644 (file)
@@ -503,7 +503,7 @@ pub fn connect_timeout(fd: sock_t,
     #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK;
 
     // Make sure the call to connect() doesn't block
-    try!(set_nonblocking(fd, true));
+    set_nonblocking(fd, true);
 
     let ret = match unsafe { libc::connect(fd, addrp, len) } {
         // If the connection is in progress, then we need to wait for it to
@@ -533,7 +533,7 @@ pub fn connect_timeout(fd: sock_t,
     };
 
     // be sure to turn blocking I/O back on
-    try!(set_nonblocking(fd, false));
+    set_nonblocking(fd, false);
     return ret;
 
     #[cfg(unix)]
@@ -626,7 +626,7 @@ pub struct Guard<'a> {
 #[unsafe_destructor]
 impl<'a> Drop for Guard<'a> {
     fn drop(&mut self) {
-        assert!(set_nonblocking(self.fd, false).is_ok());
+        set_nonblocking(self.fd, false);
     }
 }
 
@@ -694,7 +694,8 @@ fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
         setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE,
                    seconds as libc::c_int)
     }
-    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+    #[cfg(any(target_os = "freebsd",
+              target_os = "dragonfly"))]
     fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> {
         setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE,
                    seconds as libc::c_int)
@@ -722,7 +723,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
             fd: self.fd(),
             guard: self.inner.lock.lock().unwrap(),
         };
-        assert!(set_nonblocking(self.fd(), true).is_ok());
+        set_nonblocking(self.fd(), true);
         ret
     }
 
@@ -861,7 +862,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
             fd: self.fd(),
             guard: self.inner.lock.lock().unwrap(),
         };
-        assert!(set_nonblocking(self.fd(), true).is_ok());
+        set_nonblocking(self.fd(), true);
         ret
     }
 
@@ -886,9 +887,7 @@ pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
                            storagep,
                            &mut addrlen) as libc::c_int
         }));
-        sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
-            Ok((n as uint, addr))
-        })
+        Ok((n as uint, sockaddr_to_addr(&storage, addrlen as uint).unwrap()))
     }
 
     pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
@@ -909,11 +908,8 @@ pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
         };
 
         let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
-        if n != buf.len() {
-            Err(short_write(n, "couldn't send entire packet at once"))
-        } else {
-            Ok(())
-        }
+        assert!(n == buf.len(), "UDP packet not completely written.");
+        Ok(())
     }
 
     pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
index 8dd2f154fa8e3028fd5c0cd31cbc71060cca6b93..5ebc851e194efa28da8fc669fa4ebb4ebc1d5211 100644 (file)
@@ -189,7 +189,8 @@ unsafe fn target_record_sp_limit(_: uint) {
     unsafe fn target_record_sp_limit(limit: uint) {
         asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile")
     }
-    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)]
+    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))]
+    #[inline(always)]
     unsafe fn target_record_sp_limit(limit: uint) {
         asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile")
     }
@@ -233,6 +234,7 @@ unsafe fn target_record_sp_limit(limit: uint) {
     #[cfg(any(target_arch = "aarch64",
               target_arch = "powerpc",
               all(target_arch = "arm", target_os = "ios"),
+              target_os = "bitrig",
               target_os = "openbsd"))]
     unsafe fn target_record_sp_limit(_: uint) {
     }
@@ -276,14 +278,14 @@ unsafe fn target_get_sp_limit() -> uint {
         asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
-    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)]
+    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))]
+    #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         let limit;
         asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile");
         return limit;
     }
 
-
     // x86
     #[cfg(all(target_arch = "x86",
               any(target_os = "macos", target_os = "ios")))]
@@ -331,6 +333,7 @@ unsafe fn target_get_sp_limit() -> uint {
     #[cfg(any(target_arch = "aarch64",
               target_arch = "powerpc",
               all(target_arch = "arm", target_os = "ios"),
+              target_os = "bitrig",
               target_os = "openbsd"))]
     #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
index b725b6c7e6e93f3dbb8960dbaf9b1464f0eafaba..731617858e95fe3f9185048414d59e6c60189e77 100644 (file)
@@ -27,7 +27,7 @@ pub fn start_thread(main: *mut libc::c_void) -> thread::rust_thread_return {
     unsafe {
         stack::record_os_managed_stack_bounds(0, usize::MAX);
         let handler = stack_overflow::Handler::new();
-        let f: Box<Thunk> = mem::transmute(main);
+        let f: Box<Thunk> = Box::from_raw(main as *mut Thunk);
         f.invoke(());
         drop(handler);
         mem::transmute(0 as thread::rust_thread_return)
index ca3ae1a7a34360fa158012705feba28fbba07b83..fb9d6fef1faa7e0071343937f6aad0eea519eba4 100644 (file)
@@ -32,7 +32,6 @@
 use cmp;
 use fmt;
 use hash::{Hash, Hasher};
-#[cfg(stage0)] use hash::Writer;
 use iter::{FromIterator, IntoIterator};
 use mem;
 use num::Int;
@@ -796,14 +795,6 @@ fn size_hint(&self) -> (uint, Option<uint>) {
     }
 }
 
-#[cfg(stage0)]
-impl<S: Writer + Hasher> Hash<S> for CodePoint {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        self.value.hash(state)
-    }
-}
-#[cfg(not(stage0))]
 impl Hash for CodePoint {
     #[inline]
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -811,15 +802,6 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
-#[cfg(stage0)]
-impl<S: Writer + Hasher> Hash<S> for Wtf8Buf {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        state.write(&self.bytes);
-        0xfeu8.hash(state)
-    }
-}
-#[cfg(not(stage0))]
 impl Hash for Wtf8Buf {
     #[inline]
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -828,15 +810,6 @@ fn hash<H: Hasher>(&self, state: &mut H) {
     }
 }
 
-#[cfg(stage0)]
-impl<'a, S: Writer + Hasher> Hash<S> for Wtf8 {
-    #[inline]
-    fn hash(&self, state: &mut S) {
-        state.write(&self.bytes);
-        0xfeu8.hash(state)
-    }
-}
-#[cfg(not(stage0))]
 impl Hash for Wtf8 {
     #[inline]
     fn hash<H: Hasher>(&self, state: &mut H) {
@@ -1229,11 +1202,11 @@ fn cp(string: &Wtf8Buf) -> Vec<Option<char>> {
             string.code_points().map(|c| c.to_char()).collect::<Vec<_>>()
         }
         let mut string = Wtf8Buf::from_str("é ");
-        assert_eq!(cp(&string), vec![Some('é'), Some(' ')]);
+        assert_eq!(cp(&string), [Some('é'), Some(' ')]);
         string.push(c(0xD83D));
-        assert_eq!(cp(&string), vec![Some('é'), Some(' '), None]);
+        assert_eq!(cp(&string), [Some('é'), Some(' '), None]);
         string.push(c(0xDCA9));
-        assert_eq!(cp(&string), vec![Some('é'), Some(' '), Some('💩')]);
+        assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]);
     }
 
     #[test]
index 8b560339f304474c6cb67d523d69a138f7c2341f..6267792ba745e5ffa82bcca807c959d8ed4dd2a5 100644 (file)
@@ -84,8 +84,9 @@
 /// all unix platforms we support right now, so it at least gets the job done.
 
 use prelude::v1::*;
+use os::unix::prelude::*;
 
-use ffi::CStr;
+use ffi::{CStr, AsOsStr};
 use old_io::IoResult;
 use libc;
 use mem;
@@ -319,6 +320,7 @@ unsafe fn init_state() -> *mut backtrace_state {
         if !STATE.is_null() { return STATE }
         let selfname = if cfg!(target_os = "freebsd") ||
                           cfg!(target_os = "dragonfly") ||
+                          cfg!(target_os = "bitrig") ||
                           cfg!(target_os = "openbsd") {
             env::current_exe().ok()
         } else {
@@ -326,7 +328,7 @@ unsafe fn init_state() -> *mut backtrace_state {
         };
         let filename = match selfname {
             Some(path) => {
-                let bytes = path.as_vec();
+                let bytes = path.as_os_str().as_bytes();
                 if bytes.len() < LAST_FILENAME.len() {
                     let i = bytes.iter();
                     for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
index 345808189a0ceaf2c2a1dfeb76f00eb2e75385b3..14394a653b0ed5f4d848d51ca0143b43af8c7d03 100644 (file)
@@ -24,6 +24,7 @@
           target_os = "ios",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub const FIONBIO: libc::c_ulong = 0x8004667e;
 #[cfg(any(all(target_os = "linux",
@@ -43,6 +44,7 @@
           target_os = "ios",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub const FIOCLEX: libc::c_ulong = 0x20006601;
 #[cfg(any(all(target_os = "linux",
@@ -62,6 +64,7 @@
           target_os = "ios",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub const MSG_DONTWAIT: libc::c_int = 0x80;
 #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -75,7 +78,8 @@
           target_os = "freebsd",
           target_os = "dragonfly"))]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 71;
-#[cfg(target_os = "openbsd")]
+#[cfg(any(target_os = "bitrig",
+          target_os = "openbsd"))]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 101;
 #[cfg(target_os = "android")]
 pub const _SC_GETPW_R_SIZE_MAX: libc::c_int = 0x0048;
@@ -96,6 +100,7 @@ pub struct passwd {
 #[cfg(any(target_os = "macos",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub struct passwd {
     pub pw_name: *mut libc::c_char,
@@ -177,6 +182,7 @@ pub fn fd_set(set: &mut fd_set, fd: i32) {
 #[cfg(any(target_os = "android",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd",
           target_os = "linux"))]
 mod select {
@@ -302,8 +308,7 @@ pub struct sigset_t {
 #[cfg(any(target_os = "macos",
           target_os = "ios",
           target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "openbsd"))]
+          target_os = "dragonfly"))]
 mod signal {
     use libc;
 
@@ -317,8 +322,7 @@ mod signal {
     pub const SIGCHLD: libc::c_int = 20;
 
     #[cfg(any(target_os = "macos",
-              target_os = "ios",
-              target_os = "openbsd"))]
+              target_os = "ios"))]
     pub type sigset_t = u32;
     #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
     #[repr(C)]
@@ -345,3 +349,41 @@ pub struct sigaction {
         pub sa_mask: sigset_t,
     }
 }
+
+#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+mod signal {
+    use libc;
+
+    pub const SA_ONSTACK: libc::c_int = 0x0001;
+    pub const SA_RESTART: libc::c_int = 0x0002;
+    pub const SA_RESETHAND: libc::c_int = 0x0004;
+    pub const SA_NOCLDSTOP: libc::c_int = 0x0008;
+    pub const SA_NODEFER: libc::c_int = 0x0010;
+    pub const SA_NOCLDWAIT: libc::c_int = 0x0020;
+    pub const SA_SIGINFO: libc::c_int = 0x0040;
+    pub const SIGCHLD: libc::c_int = 20;
+
+    pub type sigset_t = libc::c_uint;
+
+    // This structure has more fields, but we're not all that interested in
+    // them.
+    #[repr(C)]
+    pub struct siginfo {
+        pub si_signo: libc::c_int,
+        pub si_code: libc::c_int,
+        pub si_errno: libc::c_int,
+        // FIXME: Bitrig has a crazy union here in the siginfo, I think this
+        // layout will still work tho.  The status might be off by the size of
+        // a clock_t by my reading, but we can fix this later.
+        pub pid: libc::pid_t,
+        pub uid: libc::uid_t,
+        pub status: libc::c_int,
+    }
+
+    #[repr(C)]
+    pub struct sigaction {
+        pub sa_handler: extern fn(libc::c_int),
+        pub sa_mask: sigset_t,
+        pub sa_flags: libc::c_int,
+    }
+}
index 3bc414731526300d15d5fa0d0716b132c7d892f6..90dfebc4c454c7735808255c52a5994e08452f34 100644 (file)
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use libc;
 use ptr;
-use std::option::Option::{Some, None};
 use sys::mutex::{self, Mutex};
 use sys::time;
 use sys::sync as ffi;
@@ -20,6 +21,9 @@
 
 pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
 
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
 pub const CONDVAR_INIT: Condvar = Condvar {
     inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER },
 };
index b8b9dcfb3c68920b2602ed2e1e22072ac5d106be..3f9da6e3c51bb004fb6b1cf40a917825237136b5 100644 (file)
@@ -173,10 +173,13 @@ fn to_cstring(&self) -> Result<CString, NulError> {
 
 // Unix-specific extensions to `Permissions`
 pub trait PermissionsExt {
+    fn mode(&self) -> i32;
     fn set_mode(&mut self, mode: i32);
 }
 
 impl PermissionsExt for Permissions {
+    fn mode(&self) -> i32 { self.as_inner().mode() }
+
     fn set_mode(&mut self, mode: i32) {
         *self = FromInner::from_inner(FromInner::from_inner(mode));
     }
index 5c847002d2394f35c1f4d7cb9c142f40edbe2de6..1c28d629d40f07f0c89f17290b72aae66a3c1bc6 100644 (file)
@@ -291,6 +291,33 @@ fn mkstat(stat: &libc::stat) -> FileStat {
     // FileStat times are in milliseconds
     fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
 
+    #[cfg(target_os = "bitrig")]
+    fn ctime(stat: &libc::stat) -> u64 {
+      mktime(stat.st_ctim.tv_sec as u64, stat.st_ctim.tv_nsec as u64)
+    }
+    #[cfg(not(target_os = "bitrig"))]
+    fn ctime(stat: &libc::stat) -> u64 {
+      mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64)
+    }
+
+    #[cfg(target_os = "bitrig")]
+    fn atime(stat: &libc::stat) -> u64 {
+      mktime(stat.st_atim.tv_sec as u64, stat.st_atim.tv_nsec as u64)
+    }
+    #[cfg(not(target_os = "bitrig"))]
+    fn atime(stat: &libc::stat) -> u64 {
+      mktime(stat.st_atime as u64, stat.st_atime_nsec as u64)
+    }
+
+    #[cfg(target_os = "bitrig")]
+    fn mtime(stat: &libc::stat) -> u64 {
+      mktime(stat.st_mtim.tv_sec as u64, stat.st_mtim.tv_nsec as u64)
+    }
+    #[cfg(not(target_os = "bitrig"))]
+    fn mtime(stat: &libc::stat) -> u64 {
+      mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64)
+    }
+
     #[cfg(not(any(target_os = "linux", target_os = "android")))]
     fn flags(stat: &libc::stat) -> u64 { stat.st_flags as u64 }
     #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -312,9 +339,9 @@ fn gen(_stat: &libc::stat) -> u64 { 0 }
             _ => old_io::FileType::Unknown,
         },
         perm: FilePermission::from_bits_truncate(stat.st_mode as u32),
-        created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
-        modified: mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64),
-        accessed: mktime(stat.st_atime as u64, stat.st_atime_nsec as u64),
+        created: ctime(stat),
+        modified: mtime(stat),
+        accessed: atime(stat),
         unstable: UnstableFileStat {
             device: stat.st_dev as u64,
             inode: stat.st_ino as u64,
index 92a47c6c3850df3a34b3ac132e83f72314db86d6..72e0b8dd36c66151eab686d374a2f44f928c42d3 100644 (file)
@@ -18,7 +18,7 @@
 use mem;
 use path::{Path, PathBuf};
 use ptr;
-use rc::Rc;
+use sync::Arc;
 use sys::fd::FileDesc;
 use sys::{c, cvt, cvt_r};
 use sys_common::FromInner;
@@ -31,14 +31,18 @@ pub struct FileAttr {
 }
 
 pub struct ReadDir {
-    dirp: *mut libc::DIR,
-    root: Rc<PathBuf>,
+    dirp: Dir,
+    root: Arc<PathBuf>,
 }
 
+struct Dir(*mut libc::DIR);
+
+unsafe impl Send for Dir {}
+unsafe impl Sync for Dir {}
+
 pub struct DirEntry {
-    buf: Vec<u8>,
-    dirent: *mut libc::dirent_t,
-    root: Rc<PathBuf>,
+    buf: Vec<u8>, // actually *mut libc::dirent_t
+    root: Arc<PathBuf>,
 }
 
 #[derive(Clone)]
@@ -86,6 +90,7 @@ pub fn set_readonly(&mut self, readonly: bool) {
             self.mode |= 0o222;
         }
     }
+    pub fn mode(&self) -> i32 { self.mode as i32 }
 }
 
 impl FromInner<i32> for FilePermissions {
@@ -109,7 +114,7 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 
         let mut entry_ptr = ptr::null_mut();
         loop {
-            if unsafe { libc::readdir_r(self.dirp, ptr, &mut entry_ptr) != 0 } {
+            if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } {
                 return Some(Err(Error::last_os_error()))
             }
             if entry_ptr.is_null() {
@@ -118,7 +123,6 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 
             let entry = DirEntry {
                 buf: buf,
-                dirent: entry_ptr,
                 root: self.root.clone()
             };
             if entry.name_bytes() == b"." || entry.name_bytes() == b".." {
@@ -130,9 +134,9 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
     }
 }
 
-impl Drop for ReadDir {
+impl Drop for Dir {
     fn drop(&mut self) {
-        let r = unsafe { libc::closedir(self.dirp) };
+        let r = unsafe { libc::closedir(self.0) };
         debug_assert_eq!(r, 0);
     }
 }
@@ -147,9 +151,13 @@ fn name_bytes(&self) -> &[u8] {
             fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
         }
         unsafe {
-            CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
+            CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes()
         }
     }
+
+    fn dirent(&self) -> *mut libc::dirent_t {
+        self.buf.as_ptr() as *mut _
+    }
 }
 
 impl OpenOptions {
@@ -279,14 +287,14 @@ pub fn mkdir(p: &Path) -> io::Result<()> {
 }
 
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
-    let root = Rc::new(p.to_path_buf());
+    let root = Arc::new(p.to_path_buf());
     let p = try!(cstr(p));
     unsafe {
         let ptr = libc::opendir(p.as_ptr());
         if ptr.is_null() {
             Err(Error::last_os_error())
         } else {
-            Ok(ReadDir { dirp: ptr, root: root })
+            Ok(ReadDir { dirp: Dir(ptr), root: root })
         }
     }
 }
index b79ad7031fa48dc31dcc208036ae5f5bf353eaf1..632270bc5ccbf250286bc176d1f7c08ce9ea4935 100644 (file)
@@ -214,9 +214,9 @@ pub fn wouldblock() -> bool {
     err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32
 }
 
-pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
+pub fn set_nonblocking(fd: sock_t, nb: bool) {
     let set = nb as libc::c_int;
-    mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
+    mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap();
 }
 
 // nothing needed on unix platforms
index 9e1527aef201abdfb0215143a18bdb46ef0bc4cd..f87c0339533dfb672273d881cbf9b7623e9b16c2 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
-use marker::Sync;
 use sys::sync as ffi;
 use sys_common::mutex;
 
@@ -24,6 +25,7 @@ pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
     inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
 };
 
+unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
 impl Mutex {
index 3d1ef3a2c37f7e8267dfb65d84f79ba4e0e55bc1..a38c7a30b757840983f0e523db3aae11f827af0a 100644 (file)
 use error::Error as StdError;
 use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
 use fmt;
+use io;
 use iter;
 use libc::{self, c_int, c_char, c_void};
 use mem;
-use io;
-use old_io::{IoResult, IoError, fs};
+use old_io::{IoError, IoResult};
 use ptr;
+use path::{self, PathBuf};
 use slice;
 use str;
 use sys::c;
 const BUF_BYTES: usize = 2048;
 const TMPBUF_SZ: usize = 128;
 
+fn bytes2path(b: &[u8]) -> PathBuf {
+    PathBuf::new(<OsStr as OsStrExt>::from_bytes(b))
+}
+
+fn os2path(os: OsString) -> PathBuf {
+    bytes2path(os.as_bytes())
+}
+
 /// Returns the platform-specific value of errno
 pub fn errno() -> i32 {
     #[cfg(any(target_os = "macos",
@@ -42,6 +51,16 @@ unsafe fn errno_location() -> *const c_int {
         __error()
     }
 
+    #[cfg(target_os = "bitrig")]
+    fn errno_location() -> *const c_int {
+        extern {
+            fn __errno() -> *const c_int;
+        }
+        unsafe {
+            __errno()
+        }
+    }
+
     #[cfg(target_os = "dragonfly")]
     unsafe fn errno_location() -> *const c_int {
         extern { fn __dfly_error() -> *const c_int; }
@@ -92,30 +111,30 @@ fn strerror_r(errnum: c_int, buf: *mut c_char,
     }
 }
 
-pub fn getcwd() -> IoResult<Path> {
+pub fn getcwd() -> io::Result<PathBuf> {
     let mut buf = [0 as c_char; BUF_BYTES];
     unsafe {
         if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
-            Err(IoError::last_error())
+            Err(io::Error::last_os_error())
         } else {
-            Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
+            Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes()))
         }
     }
 }
 
-pub fn chdir(p: &Path) -> IoResult<()> {
-    let p = CString::new(p.as_vec()).unwrap();
+pub fn chdir(p: &path::Path) -> io::Result<()> {
+    let p = try!(CString::new(p.as_os_str().as_bytes()));
     unsafe {
         match libc::chdir(p.as_ptr()) == (0 as c_int) {
             true => Ok(()),
-            false => Err(IoError::last_error()),
+            false => Err(io::Error::last_os_error()),
         }
     }
 }
 
 pub struct SplitPaths<'a> {
     iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
-                    fn(&'a [u8]) -> Path>,
+                    fn(&'a [u8]) -> PathBuf>,
 }
 
 pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
@@ -123,13 +142,13 @@ fn is_colon(b: &u8) -> bool { *b == b':' }
     let unparsed = unparsed.as_bytes();
     SplitPaths {
         iter: unparsed.split(is_colon as fn(&u8) -> bool)
-                      .map(Path::new as fn(&'a [u8]) ->  Path)
+                      .map(bytes2path as fn(&'a [u8]) -> PathBuf)
     }
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
-    type Item = Path;
-    fn next(&mut self) -> Option<Path> { self.iter.next() }
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
@@ -164,7 +183,7 @@ fn description(&self) -> &str { "failed to join paths" }
 }
 
 #[cfg(target_os = "freebsd")]
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         use libc::funcs::bsd44::*;
         use libc::consts::os::extra::*;
@@ -176,28 +195,27 @@ pub fn current_exe() -> IoResult<Path> {
         let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
                          ptr::null_mut(), &mut sz, ptr::null_mut(),
                          0 as libc::size_t);
-        if err != 0 { return Err(IoError::last_error()); }
-        if sz == 0 { return Err(IoError::last_error()); }
+        if err != 0 { return Err(io::Error::last_os_error()); }
+        if sz == 0 { return Err(io::Error::last_os_error()); }
         let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
         let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
                          v.as_mut_ptr() as *mut libc::c_void, &mut sz,
                          ptr::null_mut(), 0 as libc::size_t);
-        if err != 0 { return Err(IoError::last_error()); }
-        if sz == 0 { return Err(IoError::last_error()); }
+        if err != 0 { return Err(io::Error::last_os_error()); }
+        if sz == 0 { return Err(io::Error::last_os_error()); }
         v.set_len(sz as uint - 1); // chop off trailing NUL
-        Ok(Path::new(v))
+        Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v)))
     }
 }
 
 #[cfg(target_os = "dragonfly")]
-pub fn current_exe() -> IoResult<Path> {
-    fs::readlink(&Path::new("/proc/curproc/file"))
+pub fn current_exe() -> io::Result<PathBuf> {
+    ::fs::read_link("/proc/curproc/file")
 }
 
-#[cfg(target_os = "openbsd")]
-pub fn current_exe() -> IoResult<Path> {
+#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
+pub fn current_exe() -> io::Result<PathBuf> {
     use sync::{StaticMutex, MUTEX_INIT};
-
     static LOCK: StaticMutex = MUTEX_INIT;
 
     extern {
@@ -209,30 +227,31 @@ pub fn current_exe() -> IoResult<Path> {
     unsafe {
         let v = rust_current_exe();
         if v.is_null() {
-            Err(IoError::last_error())
+            Err(io::Error::last_os_error())
         } else {
-            Ok(Path::new(CStr::from_ptr(&v).to_bytes().to_vec()))
+            let vec = CStr::from_ptr(v).to_bytes().to_vec();
+            Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(vec)))
         }
     }
 }
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn current_exe() -> IoResult<Path> {
-    fs::readlink(&Path::new("/proc/self/exe"))
+pub fn current_exe() -> io::Result<PathBuf> {
+    ::fs::read_link("/proc/self/exe")
 }
 
 #[cfg(any(target_os = "macos", target_os = "ios"))]
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         use libc::funcs::extra::_NSGetExecutablePath;
         let mut sz: u32 = 0;
         _NSGetExecutablePath(ptr::null_mut(), &mut sz);
-        if sz == 0 { return Err(IoError::last_error()); }
+        if sz == 0 { return Err(io::Error::last_os_error()); }
         let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
         let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
-        if err != 0 { return Err(IoError::last_error()); }
+        if err != 0 { return Err(io::Error::last_os_error()); }
         v.set_len(sz as uint - 1); // chop off trailing NUL
-        Ok(Path::new(v))
+        Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v)))
     }
 }
 
@@ -336,6 +355,7 @@ pub fn args() -> Args {
           target_os = "android",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub fn args() -> Args {
     use rt;
@@ -441,22 +461,20 @@ pub fn page_size() -> usize {
     }
 }
 
-pub fn temp_dir() -> Path {
-    getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| {
+pub fn temp_dir() -> PathBuf {
+    getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| {
         if cfg!(target_os = "android") {
-            Path::new("/data/local/tmp")
+            PathBuf::new("/data/local/tmp")
         } else {
-            Path::new("/tmp")
+            PathBuf::new("/tmp")
         }
     })
 }
 
-pub fn home_dir() -> Option<Path> {
+pub fn home_dir() -> Option<PathBuf> {
     return getenv("HOME".as_os_str()).or_else(|| unsafe {
         fallback()
-    }).map(|os| {
-        Path::new(os.into_vec())
-    });
+    }).map(os2path);
 
     #[cfg(any(target_os = "android",
               target_os = "ios"))]
index 3c9cdc65975f6f9f5e1b7027774b2a7dd0fa564f..33863d31437f3f7f68d4a6e2aaf4d1907cbc3d75 100644 (file)
@@ -145,7 +145,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
             fd: self.fd(),
             guard: unsafe { self.inner.lock.lock().unwrap() },
         };
-        assert!(set_nonblocking(self.fd(), true).is_ok());
+        set_nonblocking(self.fd(), true);
         ret
     }
 
@@ -235,9 +235,9 @@ pub fn listen(self) -> IoResult<UnixAcceptor> {
 
             _ => {
                 let (reader, writer) = try!(unsafe { sys::os::pipe() });
-                try!(set_nonblocking(reader.fd(), true));
-                try!(set_nonblocking(writer.fd(), true));
-                try!(set_nonblocking(self.fd(), true));
+                set_nonblocking(reader.fd(), true);
+                set_nonblocking(writer.fd(), true);
+                set_nonblocking(self.fd(), true);
                 Ok(UnixAcceptor {
                     inner: Arc::new(AcceptorInner {
                         listener: self,
index b30ac889120c229343f6d48938c50658c24d891f..68c5c65e7cdb11cfac9bf64ff25732d8efbba32b 100644 (file)
@@ -12,8 +12,6 @@
 use self::Req::*;
 
 use collections::HashMap;
-#[cfg(stage0)]
-use collections::hash_map::Hasher;
 use ffi::CString;
 use hash::Hash;
 use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
@@ -64,12 +62,11 @@ pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
         mkerr_libc(r)
     }
 
-    #[cfg(stage0)]
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
         where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
-              K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
+              K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
 
@@ -79,6 +76,11 @@ mod rustrt {
             }
         }
 
+        unsafe fn set_cloexec(fd: c_int) {
+            let ret = c::ioctl(fd, c::FIOCLEX);
+            assert_eq!(ret, 0);
+        }
+
         #[cfg(all(target_os = "android", target_arch = "aarch64"))]
         unsafe fn getdtablesize() -> c_int {
             libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
@@ -88,219 +90,6 @@ unsafe fn getdtablesize() -> c_int {
             libc::funcs::bsd44::getdtablesize()
         }
 
-        unsafe fn set_cloexec(fd: c_int) {
-            let ret = c::ioctl(fd, c::FIOCLEX);
-            assert_eq!(ret, 0);
-        }
-
-        let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
-
-        // temporary until unboxed closures land
-        let cfg = unsafe {
-            mem::transmute::<&ProcessConfig<K,V>,&'static ProcessConfig<K,V>>(cfg)
-        };
-
-        with_envp(cfg.env(), move|envp: *const c_void| {
-            with_argv(cfg.program(), cfg.args(), move|argv: *const *const libc::c_char| unsafe {
-                let (input, mut output) = try!(sys::os::pipe());
-
-                // We may use this in the child, so perform allocations before the
-                // fork
-                let devnull = b"/dev/null\0";
-
-                set_cloexec(output.fd());
-
-                let pid = fork();
-                if pid < 0 {
-                    return Err(super::last_error())
-                } else if pid > 0 {
-                    #[inline]
-                    fn combine(arr: &[u8]) -> i32 {
-                        let a = arr[0] as u32;
-                        let b = arr[1] as u32;
-                        let c = arr[2] as u32;
-                        let d = arr[3] as u32;
-
-                        ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
-                    }
-
-                    let p = Process{ pid: pid };
-                    drop(output);
-                    let mut bytes = [0; 8];
-                    return match input.read(&mut bytes) {
-                        Ok(8) => {
-                            assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
-                                "Validation on the CLOEXEC pipe failed: {:?}", bytes);
-                            let errno = combine(&bytes[0.. 4]);
-                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
-                            Err(super::decode_error(errno))
-                        }
-                        Err(ref e) if e.kind == EndOfFile => Ok(p),
-                        Err(e) => {
-                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
-                            panic!("the CLOEXEC pipe failed: {:?}", e)
-                        },
-                        Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
-                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
-                            panic!("short read on the CLOEXEC pipe")
-                        }
-                    };
-                }
-
-                // And at this point we've reached a special time in the life of the
-                // child. The child must now be considered hamstrung and unable to
-                // do anything other than syscalls really. Consider the following
-                // scenario:
-                //
-                //      1. Thread A of process 1 grabs the malloc() mutex
-                //      2. Thread B of process 1 forks(), creating thread C
-                //      3. Thread C of process 2 then attempts to malloc()
-                //      4. The memory of process 2 is the same as the memory of
-                //         process 1, so the mutex is locked.
-                //
-                // This situation looks a lot like deadlock, right? It turns out
-                // that this is what pthread_atfork() takes care of, which is
-                // presumably implemented across platforms. The first thing that
-                // threads to *before* forking is to do things like grab the malloc
-                // mutex, and then after the fork they unlock it.
-                //
-                // Despite this information, libnative's spawn has been witnessed to
-                // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but
-                // all collected backtraces point at malloc/free traffic in the
-                // child spawned process.
-                //
-                // For this reason, the block of code below should contain 0
-                // invocations of either malloc of free (or their related friends).
-                //
-                // As an example of not having malloc/free traffic, we don't close
-                // this file descriptor by dropping the FileDesc (which contains an
-                // allocation). Instead we just close it manually. This will never
-                // have the drop glue anyway because this code never returns (the
-                // child will either exec() or invoke libc::exit)
-                let _ = libc::close(input.fd());
-
-                fn fail(output: &mut FileDesc) -> ! {
-                    let errno = sys::os::errno() as u32;
-                    let bytes = [
-                        (errno >> 24) as u8,
-                        (errno >> 16) as u8,
-                        (errno >>  8) as u8,
-                        (errno >>  0) as u8,
-                        CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
-                        CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
-                    ];
-                    // pipe I/O up to PIPE_BUF bytes should be atomic
-                    assert!(output.write(&bytes).is_ok());
-                    unsafe { libc::_exit(1) }
-                }
-
-                rustrt::rust_unset_sigprocmask();
-
-                // If a stdio file descriptor is set to be ignored (via a -1 file
-                // descriptor), then we don't actually close it, but rather open
-                // up /dev/null into that file descriptor. Otherwise, the first file
-                // descriptor opened up in the child would be numbered as one of the
-                // stdio file descriptors, which is likely to wreak havoc.
-                let setup = |src: Option<P>, dst: c_int| {
-                    let src = match src {
-                        None => {
-                            let flags = if dst == libc::STDIN_FILENO {
-                                libc::O_RDONLY
-                            } else {
-                                libc::O_RDWR
-                            };
-                            libc::open(devnull.as_ptr() as *const _, flags, 0)
-                        }
-                        Some(obj) => {
-                            let fd = obj.as_inner().fd();
-                            // Leak the memory and the file descriptor. We're in the
-                            // child now an all our resources are going to be
-                            // cleaned up very soon
-                            mem::forget(obj);
-                            fd
-                        }
-                    };
-                    src != -1 && retry(|| dup2(src, dst)) != -1
-                };
-
-                if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
-                if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) }
-                if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) }
-
-                // close all other fds
-                for fd in (3..getdtablesize()).rev() {
-                    if fd != output.fd() {
-                        let _ = close(fd as c_int);
-                    }
-                }
-
-                match cfg.gid() {
-                    Some(u) => {
-                        if libc::setgid(u as libc::gid_t) != 0 {
-                            fail(&mut output);
-                        }
-                    }
-                    None => {}
-                }
-                match cfg.uid() {
-                    Some(u) => {
-                        // When dropping privileges from root, the `setgroups` call
-                        // will remove any extraneous groups. If we don't call this,
-                        // then even though our uid has dropped, we may still have
-                        // groups that enable us to do super-user things. This will
-                        // fail if we aren't root, so don't bother checking the
-                        // return value, this is just done as an optimistic
-                        // privilege dropping function.
-                        extern {
-                            fn setgroups(ngroups: libc::c_int,
-                                         ptr: *const libc::c_void) -> libc::c_int;
-                        }
-                        let _ = setgroups(0, ptr::null());
-
-                        if libc::setuid(u as libc::uid_t) != 0 {
-                            fail(&mut output);
-                        }
-                    }
-                    None => {}
-                }
-                if cfg.detach() {
-                    // Don't check the error of setsid because it fails if we're the
-                    // process leader already. We just forked so it shouldn't return
-                    // error, but ignore it anyway.
-                    let _ = libc::setsid();
-                }
-                if !dirp.is_null() && chdir(dirp) == -1 {
-                    fail(&mut output);
-                }
-                if !envp.is_null() {
-                    *sys::os::environ() = envp as *const _;
-                }
-                let _ = execvp(*argv, argv as *mut _);
-                fail(&mut output);
-            })
-        })
-    }
-    #[cfg(not(stage0))]
-    pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
-                              out_fd: Option<P>, err_fd: Option<P>)
-                              -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
-              K: BytesContainer + Eq + Hash, V: BytesContainer
-    {
-        use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
-        use libc::funcs::bsd44::getdtablesize;
-
-        mod rustrt {
-            extern {
-                pub fn rust_unset_sigprocmask();
-            }
-        }
-
-        unsafe fn set_cloexec(fd: c_int) {
-            let ret = c::ioctl(fd, c::FIOCLEX);
-            assert_eq!(ret, 0);
-        }
-
         let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
 
         // temporary until unboxed closures land
@@ -564,8 +353,8 @@ fn register_sigchld() -> (libc::c_int, c::sigaction) {
             unsafe {
                 let mut pipes = [0; 2];
                 assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
-                set_nonblocking(pipes[0], true).ok().unwrap();
-                set_nonblocking(pipes[1], true).ok().unwrap();
+                set_nonblocking(pipes[0], true);
+                set_nonblocking(pipes[1], true);
                 WRITE_FD = pipes[1];
 
                 let mut old: c::sigaction = mem::zeroed();
@@ -581,7 +370,7 @@ fn register_sigchld() -> (libc::c_int, c::sigaction) {
         fn waitpid_helper(input: libc::c_int,
                           messages: Receiver<Req>,
                           (read_fd, old): (libc::c_int, c::sigaction)) {
-            set_nonblocking(input, true).ok().unwrap();
+            set_nonblocking(input, true);
             let mut set: c::fd_set = unsafe { mem::zeroed() };
             let mut tv: libc::timeval;
             let mut active = Vec::<(libc::pid_t, Sender<ProcessExit>, u64)>::new();
@@ -766,45 +555,6 @@ fn with_argv<T,F>(prog: &CString, args: &[CString],
     cb(ptrs.as_ptr())
 }
 
-#[cfg(stage0)]
-fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
-                      cb: F)
-                      -> T
-    where F : FnOnce(*const c_void) -> T,
-          K : BytesContainer + Eq + Hash<Hasher>,
-          V : BytesContainer
-{
-    // On posixy systems we can pass a char** for envp, which is a
-    // null-terminated array of "k=v\0" strings. Since we must create
-    // these strings locally, yet expose a raw pointer to them, we
-    // create a temporary vector to own the CStrings that outlives the
-    // call to cb.
-    match env {
-        Some(env) => {
-            let mut tmps = Vec::with_capacity(env.len());
-
-            for pair in env {
-                let mut kv = Vec::new();
-                kv.push_all(pair.0.container_as_bytes());
-                kv.push('=' as u8);
-                kv.push_all(pair.1.container_as_bytes());
-                kv.push(0); // terminating null
-                tmps.push(kv);
-            }
-
-            // As with `with_argv`, this is unsafe, since cb could leak the pointers.
-            let mut ptrs: Vec<*const libc::c_char> =
-                tmps.iter()
-                    .map(|tmp| tmp.as_ptr() as *const libc::c_char)
-                    .collect();
-            ptrs.push(ptr::null());
-
-            cb(ptrs.as_ptr() as *const c_void)
-        }
-        _ => cb(ptr::null())
-    }
-}
-#[cfg(not(stage0))]
 fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
                       cb: F)
                       -> T
@@ -856,6 +606,7 @@ pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
index 06fa5c4bba7253d66f4a3b45c00a6e3097168b8f..b7a1b002f55983a0048fc742f2a0167a8be32ecc 100644 (file)
@@ -141,7 +141,6 @@ pub fn spawn(cfg: &Command,
                  -> io::Result<Process>
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
-        use libc::funcs::bsd44::getdtablesize;
 
         mod rustrt {
             extern {
@@ -154,6 +153,16 @@ unsafe fn set_cloexec(fd: c_int) {
             assert_eq!(ret, 0);
         }
 
+        #[cfg(all(target_os = "android", target_arch = "aarch64"))]
+        unsafe fn getdtablesize() -> c_int {
+            libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
+        }
+
+        #[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
+        unsafe fn getdtablesize() -> c_int {
+            libc::funcs::bsd44::getdtablesize()
+        }
+
         let dirp = cfg.cwd.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null());
 
         with_envp(cfg.env.as_ref(), |envp: *const c_void| {
index 54523e0076dc3c47ce41897cb416b4b2f795b385..b857f4ab75fed31160e45e63acdf887f545acdca 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use sys::sync as ffi;
 
@@ -17,6 +19,9 @@ pub struct RWLock { inner: UnsafeCell<ffi::pthread_rwlock_t> }
     inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
 };
 
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
 impl RWLock {
     #[inline]
     pub unsafe fn new() -> RWLock {
index 3512fa36eb3b7fc07e61b56a0103fc1c02ca4ba4..c2044c502b72fb4bf1ed42ada4132e0e28fb97ee 100644 (file)
@@ -34,6 +34,7 @@ fn drop(&mut self) {
 
 #[cfg(any(target_os = "linux",
           target_os = "macos",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 mod imp {
     use core::prelude::*;
@@ -205,7 +206,9 @@ pub struct sigaltstack {
 
     }
 
-    #[cfg(any(target_os = "macos", target_os = "openbsd"))]
+    #[cfg(any(target_os = "macos",
+              target_os = "bitrig",
+              target_os = "openbsd"))]
     mod signal {
         use libc;
         use super::sighandler_t;
@@ -216,7 +219,7 @@ mod signal {
 
         #[cfg(target_os = "macos")]
         pub const SIGSTKSZ: libc::size_t = 131072;
-        #[cfg(target_os = "openbsd")]
+        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
         pub const SIGSTKSZ: libc::size_t = 40960;
 
         pub const SIG_DFL: sighandler_t = 0 as sighandler_t;
@@ -237,14 +240,14 @@ pub struct siginfo {
             pub si_addr: *mut libc::c_void
         }
 
-        #[cfg(target_os = "openbsd")]
+        #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
         #[repr(C)]
         pub struct siginfo {
             pub si_signo: libc::c_int,
             pub si_code: libc::c_int,
             pub si_errno: libc::c_int,
-            // union
-            pub si_addr: *mut libc::c_void,
+            //union
+            pub si_addr: *mut libc::c_void
         }
 
         #[repr(C)]
@@ -277,6 +280,7 @@ pub fn sigaltstack(ss: *const sigaltstack,
 
 #[cfg(not(any(target_os = "linux",
               target_os = "macos",
+              target_os = "bitrig",
               target_os = "openbsd")))]
 mod imp {
     use libc;
index bc93513af63d4609f2593ba42ef213608c23dbe6..c7d704922cb7fbdb0ac8e5c5267683e635d1b23b 100644 (file)
@@ -46,6 +46,7 @@ pub fn gettimeofday(tp: *mut libc::timeval,
 
 #[cfg(any(target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 mod os {
     use libc;
index c8f9d318482b09c39a3a2a9f993c2f1d27e11e83..b08f6ef9b9032ebe19b9af176d086164f0de2d7a 100644 (file)
@@ -67,9 +67,9 @@ pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
             -1 => Err(last_net_error()),
             _ => {
                 let (reader, writer) = try!(unsafe { sys::os::pipe() });
-                try!(set_nonblocking(reader.fd(), true));
-                try!(set_nonblocking(writer.fd(), true));
-                try!(set_nonblocking(self.fd(), true));
+                set_nonblocking(reader.fd(), true);
+                set_nonblocking(writer.fd(), true);
+                set_nonblocking(self.fd(), true);
                 Ok(TcpAcceptor {
                     inner: Arc::new(AcceptorInner {
                         listener: self,
index c90ba7645feb4b29f14a6b6854804c6d79d617e9..f4791d39da19055e6925db6d923ed98527eb4097 100644 (file)
@@ -11,6 +11,7 @@
 use core::prelude::*;
 
 use io;
+use boxed;
 use boxed::Box;
 use cmp;
 use mem;
@@ -34,6 +35,7 @@
 
 #[cfg(all(not(target_os = "linux"),
           not(target_os = "macos"),
+          not(target_os = "bitrig"),
           not(target_os = "openbsd")))]
 pub mod guard {
     pub unsafe fn current() -> uint {
@@ -51,11 +53,13 @@ pub unsafe fn init() {
 
 #[cfg(any(target_os = "linux",
           target_os = "macos",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub mod guard {
     use super::*;
     #[cfg(any(target_os = "linux",
               target_os = "android",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     use mem;
     #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -72,7 +76,9 @@ pub mod guard {
     static mut PAGE_SIZE: uint = 0;
     static mut GUARD_PAGE: uint = 0;
 
-    #[cfg(any(target_os = "macos", target_os = "openbsd"))]
+    #[cfg(any(target_os = "macos",
+              target_os = "bitrig",
+              target_os = "openbsd"))]
     unsafe fn get_stack_start() -> *mut libc::c_void {
         current() as *mut libc::c_void
     }
@@ -190,6 +196,22 @@ pub unsafe fn current() -> uint {
 
         stackaddr as uint + guardsize as uint
     }
+
+    #[cfg(target_os = "bitrig")]
+    pub unsafe fn current() -> uint {
+      let mut current_stack: stack_t = mem::zeroed();
+      if pthread_stackseg_np(pthread_self(), &mut current_stack) != 0 {
+        panic!("failed to get current stack: pthread_stackseg_np")
+      }
+
+      if pthread_main_np() == 1 {
+        // main thread
+        current_stack.ss_sp as uint - current_stack.ss_size as uint + 3 * PAGE_SIZE as uint
+      } else {
+        // new thread
+        current_stack.ss_sp as uint - current_stack.ss_size as uint
+      }
+    }
 }
 
 pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
@@ -220,13 +242,15 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
         },
     };
 
-    let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint
+    // must box since sizeof(p)=2*uint
+    let raw_p = boxed::into_raw(box p);
+    let arg = raw_p as *mut libc::c_void;
     let ret = pthread_create(&mut native, &attr, thread_start, arg);
     assert_eq!(pthread_attr_destroy(&mut attr), 0);
 
     if ret != 0 {
         // be sure to not leak the closure
-        let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
+        let _p: Box<Thunk> = Box::from_raw(raw_p);
         Err(io::Error::from_os_error(ret))
     } else {
         Ok(native)
@@ -252,6 +276,7 @@ pub unsafe fn set_name(name: &str) {
 
 #[cfg(any(target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 pub unsafe fn set_name(name: &str) {
     // pthread_set_name_np() since almost forever on all BSDs
@@ -334,6 +359,15 @@ pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
     fn pthread_setname_np(name: *const libc::c_char) -> libc::c_int;
 }
 
+#[cfg(target_os = "bitrig")]
+extern {
+    pub fn pthread_self() -> libc::pthread_t;
+    pub fn pthread_stackseg_np(thread: libc::pthread_t,
+                              sinfo: *mut stack_t) -> libc::c_uint;
+    pub fn pthread_main_np() -> libc::c_uint;
+    fn pthread_set_name_np(tid: libc::pthread_t, name: *const libc::c_char);
+}
+
 #[cfg(target_os = "openbsd")]
 extern {
         pub fn pthread_stackseg_np(thread: libc::pthread_t,
@@ -341,7 +375,7 @@ pub fn pthread_stackseg_np(thread: libc::pthread_t,
         pub fn pthread_main_np() -> libc::c_uint;
 }
 
-#[cfg(target_os = "openbsd")]
+#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
 #[repr(C)]
 pub struct stack_t {
     pub ss_sp: *mut libc::c_void,
index 62d9a33c83d7af78d0280a0118e950844b59c99b..9b7079ee10833de308a6cb70ba250e59f5a8d959 100644 (file)
@@ -43,6 +43,7 @@ pub unsafe fn destroy(key: Key) {
 
 #[cfg(any(target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 type pthread_key_t = ::libc::c_int;
 
@@ -50,6 +51,7 @@ pub unsafe fn destroy(key: Key) {
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd")))]
 type pthread_key_t = ::libc::c_uint;
 
index bddf7b075df96ab365f534484bde9e6cff17e373..1104bc995c6ea7961e8b2d2a979590b75f3614d5 100644 (file)
@@ -80,8 +80,11 @@ pub struct SteadyTime {
     }
 
     // Apparently android provides this in some other library?
+    // Bitrig's RT extensions are in the C library, not a separate librt
     // OpenBSD provide it via libc
-    #[cfg(not(any(target_os = "android", target_os = "openbsd")))]
+    #[cfg(not(any(target_os = "android",
+                  target_os = "bitrig",
+                  target_os = "openbsd")))]
     #[link(name = "rt")]
     extern {}
 
index 3a79047445cdd8d10a5a70b6c9df8d36e60649f7..8e60bbf4cbd00a5e655fb1e6d477bb0fc239a788 100644 (file)
@@ -22,6 +22,7 @@ pub struct TTY {
 
 #[cfg(any(target_os = "macos",
           target_os = "freebsd",
+          target_os = "bitrig",
           target_os = "openbsd"))]
 const TIOCGWINSZ: c_ulong = 0x40087468;
 
@@ -55,6 +56,7 @@ pub fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
               target_os = "android",
               target_os = "macos",
               target_os = "freebsd",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     pub fn get_winsize(&mut self) -> IoResult<(int, int)> {
         unsafe {
index db8038006fd6a81451a3783951609bddb7f8719f..071637e3a939f82eda497d497dabdbef9e72ea31 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use libc::{self, DWORD};
 use os;
@@ -17,6 +19,9 @@
 
 pub struct Condvar { inner: UnsafeCell<ffi::CONDITION_VARIABLE> }
 
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
 pub const CONDVAR_INIT: Condvar = Condvar {
     inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT }
 };
index 304d7e015327960747c3fc6dbb0e413d4b5845fd..309d6c9dc48c26b48c27f4cae8af38e2a11a194c 100644 (file)
@@ -368,7 +368,9 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
                                   buf as *const u16,
                                   sz - 1,
                                   libc::VOLUME_NAME_DOS)
-    }, super::os2path);
+    }, |data| {
+        Path::new(String::from_utf16(data).unwrap())
+    });
     assert!(unsafe { libc::CloseHandle(handle) } != 0);
     return ret;
 }
index 8abcd90efe8578a6cab8523babf818b1a12e8b44..117f819eeeb3fd870ac36dc485d6874630ad0ced 100644 (file)
@@ -19,6 +19,7 @@
 use mem;
 use path::{Path, PathBuf};
 use ptr;
+use sync::Arc;
 use sys::handle::Handle as RawHandle;
 use sys::{c, cvt};
 use vec::Vec;
@@ -27,12 +28,20 @@ pub struct File { handle: RawHandle }
 pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
 
 pub struct ReadDir {
-    handle: libc::HANDLE,
-    root: PathBuf,
+    handle: FindNextFileHandle,
+    root: Arc<PathBuf>,
     first: Option<libc::WIN32_FIND_DATAW>,
 }
 
-pub struct DirEntry { path: PathBuf }
+struct FindNextFileHandle(libc::HANDLE);
+
+unsafe impl Send for FindNextFileHandle {}
+unsafe impl Sync for FindNextFileHandle {}
+
+pub struct DirEntry {
+    root: Arc<PathBuf>,
+    data: libc::WIN32_FIND_DATAW,
+}
 
 #[derive(Clone, Default)]
 pub struct OpenOptions {
@@ -61,7 +70,7 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
         unsafe {
             let mut wfd = mem::zeroed();
             loop {
-                if libc::FindNextFileW(self.handle, &mut wfd) == 0 {
+                if libc::FindNextFileW(self.handle.0, &mut wfd) == 0 {
                     if libc::GetLastError() ==
                         c::ERROR_NO_MORE_FILES as libc::DWORD {
                         return None
@@ -77,15 +86,15 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
     }
 }
 
-impl Drop for ReadDir {
+impl Drop for FindNextFileHandle {
     fn drop(&mut self) {
-        let r = unsafe { libc::FindClose(self.handle) };
+        let r = unsafe { libc::FindClose(self.0) };
         debug_assert!(r != 0);
     }
 }
 
 impl DirEntry {
-    fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
+    fn new(root: &Arc<PathBuf>, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
         match &wfd.cFileName[0..3] {
             // check for '.' and '..'
             [46, 0, ..] |
@@ -93,13 +102,15 @@ fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
             _ => {}
         }
 
-        let filename = super::truncate_utf16_at_nul(&wfd.cFileName);
-        let filename: OsString = OsStringExt::from_wide(filename);
-        Some(DirEntry { path: root.join(&filename) })
+        Some(DirEntry {
+            root: root.clone(),
+            data: *wfd,
+        })
     }
 
     pub fn path(&self) -> PathBuf {
-        self.path.clone()
+        let filename = super::truncate_utf16_at_nul(&self.data.cFileName);
+        self.root.join(&<OsString as OsStringExt>::from_wide(filename))
     }
 }
 
@@ -312,7 +323,11 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
         let mut wfd = mem::zeroed();
         let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd);
         if find_handle != libc::INVALID_HANDLE_VALUE {
-            Ok(ReadDir { handle: find_handle, root: root, first: Some(wfd) })
+            Ok(ReadDir {
+                handle: FindNextFileHandle(find_handle),
+                root: Arc::new(root),
+                first: Some(wfd),
+            })
         } else {
             Err(Error::last_os_error())
         }
index a756fb29f81aeb5f32c4d446efb633cf6220b2b9..5bb2a134533ed0217b7dd9135b51e070e56fd346 100644 (file)
 
 use prelude::v1::*;
 
-use ffi::OsStr;
+use ffi::{OsStr, OsString};
 use io::{self, ErrorKind};
 use libc;
 use mem;
-use old_io::{self, IoResult, IoError};
 use num::Int;
-use os::windows::OsStrExt;
+use old_io::{self, IoResult, IoError};
+use os::windows::{OsStrExt, OsStringExt};
+use path::PathBuf;
 use sync::{Once, ONCE_INIT};
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
@@ -192,12 +193,12 @@ pub fn wouldblock() -> bool {
     err == libc::WSAEWOULDBLOCK as i32
 }
 
-pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
+pub fn set_nonblocking(fd: sock_t, nb: bool) {
     let mut set = nb as libc::c_ulong;
-    if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
-        Err(last_error())
-    } else {
-        Ok(())
+    if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 {
+        // The above function should not return an error unless we passed it
+        // invalid parameters. Panic on errors.
+        panic!("set_nonblocking called with invalid parameters: {}", last_error());
     }
 }
 
@@ -314,9 +315,10 @@ fn fill_utf16_buf_new<F1, F2, T>(f1: F1, f2: F2) -> io::Result<T>
     fill_utf16_buf_base(f1, f2).map_err(|()| io::Error::last_os_error())
 }
 
-fn os2path(s: &[u16]) -> Path {
-    // FIXME: this should not be a panicking conversion (aka path reform)
-    Path::new(String::from_utf16(s).unwrap())
+fn os2path(s: &[u16]) -> PathBuf {
+    let os = <OsString as OsStringExt>::from_wide(s);
+    // FIXME(#22751) should consume `os`
+    PathBuf::new(&os)
 }
 
 pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
index 75495efc7cbb60f9d2a7f12ffa78980f2540ab39..0847f3b52bfabe171e370bed4e1b6a43cb75bfa5 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use marker::Sync;
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use sys::sync as ffi;
 
@@ -18,6 +19,7 @@ pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
     inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
 };
 
+unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
 #[inline]
@@ -27,14 +29,15 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
 
 // So you might be asking why we're using SRWLock instead of CriticalSection?
 //
-// 1. SRWLock is several times faster than CriticalSection according to benchmarks performed on both
-// Windows 8 and Windows 7.
+// 1. SRWLock is several times faster than CriticalSection according to
+//    benchmarks performed on both Windows 8 and Windows 7.
 //
-// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix implementation
-// deadlocks so consistency is preferred. See #19962 for more details.
+// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix
+//    implementation deadlocks so consistency is preferred. See #19962 for more
+//    details.
 //
-// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy is there there are
-// no guarantees of fairness.
+// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
+//    is there there are no guarantees of fairness.
 
 impl Mutex {
     #[inline]
index 3451232f40ab89acb88de0fa53ce591dc2739cbd..6caa4df5dfe6269e58bd3fa903e4ee19d70dfe81 100644 (file)
@@ -25,6 +25,8 @@
 
 pub struct Socket(libc::SOCKET);
 
+/// Checks whether the Windows socket interface has been started already, and
+/// if not, starts it.
 pub fn init() {
     static START: Once = ONCE_INIT;
 
@@ -38,10 +40,16 @@ pub fn init() {
     });
 }
 
+/// Returns the last error from the Windows socket interface.
 fn last_error() -> io::Error {
     io::Error::from_os_error(unsafe { c::WSAGetLastError() })
 }
 
+/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
+/// and if so, returns the last error from the Windows socket interface. . This
+/// function must be called before another call to the socket API is made.
+///
+/// FIXME: generics needed?
 pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
     let one: T = Int::one();
     if t == -one {
@@ -51,11 +59,14 @@ pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
     }
 }
 
+/// Provides the functionality of `cvt` for the return values of `getaddrinfo`
+/// and similar, meaning that they return an error if the return value is 0.
 pub fn cvt_gai(err: c_int) -> io::Result<()> {
     if err == 0 { return Ok(()) }
     cvt(err).map(|_| ())
 }
 
+/// Provides the functionality of `cvt` for a closure.
 pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T {
     cvt(f())
 }
@@ -112,7 +123,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
 
 impl Drop for Socket {
     fn drop(&mut self) {
-        unsafe { let _ = libc::closesocket(self.0); }
+        unsafe { cvt(libc::closesocket(self.0)).unwrap(); }
     }
 }
 
index 6520d30487c76d978e6d5441370214c0332402c3..587ab7924fd1dc541fd7751cb82a61ff077f3362 100644 (file)
 use error::Error as StdError;
 use ffi::{OsString, OsStr, AsOsStr};
 use fmt;
-use ops::Range;
+use io;
 use libc::types::os::arch::extra::LPWCH;
 use libc::{self, c_int, c_void};
 use mem;
 use old_io::{IoError, IoResult};
+use ops::Range;
+use path::{self, PathBuf};
 use ptr;
 use slice;
 use sys::c;
@@ -151,8 +153,8 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
-    type Item = Path;
-    fn next(&mut self) -> Option<Path> {
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> {
         // On Windows, the PATH environment variable is semicolon separated.
         // Double quotes are used as a way of introducing literal semicolons
         // (since c:\some;dir is a valid Windows path). Double quotes are not
@@ -186,7 +188,7 @@ fn next(&mut self) -> Option<Path> {
         if !must_yield && in_progress.is_empty() {
             None
         } else {
-            Some(super::os2path(&in_progress[..]))
+            Some(super::os2path(&in_progress))
         }
     }
 }
@@ -228,33 +230,33 @@ impl StdError for JoinPathsError {
     fn description(&self) -> &str { "failed to join paths" }
 }
 
-pub fn current_exe() -> IoResult<Path> {
-    super::fill_utf16_buf(|buf, sz| unsafe {
+pub fn current_exe() -> io::Result<PathBuf> {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
     }, super::os2path)
 }
 
-pub fn getcwd() -> IoResult<Path> {
-    super::fill_utf16_buf(|buf, sz| unsafe {
+pub fn getcwd() -> io::Result<PathBuf> {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         libc::GetCurrentDirectoryW(sz, buf)
     }, super::os2path)
 }
 
-pub fn chdir(p: &Path) -> IoResult<()> {
+pub fn chdir(p: &path::Path) -> io::Result<()> {
     let mut p = p.as_os_str().encode_wide().collect::<Vec<_>>();
     p.push(0);
 
     unsafe {
         match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
             true => Ok(()),
-            false => Err(IoError::last_error()),
+            false => Err(io::Error::last_os_error()),
         }
     }
 }
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     let k = super::to_utf16_os(k);
-    super::fill_utf16_buf(|buf, sz| unsafe {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
     }, |buf| {
         OsStringExt::from_wide(buf)
@@ -349,18 +351,18 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
     }
 }
 
-pub fn temp_dir() -> Path {
-    super::fill_utf16_buf(|buf, sz| unsafe {
+pub fn temp_dir() -> PathBuf {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         c::GetTempPathW(sz, buf)
     }, super::os2path).unwrap()
 }
 
-pub fn home_dir() -> Option<Path> {
+pub fn home_dir() -> Option<PathBuf> {
     getenv("HOME".as_os_str()).or_else(|| {
         getenv("USERPROFILE".as_os_str())
     }).map(|os| {
-        // FIXME: OsString => Path
-        Path::new(os.to_str().unwrap())
+        // FIXME(#22751) should consume `os`
+        PathBuf::new(&os)
     }).or_else(|| unsafe {
         let me = c::GetCurrentProcess();
         let mut token = ptr::null_mut();
@@ -368,7 +370,7 @@ pub fn home_dir() -> Option<Path> {
             return None
         }
         let _handle = RawHandle::new(token);
-        super::fill_utf16_buf(|buf, mut sz| {
+        super::fill_utf16_buf_new(|buf, mut sz| {
             match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
                 0 if libc::GetLastError() != 0 => 0,
                 0 => sz,
index 60d24e6174fd757a5cd949443ebc803ae1a6b61e..334cafd3eb1136767fa4cc355360e44aafa50183 100644 (file)
@@ -10,7 +10,6 @@
 
 use prelude::v1::*;
 
-#[cfg(stage0)] use collections::hash_map::Hasher;
 use collections;
 use env;
 use ffi::CString;
@@ -106,170 +105,6 @@ pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
     }
 
     #[allow(deprecated)]
-    #[cfg(stage0)]
-    pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
-                              out_fd: Option<P>, err_fd: Option<P>)
-                              -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
-              K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
-    {
-        use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
-        use libc::consts::os::extra::{
-            TRUE, FALSE,
-            STARTF_USESTDHANDLES,
-            INVALID_HANDLE_VALUE,
-            DUPLICATE_SAME_ACCESS
-        };
-        use libc::funcs::extra::kernel32::{
-            GetCurrentProcess,
-            DuplicateHandle,
-            CloseHandle,
-            CreateProcessW
-        };
-        use libc::funcs::extra::msvcrt::get_osfhandle;
-
-        use mem;
-        use iter::IteratorExt;
-        use str::StrExt;
-
-        if cfg.gid().is_some() || cfg.uid().is_some() {
-            return Err(IoError {
-                kind: old_io::IoUnavailable,
-                desc: "unsupported gid/uid requested on windows",
-                detail: None,
-            })
-        }
-
-        // To have the spawning semantics of unix/windows stay the same, we need to
-        // read the *child's* PATH if one is provided. See #15149 for more details.
-        let program = cfg.env().and_then(|env| {
-            for (key, v) in env {
-                if b"PATH" != key.container_as_bytes() { 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())
-                                   .with_extension(env::consts::EXE_EXTENSION);
-                    if path.exists() {
-                        return Some(CString::from_slice(path.as_vec()))
-                    }
-                }
-                break
-            }
-            None
-        });
-
-        unsafe {
-            let mut si = zeroed_startupinfo();
-            si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
-            si.dwFlags = STARTF_USESTDHANDLES;
-
-            let cur_proc = GetCurrentProcess();
-
-            // Similarly to unix, we don't actually leave holes for the stdio file
-            // descriptors, but rather open up /dev/null equivalents. These
-            // equivalents are drawn from libuv's windows process spawning.
-            let set_fd = |fd: &Option<P>, slot: &mut HANDLE,
-                          is_stdin: bool| {
-                match *fd {
-                    None => {
-                        let access = if is_stdin {
-                            libc::FILE_GENERIC_READ
-                        } else {
-                            libc::FILE_GENERIC_WRITE | libc::FILE_READ_ATTRIBUTES
-                        };
-                        let size = mem::size_of::<libc::SECURITY_ATTRIBUTES>();
-                        let mut sa = libc::SECURITY_ATTRIBUTES {
-                            nLength: size as libc::DWORD,
-                            lpSecurityDescriptor: ptr::null_mut(),
-                            bInheritHandle: 1,
-                        };
-                        let mut filename: Vec<u16> = "NUL".utf16_units().collect();
-                        filename.push(0);
-                        *slot = libc::CreateFileW(filename.as_ptr(),
-                                                  access,
-                                                  libc::FILE_SHARE_READ |
-                                                      libc::FILE_SHARE_WRITE,
-                                                  &mut sa,
-                                                  libc::OPEN_EXISTING,
-                                                  0,
-                                                  ptr::null_mut());
-                        if *slot == INVALID_HANDLE_VALUE {
-                            return Err(super::last_error())
-                        }
-                    }
-                    Some(ref fd) => {
-                        let orig = get_osfhandle(fd.as_inner().fd()) as HANDLE;
-                        if orig == INVALID_HANDLE_VALUE {
-                            return Err(super::last_error())
-                        }
-                        if DuplicateHandle(cur_proc, orig, cur_proc, slot,
-                                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-                            return Err(super::last_error())
-                        }
-                    }
-                }
-                Ok(())
-            };
-
-            try!(set_fd(&in_fd, &mut si.hStdInput, true));
-            try!(set_fd(&out_fd, &mut si.hStdOutput, false));
-            try!(set_fd(&err_fd, &mut si.hStdError, false));
-
-            let cmd_str = make_command_line(program.as_ref().unwrap_or(cfg.program()),
-                                            cfg.args());
-            let mut pi = zeroed_process_information();
-            let mut create_err = None;
-
-            // stolen from the libuv code.
-            let mut flags = libc::CREATE_UNICODE_ENVIRONMENT;
-            if cfg.detach() {
-                flags |= libc::DETACHED_PROCESS | libc::CREATE_NEW_PROCESS_GROUP;
-            }
-
-            with_envp(cfg.env(), |envp| {
-                with_dirp(cfg.cwd(), |dirp| {
-                    let mut cmd_str: Vec<u16> = cmd_str.utf16_units().collect();
-                    cmd_str.push(0);
-                    let _lock = CREATE_PROCESS_LOCK.lock().unwrap();
-                    let created = CreateProcessW(ptr::null(),
-                                                 cmd_str.as_mut_ptr(),
-                                                 ptr::null_mut(),
-                                                 ptr::null_mut(),
-                                                 TRUE,
-                                                 flags, envp, dirp,
-                                                 &mut si, &mut pi);
-                    if created == FALSE {
-                        create_err = Some(super::last_error());
-                    }
-                })
-            });
-
-            assert!(CloseHandle(si.hStdInput) != 0);
-            assert!(CloseHandle(si.hStdOutput) != 0);
-            assert!(CloseHandle(si.hStdError) != 0);
-
-            match create_err {
-                Some(err) => return Err(err),
-                None => {}
-            }
-
-            // We close the thread handle because we don't care about keeping the
-            // thread id valid, and we aren't keeping the thread handle around to be
-            // able to close it later. We don't close the process handle however
-            // because std::we want the process id to stay valid at least until the
-            // calling code closes the process handle.
-            assert!(CloseHandle(pi.hThread) != 0);
-
-            Ok(Process {
-                pid: pi.dwProcessId as pid_t,
-                handle: pi.hProcess as *mut ()
-            })
-        }
-    }
-    #[allow(deprecated)]
-    #[cfg(not(stage0))]
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
@@ -589,35 +424,6 @@ fn backslash_run_ends_in_quote(s: &[char], mut i: uint) -> bool {
     }
 }
 
-#[cfg(stage0)]
-fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
-    where K: BytesContainer + Eq + Hash<Hasher>,
-          V: BytesContainer,
-          F: FnOnce(*mut c_void) -> T,
-{
-    // On Windows we pass an "environment block" which is not a char**, but
-    // rather a concatenation of null-terminated k=v\0 sequences, with a final
-    // \0 to terminate.
-    match env {
-        Some(env) => {
-            let mut blk = Vec::new();
-
-            for pair in env {
-                let kv = format!("{}={}",
-                                 pair.0.container_as_str().unwrap(),
-                                 pair.1.container_as_str().unwrap());
-                blk.extend(kv.utf16_units());
-                blk.push(0);
-            }
-
-            blk.push(0);
-
-            cb(blk.as_mut_ptr() as *mut c_void)
-        }
-        _ => cb(ptr::null_mut())
-    }
-}
-#[cfg(not(stage0))]
 fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
     where K: BytesContainer + Eq + Hash,
           V: BytesContainer,
index 19e38196d199fc360f20c199dd5047ed9cf5d939..d4c6e85489f5d25d87f82e01791834869ba96fea 100644 (file)
 use env;
 use ffi::{OsString, OsStr};
 use fmt;
+use fs;
 use io::{self, Error};
 use libc::{self, c_void};
-use old_io::fs;
-use old_path;
 use os::windows::OsStrExt;
 use ptr;
 use sync::{StaticMutex, MUTEX_INIT};
+use sys::handle::Handle;
 use sys::pipe2::AnonPipe;
 use sys::{self, cvt};
-use sys::handle::Handle;
 use sys_common::{AsInner, FromInner};
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -142,9 +141,8 @@ pub fn spawn(cfg: &Command,
                 for path in split_paths(&v) {
                     let path = path.join(cfg.program.to_str().unwrap())
                                    .with_extension(env::consts::EXE_EXTENSION);
-                    // FIXME: update with new fs module once it lands
-                    if fs::stat(&old_path::Path::new(&path)).is_ok() {
-                        return Some(OsString::from_str(path.as_str().unwrap()))
+                    if fs::metadata(&path).is_ok() {
+                        return Some(path.into_os_string())
                     }
                 }
                 break
index 76fe352ed7717cf6ca623bb693a1fcf48663d5c1..009605535a0237026d18ec29e0d783feb626a362 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use sys::sync as ffi;
 
@@ -17,6 +19,9 @@ pub struct RWLock { inner: UnsafeCell<ffi::SRWLOCK> }
     inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
 };
 
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
 impl RWLock {
     #[inline]
     pub unsafe fn read(&self) {
index 4804ca510cb0ba0e9be1b8fffdbd75285e78a703..25b70918591d0fc54c6ad488f36f8e42643013ac 100644 (file)
@@ -192,7 +192,7 @@ pub fn accept(&mut self) -> IoResult<TcpStream> {
                         c::WSAEventSelect(socket, events[1], 0)
                     };
                     if ret != 0 { return Err(last_net_error()) }
-                    try!(set_nonblocking(socket, false));
+                    set_nonblocking(socket, false);
                     return Ok(stream)
                 }
             }
index f3a27877e5c58512fc8c6dce9dc08749141f12d5..aa22b6b1307a340247269dbb02c16f4bc177a620 100644 (file)
@@ -10,9 +10,9 @@
 
 use prelude::v1::*;
 
+use boxed;
 use cmp;
 use io;
-use mem;
 use ptr;
 use libc;
 use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
@@ -45,7 +45,8 @@ pub unsafe fn init() {
 }
 
 pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
-    let arg: *mut libc::c_void = mem::transmute(box p);
+    let raw_p = boxed::into_raw(box p);
+    let arg = raw_p as *mut libc::c_void;
     // FIXME On UNIX, we guard against stack sizes that are too small but
     // that's because pthreads enforces that stacks are at least
     // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
@@ -61,7 +62,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result<rust_thread> {
 
     if ret as uint == 0 {
         // be sure to not leak the closure
-        let _p: Box<Thunk> = mem::transmute(arg);
+        let _p: Box<Thunk> = Box::from_raw(raw_p);
         Err(io::Error::last_os_error())
     } else {
         Ok(ret)
index 0c24ab1fa09b4e964f1f424f5c4d117e8e4e93bc..30c483ac52fa261a4c3a0b6d4052b038ef6cd374 100644 (file)
@@ -12,7 +12,7 @@
 
 use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
 
-use mem;
+use boxed;
 use ptr;
 use rt;
 use sys_common::mutex::{MUTEX_INIT, Mutex};
@@ -133,13 +133,13 @@ unsafe fn init_dtors() {
     if !DTORS.is_null() { return }
 
     let dtors = box Vec::<(Key, Dtor)>::new();
-    DTORS = mem::transmute(dtors);
+    DTORS = boxed::into_raw(dtors);
 
     rt::at_exit(move|| {
         DTOR_LOCK.lock();
         let dtors = DTORS;
         DTORS = ptr::null_mut();
-        mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
+        Box::from_raw(dtors);
         assert!(DTORS.is_null()); // can't re-init after destructing
         DTOR_LOCK.unlock();
     });
index 8a8b53090570cadcd188b6f840b41ffbe81771ed..c9bac69c434c32ff965213742d1c4d0c08346d51 100644 (file)
@@ -52,7 +52,7 @@ fn invalid_encoding() -> IoError {
 
 pub fn is_tty(fd: c_int) -> bool {
     let mut out: DWORD = 0;
-    // If this function doesn't panic then fd is a TTY
+    // If this function doesn't return an error, then fd is a TTY
     match unsafe { GetConsoleMode(get_osfhandle(fd) as HANDLE,
                                   &mut out as LPDWORD) } {
         0 => false,
index 3653e7e31d5c6df556132b437f9ea107f16547a4..6aad2bbcc7f08b47ab57f6dbd0f097cedbd2ce08 100644 (file)
@@ -342,12 +342,15 @@ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
     }
 }
 
-/// Spawn a new, returning a join handle for it.
+/// Spawn a new thread, returning a `JoinHandle` for it.
 ///
-/// The child thread may outlive the parent (unless the parent thread
-/// is the main thread; the whole process is terminated when the main
-/// thread finishes.) The join handle can be used to block on
-/// termination of the child thread, including recovering its panics.
+/// The join handle will implicitly *detach* the child thread upon being
+/// dropped. In this case, the child thread may outlive the parent (unless
+/// the parent thread is the main thread; the whole process is terminated when
+/// the main thread finishes.) Additionally, the join handle provides a `join`
+/// method that can be used to join the child thread. If the child thread
+/// panics, `join` will return an `Err` containing the argument given to
+/// `panic`.
 ///
 /// # Panics
 ///
@@ -465,16 +468,16 @@ fn new(name: Option<String>) -> Thread {
         }
     }
 
-    /// Deprecated: use module-level free fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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 fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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
@@ -483,30 +486,30 @@ pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
         Builder::new().scoped(f).unwrap()
     }
 
-    /// Deprecated: use module-level free fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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 fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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 fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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 fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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();
@@ -517,8 +520,8 @@ pub fn park() {
         *guard = false;
     }
 
-    /// Deprecated: use module-level free fucntion.
-    #[deprecated(since = "1.0.0", reason = "use module-level free fucntion")]
+    /// 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(dur: Duration) {
         let thread = current();
@@ -702,7 +705,7 @@ mod test {
     use boxed::BoxAny;
     use result;
     use std::old_io::{ChanReader, ChanWriter};
-    use super::{Thread, Builder};
+    use super::{Builder};
     use thread;
     use thunk::Thunk;
     use time::Duration;
@@ -767,7 +770,7 @@ fn test_scoped_panic() {
     #[test]
     #[should_fail]
     fn test_scoped_implicit_panic() {
-        thread::scoped(|| panic!());
+        let _ = thread::scoped(|| panic!());
     }
 
     #[test]
index 2ed296e081c90f3b4a5988fbaf4332633d43bba6..d65156dae9604835e9459e8874a1823a79d0d9de 100644 (file)
@@ -74,7 +74,7 @@ pub mod __impl {
 /// use std::cell::RefCell;
 /// use std::thread;
 ///
-/// thread_local!(static FOO: RefCell<uint> = RefCell::new(1));
+/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
 ///
 /// FOO.with(|f| {
 ///     assert_eq!(*f.borrow(), 1);
@@ -388,6 +388,7 @@ unsafe fn register_dtor(&self) {
     // Due to rust-lang/rust#18804, make sure this is not generic!
     #[cfg(target_os = "linux")]
     unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+        use boxed;
         use mem;
         use libc;
         use sys_common::thread_local as os;
@@ -422,14 +423,14 @@ unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
         type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
         if DTORS.get().is_null() {
             let v: Box<List> = box Vec::new();
-            DTORS.set(mem::transmute(v));
+            DTORS.set(boxed::into_raw(v) as *mut u8);
         }
         let list: &mut List = &mut *(DTORS.get() as *mut List);
         list.push((t, dtor));
 
         unsafe extern fn run_dtors(mut ptr: *mut u8) {
             while !ptr.is_null() {
-                let list: Box<List> = mem::transmute(ptr);
+                let list: Box<List> = Box::from_raw(ptr as *mut List);
                 for &(ptr, dtor) in &*list {
                     dtor(ptr);
                 }
@@ -467,6 +468,7 @@ fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
 mod imp {
     use prelude::v1::*;
 
+    use alloc::boxed;
     use cell::UnsafeCell;
     use mem;
     use ptr;
@@ -501,7 +503,7 @@ pub unsafe fn get(&'static self) -> Option<&'static T> {
         unsafe fn ptr(&'static self) -> Option<*mut T> {
             let ptr = self.os.get() as *mut Value<T>;
             if !ptr.is_null() {
-                if ptr as uint == 1 {
+                if ptr as usize == 1 {
                     return None
                 }
                 return Some(&mut (*ptr).value as *mut T);
@@ -517,7 +519,7 @@ unsafe fn ptr(&'static self) -> Option<*mut T> {
                 key: self,
                 value: mem::transmute_copy(&self.inner),
             };
-            let ptr: *mut Value<T> = mem::transmute(ptr);
+            let ptr: *mut Value<T> = boxed::into_raw(ptr);
             self.os.set(ptr as *mut u8);
             Some(&mut (*ptr).value as *mut T)
         }
@@ -533,7 +535,7 @@ unsafe fn ptr(&'static self) -> Option<*mut T> {
         //
         // Note that to prevent an infinite loop we reset it back to null right
         // before we return from the destructor ourselves.
-        let ptr: Box<Value<T>> = mem::transmute(ptr);
+        let ptr: Box<Value<T>> = Box::from_raw(ptr as *mut Value<T>);
         let key = ptr.key;
         key.os.set(1 as *mut u8);
         drop(ptr);
@@ -561,7 +563,7 @@ fn drop(&mut self) {
 
     #[test]
     fn smoke_no_dtor() {
-        thread_local!(static FOO: UnsafeCell<int> = UnsafeCell { value: 1 });
+        thread_local!(static FOO: UnsafeCell<i32> = UnsafeCell { value: 1 });
 
         FOO.with(|f| unsafe {
             assert_eq!(*f.get(), 1);
@@ -630,7 +632,7 @@ fn circular() {
         thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
             value: None
         });
-        static mut HITS: uint = 0;
+        static mut HITS: u32 = 0;
 
         impl Drop for S1 {
             fn drop(&mut self) {
@@ -721,8 +723,8 @@ mod dynamic_tests {
 
     #[test]
     fn smoke() {
-        fn square(i: int) -> int { i * i }
-        thread_local!(static FOO: int = square(3));
+        fn square(i: i32) -> i32 { i * i }
+        thread_local!(static FOO: i32 = square(3));
 
         FOO.with(|f| {
             assert_eq!(*f, 9);
@@ -731,12 +733,12 @@ fn square(i: int) -> int { i * i }
 
     #[test]
     fn hashmap() {
-        fn map() -> RefCell<HashMap<int, int>> {
+        fn map() -> RefCell<HashMap<i32, i32>> {
             let mut m = HashMap::new();
             m.insert(1, 2);
             RefCell::new(m)
         }
-        thread_local!(static FOO: RefCell<HashMap<int, int>> = map());
+        thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
 
         FOO.with(|map| {
             assert_eq!(map.borrow()[1], 2);
@@ -745,7 +747,7 @@ fn map() -> RefCell<HashMap<int, int>> {
 
     #[test]
     fn refcell_vec() {
-        thread_local!(static FOO: RefCell<Vec<uint>> = RefCell::new(vec![1, 2, 3]));
+        thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
 
         FOO.with(|vec| {
             assert_eq!(vec.borrow().len(), 3);
index 01220e7bc1fe1d0baf0460af5dab84a342b94e4a..a2a5d8b81f40458e43b018fe77bb9d5426ee294d 100644 (file)
@@ -24,7 +24,7 @@
 //! # Example
 //!
 //! ```
-//! scoped_thread_local!(static FOO: uint);
+//! scoped_thread_local!(static FOO: u32);
 //!
 //! // Initially each scoped slot is empty.
 //! assert!(!FOO.is_set());
@@ -140,7 +140,7 @@ impl<T> Key<T> {
     /// # Example
     ///
     /// ```
-    /// scoped_thread_local!(static FOO: uint);
+    /// scoped_thread_local!(static FOO: u32);
     ///
     /// FOO.set(&100, || {
     ///     let val = FOO.with(|v| *v);
@@ -192,7 +192,7 @@ fn drop(&mut self) {
     /// # Example
     ///
     /// ```no_run
-    /// scoped_thread_local!(static FOO: uint);
+    /// scoped_thread_local!(static FOO: u32);
     ///
     /// FOO.with(|slot| {
     ///     // work with `slot`
@@ -269,11 +269,11 @@ mod tests {
     use cell::Cell;
     use prelude::v1::*;
 
-    scoped_thread_local!(static FOO: uint);
+    scoped_thread_local!(static FOO: u32);
 
     #[test]
     fn smoke() {
-        scoped_thread_local!(static BAR: uint);
+        scoped_thread_local!(static BAR: u32);
 
         assert!(!BAR.is_set());
         BAR.set(&1, || {
@@ -287,7 +287,7 @@ fn smoke() {
 
     #[test]
     fn cell_allowed() {
-        scoped_thread_local!(static BAR: Cell<uint>);
+        scoped_thread_local!(static BAR: Cell<u32>);
 
         BAR.set(&Cell::new(1), || {
             BAR.with(|slot| {
index fe39954f0d446fd5ae3b45d8971b097a8ecae6a6..5bede984f13c7bc37bdb9bb00ccc443419664340 100644 (file)
@@ -17,9 +17,6 @@
 use core::ops::FnOnce;
 
 pub struct Thunk<'a, A=(),R=()> {
-    #[cfg(stage0)]
-    invoke: Box<Invoke<A,R>+Send>,
-    #[cfg(not(stage0))]
     invoke: Box<Invoke<A,R>+Send + 'a>,
 }
 
index de3fa1135b161382d5cb13eb363c026cd72c6aae..2cf157bd245227f3710a0243b14c4b52919a0d4c 100644 (file)
@@ -24,6 +24,7 @@ pub enum Os {
     OsFreebsd,
     OsiOS,
     OsDragonfly,
+    OsBitrig,
     OsOpenbsd,
 }
 
@@ -136,6 +137,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             OsAndroid => "android".fmt(f),
             OsFreebsd => "freebsd".fmt(f),
             OsDragonfly => "dragonfly".fmt(f),
+            OsBitrig => "bitrig".fmt(f),
             OsOpenbsd => "openbsd".fmt(f),
         }
     }
index 140e21b5d04b756cb0a1abcf4e838f74a56e3231..6d6fdffa95095b25c6fd6b5684df59d12d8ae611 100644 (file)
@@ -753,11 +753,10 @@ pub enum Expr_ {
     ExprIndex(P<Expr>, P<Expr>),
     ExprRange(Option<P<Expr>>, Option<P<Expr>>),
 
-    /// Variable reference, possibly containing `::` and/or
-    /// type parameters, e.g. foo::bar::<baz>
-    ExprPath(Path),
-    /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
-    ExprQPath(P<QPath>),
+    /// Variable reference, possibly containing `::` and/or type
+    /// parameters, e.g. foo::bar::<baz>. Optionally "qualified",
+    /// e.g. `<Vec<T> as SomeTrait>::SomeType`.
+    ExprPath(Option<QSelf>, Path),
 
     ExprAddrOf(Mutability, P<Expr>),
     ExprBreak(Option<Ident>),
@@ -778,16 +777,22 @@ pub enum Expr_ {
     ExprParen(P<Expr>)
 }
 
-/// A "qualified path":
+/// The explicit Self type in a "qualified path". The actual
+/// path, including the trait and the associated item, is stored
+/// sepparately. `position` represents the index of the associated
+/// item qualified with this Self type.
 ///
-///     <Vec<T> as SomeTrait>::SomeAssociatedItem
-///      ^~~~~     ^~~~~~~~~   ^~~~~~~~~~~~~~~~~~
-///      self_type  trait_name  item_path
+///     <Vec<T> as a::b::Trait>::AssociatedItem
+///      ^~~~~     ~~~~~~~~~~~~~~^
+///      ty        position = 3
+///
+///     <Vec<T>>::AssociatedItem
+///      ^~~~~    ^
+///      ty       position = 0
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct QPath {
-    pub self_type: P<Ty>,
-    pub trait_ref: P<TraitRef>,
-    pub item_path: PathSegment,
+pub struct QSelf {
+    pub ty: P<Ty>,
+    pub position: usize
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1254,16 +1259,15 @@ pub enum Ty_ {
     TyBareFn(P<BareFnTy>),
     /// A tuple (`(A, B, C, D,...)`)
     TyTup(Vec<P<Ty>> ),
-    /// A path (`module::module::...::Type`) or primitive
+    /// A path (`module::module::...::Type`), optionally
+    /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
     ///
     /// Type parameters are stored in the Path itself
-    TyPath(Path, NodeId),
+    TyPath(Option<QSelf>, Path),
     /// Something like `A+B`. Note that `B` must always be a path.
     TyObjectSum(P<Ty>, TyParamBounds),
     /// A type like `for<'a> Foo<&'a Bar>`
     TyPolyTraitRef(TyParamBounds),
-    /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
-    TyQPath(P<QPath>),
     /// No-op; kept solely so that we can pretty-print faithfully
     TyParen(P<Ty>),
     /// Unused for now
@@ -1641,6 +1645,10 @@ pub enum Item_ {
               Generics,
               TyParamBounds,
               Vec<TraitItem>),
+
+    // Default trait implementations
+    // `impl Trait for ..`
+    ItemDefaultImpl(Unsafety, TraitRef),
     ItemImpl(Unsafety,
              ImplPolarity,
              Generics,
@@ -1666,7 +1674,8 @@ pub fn descriptive_variant(&self) -> &str {
             ItemStruct(..) => "struct",
             ItemTrait(..) => "trait",
             ItemMac(..) |
-            ItemImpl(..) => "item"
+            ItemImpl(..) |
+            ItemDefaultImpl(..) => "item"
         }
     }
 }
index ba08f61b5575ccef6c7817b9ddc712605b296a1e..c33158193ce215a6c835df3798bed0694c5ce294 100644 (file)
@@ -1044,6 +1044,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
                 ItemStruct(..) => "struct",
                 ItemTrait(..) => "trait",
                 ItemImpl(..) => "impl",
+                ItemDefaultImpl(..) => "default impl",
                 ItemMac(..) => "macro"
             };
             format!("{} {}{}", item_str, path_str, id_str)
index f660296fcd7b6c72892ac064bf3c0963376256a0..79f0433761da531ec4a01d34401a344ce1efed58 100644 (file)
@@ -134,7 +134,7 @@ pub fn unop_to_string(op: UnOp) -> &'static str {
 }
 
 pub fn is_path(e: P<Expr>) -> bool {
-    return match e.node { ExprPath(_) => true, _ => false };
+    match e.node { ExprPath(..) => true, _ => false }
 }
 
 /// Get a string representation of a signed int type, with its value.
@@ -252,8 +252,12 @@ pub fn name_to_dummy_lifetime(name: Name) -> Lifetime {
 /// hint of where they came from, (previously they would all just be
 /// listed as `__extensions__::method_name::hash`, with no indication
 /// of the type).
-pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: &Ty) -> Ident {
-    let mut pretty = pprust::ty_to_string(ty);
+pub fn impl_pretty_name(trait_ref: &Option<TraitRef>, ty: Option<&Ty>) -> Ident {
+    let mut pretty = match ty {
+        Some(t) => pprust::ty_to_string(t),
+        None => String::from_str("..")
+    };
+
     match *trait_ref {
         Some(ref trait_ref) => {
             pretty.push('.');
@@ -484,9 +488,6 @@ fn visit_expr(&mut self, expression: &Expr) {
 
     fn visit_ty(&mut self, typ: &Ty) {
         self.operation.visit_id(typ.id);
-        if let TyPath(_, id) = typ.node {
-            self.operation.visit_id(id);
-        }
         visit::walk_ty(self, typ)
     }
 
@@ -560,13 +561,18 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
         visit::walk_trait_item(self, tm);
     }
 
-    fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
+    fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
         self.operation.visit_id(lifetime.id);
     }
 
-    fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) {
+    fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
         self.visit_lifetime_ref(&def.lifetime);
     }
+
+    fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
+        self.operation.visit_id(trait_ref.ref_id);
+        visit::walk_trait_ref(self, trait_ref);
+    }
 }
 
 pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
index 62e676891a0e6c349fc6581cacf302c8de2484e5..4fc08c0c2b28caaccfcabe40924c848cbcf917ac 100644 (file)
@@ -292,7 +292,7 @@ pub enum InlineAttr {
 }
 
 /// Determine what `#[inline]` attribute is present in `attrs`, if any.
-pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
+pub fn find_inline_attr(diagnostic: Option<&SpanHandler>, attrs: &[Attribute]) -> InlineAttr {
     // FIXME (#2809)---validate the usage of #[inline] and #[inline]
     attrs.iter().fold(InlineNone, |ia,attr| {
         match attr.node.value.node {
@@ -302,12 +302,16 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
             }
             MetaList(ref n, ref items) if *n == "inline" => {
                 mark_used(attr);
-                if contains_name(&items[..], "always") {
+                if items.len() != 1 {
+                    diagnostic.map(|d|{ d.span_err(attr.span, "expected one argument"); });
+                    InlineNone
+                } else if contains_name(&items[..], "always") {
                     InlineAlways
                 } else if contains_name(&items[..], "never") {
                     InlineNever
                 } else {
-                    InlineHint
+                    diagnostic.map(|d|{ d.span_err((*items[0]).span, "invalid argument"); });
+                    InlineNone
                 }
             }
             _ => ia
@@ -317,7 +321,7 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr {
 
 /// True if `#[inline]` or `#[inline(always)]` is present in `attrs`.
 pub fn requests_inline(attrs: &[Attribute]) -> bool {
-    match find_inline_attr(attrs) {
+    match find_inline_attr(None, attrs) {
         InlineHint | InlineAlways => true,
         InlineNone | InlineNever => false,
     }
index d8cba139fb5979b9258c5d8e6498a24e00be8f42..009bfef86230f76add03dc90a0232912a67969b6 100644 (file)
@@ -113,7 +113,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                         Some(('=', _)) => None,
                         Some(('+', operand)) => {
                             Some(token::intern_and_get_ident(&format!(
-                                        "={}", operand)[]))
+                                        "={}", operand)))
                         }
                         _ => {
                             cx.span_err(span, "output operand constraint lacks '=' or '+'");
index d4ccabbd63b4a2edfb5f411a13b06b317e27440c..2ef90f04f7527d214cf07b779a1a453ec0041f61 100644 (file)
@@ -83,15 +83,15 @@ pub enum Annotatable {
 impl Annotatable {
     pub fn attrs(&self) -> &[ast::Attribute] {
         match *self {
-            Annotatable::Item(ref i) => &i.attrs[],
+            Annotatable::Item(ref i) => &i.attrs,
             Annotatable::TraitItem(ref i) => match *i {
-                ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs[],
-                ast::TraitItem::ProvidedMethod(ref m) => &m.attrs[],
-                ast::TraitItem::TypeTraitItem(ref at) => &at.attrs[],
+                ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs,
+                ast::TraitItem::ProvidedMethod(ref m) => &m.attrs,
+                ast::TraitItem::TypeTraitItem(ref at) => &at.attrs,
             },
             Annotatable::ImplItem(ref i) => match *i {
-                ast::ImplItem::MethodImplItem(ref m) => &m.attrs[],
-                ast::ImplItem::TypeImplItem(ref t) => &t.attrs[],
+                ast::ImplItem::MethodImplItem(ref m) => &m.attrs,
+                ast::ImplItem::TypeImplItem(ref t) => &t.attrs,
             }
         }
     }
@@ -639,7 +639,7 @@ pub fn original_span_in_file(&self) -> Span {
     pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
     pub fn mod_path(&self) -> Vec<ast::Ident> {
         let mut v = Vec::new();
-        v.push(token::str_to_ident(&self.ecfg.crate_name[]));
+        v.push(token::str_to_ident(&self.ecfg.crate_name));
         v.extend(self.mod_path.iter().cloned());
         return v;
     }
@@ -648,7 +648,7 @@ pub fn bt_push(&mut self, ei: ExpnInfo) {
         if self.recursion_count > self.ecfg.recursion_limit {
             self.span_fatal(ei.call_site,
                             &format!("recursion limit reached while expanding the macro `{}`",
-                                    ei.callee.name)[]);
+                                    ei.callee.name));
         }
 
         let mut call_site = ei.call_site;
@@ -773,7 +773,7 @@ pub fn check_zero_tts(cx: &ExtCtxt,
                       tts: &[ast::TokenTree],
                       name: &str) {
     if tts.len() != 0 {
-        cx.span_err(sp, &format!("{} takes no arguments", name)[]);
+        cx.span_err(sp, &format!("{} takes no arguments", name));
     }
 }
 
@@ -786,12 +786,12 @@ pub fn get_single_str_from_tts(cx: &mut ExtCtxt,
                                -> Option<String> {
     let mut p = cx.new_parser_from_tts(tts);
     if p.token == token::Eof {
-        cx.span_err(sp, &format!("{} takes 1 argument", name)[]);
+        cx.span_err(sp, &format!("{} takes 1 argument", name));
         return None
     }
     let ret = cx.expander().fold_expr(p.parse_expr());
     if p.token != token::Eof {
-        cx.span_err(sp, &format!("{} takes 1 argument", name)[]);
+        cx.span_err(sp, &format!("{} takes 1 argument", name));
     }
     expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| {
         s.to_string()
index 5bfd4a9f6111c6a48f4564f2d578eac979c1c83d..d916651b05617d25cedd8bd6f06867eba885f712 100644 (file)
@@ -41,16 +41,16 @@ fn path_all(&self, sp: Span,
         -> ast::Path;
 
     fn qpath(&self, self_type: P<ast::Ty>,
-             trait_ref: P<ast::TraitRef>,
-             ident: ast::Ident )
-        -> P<ast::QPath>;
+             trait_path: ast::Path,
+             ident: ast::Ident)
+             -> (ast::QSelf, ast::Path);
     fn qpath_all(&self, self_type: P<ast::Ty>,
-                trait_ref: P<ast::TraitRef>,
+                trait_path: ast::Path,
                 ident: ast::Ident,
                 lifetimes: Vec<ast::Lifetime>,
                 types: Vec<P<ast::Ty>>,
-                bindings: Vec<P<ast::TypeBinding>> )
-        -> P<ast::QPath>;
+                bindings: Vec<P<ast::TypeBinding>>)
+                -> (ast::QSelf, ast::Path);
 
     // types
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
@@ -114,7 +114,7 @@ fn block_all(&self, span: Span,
     // expressions
     fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr>;
     fn expr_path(&self, path: ast::Path) -> P<ast::Expr>;
-    fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr>;
+    fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr>;
     fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
 
     fn expr_self(&self, span: Span) -> P<ast::Expr>;
@@ -148,6 +148,7 @@ fn expr_struct_ident(&self, span: Span, id: ast::Ident,
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr>;
     fn expr_int(&self, sp: Span, i: isize) -> P<ast::Expr>;
     fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr>;
+    fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr>;
     fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr>;
 
     fn expr_vec(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr>;
@@ -345,40 +346,40 @@ fn path_all(&self,
 
     /// Constructs a qualified path.
     ///
-    /// Constructs a path like `<self_type as trait_ref>::ident`.
+    /// Constructs a path like `<self_type as trait_path>::ident`.
     fn qpath(&self,
              self_type: P<ast::Ty>,
-             trait_ref: P<ast::TraitRef>,
+             trait_path: ast::Path,
              ident: ast::Ident)
-             -> P<ast::QPath> {
-        self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new())
+             -> (ast::QSelf, ast::Path) {
+        self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
     }
 
     /// Constructs a qualified path.
     ///
-    /// Constructs a path like `<self_type as trait_ref>::ident<a, T, A=Bar>`.
+    /// Constructs a path like `<self_type as trait_path>::ident<'a, T, A=Bar>`.
     fn qpath_all(&self,
                  self_type: P<ast::Ty>,
-                 trait_ref: P<ast::TraitRef>,
+                 trait_path: ast::Path,
                  ident: ast::Ident,
                  lifetimes: Vec<ast::Lifetime>,
                  types: Vec<P<ast::Ty>>,
-                 bindings: Vec<P<ast::TypeBinding>> )
-                 -> P<ast::QPath> {
-        let segment = ast::PathSegment {
+                 bindings: Vec<P<ast::TypeBinding>>)
+                 -> (ast::QSelf, ast::Path) {
+        let mut path = trait_path;
+        path.segments.push(ast::PathSegment {
             identifier: ident,
             parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
                 lifetimes: lifetimes,
                 types: OwnedSlice::from_vec(types),
                 bindings: OwnedSlice::from_vec(bindings),
             })
-        };
+        });
 
-        P(ast::QPath {
-            self_type: self_type,
-            trait_ref: trait_ref,
-            item_path: segment,
-        })
+        (ast::QSelf {
+            ty: self_type,
+            position: path.segments.len() - 1
+        }, path)
     }
 
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
@@ -397,7 +398,7 @@ fn ty(&self, span: Span, ty: ast::Ty_) -> P<ast::Ty> {
     }
 
     fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
-        self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID))
+        self.ty(path.span, ast::TyPath(None, path))
     }
 
     fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice<ast::TyParamBound>) -> P<ast::Ty> {
@@ -602,12 +603,12 @@ fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr> {
     }
 
     fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
-        self.expr(path.span, ast::ExprPath(path))
+        self.expr(path.span, ast::ExprPath(None, path))
     }
 
     /// Constructs a QPath expression.
-    fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr> {
-        self.expr(span, ast::ExprQPath(qpath))
+    fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr> {
+        self.expr(span, ast::ExprPath(Some(qself), path))
     }
 
     fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> {
@@ -701,6 +702,9 @@ fn expr_int(&self, sp: Span, i: isize) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs(false),
                                                                   ast::Sign::new(i))))
     }
+    fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
+        self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU32)))
+    }
     fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8)))
     }
@@ -762,7 +766,7 @@ fn expr_tuple(&self, sp: Span, exprs: Vec<P<ast::Expr>>) -> P<ast::Expr> {
     fn expr_fail(&self, span: Span, msg: InternedString) -> P<ast::Expr> {
         let loc = self.codemap().lookup_char_pos(span.lo);
         let expr_file = self.expr_str(span,
-                                      token::intern_and_get_ident(&loc.file.name[]));
+                                      token::intern_and_get_ident(&loc.file.name));
         let expr_line = self.expr_usize(span, loc.line);
         let expr_file_line_tuple = self.expr_tuple(span, vec!(expr_file, expr_line));
         let expr_file_line_ptr = self.expr_addr_of(span, expr_file_line_tuple);
index 38098e50dee83750ef905ce8309433f51f5c021e..84f786e9780f0425bbdc089827060c50d0e31ad6 100644 (file)
@@ -40,14 +40,14 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt,
                     ast::LitInt(i, ast::UnsignedIntLit(_)) |
                     ast::LitInt(i, ast::SignedIntLit(_, ast::Plus)) |
                     ast::LitInt(i, ast::UnsuffixedIntLit(ast::Plus)) => {
-                        accumulator.push_str(&format!("{}", i)[]);
+                        accumulator.push_str(&format!("{}", i));
                     }
                     ast::LitInt(i, ast::SignedIntLit(_, ast::Minus)) |
                     ast::LitInt(i, ast::UnsuffixedIntLit(ast::Minus)) => {
-                        accumulator.push_str(&format!("-{}", i)[]);
+                        accumulator.push_str(&format!("-{}", i));
                     }
                     ast::LitBool(b) => {
-                        accumulator.push_str(&format!("{}", b)[]);
+                        accumulator.push_str(&format!("{}", b));
                     }
                     ast::LitByte(..) |
                     ast::LitBinary(..) => {
index 9410a51e7a5f660a368534d275fa651d7d5e13e1..2303eb9645b640415c7c3a1f9eaac7aa1e25315e 100644 (file)
@@ -53,7 +53,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]
 
     let e = P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
-        node: ast::ExprPath(
+        node: ast::ExprPath(None,
             ast::Path {
                  span: sp,
                  global: false,
index 518fbcc80ee95fc8c4b248b55da91c9bc8be585e..5f460264216a1567182a5c8b63f3d6bb44623455 100644 (file)
@@ -81,11 +81,11 @@ fn cs_clone(
         EnumNonMatchingCollapsed (..) => {
             cx.span_bug(trait_span,
                         &format!("non-matching enum variants in \
-                                 `derive({})`", name)[])
+                                 `derive({})`", name))
         }
         StaticEnum(..) | StaticStruct(..) => {
             cx.span_bug(trait_span,
-                        &format!("static method in `derive({})`", name)[])
+                        &format!("static method in `derive({})`", name))
         }
     }
 
@@ -102,7 +102,7 @@ fn cs_clone(
                 None => {
                     cx.span_bug(trait_span,
                                 &format!("unnamed field in normal struct in \
-                                         `derive({})`", name)[])
+                                         `derive({})`", name))
                 }
             };
             cx.field_imm(field.span, ident, subcall(field))
index 91212a86958962d08c71761b30545ea7432e15f5..80ef882745f878e152f3d24b29276bf6624db513 100644 (file)
@@ -70,7 +70,7 @@ macro_rules! md {
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
                 args: vec!(borrowed_self()),
-                ret_ty: Literal(path!(bool)),
+                ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 combine_substructure: combine_substructure(box |a, b, c| {
                     $f(a, b, c)
index b109850a6bd23dac42f217f7e4b742bb527dcc7c..be4a33002aa1c69e87f2227fa0e6490e6571c120 100644 (file)
@@ -36,7 +36,7 @@ macro_rules! md {
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
                 args: vec!(borrowed_self()),
-                ret_ty: Literal(path!(bool)),
+                ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 combine_substructure: combine_substructure(box |cx, span, substr| {
                     cs_op($op, $equal, cx, span, substr)
index ab0f64e823f9c197427ee0c27d2725da419b7551..f27bbc338e5704b05f89bb5573d3834c1ca01695 100644 (file)
@@ -204,7 +204,7 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
             } else {
                 let fields = fields.iter().enumerate().map(|(i, &span)| {
                     getarg(cx, span,
-                           token::intern_and_get_ident(&format!("_field{}", i)[]),
+                           token::intern_and_get_ident(&format!("_field{}", i)),
                            i)
                 }).collect();
 
index dd6094705995e94a4b70818984235fb81c0dad3b..8038074cee14fbe3473da0f0ce5997bbb6a9b800 100644 (file)
@@ -191,7 +191,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                 let name = match name {
                     Some(id) => token::get_ident(id),
                     None => {
-                        token::intern_and_get_ident(&format!("_field{}", i)[])
+                        token::intern_and_get_ident(&format!("_field{}", i))
                     }
                 };
                 let enc = cx.expr_method_call(span, self_.clone(),
index b912ed34ae0ad19c780be51cbd640736a7020053..a36d3a155b8d86de2db26d46d15627bfba53e99d 100644 (file)
@@ -363,7 +363,7 @@ pub fn expand<F>(&self,
         // generated implementations are linted
         let mut attrs = newitem.attrs.clone();
         attrs.extend(item.attrs.iter().filter(|a| {
-            match &a.name()[] {
+            match &a.name()[..] {
                 "allow" | "warn" | "deny" | "forbid" => true,
                 _ => false,
             }
@@ -498,7 +498,7 @@ fn create_derived_impl(&self,
         // Just mark it now since we know that it'll end up used downstream
         attr::mark_used(&attr);
         let opt_trait_ref = Some(trait_ref);
-        let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type);
+        let ident = ast_util::impl_pretty_name(&opt_trait_ref, Some(&*self_type));
         let mut a = vec![attr];
         a.extend(self.attributes.iter().cloned());
         cx.item(
@@ -671,7 +671,7 @@ fn split_self_nonself_args(&self,
 
         for (i, ty) in self.args.iter().enumerate() {
             let ast_ty = ty.to_ty(cx, trait_.span, type_ident, generics);
-            let ident = cx.ident_of(&format!("__arg_{}", i)[]);
+            let ident = cx.ident_of(&format!("__arg_{}", i));
             arg_tys.push((ident, ast_ty));
 
             let arg_expr = cx.expr_ident(trait_.span, ident);
@@ -778,7 +778,7 @@ fn expand_struct_method_body(&self,
                                              struct_path,
                                              struct_def,
                                              &format!("__self_{}",
-                                                     i)[],
+                                                     i),
                                              ast::MutImmutable);
             patterns.push(pat);
             raw_fields.push(ident_expr);
@@ -971,7 +971,7 @@ fn build_enum_match_tuple(
                 let mut subpats = Vec::with_capacity(self_arg_names.len());
                 let mut self_pats_idents = Vec::with_capacity(self_arg_names.len() - 1);
                 let first_self_pat_idents = {
-                    let (p, idents) = mk_self_pat(cx, &self_arg_names[0][]);
+                    let (p, idents) = mk_self_pat(cx, &self_arg_names[0]);
                     subpats.push(p);
                     idents
                 };
@@ -1289,7 +1289,7 @@ fn create_struct_pattern(&self,
                     cx.span_bug(sp, "a struct with named and unnamed fields in `derive`");
                 }
             };
-            let ident = cx.ident_of(&format!("{}_{}", prefix, i)[]);
+            let ident = cx.ident_of(&format!("{}_{}", prefix, i));
             paths.push(codemap::Spanned{span: sp, node: ident});
             let val = cx.expr(
                 sp, ast::ExprParen(cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)))));
@@ -1335,7 +1335,7 @@ fn create_enum_variant_pattern(&self,
                 let mut ident_expr = Vec::new();
                 for (i, va) in variant_args.iter().enumerate() {
                     let sp = self.set_expn_info(cx, va.ty.span);
-                    let ident = cx.ident_of(&format!("{}_{}", prefix, i)[]);
+                    let ident = cx.ident_of(&format!("{}_{}", prefix, i));
                     let path1 = codemap::Spanned{span: sp, node: ident};
                     paths.push(path1);
                     let expr_path = cx.expr_path(cx.path_ident(sp, ident));
@@ -1378,7 +1378,7 @@ pub fn cs_fold<F>(use_foldl: bool,
                       field.span,
                       old,
                       field.self_.clone(),
-                      &field.other[])
+                      &field.other)
                 })
             } else {
                 all_fields.iter().rev().fold(base, |old, field| {
@@ -1386,7 +1386,7 @@ pub fn cs_fold<F>(use_foldl: bool,
                       field.span,
                       old,
                       field.self_.clone(),
-                      &field.other[])
+                      &field.other)
                 })
             }
         },
index f8bc331bfcfe7697a13bc4a0df84e03229f57075..973c8f5fa1e0b4b26a39defe621cbe74107aab0f 100644 (file)
@@ -30,6 +30,12 @@ macro_rules! path {
     )
 }
 
+macro_rules! path_local {
+    ($x:ident) => (
+        ::ext::deriving::generic::ty::Path::new_local(stringify!($x))
+    )
+}
+
 macro_rules! pathvec_std {
     ($cx:expr, $first:ident :: $($rest:ident)::+) => (
         if $cx.use_std {
@@ -157,7 +163,7 @@ macro_rules! expand {
                                 cx.span_err(titem.span,
                                             &format!("unknown `derive` \
                                                      trait: `{}`",
-                                                    *tname)[]);
+                                                    *tname));
                             }
                         };
                     }
index 22c87d978c9e5aa2771d3971e71b2c155693527a..3b96292323a95039ab6f17535c704ce75023138b 100644 (file)
@@ -38,7 +38,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                 name: "from_i64",
                 generics: LifetimeBounds::empty(),
                 explicit_self: None,
-                args: vec!(Literal(path!(i64))),
+                args: vec!(Literal(path_local!(i64))),
                 ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
                                            None,
                                            vec!(box Self_),
@@ -53,7 +53,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                 name: "from_u64",
                 generics: LifetimeBounds::empty(),
                 explicit_self: None,
-                args: vec!(Literal(path!(u64))),
+                args: vec!(Literal(path_local!(u64))),
                 ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
                                            None,
                                            vec!(box Self_),
index 9c04d1e928295d42c387eb8d3748b1e91d301c4d..93f8ee5042bb1674e7843180e51bbc5832c827d7 100644 (file)
@@ -83,7 +83,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
         None => {
             token::intern_and_get_ident(&format!("environment variable `{}` \
                                                  not defined",
-                                                var)[])
+                                                var))
         }
         Some(second) => {
             match expr_to_string(cx, second, "expected string literal") {
index d4dda7390a52f7788dae1cc2e2d7fcf25de6ccf0..bea57ae14e4af27c91d8600e7016525bdda30456 100644 (file)
@@ -41,7 +41,7 @@ pub fn expand_type(t: P<ast::Ty>,
     debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty);
     let t = match (t.node.clone(), impl_ty) {
         // Expand uses of `Self` in impls to the concrete type.
-        (ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => {
+        (ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => {
             let path_as_ident = path_to_ident(path);
             // Note unhygenic comparison here. I think this is correct, since
             // even though `Self` is almost just a type parameter, the treatment
@@ -389,7 +389,7 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span,
                     fld.cx.span_err(
                         pth.span,
                         &format!("macro undefined: '{}!'",
-                                &extnamestr)[]);
+                                &extnamestr));
 
                     // let compilation continue
                     None
@@ -426,7 +426,7 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span,
                                     pth.span,
                                     &format!("non-expression macro in expression position: {}",
                                             &extnamestr[..]
-                                            )[]);
+                                            ));
                                 return None;
                             }
                         };
@@ -436,7 +436,7 @@ fn expand_mac_invoc<T, F, G>(mac: ast::Mac, span: codemap::Span,
                         fld.cx.span_err(
                             pth.span,
                             &format!("'{}' is not a tt-style macro",
-                                    &extnamestr)[]);
+                                    &extnamestr));
                         None
                     }
                 }
@@ -608,7 +608,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
             None => {
                 fld.cx.span_err(path_span,
                                 &format!("macro undefined: '{}!'",
-                                        extnamestr)[]);
+                                        extnamestr));
                 // let compilation continue
                 return SmallVector::zero();
             }
@@ -618,10 +618,9 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     if it.ident.name != parse::token::special_idents::invalid.name {
                         fld.cx
                             .span_err(path_span,
-                                      &format!("macro {}! expects no ident argument, \
-                                        given '{}'",
-                                      extnamestr,
-                                      token::get_ident(it.ident))[]);
+                                      &format!("macro {}! expects no ident argument, given '{}'",
+                                               extnamestr,
+                                               token::get_ident(it.ident)));
                         return SmallVector::zero();
                     }
                     fld.cx.bt_push(ExpnInfo {
@@ -640,7 +639,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     if it.ident.name == parse::token::special_idents::invalid.name {
                         fld.cx.span_err(path_span,
                                         &format!("macro {}! expects an ident argument",
-                                                &extnamestr)[]);
+                                                &extnamestr));
                         return SmallVector::zero();
                     }
                     fld.cx.bt_push(ExpnInfo {
@@ -659,7 +658,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                     if it.ident.name == parse::token::special_idents::invalid.name {
                         fld.cx.span_err(path_span,
                                         &format!("macro_rules! expects an ident argument")
-                                        []);
+                                        );
                         return SmallVector::zero();
                     }
                     fld.cx.bt_push(ExpnInfo {
@@ -691,7 +690,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
                 _ => {
                     fld.cx.span_err(it.span,
                                     &format!("{}! is not legal in item position",
-                                            &extnamestr)[]);
+                                            &extnamestr));
                     return SmallVector::zero();
                 }
             }
@@ -710,7 +709,7 @@ pub fn expand_item_mac(it: P<ast::Item>,
         None => {
             fld.cx.span_err(path_span,
                             &format!("non-item macro in item position: {}",
-                                    &extnamestr)[]);
+                                    &extnamestr));
             return SmallVector::zero();
         }
     };
@@ -954,7 +953,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
             None => {
                 fld.cx.span_err(pth.span,
                                 &format!("macro undefined: '{}!'",
-                                        extnamestr)[]);
+                                        extnamestr));
                 // let compilation continue
                 return DummyResult::raw_pat(span);
             }
@@ -983,7 +982,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
                                 &format!(
                                     "non-pattern macro in pattern position: {}",
                                     &extnamestr
-                                    )[]
+                                    )
                             );
                             return DummyResult::raw_pat(span);
                         }
@@ -995,7 +994,7 @@ fn expand_pat(p: P<ast::Pat>, fld: &mut MacroExpander) -> P<ast::Pat> {
                 _ => {
                     fld.cx.span_err(span,
                                     &format!("{}! is not legal in pattern position",
-                                            &extnamestr)[]);
+                                            &extnamestr));
                     return DummyResult::raw_pat(span);
                 }
             }
@@ -1595,13 +1594,10 @@ struct PathExprFinderContext {
 
     impl<'v> Visitor<'v> for PathExprFinderContext {
         fn visit_expr(&mut self, expr: &ast::Expr) {
-            match expr.node {
-                ast::ExprPath(ref p) => {
-                    self.path_accumulator.push(p.clone());
-                    // not calling visit_path, but it should be fine.
-                }
-                _ => visit::walk_expr(self, expr)
+            if let ast::ExprPath(None, ref p) = expr.node {
+                self.path_accumulator.push(p.clone());
             }
+            visit::walk_expr(self, expr);
         }
     }
 
@@ -1981,7 +1977,7 @@ fn run_renaming_test(t: &RenamingTest, test_idx: usize) {
         // the xx binding should bind all of the xx varrefs:
         for (idx,v) in varrefs.iter().filter(|p| {
             p.segments.len() == 1
-            && "xx" == &token::get_ident(p.segments[0].identifier)[]
+            && "xx" == &*token::get_ident(p.segments[0].identifier)
         }).enumerate() {
             if mtwt::resolve(v.segments[0].identifier) != resolved_binding {
                 println!("uh oh, xx binding didn't match xx varref:");
@@ -2029,7 +2025,7 @@ fn ident_renamer_test () {
         let renamed_crate = renamer.fold_crate(the_crate);
         let idents = crate_idents(&renamed_crate);
         let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
-        assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16)));
+        assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16)]);
     }
 
     // test the PatIdentRenamer; only PatIdents get renamed
@@ -2045,8 +2041,6 @@ fn pat_ident_renamer_test () {
         let idents = crate_idents(&renamed_crate);
         let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
         let x_name = x_ident.name;
-        assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name));
+        assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name]);
     }
-
-
 }
index e17329d7d33002b96f85c9060a1962a82330b7fe..91262556abd706f72ee4bcc91b90d279d1292221 100644 (file)
@@ -113,7 +113,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 _ => {
                     ecx.span_err(p.span,
                                  &format!("expected ident for named argument, found `{}`",
-                                         p.this_token_to_string())[]);
+                                         p.this_token_to_string()));
                     return None;
                 }
             };
@@ -127,7 +127,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
                 Some(prev) => {
                     ecx.span_err(e.span,
                                  &format!("duplicate argument named `{}`",
-                                         name)[]);
+                                         name));
                     ecx.parse_sess.span_diagnostic.span_note(prev.span, "previously here");
                     continue
                 }
@@ -281,19 +281,19 @@ fn verify_same(&self,
                                   &format!("argument redeclared with type `{}` when \
                                            it was previously `{}`",
                                           *ty,
-                                          *cur)[]);
+                                          *cur));
             }
             (&Known(ref cur), _) => {
                 self.ecx.span_err(sp,
                                   &format!("argument used to format with `{}` was \
                                            attempted to not be used for formatting",
-                                           *cur)[]);
+                                           *cur));
             }
             (_, &Known(ref ty)) => {
                 self.ecx.span_err(sp,
                                   &format!("argument previously used as a format \
                                            argument attempted to be used as `{}`",
-                                           *ty)[]);
+                                           *ty));
             }
             (_, _) => {
                 self.ecx.span_err(sp, "argument declared with multiple formats");
@@ -337,7 +337,7 @@ fn trans_count(&self, c: parse::Count) -> P<ast::Expr> {
     /// Translate the accumulated string literals to a literal expression
     fn trans_literal_string(&mut self) -> P<ast::Expr> {
         let sp = self.fmtsp;
-        let s = token::intern_and_get_ident(&self.literal[]);
+        let s = token::intern_and_get_ident(&self.literal);
         self.literal.clear();
         self.ecx.expr_str(sp, s)
     }
@@ -417,7 +417,7 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> Option<P<ast::Expr>> {
                     parse::AlignUnknown => align("Unknown"),
                 };
                 let align = self.ecx.expr_path(align);
-                let flags = self.ecx.expr_usize(sp, arg.format.flags);
+                let flags = self.ecx.expr_u32(sp, arg.format.flags);
                 let prec = self.trans_count(arg.format.precision);
                 let width = self.trans_count(arg.format.width);
                 let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec"));
@@ -494,7 +494,7 @@ fn into_expr(mut self) -> P<ast::Expr> {
                 None => continue // error already generated
             };
 
-            let name = self.ecx.ident_of(&format!("__arg{}", i)[]);
+            let name = self.ecx.ident_of(&format!("__arg{}", i));
             pats.push(self.ecx.pat_ident(e.span, name));
             locals.push(Context::format_arg(self.ecx, e.span, arg_ty,
                                             self.ecx.expr_ident(e.span, name)));
@@ -511,7 +511,7 @@ fn into_expr(mut self) -> P<ast::Expr> {
             };
 
             let lname = self.ecx.ident_of(&format!("__arg{}",
-                                                  *name)[]);
+                                                  *name));
             pats.push(self.ecx.pat_ident(e.span, lname));
             names[self.name_positions[*name]] =
                 Some(Context::format_arg(self.ecx, e.span, arg_ty,
@@ -600,7 +600,7 @@ fn format_arg(ecx: &ExtCtxt, sp: Span,
                     _ => {
                         ecx.span_err(sp,
                                      &format!("unknown format trait `{}`",
-                                             *tyname)[]);
+                                             *tyname));
                         "Dummy"
                     }
                 }
@@ -610,7 +610,7 @@ fn format_arg(ecx: &ExtCtxt, sp: Span,
                         ecx.ident_of_std("core"),
                         ecx.ident_of("fmt"),
                         ecx.ident_of("ArgumentV1"),
-                        ecx.ident_of("from_uint")], vec![arg])
+                        ecx.ident_of("from_usize")], vec![arg])
             }
         };
 
@@ -694,7 +694,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
     }
     if !parser.errors.is_empty() {
         cx.ecx.span_err(cx.fmtsp, &format!("invalid format string: {}",
-                                          parser.errors.remove(0))[]);
+                                          parser.errors.remove(0)));
         return DummyResult::raw_expr(sp);
     }
     if !cx.literal.is_empty() {
index b6563d77b8864e7df854dd6be4dbee1af75fecae..72431d8e6aa2c317ccd23aa9449193f01445c344 100644 (file)
@@ -288,19 +288,19 @@ mod tests {
     fn xorpush_test () {
         let mut s = Vec::new();
         xor_push(&mut s, 14);
-        assert_eq!(s.clone(), vec!(14));
+        assert_eq!(s.clone(), [14]);
         xor_push(&mut s, 14);
-        assert_eq!(s.clone(), Vec::new());
+        assert_eq!(s.clone(), []);
         xor_push(&mut s, 14);
-        assert_eq!(s.clone(), vec!(14));
+        assert_eq!(s.clone(), [14]);
         xor_push(&mut s, 15);
-        assert_eq!(s.clone(), vec!(14, 15));
+        assert_eq!(s.clone(), [14, 15]);
         xor_push(&mut s, 16);
-        assert_eq!(s.clone(), vec!(14, 15, 16));
+        assert_eq!(s.clone(), [14, 15, 16]);
         xor_push(&mut s, 16);
-        assert_eq!(s.clone(), vec!(14, 15));
+        assert_eq!(s.clone(), [14, 15]);
         xor_push(&mut s, 15);
-        assert_eq!(s.clone(), vec!(14));
+        assert_eq!(s.clone(), [14]);
     }
 
     fn id(n: u32, s: SyntaxContext) -> Ident {
@@ -389,13 +389,13 @@ fn test_marksof () {
         assert_eq!(marksof_internal (EMPTY_CTXT,stopname,&t),Vec::new());
         // FIXME #5074: ANF'd to dodge nested calls
         { let ans = unfold_marks(vec!(4,98),EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans,stopname,&t),vec!(4,98));}
+         assert_eq! (marksof_internal (ans,stopname,&t), [4, 98]);}
         // does xoring work?
         { let ans = unfold_marks(vec!(5,5,16),EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans,stopname,&t), vec!(16));}
+         assert_eq! (marksof_internal (ans,stopname,&t), [16]);}
         // does nested xoring work?
         { let ans = unfold_marks(vec!(5,10,10,5,16),EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans, stopname,&t), vec!(16));}
+         assert_eq! (marksof_internal (ans, stopname,&t), [16]);}
         // rename where stop doesn't match:
         { let chain = vec!(M(9),
                         R(id(name1.usize() as u32,
@@ -403,7 +403,7 @@ fn test_marksof () {
                           Name(100101102)),
                         M(14));
          let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans, stopname, &t), vec!(9,14));}
+         assert_eq! (marksof_internal (ans, stopname, &t), [9, 14]);}
         // rename where stop does match
         { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t);
          let chain = vec!(M(9),
@@ -411,7 +411,7 @@ fn test_marksof () {
                          stopname),
                        M(14));
          let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans, stopname, &t), vec!(9)); }
+         assert_eq! (marksof_internal (ans, stopname, &t), [9]); }
     }
 
 
index 2c7bf713aad85d67728d2abaddaa95906c5e9dac..554529b5cb23cc4a805d1d9f69cce55372ac905a 100644 (file)
@@ -466,7 +466,7 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt,
 }
 
 fn ids_ext(strs: Vec<String> ) -> Vec<ast::Ident> {
-    strs.iter().map(|str| str_to_ident(&(*str)[])).collect()
+    strs.iter().map(|str| str_to_ident(&(*str))).collect()
 }
 
 fn id_ext(str: &str) -> ast::Ident {
index c8d48750c75093259d428d491914075dd202b827..af43f5a150190cc3ac0d4ac5f3e20ecb73a871e8 100644 (file)
@@ -35,7 +35,7 @@ pub fn expand_line(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
     let topmost = cx.original_span_in_file();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
 
-    base::MacExpr::new(cx.expr_usize(topmost, loc.line))
+    base::MacExpr::new(cx.expr_u32(topmost, loc.line as u32))
 }
 
 /* column!(): expands to the current column number */
@@ -45,7 +45,8 @@ pub fn expand_column(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
     let topmost = cx.original_span_in_file();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
-    base::MacExpr::new(cx.expr_usize(topmost, loc.col.to_usize()))
+
+    base::MacExpr::new(cx.expr_u32(topmost, loc.col.to_usize() as u32))
 }
 
 /// file!(): expands to the current filename */
@@ -57,7 +58,7 @@ pub fn expand_file(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
 
     let topmost = cx.original_span_in_file();
     let loc = cx.codemap().lookup_char_pos(topmost.lo);
-    let filename = token::intern_and_get_ident(&loc.file.name[]);
+    let filename = token::intern_and_get_ident(&loc.file.name);
     base::MacExpr::new(cx.expr_str(topmost, filename))
 }
 
index 664f7b3e088480e2a55ef7e6a93cba00eab2a9f1..ce513bc91f5a998fda321bb638b4a68bbd0d926c 100644 (file)
@@ -153,7 +153,7 @@ pub fn count_names(ms: &[TokenTree]) -> usize {
                 seq.num_captures
             }
             &TtDelimited(_, ref delim) => {
-                count_names(&delim.tts[])
+                count_names(&delim.tts)
             }
             &TtToken(_, MatchNt(..)) => {
                 1
index 071158fcebb5cf32da776b2e98394450dbf47108..ffc136d5a1d1a19b41bab604f7774b2e8fabfb54 100644 (file)
@@ -187,6 +187,7 @@ enum Status {
     ("no_link", Normal),
     ("derive", Normal),
     ("should_fail", Normal),
+    ("should_panic", Normal),
     ("ignore", Normal),
     ("no_implicit_prelude", Normal),
     ("reexport_test_harness_main", Normal),
@@ -243,7 +244,9 @@ enum Status {
     ("static_assert", Whitelisted),
     ("no_debug", Whitelisted),
     ("omit_gdb_pretty_printer_section", Whitelisted),
-    ("unsafe_no_drop_flag", Whitelisted),
+    ("unsafe_no_drop_flag", Gated("unsafe_no_drop_flag",
+                                  "unsafe_no_drop_flag has unstable semantics \
+                                   and may be removed in the future")),
 
     // used in resolve
     ("prelude_import", Whitelisted),
@@ -549,7 +552,7 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
 
     fn visit_ty(&mut self, t: &ast::Ty) {
         match t.node {
-            ast::TyPath(ref p, _) => {
+            ast::TyPath(None, ref p) => {
                 match &*p.segments {
 
                     [ast::PathSegment { identifier, .. }] => {
index 1fb0642d24ff74fdb0665916b7a66516da204901..a556b2dfd2a99a88104844817f329d13a9f6669e 100644 (file)
@@ -146,10 +146,6 @@ fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
         noop_fold_ty(t, self)
     }
 
-    fn fold_qpath(&mut self, t: P<QPath>) -> P<QPath> {
-        noop_fold_qpath(t, self)
-    }
-
     fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
         noop_fold_ty_binding(t, self)
     }
@@ -428,17 +424,19 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             }
             TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
             TyParen(ty) => TyParen(fld.fold_ty(ty)),
-            TyPath(path, id) => {
-                let id = fld.new_id(id);
-                TyPath(fld.fold_path(path), id)
+            TyPath(qself, path) => {
+                let qself = qself.map(|QSelf { ty, position }| {
+                    QSelf {
+                        ty: fld.fold_ty(ty),
+                        position: position
+                    }
+                });
+                TyPath(qself, fld.fold_path(path))
             }
             TyObjectSum(ty, bounds) => {
                 TyObjectSum(fld.fold_ty(ty),
                             fld.fold_bounds(bounds))
             }
-            TyQPath(qpath) => {
-                TyQPath(fld.fold_qpath(qpath))
-            }
             TyFixedLengthVec(ty, e) => {
                 TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
             }
@@ -453,19 +451,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
     })
 }
 
-pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
-    qpath.map(|qpath| {
-        QPath {
-            self_type: fld.fold_ty(qpath.self_type),
-            trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
-            item_path: PathSegment {
-                identifier: fld.fold_ident(qpath.item_path.identifier),
-                parameters: fld.fold_path_parameters(qpath.item_path.parameters),
-            }
-        }
-    })
-}
-
 pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
                                         fld: &mut T) -> ForeignMod {
     ForeignMod {
@@ -999,6 +984,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             let struct_def = folder.fold_struct_def(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
+        ItemDefaultImpl(unsafety, ref trait_ref) => {
+            ItemDefaultImpl(unsafety, folder.fold_trait_ref((*trait_ref).clone()))
+        }
         ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
             let new_impl_items = impl_items.into_iter().flat_map(|item| {
                 folder.fold_impl_item(item).into_iter()
@@ -1150,7 +1138,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span}
     let ident = match node {
         // The node may have changed, recompute the "pretty" impl name.
         ItemImpl(_, _, _, ref maybe_trait, ref ty, _) => {
-            ast_util::impl_pretty_name(maybe_trait, &**ty)
+            ast_util::impl_pretty_name(maybe_trait, Some(&**ty))
         }
         _ => ident
     };
@@ -1361,8 +1349,15 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 ExprRange(e1.map(|x| folder.fold_expr(x)),
                           e2.map(|x| folder.fold_expr(x)))
             }
-            ExprPath(pth) => ExprPath(folder.fold_path(pth)),
-            ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
+            ExprPath(qself, path) => {
+                let qself = qself.map(|QSelf { ty, position }| {
+                    QSelf {
+                        ty: folder.fold_ty(ty),
+                        position: position
+                    }
+                });
+                ExprPath(qself, folder.fold_path(path))
+            }
             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
index 06e8728d23672d101463d36144b5c9bee83c6be8..a0e2b4dbf5a70bae65ede6b0efb4c520ac2a8f1e 100644 (file)
@@ -94,7 +94,7 @@ fn parse_attribute(&mut self, permit_inner: bool) -> ast::Attribute {
             }
             _ => {
                 let token_str = self.this_token_to_string();
-                self.fatal(&format!("expected `#`, found `{}`", token_str)[]);
+                self.fatal(&format!("expected `#`, found `{}`", token_str));
             }
         };
 
index 1f06db600278b4162c807fcc83d8f36bae593d2d..7a5d75581a511447cf5cd4c16950f2c80dadaf38 100644 (file)
@@ -92,7 +92,7 @@ fn horizontal_trim(lines: Vec<String> ) -> Vec<String> {
         let mut first = true;
         for line in &lines {
             for (j, c) in line.chars().enumerate() {
-                if j > i || !"* \t".contains_char(c) {
+                if j > i || !"* \t".contains(c) {
                     can_trim = false;
                     break;
                 }
@@ -264,7 +264,7 @@ fn read_block_comment(rdr: &mut StringReader,
         if is_block_doc_comment(&curr_line[..]) {
             return
         }
-        assert!(!curr_line.contains_char('\n'));
+        assert!(!curr_line.contains('\n'));
         lines.push(curr_line);
     } else {
         let mut level: isize = 1;
index fd08cbd161bfe3db302137e480539c2b3de8d6ff..83d2bb0cc70a9b542572ab7ddd6f86a16e80f68c 100644 (file)
@@ -1109,7 +1109,7 @@ fn next_token_inner(&mut self) -> token::Token {
                 // expansion purposes. See #12512 for the gory details of why
                 // this is necessary.
                 let ident = self.with_str_from(start, |lifetime_name| {
-                    str_to_ident(&format!("'{}", lifetime_name)[])
+                    str_to_ident(&format!("'{}", lifetime_name))
                 });
 
                 // Conjure up a "keyword checking ident" to make sure that
index 7ed48bdbb928dc9ace647ea772f902f3c1228e96..4d099529cb49ae50439b15fe1b3a03142d419af8 100644 (file)
@@ -254,7 +254,7 @@ pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
         Ok(bytes) => bytes,
         Err(e) => {
             err(&format!("couldn't read {:?}: {}",
-                        path.display(), e)[]);
+                        path.display(), e));
             unreachable!()
         }
     };
@@ -264,7 +264,7 @@ pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option<Span>)
                                      path.as_str().unwrap().to_string())
         }
         None => {
-            err(&format!("{:?} is not UTF-8 encoded", path.display())[])
+            err(&format!("{:?} is not UTF-8 encoded", path.display()))
         }
     }
     unreachable!()
@@ -774,7 +774,7 @@ fn sp(a: u32, b: u32) -> Span {
         assert!(string_to_expr("a".to_string()) ==
                    P(ast::Expr{
                     id: ast::DUMMY_NODE_ID,
-                    node: ast::ExprPath(ast::Path {
+                    node: ast::ExprPath(None, ast::Path {
                         span: sp(0, 1),
                         global: false,
                         segments: vec!(
@@ -792,7 +792,7 @@ fn sp(a: u32, b: u32) -> Span {
         assert!(string_to_expr("::a::b".to_string()) ==
                    P(ast::Expr {
                     id: ast::DUMMY_NODE_ID,
-                    node: ast::ExprPath(ast::Path {
+                    node: ast::ExprPath(None, ast::Path {
                             span: sp(0, 6),
                             global: true,
                             segments: vec!(
@@ -827,19 +827,19 @@ fn string_to_tts_macro () {
              ast::TtDelimited(_, ref macro_delimed)]
             if name_macro_rules.as_str() == "macro_rules"
             && name_zip.as_str() == "zip" => {
-                match &macro_delimed.tts[] {
+                match &macro_delimed.tts[..] {
                     [ast::TtDelimited(_, ref first_delimed),
                      ast::TtToken(_, token::FatArrow),
                      ast::TtDelimited(_, ref second_delimed)]
                     if macro_delimed.delim == token::Paren => {
-                        match &first_delimed.tts[] {
+                        match &first_delimed.tts[..] {
                             [ast::TtToken(_, token::Dollar),
                              ast::TtToken(_, token::Ident(name, token::Plain))]
                             if first_delimed.delim == token::Paren
                             && name.as_str() == "a" => {},
                             _ => panic!("value 3: {:?}", **first_delimed),
                         }
-                        match &second_delimed.tts[] {
+                        match &second_delimed.tts[..] {
                             [ast::TtToken(_, token::Dollar),
                              ast::TtToken(_, token::Ident(name, token::Plain))]
                             if second_delimed.delim == token::Paren
@@ -974,7 +974,7 @@ fn string_to_tts_1 () {
                     id: ast::DUMMY_NODE_ID,
                     node:ast::ExprRet(Some(P(ast::Expr{
                         id: ast::DUMMY_NODE_ID,
-                        node:ast::ExprPath(ast::Path{
+                        node:ast::ExprPath(None, ast::Path{
                             span: sp(7, 8),
                             global: false,
                             segments: vec!(
@@ -995,7 +995,7 @@ fn string_to_tts_1 () {
                    P(Spanned{
                        node: ast::StmtExpr(P(ast::Expr {
                            id: ast::DUMMY_NODE_ID,
-                           node: ast::ExprPath(ast::Path {
+                           node: ast::ExprPath(None, ast::Path {
                                span:sp(0,1),
                                global:false,
                                segments: vec!(
@@ -1041,7 +1041,7 @@ fn parser_done(p: Parser){
                             node: ast::ItemFn(P(ast::FnDecl {
                                 inputs: vec!(ast::Arg{
                                     ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
-                                                  node: ast::TyPath(ast::Path{
+                                                  node: ast::TyPath(None, ast::Path{
                                         span:sp(10,13),
                                         global:false,
                                         segments: vec!(
@@ -1051,7 +1051,7 @@ fn parser_done(p: Parser){
                                                 parameters: ast::PathParameters::none(),
                                             }
                                         ),
-                                        }, ast::DUMMY_NODE_ID),
+                                        }),
                                         span:sp(10,13)
                                     }),
                                     pat: P(ast::Pat {
@@ -1084,7 +1084,7 @@ fn parser_done(p: Parser){
                                         stmts: vec!(P(Spanned{
                                             node: ast::StmtSemi(P(ast::Expr{
                                                 id: ast::DUMMY_NODE_ID,
-                                                node: ast::ExprPath(
+                                                node: ast::ExprPath(None,
                                                       ast::Path{
                                                         span:sp(17,18),
                                                         global:false,
@@ -1207,7 +1207,7 @@ fn wb() -> c_int { O_WRONLY as c_int }
 
         let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
         let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap();
-        let docs = item.attrs.iter().filter(|a| &a.name()[] == "doc")
+        let docs = item.attrs.iter().filter(|a| &*a.name() == "doc")
                     .map(|a| a.value_str().unwrap().to_string()).collect::<Vec<_>>();
         let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()];
         assert_eq!(&docs[..], b);
index 8480772ce6c1ad1b7c1528031800a9bafb06327f..e6bcb8ac745675b0c4a8ec2320db2311805f6dfb 100644 (file)
@@ -106,16 +106,16 @@ fn report(&mut self,
               desc: &str,
               error: bool) {
         if error {
-            self.span_err(sp, &format!("obsolete syntax: {}", kind_str)[]);
+            self.span_err(sp, &format!("obsolete syntax: {}", kind_str));
         } else {
-            self.span_warn(sp, &format!("obsolete syntax: {}", kind_str)[]);
+            self.span_warn(sp, &format!("obsolete syntax: {}", kind_str));
         }
 
         if !self.obsolete_set.contains(&kind) {
             self.sess
                 .span_diagnostic
                 .handler()
-                .note(&format!("{}", desc)[]);
+                .note(&format!("{}", desc));
             self.obsolete_set.insert(kind);
         }
     }
index 370201e53825efef69f01d9c7313127f3a436cef..f171e8279f49c47440ce715dd1e616d469a614fb 100644 (file)
 use ast::{ExprBreak, ExprCall, ExprCast};
 use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
-use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath};
+use ast::{ExprMethodCall, ExprParen, ExprPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
 use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
 use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
-use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
+use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy, ItemDefaultImpl};
 use ast::{ItemExternCrate, ItemUse};
 use ast::{LifetimeDef, Lit, Lit_};
 use ast::{LitBool, LitChar, LitByte, LitBinary};
@@ -43,7 +43,7 @@
 use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
 use ast::{PolyTraitRef};
-use ast::{QPath, RequiredMethod};
+use ast::{QSelf, RequiredMethod};
 use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
 use ast::{StructVariantKind, BiSub, StrStyle};
@@ -53,7 +53,7 @@
 use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
 use ast::{TyFixedLengthVec, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
-use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
+use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr};
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
 use ast::{TypeImplItem, TypeTraitItem, Typedef,};
 use ast::{UnnamedField, UnsafeBlock};
@@ -143,7 +143,7 @@ macro_rules! maybe_whole_expr {
                         _ => unreachable!()
                     };
                     let span = $p.span;
-                    Some($p.mk_expr(span.lo, span.hi, ExprPath(pt)))
+                    Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt)))
                 }
                 token::Interpolated(token::NtBlock(_)) => {
                     // FIXME: The following avoids an issue with lexical borrowck scopes,
@@ -1076,8 +1076,7 @@ pub fn parse_for_in_type(&mut self) -> Ty_ {
     }
 
     pub fn parse_ty_path(&mut self) -> Ty_ {
-        let path = self.parse_path(LifetimeAndTypesWithoutColons);
-        TyPath(path, ast::DUMMY_NODE_ID)
+        TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons))
     }
 
     /// parse a TyBareFn type:
@@ -1525,19 +1524,36 @@ pub fn parse_ty(&mut self) -> P<Ty> {
         } else if self.eat_lt() {
             // QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
             let self_type = self.parse_ty_sum();
-            self.expect_keyword(keywords::As);
-            let trait_ref = self.parse_trait_ref();
+
+            let mut path = if self.eat_keyword(keywords::As) {
+                self.parse_path(LifetimeAndTypesWithoutColons)
+            } else {
+                ast::Path {
+                    span: self.span,
+                    global: false,
+                    segments: vec![]
+                }
+            };
+
+            let qself = QSelf {
+                ty: self_type,
+                position: path.segments.len()
+            };
+
             self.expect(&token::Gt);
             self.expect(&token::ModSep);
-            let item_name = self.parse_ident();
-            TyQPath(P(QPath {
-                self_type: self_type,
-                trait_ref: P(trait_ref),
-                item_path: ast::PathSegment {
-                    identifier: item_name,
-                    parameters: ast::PathParameters::none()
-                }
-            }))
+
+            path.segments.push(ast::PathSegment {
+                identifier: self.parse_ident(),
+                parameters: ast::PathParameters::none()
+            });
+
+            if path.segments.len() == 1 {
+                path.span.lo = self.last_span.lo;
+            }
+            path.span.hi = self.last_span.hi;
+
+            TyPath(Some(qself), path)
         } else if self.check(&token::ModSep) ||
                   self.token.is_ident() ||
                   self.token.is_path() {
@@ -2178,7 +2194,7 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                          }, token::Plain) => {
                 self.bump();
                 let path = ast_util::ident_to_path(mk_sp(lo, hi), id);
-                ex = ExprPath(path);
+                ex = ExprPath(None, path);
                 hi = self.last_span.hi;
             }
             token::OpenDelim(token::Bracket) => {
@@ -2220,10 +2236,22 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                 if self.eat_lt() {
                     // QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
                     let self_type = self.parse_ty_sum();
-                    self.expect_keyword(keywords::As);
-                    let trait_ref = self.parse_trait_ref();
+                    let mut path = if self.eat_keyword(keywords::As) {
+                        self.parse_path(LifetimeAndTypesWithoutColons)
+                    } else {
+                        ast::Path {
+                            span: self.span,
+                            global: false,
+                            segments: vec![]
+                        }
+                    };
+                    let qself = QSelf {
+                        ty: self_type,
+                        position: path.segments.len()
+                    };
                     self.expect(&token::Gt);
                     self.expect(&token::ModSep);
+
                     let item_name = self.parse_ident();
                     let parameters = if self.eat(&token::ModSep) {
                         self.expect_lt();
@@ -2238,15 +2266,18 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                     } else {
                         ast::PathParameters::none()
                     };
+                    path.segments.push(ast::PathSegment {
+                        identifier: item_name,
+                        parameters: parameters
+                    });
+
+                    if path.segments.len() == 1 {
+                        path.span.lo = self.last_span.lo;
+                    }
+                    path.span.hi = self.last_span.hi;
+
                     let hi = self.span.hi;
-                    return self.mk_expr(lo, hi, ExprQPath(P(QPath {
-                        self_type: self_type,
-                        trait_ref: P(trait_ref),
-                        item_path: ast::PathSegment {
-                            identifier: item_name,
-                            parameters: parameters
-                        }
-                    })));
+                    return self.mk_expr(lo, hi, ExprPath(Some(qself), path));
                 }
                 if self.eat_keyword(keywords::Move) {
                     return self.parse_lambda_expr(CaptureByValue);
@@ -2386,7 +2417,7 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                     }
 
                     hi = pth.span.hi;
-                    ex = ExprPath(pth);
+                    ex = ExprPath(None, pth);
                 } else {
                     // other literal expression
                     let lit = self.parse_lit();
@@ -2496,7 +2527,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P<Expr>) -> P<Expr> {
                     let fstr = n.as_str();
                     self.span_err(last_span,
                                   &format!("unexpected token: `{}`", n.as_str()));
-                    if fstr.chars().all(|x| "0123456789.".contains_char(x)) {
+                    if fstr.chars().all(|x| "0123456789.".contains(x)) {
                         let float = match fstr.parse::<f64>().ok() {
                             Some(f) => f,
                             None => continue,
@@ -2562,7 +2593,8 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P<Expr>) -> P<Expr> {
                     let index = self.mk_index(e, ix);
                     e = self.mk_expr(lo, hi, index);
 
-                    self.obsolete(span, ObsoleteSyntax::EmptyIndex);
+                    let obsolete_span = mk_sp(bracket_pos, hi);
+                    self.obsolete(obsolete_span, ObsoleteSyntax::EmptyIndex);
                 } else {
                     let ix = self.parse_expr();
                     hi = self.span.hi;
@@ -3427,7 +3459,7 @@ pub fn parse_pat(&mut self) -> P<Pat> {
                 let end = if self.token.is_ident() || self.token.is_path() {
                     let path = self.parse_path(LifetimeAndTypesWithColons);
                     let hi = self.span.hi;
-                    self.mk_expr(lo, hi, ExprPath(path))
+                    self.mk_expr(lo, hi, ExprPath(None, path))
                 } else {
                     self.parse_literal_maybe_minus()
                 };
@@ -3493,6 +3525,9 @@ pub fn parse_pat(&mut self) -> P<Pat> {
                     };
                     pat = PatIdent(BindByValue(MutImmutable), pth1, sub);
                 }
+            } else if self.look_ahead(1, |t| *t == token::Lt) {
+                self.bump();
+                self.unexpected()
             } else {
                 // parse an enum pat
                 let enum_path = self.parse_path(LifetimeAndTypesWithColons);
@@ -4783,10 +4818,13 @@ fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
         (impl_items, inner_attrs)
     }
 
-    /// Parses two variants (with the region/type params always optional):
+    /// Parses items implementations variants
     ///    impl<T> Foo { ... }
-    ///    impl<T> ToString for ~[T] { ... }
+    ///    impl<T> ToString for &'static T { ... }
+    ///    impl Send for .. {}
     fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
+        let impl_span = self.span;
+
         // First, parse type parameters if necessary.
         let mut generics = self.parse_generics();
 
@@ -4807,21 +4845,18 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
         // Parse traits, if necessary.
         let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
             // New-style trait. Reinterpret the type as a trait.
-            let opt_trait_ref = match ty.node {
-                TyPath(ref path, node_id) => {
+            match ty.node {
+                TyPath(None, ref path) => {
                     Some(TraitRef {
                         path: (*path).clone(),
-                        ref_id: node_id,
+                        ref_id: ty.id,
                     })
                 }
                 _ => {
                     self.span_err(ty.span, "not a trait");
                     None
                 }
-            };
-
-            ty = self.parse_ty_sum();
-            opt_trait_ref
+            }
         } else {
             match polarity {
                 ast::ImplPolarity::Negative => {
@@ -4834,14 +4869,27 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
             None
         };
 
-        self.parse_where_clause(&mut generics);
-        let (impl_items, attrs) = self.parse_impl_items();
+        if self.eat(&token::DotDot) {
+            if generics.is_parameterized() {
+                self.span_err(impl_span, "default trait implementations are not \
+                                          allowed to have genercis");
+            }
 
-        let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
+            self.expect(&token::OpenDelim(token::Brace));
+            self.expect(&token::CloseDelim(token::Brace));
+            (ast_util::impl_pretty_name(&opt_trait, None),
+             ItemDefaultImpl(unsafety, opt_trait.unwrap()), None)
+        } else {
+            if opt_trait.is_some() {
+                ty = self.parse_ty_sum();
+            }
+            self.parse_where_clause(&mut generics);
+            let (impl_items, attrs) = self.parse_impl_items();
 
-        (ident,
-         ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
-         Some(attrs))
+            (ast_util::impl_pretty_name(&opt_trait, Some(&*ty)),
+             ItemImpl(unsafety, polarity, generics, opt_trait, ty, impl_items),
+             Some(attrs))
+        }
     }
 
     /// Parse a::B<String,i32>
@@ -5190,7 +5238,7 @@ fn eval_src_mod(&mut self,
                     -> (ast::Item_, Vec<ast::Attribute> ) {
         let mut prefix = Path::new(self.sess.span_diagnostic.cm.span_to_filename(self.span));
         prefix.pop();
-        let mod_path = Path::new(".").join_many(&self.mod_path_stack[]);
+        let mod_path = Path::new(".").join_many(&self.mod_path_stack);
         let dir_path = prefix.join(&mod_path);
         let mod_string = token::get_ident(id);
         let (file_path, owns_directory) = match ::attr::first_attr_value_str_by_name(
index 433c013591c2d1557b84fcbb3c7a01d69b03d506..2797ef084d9caf36185d985b3bd46ed437f9b755 100644 (file)
@@ -652,47 +652,47 @@ fn container_as_bytes<'a>(&'a self) -> &'a [u8] {
 
 impl fmt::Debug for InternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Debug::fmt(&self.string[], f)
+        fmt::Debug::fmt(&self.string, f)
     }
 }
 
 impl fmt::Display for InternedString {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        fmt::Display::fmt(&self.string[], f)
+        fmt::Display::fmt(&self.string, f)
     }
 }
 
 impl<'a> PartialEq<&'a str> for InternedString {
     #[inline(always)]
     fn eq(&self, other: & &'a str) -> bool {
-        PartialEq::eq(&self.string[], *other)
+        PartialEq::eq(&self.string[..], *other)
     }
     #[inline(always)]
     fn ne(&self, other: & &'a str) -> bool {
-        PartialEq::ne(&self.string[], *other)
+        PartialEq::ne(&self.string[..], *other)
     }
 }
 
 impl<'a> PartialEq<InternedString > for &'a str {
     #[inline(always)]
     fn eq(&self, other: &InternedString) -> bool {
-        PartialEq::eq(*self, &other.string[])
+        PartialEq::eq(*self, &other.string[..])
     }
     #[inline(always)]
     fn ne(&self, other: &InternedString) -> bool {
-        PartialEq::ne(*self, &other.string[])
+        PartialEq::ne(*self, &other.string[..])
     }
 }
 
 impl Decodable for InternedString {
     fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
-        Ok(get_name(get_ident_interner().intern(&try!(d.read_str())[])))
+        Ok(get_name(get_ident_interner().intern(&try!(d.read_str())[..])))
     }
 }
 
 impl Encodable for InternedString {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_str(&self.string[])
+        s.emit_str(&self.string)
     }
 }
 
index 1593bfb97fe1da755ff08f1697d05c65e85d9eb1..5b3fde8535b3df4dfd1a8a189a722047e0d8e02b 100644 (file)
@@ -139,7 +139,7 @@ pub fn buf_str(toks: &[Token],
         }
         s.push_str(&format!("{}={}",
                            szs[i],
-                           tok_str(&toks[i]))[]);
+                           tok_str(&toks[i])));
         i += 1;
         i %= n;
     }
index f26578e740120d8f33695834534ac2a6c6d15d1d..af16e19c9f034a1c33399045ef009407cdbf09c1 100644 (file)
@@ -373,7 +373,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
-    $to_string(|s| s.print_path(p, false))
+    $to_string(|s| s.print_path(p, false, 0))
 }
 
 pub fn ident_to_string(id: &ast::Ident) -> String {
@@ -729,8 +729,11 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       &generics,
                                       None));
             }
-            ast::TyPath(ref path, _) => {
-                try!(self.print_path(path, false));
+            ast::TyPath(None, ref path) => {
+                try!(self.print_path(path, false, 0));
+            }
+            ast::TyPath(Some(ref qself), ref path) => {
+                try!(self.print_qpath(path, qself, false))
             }
             ast::TyObjectSum(ref ty, ref bounds) => {
                 try!(self.print_type(&**ty));
@@ -739,9 +742,6 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
             ast::TyPolyTraitRef(ref bounds) => {
                 try!(self.print_bounds("", &bounds[..]));
             }
-            ast::TyQPath(ref qpath) => {
-                try!(self.print_qpath(&**qpath, false))
-            }
             ast::TyFixedLengthVec(ref ty, ref v) => {
                 try!(word(&mut self.s, "["));
                 try!(self.print_type(&**ty));
@@ -926,6 +926,18 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
                 try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
             }
 
+            ast::ItemDefaultImpl(unsafety, ref trait_ref) => {
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("impl"));
+                try!(self.print_trait_ref(trait_ref));
+                try!(space(&mut self.s));
+                try!(self.word_space("for"));
+                try!(self.word_space(".."));
+                try!(self.bopen());
+                try!(self.bclose(item.span));
+            }
             ast::ItemImpl(unsafety,
                           polarity,
                           ref generics,
@@ -1006,7 +1018,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
             ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
                                             ..}) => {
                 try!(self.print_visibility(item.vis));
-                try!(self.print_path(pth, false));
+                try!(self.print_path(pth, false, 0));
                 try!(word(&mut self.s, "! "));
                 try!(self.print_ident(item.ident));
                 try!(self.cbox(indent_unit));
@@ -1021,7 +1033,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
-        self.print_path(&t.path, false)
+        self.print_path(&t.path, false, 0)
     }
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> {
@@ -1285,7 +1297,7 @@ pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> {
             ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
                                             ..}) => {
                 // code copied from ItemMac:
-                try!(self.print_path(pth, false));
+                try!(self.print_path(pth, false, 0));
                 try!(word(&mut self.s, "! "));
                 try!(self.cbox(indent_unit));
                 try!(self.popen());
@@ -1502,7 +1514,7 @@ pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
         match m.node {
             // I think it's reasonable to hide the ctxt here:
             ast::MacInvocTT(ref pth, ref tts, _) => {
-                try!(self.print_path(pth, false));
+                try!(self.print_path(pth, false, 0));
                 try!(word(&mut self.s, "!"));
                 match delim {
                     token::Paren => try!(self.popen()),
@@ -1572,7 +1584,7 @@ fn print_expr_struct(&mut self,
                          path: &ast::Path,
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>) -> IoResult<()> {
-        try!(self.print_path(path, true));
+        try!(self.print_path(path, true, 0));
         if !(fields.is_empty() && wth.is_none()) {
             try!(word(&mut self.s, "{"));
             try!(self.commasep_cmnt(
@@ -1840,8 +1852,12 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                     try!(self.print_expr(&**e));
                 }
             }
-            ast::ExprPath(ref path) => try!(self.print_path(path, true)),
-            ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
+            ast::ExprPath(None, ref path) => {
+                try!(self.print_path(path, true, 0))
+            }
+            ast::ExprPath(Some(ref qself), ref path) => {
+                try!(self.print_qpath(path, qself, true))
+            }
             ast::ExprBreak(opt_ident) => {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
@@ -2002,16 +2018,14 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
 
     fn print_path(&mut self,
                   path: &ast::Path,
-                  colons_before_params: bool)
+                  colons_before_params: bool,
+                  depth: usize)
                   -> IoResult<()>
     {
         try!(self.maybe_print_comment(path.span.lo));
-        if path.global {
-            try!(word(&mut self.s, "::"));
-        }
 
-        let mut first = true;
-        for segment in &path.segments {
+        let mut first = !path.global;
+        for segment in &path.segments[..path.segments.len()-depth] {
             if first {
                 first = false
             } else {
@@ -2027,19 +2041,24 @@ fn print_path(&mut self,
     }
 
     fn print_qpath(&mut self,
-                   qpath: &ast::QPath,
+                   path: &ast::Path,
+                   qself: &ast::QSelf,
                    colons_before_params: bool)
                    -> IoResult<()>
     {
         try!(word(&mut self.s, "<"));
-        try!(self.print_type(&*qpath.self_type));
-        try!(space(&mut self.s));
-        try!(self.word_space("as"));
-        try!(self.print_trait_ref(&*qpath.trait_ref));
+        try!(self.print_type(&qself.ty));
+        if qself.position > 0 {
+            try!(space(&mut self.s));
+            try!(self.word_space("as"));
+            let depth = path.segments.len() - qself.position;
+            try!(self.print_path(&path, false, depth));
+        }
         try!(word(&mut self.s, ">"));
         try!(word(&mut self.s, "::"));
-        try!(self.print_ident(qpath.item_path.identifier));
-        self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
+        let item_segment = path.segments.last().unwrap();
+        try!(self.print_ident(item_segment.identifier));
+        self.print_path_parameters(&item_segment.parameters, colons_before_params)
     }
 
     fn print_path_parameters(&mut self,
@@ -2144,7 +2163,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
                 }
             }
             ast::PatEnum(ref path, ref args_) => {
-                try!(self.print_path(path, true));
+                try!(self.print_path(path, true, 0));
                 match *args_ {
                     None => try!(word(&mut self.s, "(..)")),
                     Some(ref args) => {
@@ -2158,7 +2177,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
                 }
             }
             ast::PatStruct(ref path, ref fields, etc) => {
-                try!(self.print_path(path, true));
+                try!(self.print_path(path, true, 0));
                 try!(self.nbsp());
                 try!(self.word_space("{"));
                 try!(self.commasep_cmnt(
@@ -2342,7 +2361,7 @@ pub fn print_fn_args(&mut self, decl: &ast::FnDecl,
 
         // HACK(eddyb) ignore the separately printed self argument.
         let args = if first {
-            &decl.inputs[]
+            &decl.inputs[..]
         } else {
             &decl.inputs[1..]
         };
@@ -2543,7 +2562,7 @@ pub fn print_where_clause(&mut self, generics: &ast::Generics)
                     }
                 }
                 &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
-                    try!(self.print_path(path, false));
+                    try!(self.print_path(path, false, 0));
                     try!(space(&mut self.s));
                     try!(self.word_space("="));
                     try!(self.print_type(&**ty));
@@ -2580,7 +2599,7 @@ pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> {
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path) => {
-                try!(self.print_path(path, false));
+                try!(self.print_path(path, false, 0));
 
                 // FIXME(#6993) can't compare identifiers directly here
                 if path.segments.last().unwrap().identifier.name !=
@@ -2594,7 +2613,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
             }
 
             ast::ViewPathGlob(ref path) => {
-                try!(self.print_path(path, false));
+                try!(self.print_path(path, false, 0));
                 word(&mut self.s, "::*")
             }
 
@@ -2602,7 +2621,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
                 if path.segments.is_empty() {
                     try!(word(&mut self.s, "{"));
                 } else {
-                    try!(self.print_path(path, false));
+                    try!(self.print_path(path, false, 0));
                     try!(word(&mut self.s, "::{"));
                 }
                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
index adb5383a8fd544d0f666dbf74d92e2fb729f20d5..ca3a1848c3a6161313590be914a2b5d1a2756302 100644 (file)
@@ -111,13 +111,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[cfg(stage0)]
-impl<S: Hasher, T: Hash<S>> Hash<S> for P<T> {
-    fn hash(&self, state: &mut S) {
-        (**self).hash(state);
-    }
-}
-#[cfg(not(stage0))]
 impl<T: Hash> Hash for P<T> {
     fn hash<H: Hasher>(&self, state: &mut H) {
         (**self).hash(state);
index 4e4a571ede7b864af3b797be5784fb6fc582e7b9..ac7cdb1b4130703ba30b7150a4eb25331b6cc7e8 100644 (file)
@@ -38,7 +38,7 @@ pub fn maybe_inject_prelude(krate: ast::Crate) -> ast::Crate {
 }
 
 pub fn use_std(krate: &ast::Crate) -> bool {
-    !attr::contains_name(&krate.attrs[], "no_std")
+    !attr::contains_name(&krate.attrs, "no_std")
 }
 
 fn no_prelude(attrs: &[ast::Attribute]) -> bool {
@@ -88,14 +88,14 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
         // only add `use std::prelude::*;` if there wasn't a
         // `#![no_implicit_prelude]` at the crate level.
         // fold_mod() will insert glob path.
-        if !no_prelude(&krate.attrs[]) {
+        if !no_prelude(&krate.attrs) {
             krate.module = self.fold_mod(krate.module);
         }
         krate
     }
 
     fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
-        if !no_prelude(&item.attrs[]) {
+        if !no_prelude(&item.attrs) {
             // only recur if there wasn't `#![no_implicit_prelude]`
             // on this item, i.e. this means that the prelude is not
             // implicitly imported though the whole subtree
index 7b1fc91e45b5bb3547841faf5f7505210a03b5f0..5bada41badfd8077b4980f4bb79deb6c6fc4066a 100644 (file)
@@ -73,14 +73,14 @@ pub fn modify_for_testing(sess: &ParseSess,
     // We generate the test harness when building in the 'test'
     // configuration, either with the '--test' or '--cfg test'
     // command line options.
-    let should_test = attr::contains_name(&krate.config[], "test");
+    let should_test = attr::contains_name(&krate.config, "test");
 
     // Check for #[reexport_test_harness_main = "some_name"] which
     // creates a `use some_name = __test::main;`. This needs to be
     // unconditional, so that the attribute is still marked as used in
     // non-test builds.
     let reexport_test_harness_main =
-        attr::first_attr_value_str_by_name(&krate.attrs[],
+        attr::first_attr_value_str_by_name(&krate.attrs,
                                            "reexport_test_harness_main");
 
     if should_test {
@@ -306,7 +306,7 @@ enum HasTestSignature {
 
 
 fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
-    let has_test_attr = attr::contains_name(&i.attrs[], "test");
+    let has_test_attr = attr::contains_name(&i.attrs, "test");
 
     fn has_test_signature(i: &ast::Item) -> HasTestSignature {
         match &i.node {
@@ -342,7 +342,7 @@ fn has_test_signature(i: &ast::Item) -> HasTestSignature {
 }
 
 fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
-    let has_bench_attr = attr::contains_name(&i.attrs[], "bench");
+    let has_bench_attr = attr::contains_name(&i.attrs, "bench");
 
     fn has_test_signature(i: &ast::Item) -> bool {
         match i.node {
@@ -562,7 +562,7 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
 }
 
 fn is_test_crate(krate: &ast::Crate) -> bool {
-    match attr::find_crate_name(&krate.attrs[]) {
+    match attr::find_crate_name(&krate.attrs) {
         Some(ref s) if "test" == &s[..] => true,
         _ => false
     }
index dffeac6f3f7938df88ae352309b3a9fb068c42f3..5be45a2698f40ae34c295c3e2e892994d465fc2a 100644 (file)
@@ -18,7 +18,6 @@
 use std::cell::RefCell;
 use std::cmp::Ordering;
 use std::collections::HashMap;
-#[cfg(stage0)] use std::collections::hash_map::Hasher;
 use std::fmt;
 use std::hash::Hash;
 use std::ops::Deref;
@@ -30,71 +29,6 @@ pub struct Interner<T> {
 }
 
 // when traits can extend traits, we should extend index<Name,T> to get []
-#[cfg(stage0)]
-impl<T: Eq + Hash<Hasher> + Clone + 'static> Interner<T> {
-    pub fn new() -> Interner<T> {
-        Interner {
-            map: RefCell::new(HashMap::new()),
-            vect: RefCell::new(Vec::new()),
-        }
-    }
-
-    pub fn prefill(init: &[T]) -> Interner<T> {
-        let rv = Interner::new();
-        for v in init {
-            rv.intern((*v).clone());
-        }
-        rv
-    }
-
-    pub fn intern(&self, val: T) -> Name {
-        let mut map = self.map.borrow_mut();
-        match (*map).get(&val) {
-            Some(&idx) => return idx,
-            None => (),
-        }
-
-        let mut vect = self.vect.borrow_mut();
-        let new_idx = Name((*vect).len() as u32);
-        (*map).insert(val.clone(), new_idx);
-        (*vect).push(val);
-        new_idx
-    }
-
-    pub fn gensym(&self, val: T) -> Name {
-        let mut vect = self.vect.borrow_mut();
-        let new_idx = Name((*vect).len() as u32);
-        // leave out of .map to avoid colliding
-        (*vect).push(val);
-        new_idx
-    }
-
-    pub fn get(&self, idx: Name) -> T {
-        let vect = self.vect.borrow();
-        (*vect)[idx.usize()].clone()
-    }
-
-    pub fn len(&self) -> usize {
-        let vect = self.vect.borrow();
-        (*vect).len()
-    }
-
-    pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
-    where T: Borrow<Q>, Q: Eq + Hash<Hasher> {
-        let map = self.map.borrow();
-        match (*map).get(val) {
-            Some(v) => Some(*v),
-            None => None,
-        }
-    }
-
-    pub fn clear(&self) {
-        *self.map.borrow_mut() = HashMap::new();
-        *self.vect.borrow_mut() = Vec::new();
-    }
-}
-// when traits can extend traits, we should extend index<Name,T> to get []
-#[cfg(not(stage0))]
 impl<T: Eq + Hash + Clone + 'static> Interner<T> {
     pub fn new() -> Interner<T> {
         Interner {
@@ -275,15 +209,6 @@ pub fn len(&self) -> usize {
         self.vect.borrow().len()
     }
 
-    #[cfg(stage0)]
-    pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
-    where RcStr: Borrow<Q>, Q: Eq + Hash<Hasher> {
-        match (*self.map.borrow()).get(val) {
-            Some(v) => Some(*v),
-            None => None,
-        }
-    }
-    #[cfg(not(stage0))]
     pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
     where RcStr: Borrow<Q>, Q: Eq + Hash {
         match (*self.map.borrow()).get(val) {
index 0a39d3809045a2e56f745255e6b204bc5d43f8d0..90df23882a1d4bf53c790a36ed40dae5ac899696 100644 (file)
@@ -229,10 +229,10 @@ fn test_move_iter() {
         assert_eq!(Vec::new(), v);
 
         let v = SmallVector::one(1);
-        assert_eq!(vec![1], v.into_iter().collect::<Vec<_>>());
+        assert_eq!([1], v.into_iter().collect::<Vec<_>>());
 
         let v = SmallVector::many(vec![1, 2, 3]);
-        assert_eq!(vec!(1, 2, 3), v.into_iter().collect::<Vec<_>>());
+        assert_eq!([1, 2, 3], v.into_iter().collect::<Vec<_>>());
     }
 
     #[test]
index 21cb62b0a0c112818f30308c2ec7f3888906950d..33d8d56b4b11469cb6ccbf9890a57ba9d7555389 100644 (file)
@@ -125,9 +125,6 @@ fn visit_mac(&mut self, _mac: &'v Mac) {
     fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
         walk_path(self, path)
     }
-    fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) {
-        walk_qpath(self, qpath_span, qpath)
-    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -282,6 +279,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_enum_def(visitor, enum_definition, type_parameters)
         }
+        ItemDefaultImpl(_, ref trait_ref) => {
+            visitor.visit_trait_ref(trait_ref)
+        }
         ItemImpl(_, _,
                  ref type_parameters,
                  ref trait_reference,
@@ -396,16 +396,16 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
             walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
         }
-        TyPath(ref path, id) => {
-            visitor.visit_path(path, id);
+        TyPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            visitor.visit_path(path, typ.id);
         }
         TyObjectSum(ref ty, ref bounds) => {
             visitor.visit_ty(&**ty);
             walk_ty_param_bounds_helper(visitor, bounds);
         }
-        TyQPath(ref qpath) => {
-            visitor.visit_qpath(typ.span, &**qpath);
-        }
         TyFixedLengthVec(ref ty, ref expression) => {
             visitor.visit_ty(&**ty);
             visitor.visit_expr(&**expression)
@@ -433,14 +433,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     }
 }
 
-pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
-                                      qpath_span: Span,
-                                      qpath: &'v QPath) {
-    visitor.visit_ty(&*qpath.self_type);
-    visitor.visit_trait_ref(&*qpath.trait_ref);
-    visitor.visit_path_segment(qpath_span, &qpath.item_path);
-}
-
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
@@ -866,12 +858,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             walk_expr_opt(visitor, start);
             walk_expr_opt(visitor, end)
         }
-        ExprPath(ref path) => {
+        ExprPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
             visitor.visit_path(path, expression.id)
         }
-        ExprQPath(ref qpath) => {
-            visitor.visit_qpath(expression.span, &**qpath)
-        }
         ExprBreak(_) | ExprAgain(_) => {}
         ExprRet(ref optional_expression) => {
             walk_expr_opt(visitor, optional_expression)
index 5418533aff1d918129f9bae1f6f5059dd603fe55..823d2879236d1a9d961a60f5c9a8a646968fb7a0 100644 (file)
@@ -60,6 +60,7 @@
 #![feature(unicode)]
 #![feature(std_misc)]
 #![feature(env)]
+#![feature(os)]
 #![cfg_attr(windows, feature(libc))]
 
 #[macro_use] extern crate log;
index 0b577f8de74c2a9b2e8178584173c29e8d134b7a..112525fcce96efe2a1762a6555f4ddee0a80daa5 100644 (file)
@@ -652,15 +652,15 @@ fn test_comparison_ops() {
             let s = format!("%{{1}}%{{2}}%{}%d", op);
             let res = expand(s.as_bytes(), &[], &mut Variables::new());
             assert!(res.is_ok(), res.err().unwrap());
-            assert_eq!(res.unwrap(), vec!(b'0' + bs[0]));
+            assert_eq!(res.unwrap(), [b'0' + bs[0]]);
             let s = format!("%{{1}}%{{1}}%{}%d", op);
             let res = expand(s.as_bytes(), &[], &mut Variables::new());
             assert!(res.is_ok(), res.err().unwrap());
-            assert_eq!(res.unwrap(), vec!(b'0' + bs[1]));
+            assert_eq!(res.unwrap(), [b'0' + bs[1]]);
             let s = format!("%{{2}}%{{1}}%{}%d", op);
             let res = expand(s.as_bytes(), &[], &mut Variables::new());
             assert!(res.is_ok(), res.err().unwrap());
-            assert_eq!(res.unwrap(), vec!(b'0' + bs[2]));
+            assert_eq!(res.unwrap(), [b'0' + bs[2]]);
         }
     }
 
index c40a5534efbbb4e8d3d6146c6c513a124a420c62..a0cd78420700187e78aa2ef451e5ff81f0bf2a3a 100644 (file)
 use std::env;
 
 /// Return path to database entry for `term`
+#[allow(deprecated)]
 pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
     if term.len() == 0 {
         return None;
     }
 
-    let homedir = env::home_dir();
+    let homedir = ::std::os::homedir();
 
     let mut dirs_to_search = Vec::new();
     let first_char = term.char_at(0);
index 4e94be59ade0dd540f2f743138df9cae9ae52dd1..7cc07e926b267b4b27b97c82e2f7c2adfd47b046 100644 (file)
@@ -332,6 +332,7 @@ pub fn winsorize<T: Float + FromPrimitive>(samples: &mut [T], pct: T) {
 
 /// Returns a HashMap with the number of occurrences of every element in the
 /// sequence that the iterator exposes.
+#[cfg(not(stage0))]
 pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint>
   where T: Iterator<Item=U>, U: Eq + Clone + Hash
 {
index 9bd8c5525a056828966e0838637722518d0370f6..38cbe5c7dea16218d1942fc7eef3f9e70406dc18 100644 (file)
@@ -84,7 +84,7 @@ fn width(&self, is_cjk: bool) -> usize {
 
     #[inline]
     fn trim(&self) -> &str {
-        self.trim_left().trim_right()
+        self.trim_matches(|c: char| c.is_whitespace())
     }
 
     #[inline]
index 4891e6382e3e8aa89d530aa18427836428c47157..b89c3f039b61edbb077771eda2ee8a718dbec7e0 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 4891e6382e3e8aa89d530aa18427836428c47157
+Subproject commit b89c3f039b61edbb077771eda2ee8a718dbec7e0
index c82da57c12847af48603e9bbc1660d0a57a4e36f..cf2b9b9f717c57ff13ff997c99a33e467cd26dd6 100644 (file)
 
 #if defined(__APPLE__)
 #define EXHAUSTED               _rust_stack_exhausted
-#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#elif defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__Bitrig__)
 #define EXHAUSTED               rust_stack_exhausted@PLT
 #else
 #define EXHAUSTED               rust_stack_exhausted
 #endif
 
-#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__Bitrig__)
        .hidden MORESTACK
 #else
 #if defined(__APPLE__)
index b756602ead4f43286408ad769742f79e4fc32934..db1a602b404f60028282d84073bb3f7a2206dc98 100644 (file)
@@ -47,8 +47,8 @@ extern char **environ;
 #endif
 #endif
 
-#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) \
-  || defined(__DragonFly__) || defined(__OpenBSD__)
+#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || \
+    defined(__DragonFly__) || defined(__Bitrig__) || defined(__OpenBSD__)
 extern char **environ;
 #endif
 
@@ -200,7 +200,282 @@ rust_unset_sigprocmask() {
 int *__dfly_error(void) { return __error(); }
 #endif
 
-#if defined(__OpenBSD__)
+#if defined(__Bitrig__)
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <limits.h>
+
+int rust_get_path(void *p, size_t* sz)
+{
+  int mib[4];
+  char *eq = NULL;
+  char *key = NULL;
+  char *val = NULL;
+  char **menv = NULL;
+  size_t maxlen, len;
+  int nenv = 0;
+  int i;
+
+  if ((p == NULL) && (sz == NULL))
+    return -1;
+
+  /* get the argv array */
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC_ARGS;
+  mib[2] = getpid();
+  mib[3] = KERN_PROC_ENV;
+
+  /* get the number of bytes needed to get the env */
+  maxlen = 0;
+  if (sysctl(mib, 4, NULL, &maxlen, NULL, 0) == -1)
+    return -1;
+
+  /* allocate the buffer */
+  if ((menv = calloc(maxlen, sizeof(char))) == NULL)
+    return -1;
+
+  /* get the env array */
+  if (sysctl(mib, 4, menv, &maxlen, NULL, 0) == -1)
+  {
+    free(menv);
+    return -1;
+  }
+
+  mib[3] = KERN_PROC_NENV;
+  len = sizeof(int);
+  /* get the length of env array */
+  if (sysctl(mib, 4, &nenv, &len, NULL, 0) == -1)
+  {
+    free(menv);
+    return -1;
+  }
+
+  /* find _ key and resolve the value */
+  for (i = 0; i < nenv; i++)
+  {
+    if ((eq = strstr(menv[i], "=")) == NULL)
+      continue;
+
+    key = menv[i];
+    val = eq + 1;
+    *eq = '\0';
+
+    if (strncmp(key, "PATH", maxlen) != 0)
+      continue;
+
+    if (p == NULL)
+    {
+      /* return the length of the value + NUL */
+      *sz = strnlen(val, maxlen) + 1;
+      free(menv);
+      return 0;
+    }
+    else
+    {
+      /* copy *sz bytes to the output buffer */
+      memcpy(p, val, *sz);
+      free(menv);
+      return 0;
+    }
+  }
+
+  free(menv);
+  return -1;
+}
+
+int rust_get_path_array(void * p, size_t * sz)
+{
+  char *path, *str;
+  char **buf;
+  int i, num;
+  size_t len;
+
+  if ((p == NULL) && (sz == NULL))
+    return -1;
+
+  /* get the length of the PATH value */
+  if (rust_get_path(NULL, &len) == -1)
+    return -1;
+
+  if (len == 0)
+    return -1;
+
+  /* allocate the buffer */
+  if ((path = calloc(len, sizeof(char))) == NULL)
+    return -1;
+
+  /* get the PATH value */
+  if (rust_get_path(path, &len) == -1)
+  {
+    free(path);
+    return -1;
+  }
+
+  /* count the number of parts in the PATH */
+  num = 1;
+  for(str = path; *str != '\0'; str++)
+  {
+    if (*str == ':')
+      num++;
+  }
+
+  /* calculate the size of the buffer for the 2D array */
+  len = (num * sizeof(char*) + 1) + strlen(path) + 1;
+
+  if (p == NULL)
+  {
+    free(path);
+    *sz = len;
+    return 0;
+  }
+
+  /* make sure we have enough buffer space */
+  if (*sz < len)
+  {
+    free(path);
+    return -1;
+  }
+
+  /* zero out the buffer */
+  buf = (char**)p;
+  memset(buf, 0, *sz);
+
+  /* copy the data into the right place */
+  str = p + ((num+1) * sizeof(char*));
+  memcpy(str, path, strlen(path));
+
+  /* parse the path into it's parts */
+  for (i = 0; i < num && (buf[i] = strsep(&str, ":")) != NULL; i++) {;}
+  buf[num] = NULL;
+
+  free(path);
+  return 0;
+}
+
+int rust_get_argv_zero(void* p, size_t* sz)
+{
+  int mib[4];
+  char **argv = NULL;
+  size_t len;
+
+  if ((p == NULL) && (sz == NULL))
+    return -1;
+
+  /* get the argv array */
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_PROC_ARGS;
+  mib[2] = getpid();
+  mib[3] = KERN_PROC_ARGV;
+
+  /* request KERN_PROC_ARGV size */
+  len = 0;
+  if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1)
+    return -1;
+
+  /* allocate buffer to receive the values */
+  if ((argv = malloc(len)) == NULL)
+    return -1;
+
+  /* get the argv array */
+  if (sysctl(mib, 4, argv, &len, NULL, 0) == -1)
+  {
+    free(argv);
+    return -1;
+  }
+
+  /* get length of argv[0] */
+  len = strnlen(argv[0], len) + 1;
+
+  if (p == NULL)
+  {
+    *sz = len;
+    free(argv);
+    return 0;
+  }
+
+  if (*sz < len)
+  {
+    free(argv);
+    return -1;
+  }
+
+  memset(p, 0, len);
+  memcpy(p, argv[0], len);
+  free(argv);
+  return 0;
+}
+
+const char * rust_current_exe()
+{
+  static char *self = NULL;
+  char *argv0;
+  char **paths;
+  size_t sz;
+  int i;
+  char buf[2*PATH_MAX], exe[2*PATH_MAX];
+
+  if (self != NULL)
+    return self;
+
+  if (rust_get_argv_zero(NULL, &sz) == -1)
+    return NULL;
+  if ((argv0 = calloc(sz, sizeof(char))) == NULL)
+    return NULL;
+  if (rust_get_argv_zero(argv0, &sz) == -1)
+  {
+    free(argv0);
+    return NULL;
+  }
+
+  /* if argv0 is a relative or absolute path, resolve it with realpath */
+  if ((*argv0 == '.') || (*argv0 == '/') || (strstr(argv0, "/") != NULL))
+  {
+    self = realpath(argv0, NULL);
+    free(argv0);
+    return self;
+  }
+
+  /* get the path array */
+  if (rust_get_path_array(NULL, &sz) == -1)
+  {
+    free(argv0);
+    return NULL;
+  }
+  if ((paths = calloc(sz, sizeof(char))) == NULL)
+  {
+    free(argv0);
+    return NULL;
+  }
+  if (rust_get_path_array(paths, &sz) == -1)
+  {
+    free(argv0);
+    free(paths);
+    return NULL;
+  }
+
+  for(i = 0; paths[i] != NULL; i++)
+  {
+    snprintf(buf, 2*PATH_MAX, "%s/%s", paths[i], argv0);
+    if (realpath(buf, exe) == NULL)
+      continue;
+
+    if (access(exe, F_OK | X_OK) == -1)
+      continue;
+
+    self = strdup(exe);
+    free(argv0);
+    free(paths);
+    return self;
+  }
+
+  free(argv0);
+  free(paths);
+  return NULL;
+}
+
+#elif defined(__OpenBSD__)
+
 #include <sys/param.h>
 #include <sys/sysctl.h>
 #include <limits.h>
@@ -248,6 +523,7 @@ const char * rust_current_exe() {
 
     return (self);
 }
+
 #endif
 
 //
index 21f8a7793dc0ca680ac61cce813eb20576c64ef5..3c116aa860bca9c10c1cf285832dde4f028ca07b 100644 (file)
@@ -50,14 +50,14 @@ fn next(&mut self) -> Option<(String, &'a BookItem)> {
 
                 let mut section = "".to_string();
                 for &(_, idx) in &self.stack {
-                    section.push_str(&(idx + 1).to_string()[]);
+                    section.push_str(&(idx + 1).to_string()[..]);
                     section.push('.');
                 }
-                section.push_str(&(self.cur_idx + 1).to_string()[]);
+                section.push_str(&(self.cur_idx + 1).to_string()[..]);
                 section.push('.');
 
                 self.stack.push((self.cur_items, self.cur_idx));
-                self.cur_items = &cur.children[];
+                self.cur_items = &cur.children[..];
                 self.cur_idx = 0;
                 return Some((section, cur))
             }
@@ -68,7 +68,7 @@ fn next(&mut self) -> Option<(String, &'a BookItem)> {
 impl Book {
     pub fn iter(&self) -> BookItems {
         BookItems {
-            cur_items: &self.chapters[],
+            cur_items: &self.chapters[..],
             cur_idx: 0,
             stack: Vec::new(),
         }
index 224f1ef1a8b9b6feaaa5e559b6bbfea5f2c953e5..f36d97d6d120d50ef2f42aaa2f47f3de788e49c7 100644 (file)
@@ -10,8 +10,8 @@
 
 //! Implementation of the `build` subcommand, used to compile a book.
 
-use std::os;
 use std::env;
+use std::os;
 use std::old_io;
 use std::old_io::{fs, File, BufferedWriter, TempDir, IoResult};
 
@@ -41,7 +41,7 @@ fn walk_items(items: &[BookItem],
                   path_to_root: &Path,
                   out: &mut Writer) -> IoResult<()> {
         for (i, item) in items.iter().enumerate() {
-            try!(walk_item(item, &format!("{}{}.", section, i + 1)[], path_to_root, out));
+            try!(walk_item(item, &format!("{}{}.", section, i + 1)[..], path_to_root, out));
         }
         Ok(())
     }
@@ -55,7 +55,7 @@ fn walk_item(item: &BookItem,
                  item.title));
         if !item.children.is_empty() {
             try!(writeln!(out, "<ul class='section'>"));
-            let _ = walk_items(&item.children[], section, path_to_root, out);
+            let _ = walk_items(&item.children[..], section, path_to_root, out);
             try!(writeln!(out, "</ul>"));
         }
         try!(writeln!(out, "</li>"));
@@ -65,7 +65,7 @@ fn walk_item(item: &BookItem,
 
     try!(writeln!(out, "<div id='toc' class='mobile-hidden'>"));
     try!(writeln!(out, "<ul class='chapter'>"));
-    try!(walk_items(&book.chapters[], "", path_to_root, out));
+    try!(walk_items(&book.chapters[..], "", path_to_root, out));
     try!(writeln!(out, "</ul>"));
     try!(writeln!(out, "</div>"));
 
@@ -179,7 +179,7 @@ fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
             Err(errors) => {
                 let n = errors.len();
                 for err in errors {
-                    term.err(&format!("error: {}", err)[]);
+                    term.err(&format!("error: {}", err)[..]);
                 }
 
                 Err(box format!("{} errors occurred", n) as Box<Error>)
index ace57f0ac2c0b9351e6df4860955697cedd209b4..b9fc011e8b9a584edf198247e2eb1d0de9f67399 100644 (file)
@@ -12,8 +12,8 @@
 #![feature(collections)]
 #![feature(core)]
 #![feature(old_io)]
-#![feature(os)]
 #![feature(env)]
+#![feature(os)]
 #![feature(old_path)]
 #![feature(rustdoc)]
 
@@ -54,16 +54,16 @@ fn main() {
     if cmd.len() <= 1 {
         help::usage()
     } else {
-        match subcommand::parse_name(&cmd[1][]) {
+        match subcommand::parse_name(&cmd[1][..]) {
             Some(mut subcmd) => {
                 match subcmd.parse_args(cmd.tail()) {
                     Ok(_) => {
                         match subcmd.execute(&mut term) {
                             Ok(_) => (),
                             Err(err) => {
-                                term.err(&format!("error: {}", err.description())[]);
+                                term.err(&format!("error: {}", err.description())[..]);
                                 err.detail().map(|detail| {
-                                    term.err(&format!("detail: {}", detail)[]);
+                                    term.err(&format!("detail: {}", detail)[..]);
                                 });
                             }
                         }
index c5d4875423ae1ee62893be77b7183018ff35ccf4..727a385a8f02811e19eb7a43d87b6500cd369e63 100644 (file)
@@ -50,8 +50,8 @@ fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
                         Ok(output) => {
                             if !output.status.success() {
                                 term.err(&format!("{}\n{}",
-                                         String::from_utf8_lossy(&output.output[]),
-                                         String::from_utf8_lossy(&output.error[]))[]);
+                                         String::from_utf8_lossy(&output.output[..]),
+                                         String::from_utf8_lossy(&output.error[..]))[..]);
                                 return Err(box "Some tests failed." as Box<Error>);
                             }
 
index 1317343712430d241e9115d1c70fd69d63a57e4c..2cd7ed6c1550781d31be6ab2bf7a54e56b264294 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2015-02-13
+2015-02-19
index 4759c44259d5289d7a71a29b47a6ff1387882c2f..318f66b946585d6cbd44f6760ab8e0e56f54d62b 100644 (file)
@@ -1,3 +1,21 @@
+S 2015-02-25 880fb89
+  freebsd-x86_64 f4cbe4227739de986444211f8ee8d74745ab8f7f
+  linux-i386 3278ebbce8cb269acc0614dac5ddac07eab6a99c
+  linux-x86_64 72287d0d88de3e5a53bae78ac0d958e1a7637d73
+  macos-i386 33b366b5287427a340a0aa6ed886d5ff4edf6a76
+  macos-x86_64 914bf9baa32081a9d5633f1d06f4d382cd71504e
+  winnt-i386 d58b415b9d8629cb6c4952f1f6611a526a38323f
+  winnt-x86_64 2cb1dcc563d2ac6deada054de15748f5dd599c7e
+
+S 2015-02-19 522d09d
+  freebsd-x86_64 7ea14ef85a25bca70a310a2cd660b356cf61abc7
+  linux-i386 26e3caa1ce1c482b9941a6bdc64b3e65d036c200
+  linux-x86_64 44f514aabb4e4049e4db9a4e1fdeb16f6cee60f2
+  macos-i386 157910592224083df56f5f31ced3e6f3dc9b1de0
+  macos-x86_64 56c28aa0e14ec6991ad6ca213568f1155561105d
+  winnt-i386 da0f7a3fbc913fbb177917f2850bb41501affb5c
+  winnt-x86_64 22bd816ccd2690fc9804b27ca525f603be8aeaa5
+
 S 2015-02-17 f1bb6c2
   freebsd-x86_64 59f3a2c6350c170804fb65838e1b504eeab89105
   linux-i386 191ed5ec4f17e32d36abeade55a1c6085e51245c
index dd272bf639b9723cb53da920f1c2502b250266ac..96a06968c5fa3cc961496cba8a20ee33163eddc7 100644 (file)
@@ -17,7 +17,7 @@ pub struct cat {
       pub name : String,
     }
 
-    impl fmt::String for cat {
+    impl fmt::Display for cat {
         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             write!(f, "{}", self.name)
         }
diff --git a/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs b/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs
new file mode 100644 (file)
index 0000000..ce97019
--- /dev/null
@@ -0,0 +1,52 @@
+// 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 equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Box {
+    type Color;
+
+    fn mail(&self) {  }
+}
+
+fn a<C:Vehicle+Box>(_: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn b<C>(_: C::Color) where C : Vehicle+Box {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn c<C>(_: C::Color) where C : Vehicle, C : Box {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+struct D<X>;
+impl<X> D<X> where X : Vehicle {
+    fn d(&self, _: X::Color) where X : Box { }
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+}
+
+trait E<X:Vehicle> {
+    fn e(&self, _: X::Color) where X : Box;
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+
+    fn f(&self, _: X::Color) where X : Box { }
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+}
+
+pub fn main() { }
index 3999e9cbe753d1d90ab8294ada23d1d1be274f6a..becbc27138b770e700d524844357252c7c017c95 100644 (file)
@@ -22,5 +22,8 @@ trait Grab {
     //~^ ERROR ambiguous associated type
 }
 
+type X = std::ops::Deref::Target;
+//~^ ERROR ambiguous associated type
+
 fn main() {
 }
index 3e02a11c378bd5a2292e8824c149cc4792479098..7a7406115d39365a5735d7f24a735eaa43c91941 100644 (file)
@@ -43,7 +43,7 @@ fn foo<'a>() {
     //~^ ERROR too many type parameters provided
 
     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR too many lifetime parameters provided
+    //~^ ERROR wrong number of lifetime parameters
 
     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
     //~^ ERROR too many type parameters provided
index 9126058a4e6f41cacf0ecc08f0d87948b9dc1de1..d60751eddc7bc201866255cb0b129c90744be516 100644 (file)
@@ -11,7 +11,7 @@
 // Test that attempt to reborrow an `&mut` pointer in an aliasable
 // location yields an error.
 //
-// Example from src/middle/borrowck/doc.rs
+// Example from src/librustc_borrowck/borrowck/README.md
 
 fn foo(t0: & &mut isize) {
     let t1 = t0;
diff --git a/src/test/compile-fail/borrowck-fn-in-const-a.rs b/src/test/compile-fail/borrowck-fn-in-const-a.rs
new file mode 100644 (file)
index 0000000..3098807
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+const MOVE: fn(&String) -> String = {
+    fn broken(x: &String) -> String {
+        return *x //~ ERROR cannot move
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/compile-fail/borrowck-fn-in-const-b.rs b/src/test/compile-fail/borrowck-fn-in-const-b.rs
new file mode 100644 (file)
index 0000000..7e29b2e
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// How about mutating an immutable vector?
+const MUTATE: fn(&Vec<String>) = {
+    fn broken(x: &Vec<String>) {
+        x.push(format!("this is broken"));
+        //~^ ERROR cannot borrow
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/compile-fail/borrowck-fn-in-const-c.rs b/src/test/compile-fail/borrowck-fn-in-const-c.rs
new file mode 100644 (file)
index 0000000..e607397
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// Returning local references?
+struct DropString {
+    inner: String
+}
+impl Drop for DropString {
+    fn drop(&mut self) {
+        self.inner.clear();
+        self.inner.push_str("dropped");
+    }
+}
+const LOCAL_REF: fn() -> &'static str = {
+    fn broken() -> &'static str {
+        let local = DropString { inner: format!("Some local string") };
+        return &local.inner; //~ ERROR does not live long enough
+    }
+    broken
+};
+
+fn main() {
+}
index 5bdea6a2bd9962898812feaeb71637fc7372ae76..2fb89e6364bb1e8b24a8607cd18d46f9329fe502 100644 (file)
@@ -11,7 +11,7 @@
 // Test that attempt to move `&mut` pointer while pointee is borrowed
 // yields an error.
 //
-// Example from src/middle/borrowck/doc.rs
+// Example from src/librustc_borrowck/borrowck/README.md
 
 fn foo(t0: &mut isize) {
     let p: &isize = &*t0; // Freezes `*t0`
index 71dc61abb64e9c7d7e3e44b20e230b3917c0445d..bdeb7ea69bdfb84d416420bc26f3474e373d6c90 100644 (file)
@@ -11,7 +11,7 @@
 // Test that attempt to mutably borrow `&mut` pointer while pointee is
 // borrowed yields an error.
 //
-// Example from src/middle/borrowck/doc.rs
+// Example from src/librustc_borrowck/borrowck/README.md
 
 fn foo<'a>(mut t0: &'a mut isize,
            mut t1: &'a mut isize) {
index 0102a909188468ff92dc6625fc6e916abe974fae..552fcec8e2858e921fd6a8842b3981667986e5a0 100644 (file)
@@ -11,7 +11,7 @@
 // Test that attempt to swap `&mut` pointer while pointee is borrowed
 // yields an error.
 //
-// Example from src/middle/borrowck/doc.rs
+// Example from src/librustc_borrowck/borrowck/README.md
 
 use std::mem::swap;
 
index d4decb713498df2e3e35eff101178d59b87af488..98a9c713e84c331c9d305a63ff0ffa0cb79cec4f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 use std::marker::MarkerTrait;
 
index b1ee1762b6e71ab2d9c722de3564acc3da722821..57d25a3bf586dcab40fe8df4857095ca8db25ed7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that two blanket impls conflict (at least without negative
index 1f6bb08871c76db6ff94850c8fb35d2c3be3548f..b3ef79c6cc01e98474df89b02339b3406df1f5fa 100644 (file)
@@ -13,7 +13,7 @@
 extern crate go_trait;
 
 use go_trait::{Go,GoMut};
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 struct MyThingy;
index c3563792ce3c7d2e5b9f8c17a183560838ff5f9a..7b60a5ecbd71f4ac8533599cfb20cb73c4b42a71 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that a blank impl for all T conflicts with an impl for some
index 980e4256d2b854d635c4ccdaff00a97a4d710025..d218b64af05270f0dec430b4b1001d410edfd0e9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that a blank impl for all T conflicts with an impl for some
diff --git a/src/test/compile-fail/coherence-default-trait-impl.rs b/src/test/compile-fail/coherence-default-trait-impl.rs
new file mode 100644 (file)
index 0000000..6bcbefb
--- /dev/null
@@ -0,0 +1,24 @@
+// 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
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait MyTrait: MarkerTrait {}
+
+impl MyTrait for .. {}
+
+impl MyTrait for .. {}
+//~^ ERROR conflicting implementations for trait `MyTrait`
+
+fn main() {}
index 38730d241f68532b43f35c2dc15f3d1177c46d67..3e132dcb11fa32a3188efc241446b407c469562e 100644 (file)
@@ -34,6 +34,7 @@ unsafe impl Send for [MyType] {}
 
 unsafe impl Send for &'static [NotSync] {}
 //~^ ERROR builtin traits can only be implemented on structs or enums
+//~^^ ERROR conflicting implementations for trait `core::marker::Send`
 
 fn is_send<T: Send>() {}
 
index 9673fb6a21392dd3e619715beaa4c51b98fa31c2..87b007fdd698239d3af23c2558975c29ad994eb2 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that a blank impl for all T conflicts with an impl for some
diff --git a/src/test/compile-fail/cycle-projection-based-on-where-clause.rs b/src/test/compile-fail/cycle-projection-based-on-where-clause.rs
new file mode 100644 (file)
index 0000000..abcbf56
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Example cycle where a bound on `T` uses a shorthand for `T`. This
+// creates a cycle because we have to know the bounds on `T` to figure
+// out what trait defines `Item`, but we can't know the bounds on `T`
+// without knowing how to handle `T::Item`.
+//
+// Note that in the future cases like this could perhaps become legal,
+// if we got more fine-grained about our cycle detection or changed
+// how we handle `T::Item` resolution.
+
+use std::ops::Add;
+
+// Preamble.
+trait Trait { type Item; }
+
+struct A<T>
+    where T : Trait,
+          T : Add<T::Item>
+    //~^ ERROR illegal recursive type
+{
+    data: T
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/cycle-trait-supertrait-direct.rs b/src/test/compile-fail/cycle-trait-supertrait-direct.rs
new file mode 100644 (file)
index 0000000..ef3fead
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a supertrait cycle where a trait extends itself.
+
+trait Chromosome: Chromosome {
+    //~^ ERROR unsupported cyclic reference
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/cycle-trait-supertrait-indirect.rs b/src/test/compile-fail/cycle-trait-supertrait-indirect.rs
new file mode 100644 (file)
index 0000000..6ebd9a1
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a supertrait cycle where the first trait we find (`A`) is not
+// a direct participant in the cycle.
+
+trait A: B {
+}
+
+trait B: C { }
+
+trait C: B { }
+    //~^ ERROR unsupported cyclic reference
+
+fn main() { }
index ade8b397e0003d0e306f145ee334f934a8850a0d..21334e1d51375420c373ed906fdd09e59f1c6bc0 100644 (file)
@@ -24,7 +24,7 @@
 
     // Unresolved bounds should still error.
     fn align_of<T: NoSuchTrait>() -> usize;
-    //~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait`
+    //~^ ERROR use of undeclared trait name `NoSuchTrait`
 }
 
 fn main() {}
index 71e1f7091b2c99094e9459e64ba25fe261906ecc..d682ef7d70c9db931e5cbb28f74bee4b2c3ed41c 100644 (file)
@@ -15,8 +15,7 @@ fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
 
 fn main() {
     let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
-    //~^ ERROR object-safe
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     //~| expected `()`
     //~| found `Box<core::ops::FnOnce(isize)>`
     //~| expected ()
index 9fea5e609d1f4807812476ea8b2e53c5da09fcdf..5fa429445a35e66fc5d68df606e872227e308adf 100644 (file)
@@ -19,5 +19,5 @@ fn new() -> Foo<A, B, C> {Foo(marker::PhantomData)}
 
 fn main() {
     Foo::<isize>::new();
-    //~^ ERROR too few type parameters provided
+    //~^ ERROR wrong number of type arguments
 }
index 73c19aa012dcf67dd0d39d97f8a748f9cb1a436c..d3babb8982ddca652bdd9c16e113d89ea74f445a 100644 (file)
@@ -21,5 +21,5 @@ fn new() -> Vec<T, A> {Vec(marker::PhantomData)}
 
 fn main() {
     Vec::<isize, Heap, bool>::new();
-    //~^ ERROR too many type parameters provided
+    //~^ ERROR wrong number of type arguments
 }
index fce8a07d7270d3444fb83e4343a77e2bc90f7886..181503db818462907d8854a0cbb9e6b4cd4752dd 100644 (file)
@@ -36,9 +36,6 @@ fn main() {
     import(); //~ ERROR: unresolved
 
     foo::<A>(); //~ ERROR: undeclared
-    //~^ ERROR: undeclared
     foo::<C>(); //~ ERROR: undeclared
-    //~^ ERROR: undeclared
     foo::<D>(); //~ ERROR: undeclared
-    //~^ ERROR: undeclared
 }
diff --git a/src/test/compile-fail/if-loop.rs b/src/test/compile-fail/if-loop.rs
new file mode 100644 (file)
index 0000000..15f04df
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+// This used to ICE because the "if" being unreachable was not handled correctly
+fn err() {
+    if loop {} {}
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
index c6ce4d04e10866951d30c17fadb8c4dfefb1e56b..c0c951dd8b10835c990421bfc3a26ddfa2a9f055 100644 (file)
@@ -11,7 +11,7 @@
 struct Foo;
 impl Foo {
     fn orange(&self){}
-    fn orange(&self){}   //~ ERROR error: duplicate definition of value `orange`
+    fn orange(&self){}   //~ ERROR error: duplicate method in trait impl
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/impl-not-adjacent-to-type.rs b/src/test/compile-fail/impl-not-adjacent-to-type.rs
deleted file mode 100644 (file)
index 7a7673d..0000000
+++ /dev/null
@@ -1,24 +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.
-
-mod foo {
-    pub struct Foo {
-        x: isize,
-        y: isize,
-    }
-}
-
-impl foo::Foo {
-//~^ ERROR implementations may only be implemented in the same module
-    fn bar() {}
-}
-
-fn main() {}
-
index 2642ac6204ce4d8490f021c563994e7dd52c3b58..d39efa3c2ab78f909815c6db507a9a0be4a6419a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,28 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: reached the recursion limit during monomorphization
-// issue 2258
+//~^^^^^^^^^^ ERROR overflow
+//
+// We get an error message at the top of file (dummy span).
+// This is not helpful, but also kind of annoying to prevent,
+// so for now just live with it.
+// This test case was originally for issue #2258.
 
-trait to_opt {
+trait ToOpt {
     fn to_option(&self) -> Option<Self>;
 }
 
-impl to_opt for usize {
+impl ToOpt for usize {
     fn to_option(&self) -> Option<usize> {
         Some(*self)
     }
 }
 
-impl<T:Clone> to_opt for Option<T> {
+impl<T:Clone> ToOpt for Option<T> {
     fn to_option(&self) -> Option<Option<T>> {
         Some((*self).clone())
     }
 }
 
-fn function<T:to_opt + Clone>(counter: usize, t: T) {
+fn function<T:ToOpt + Clone>(counter: usize, t: T) {
     if counter > 0_usize {
         function(counter - 1_usize, t.to_option());
+        // FIXME(#4287) Error message should be here. It should be
+        // a type error to instantiate `test` at a type other than T.
     }
 }
 
index abd7efe0e8ed1faf141b88d662d7e4482294cc3c..cf2a70deee513cf3945a6389557febc52367ec1f 100644 (file)
@@ -14,7 +14,8 @@ enum Bar<T> { What }
 
 fn foo<T>() {
     static a: Bar<T> = Bar::What;
-    //~^ ERROR: cannot use an outer type parameter in this context
+    //~^ ERROR cannot use an outer type parameter in this context
+    //~| ERROR use of undeclared type name `T`
 }
 
 fn main() {
diff --git a/src/test/compile-fail/invalid-inline.rs b/src/test/compile-fail/invalid-inline.rs
new file mode 100644 (file)
index 0000000..ad89087
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![allow(dead_code)]
+
+#[inline(please_no)] //~ ERROR invalid argument
+fn a() {
+}
+
+#[inline(please,no)] //~ ERROR expected one argument
+fn b() {
+}
+
+#[inline()] //~ ERROR expected one argument
+fn c() {
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-12729.rs b/src/test/compile-fail/issue-12729.rs
deleted file mode 100644 (file)
index ae033bb..0000000
+++ /dev/null
@@ -1,23 +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.
-
-// ignore-tidy-linelength
-
-pub struct Foo;
-
-mod bar {
-    use Foo;
-
-    impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
-        fn baz(&self) {}
-    }
-}
-fn main() {}
-
index 3f5d29a82175805b40221dac4818821908952190..51b6dc0d07865eda130cbc0e8633f90907501550 100644 (file)
@@ -17,9 +17,9 @@ impl Bar { pub fn new() {} }
 
 fn main() {
     a::Foo::new();
-    //~^ ERROR: static method `new` is inaccessible
+    //~^ ERROR: method `new` is inaccessible
     //~^^ NOTE: struct `Foo` is private
     a::Bar::new();
-    //~^ ERROR: static method `new` is inaccessible
+    //~^ ERROR: method `new` is inaccessible
     //~^^ NOTE: enum `Bar` is private
 }
index 74eea0c57a01aaf3e29e86a5b197986134119815..ce5fa1f1fe1a5e66e4fc4cb9fc54f8d4de85c873 100644 (file)
@@ -29,7 +29,7 @@ fn bar(&self) {
         baz();
         //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
         a;
-        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        //~^ ERROR: unresolved name `a`
     }
 }
 
@@ -42,11 +42,11 @@ fn bar(&self) {
         y;
         //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
         a;
-        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        //~^ ERROR: unresolved name `a`
         bah;
         //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
         b;
-        //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+        //~^ ERROR: unresolved name `b`
     }
 }
 
@@ -59,11 +59,11 @@ fn bar(&self) {
         y;
         //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
         a;
-        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        //~^ ERROR: unresolved name `a`
         bah;
         //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
         b;
-        //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+        //~^ ERROR: unresolved name `b`
     }
 }
 
index 321b8b260daa9c6c04d2285889b108cce1c08dba..9f76f360f26ba7db9cf81f7def9321c8110111ad 100644 (file)
@@ -14,11 +14,11 @@ fn main() {
     let _foo = &[1_usize, 2] as [usize];
     //~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
     //~^^ HELP consider using an implicit coercion to `&[usize]` instead
-    let _bar = box 1_usize as std::fmt::Show;
-    //~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Show`
-    //~^^ HELP did you mean `Box<core::fmt::Show>`?
-    let _baz = 1_usize as std::fmt::Show;
-    //~^ ERROR cast to unsized type: `usize` as `core::fmt::Show`
+    let _bar = box 1_usize as std::fmt::Debug;
+    //~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Debug`
+    //~^^ HELP did you mean `Box<core::fmt::Debug>`?
+    let _baz = 1_usize as std::fmt::Debug;
+    //~^ ERROR cast to unsized type: `usize` as `core::fmt::Debug`
     //~^^ HELP consider using a box or reference as appropriate
     let _quux = [1_usize, 2] as [usize];
     //~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]`
index 368f3c16f5188c47debf096ae1caedd17426be68..8fb543fb96703cda1a50fc7c0731dfc11288656f 100644 (file)
@@ -17,7 +17,11 @@ impl Foo for Thing {
     fn foo<T>(&self, _: &T) {}
 }
 
-#[inline(never)] fn foo(b: &Bar) { b.foo(&0_usize) }
+#[inline(never)]
+fn foo(b: &Bar) {
+    b.foo(&0usize)
+    //~^ ERROR the trait `Foo` is not implemented for the type `Bar`
+}
 
 fn main() {
     let mut thing = Thing;
index bbc5ee6c8f36e336e453eb9c0920de56faf1e0fb..c6ff82364b3e7cd57c279b9e4772aab1d386c51f 100644 (file)
@@ -15,18 +15,11 @@ trait From<Src> {
 }
 
 trait To {
-    // This is a typo, the return type should be `<Dst as From<Self>>::Output`
-    fn to<Dst: From<Self>>(
-        self
-        //~^ error: the trait `core::marker::Sized` is not implemented
-    ) ->
+    fn to<Dst: From<Self>>(self) ->
         <Dst as From<Self>>::Dst
-        //~^ error: the trait `core::marker::Sized` is not implemented
+        //~^ ERROR use of undeclared associated type `From::Dst`
     {
-        From::from(
-            //~^ error: the trait `core::marker::Sized` is not implemented
-            self
-        )
+        From::from(self)
     }
 }
 
index 5c1de6dfc55b46a0e2ed3055093d869ab8e08540..05485008e51fddabce97136adf959f142d0fb3cf 100644 (file)
@@ -18,7 +18,7 @@ mod B {
     use crate1::A::Foo;
     fn bar(f: Foo) {
         Foo::foo(&f);
-        //~^ ERROR: function `foo` is private
+        //~^ ERROR: method `foo` is private
     }
 }
 
diff --git a/src/test/compile-fail/issue-22426-1.rs b/src/test/compile-fail/issue-22426-1.rs
new file mode 100644 (file)
index 0000000..f026a5d
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+  match 42 {
+    x < 7 => (),
+   //~^ error: unexpected token: `<`
+    _ => ()
+  }
+}
diff --git a/src/test/compile-fail/issue-22426-2.rs b/src/test/compile-fail/issue-22426-2.rs
new file mode 100644 (file)
index 0000000..ea5180e
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.
+
+fn a(B<) {}
+   //~^ error: unexpected token: `<`
diff --git a/src/test/compile-fail/issue-22426-3.rs b/src/test/compile-fail/issue-22426-3.rs
new file mode 100644 (file)
index 0000000..2e0b5d6
--- /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.
+
+struct Foo<T>(T, T);
+
+impl<T> Foo<T> {
+    fn foo(&self) {
+        match *self {
+            Foo<T>(x, y) => {
+            //~^ error: unexpected token: `<`
+              println!("Goodbye, World!")
+            }
+        }
+    }
+}
index f0ae0eb59f532f768622a6f249f078161b039992..48cc27e228940b74f93d71640562f64224e88f59 100644 (file)
@@ -36,7 +36,7 @@ fn shave(&self, other: usize) {
     shave(4);
     //~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
     purr();
-    //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+    //~^ ERROR: unresolved name `purr`
   }
 }
 
@@ -45,13 +45,13 @@ fn static_method() {}
 
     fn purr_louder() {
         static_method();
-        //~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method`
+        //~^ ERROR: unresolved name `static_method`
         purr();
-        //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+        //~^ ERROR: unresolved name `purr`
         purr();
-        //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+        //~^ ERROR: unresolved name `purr`
         purr();
-        //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+        //~^ ERROR: unresolved name `purr`
     }
 }
 
@@ -65,7 +65,7 @@ fn meow() {
 
   fn purr(&self) {
     grow_older();
-    //~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older`
+    //~^ ERROR: unresolved name `grow_older`
     shave();
     //~^ ERROR: unresolved name `shave`
   }
@@ -79,7 +79,7 @@ pub fn grow_older(other:usize) {
     whiskers = 4;
     //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
     purr_louder();
-    //~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder`
+    //~^ ERROR: unresolved name `purr_louder`
   }
 }
 
index 678618d721692a9db1d3885679bba38fbacc1939..ad5bc4e445c9839b7ebc41064ef684f460087340 100644 (file)
@@ -11,7 +11,9 @@
 fn main() {
     let foo = 100;
 
-    static y: isize = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant
+    static y: isize = foo + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+    //~| ERROR unresolved name `foo`
 
     println!("{}", y);
 }
index c49959c16a62180c7c1b7276173585687d22c694..f06aa45ac38fd1848c106847d37e1e5421e717af 100644 (file)
@@ -13,7 +13,9 @@ fn main() {
 
     #[derive(Debug)]
     enum Stuff {
-        Bar = foo //~ ERROR attempt to use a non-constant value in a constant
+        Bar = foo
+        //~^ ERROR attempt to use a non-constant value in a constant
+        //~| ERROR unresolved name `foo`
     }
 
     println!("{}", Stuff::Bar);
index 0577b1527234d03b48c62f1d69ccc56909c7c9d9..a09c8090de06de5716e718d3d33e6291f7edfaf9 100644 (file)
@@ -9,7 +9,9 @@
 // except according to those terms.
 
 fn f(x:isize) {
-    static child: isize = x + 1; //~ ERROR attempt to use a non-constant value in a constant
+    static child: isize = x + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+    //~| ERROR unresolved name `x`
 }
 
 fn main() {}
index 9c31dc1e38ef8ff312193b105a73e9346e9d0153..9b7476244f0d26a19e0d91639fea3c306c20406f 100644 (file)
@@ -17,6 +17,7 @@ impl PTrait for P {
    fn getChildOption(&self) -> Option<Box<P>> {
        static childVal: Box<P> = self.child.get();
        //~^ ERROR attempt to use a non-constant value in a constant
+       //~| ERROR unresolved name `self`
        panic!();
    }
 }
index e4f7521c33303cc340faabfacff70c593b767580..2652fb5dfc2fd6dc453f73f1d3d9094847ccbe86 100644 (file)
@@ -30,7 +30,5 @@ fn to_string(&self) -> String {
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    //~^ ERROR unresolved name `Point::new`
-    //~^^ ERROR failed to resolve. Use of undeclared type or module `Point`
     println!("{}", p.to_string());
 }
index b4bc7ecdc5f89693cb35bb449882fdc9693bb247..ab18e0bcddcf08ef7005c27a814343b131404578 100644 (file)
@@ -17,7 +17,7 @@ fn bar() {
         Foo { baz: 0 }.bar();
     }
 
-    fn bar() { //~ ERROR duplicate definition of value `bar`
+    fn bar() { //~ ERROR duplicate method in trait impl
     }
 }
 
index 48fc393d0da8e1cabeddd386cff78b130c727158..4ac901776099d0b0e4164e4d6296645ccbbd57b0 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-tidy-linelength
-
 struct Foo {
     x: isize
 }
 
-impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module
+impl Fo { //~ ERROR use of undeclared type name `Fo`
     fn foo() {}
 }
 
diff --git a/src/test/compile-fail/issue-7607-2.rs b/src/test/compile-fail/issue-7607-2.rs
deleted file mode 100644 (file)
index 9541899..0000000
+++ /dev/null
@@ -1,26 +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.
-
-// ignore-tidy-linelength
-
-pub mod a {
-    pub struct Foo { a: usize }
-}
-
-pub mod b {
-    use a::Foo;
-    impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
-        fn bar(&self) { }
-    }
-}
-
-pub fn main() { }
-
-
index 6c5bac5e0cb34bce3fbc4e38c6c300b23adc661c..2ef0a75f77b5a9fb25b4b1784d24c98d24075861 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-tidy-linelength
 
-impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module
+impl B { //~ ERROR use of undeclared type name `B`
 }
 
 fn main() {
index 73a58741bbbbc42ddbcf7efa384d9d578f86fed4..cb2d4e10e6e7166237e4e459a2c35b08f4c7ec50 100644 (file)
 #![doc="More garbage"]
 
 type Typedef = String;
-pub type PubTypedef = String; //~ ERROR: missing documentation
+pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias
 
 struct Foo {
     a: isize,
     b: isize,
 }
 
-pub struct PubFoo { //~ ERROR: missing documentation
-    pub a: isize,      //~ ERROR: missing documentation
+pub struct PubFoo { //~ ERROR: missing documentation for a struct
+    pub a: isize,      //~ ERROR: missing documentation for a struct field
     b: isize,
 }
 
@@ -36,11 +36,11 @@ pub struct PubFoo2 {
 }
 
 mod module_no_dox {}
-pub mod pub_module_no_dox {} //~ ERROR: missing documentation
+pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module
 
 /// dox
 pub fn foo() {}
-pub fn foo2() {} //~ ERROR: missing documentation
+pub fn foo2() {} //~ ERROR: missing documentation for a function
 fn foo3() {}
 #[allow(missing_docs)] pub fn foo4() {}
 
@@ -58,9 +58,9 @@ trait B {
     fn foo_with_impl(&self) {}
 }
 
-pub trait C { //~ ERROR: missing documentation
-    fn foo(&self); //~ ERROR: missing documentation
-    fn foo_with_impl(&self) {} //~ ERROR: missing documentation
+pub trait C { //~ ERROR: missing documentation for a trait
+    fn foo(&self); //~ ERROR: missing documentation for a type method
+    fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a method
 }
 
 #[allow(missing_docs)]
@@ -68,13 +68,26 @@ pub trait D {
     fn dummy(&self) { }
 }
 
+/// dox
+pub trait E {
+    type AssociatedType; //~ ERROR: missing documentation for an associated type
+    type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type
+
+    /// dox
+    type DocumentedType;
+    /// dox
+    type DocumentedTypeDef = Self;
+    /// dox
+    fn dummy(&self) {}
+}
+
 impl Foo {
     pub fn foo() {}
     fn bar() {}
 }
 
 impl PubFoo {
-    pub fn foo() {} //~ ERROR: missing documentation
+    pub fn foo() {} //~ ERROR: missing documentation for a method
     /// dox
     pub fn foo1() {}
     fn foo2() {}
@@ -111,9 +124,9 @@ enum Baz {
     BarB
 }
 
-pub enum PubBaz { //~ ERROR: missing documentation
-    PubBazA { //~ ERROR: missing documentation
-        a: isize, //~ ERROR: missing documentation
+pub enum PubBaz { //~ ERROR: missing documentation for an enum
+    PubBazA { //~ ERROR: missing documentation for a variant
+        a: isize, //~ ERROR: missing documentation for a struct field
     },
 }
 
@@ -139,14 +152,14 @@ pub fn baz() {}
 mod internal_impl {
     /// dox
     pub fn documented() {}
-    pub fn undocumented1() {} //~ ERROR: missing documentation
-    pub fn undocumented2() {} //~ ERROR: missing documentation
+    pub fn undocumented1() {} //~ ERROR: missing documentation for a function
+    pub fn undocumented2() {} //~ ERROR: missing documentation for a function
     fn undocumented3() {}
     /// dox
     pub mod globbed {
         /// dox
         pub fn also_documented() {}
-        pub fn also_undocumented1() {} //~ ERROR: missing documentation
+        pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function
         fn also_undocumented2() {}
     }
 }
index 88f2cbdea6d7bf81332f15efb3caf5e1dc4e6d47..90792848855721b89f39ed4342a9ab3090685411 100644 (file)
@@ -29,45 +29,104 @@ mod cross_crate {
     use lint_stability::*;
 
     fn test() {
+        type Foo = MethodTester;
         let foo = MethodTester;
 
         deprecated(); //~ ERROR use of deprecated item
         foo.method_deprecated(); //~ ERROR use of deprecated item
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
 
         deprecated_text(); //~ ERROR use of deprecated item: text
         foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
 
         deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
         foo.method_deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
+        Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo>::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
         foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
 
         deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
         foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
+        Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo>::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
         foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
 
         unstable(); //~ WARNING use of unstable library feature
         foo.method_unstable(); //~ WARNING use of unstable library feature
+        Foo::method_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo>::method_unstable(&foo); //~ WARNING use of unstable library feature
         foo.trait_unstable(); //~ WARNING use of unstable library feature
+        Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo>::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo as Trait>::trait_unstable(&foo); //~ WARNING use of unstable library feature
 
-        unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
-        foo.method_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
-        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        foo.method_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        Foo::method_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo>::method_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        Trait::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo as Trait>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
 
         stable();
         foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
 
         stable_text();
         foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
         foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
         let _ = DeprecatedUnstableStruct { i: 0 }; //~ ERROR use of deprecated item
@@ -104,16 +163,47 @@ fn test() {
         macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
     }
 
-    fn test_method_param<F: Trait>(foo: F) {
+    fn test_method_param<Foo: Trait>(foo: Foo) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
         foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
         foo.trait_unstable(); //~ WARNING use of unstable library feature
-        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo>::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo as Trait>::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        foo.trait_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        Trait::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo as Trait>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
     }
 
     fn test_method_object(foo: &Trait) {
@@ -124,7 +214,8 @@ fn test_method_object(foo: &Trait) {
         foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
         foo.trait_unstable(); //~ WARNING use of unstable library feature
-        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
         foo.trait_stable();
     }
 
@@ -264,31 +355,62 @@ fn test() {
         // errors, because other stability attributes now have meaning
         // only *across* crates, not within a single crate.
 
+        type Foo = MethodTester;
         let foo = MethodTester;
 
         deprecated(); //~ ERROR use of deprecated item
         foo.method_deprecated(); //~ ERROR use of deprecated item
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
 
         deprecated_text(); //~ ERROR use of deprecated item: text
         foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
 
         unstable();
         foo.method_unstable();
+        Foo::method_unstable(&foo);
+        <Foo>::method_unstable(&foo);
         foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
 
         unstable_text();
         foo.method_unstable_text();
+        Foo::method_unstable_text(&foo);
+        <Foo>::method_unstable_text(&foo);
         foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
 
         stable();
         foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
 
         stable_text();
         foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
         foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
         let _ = UnstableStruct { i: 0 };
@@ -307,12 +429,27 @@ fn test() {
         let _ = StableTupleStruct (1);
     }
 
-    fn test_method_param<F: Trait>(foo: F) {
+    fn test_method_param<Foo: Trait>(foo: Foo) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
         foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
     }
 
     fn test_method_object(foo: &Trait) {
diff --git a/src/test/compile-fail/lint-unsafe-block.rs b/src/test/compile-fail/lint-unsafe-block.rs
deleted file mode 100644 (file)
index 56d2b2c..0000000
+++ /dev/null
@@ -1,28 +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.
-
-#![allow(unused_unsafe)]
-#![allow(dead_code)]
-#![deny(unsafe_blocks)]
-unsafe fn allowed() {}
-
-#[allow(unsafe_blocks)] fn also_allowed() { unsafe {} }
-
-macro_rules! unsafe_in_macro {
-    () => {
-        unsafe {} //~ ERROR: usage of an `unsafe` block
-    }
-}
-
-fn main() {
-    unsafe {} //~ ERROR: usage of an `unsafe` block
-
-    unsafe_in_macro!()
-}
diff --git a/src/test/compile-fail/lint-unsafe-code.rs b/src/test/compile-fail/lint-unsafe-code.rs
new file mode 100644 (file)
index 0000000..8440cf3
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused_unsafe)]
+#![allow(dead_code)]
+#![deny(unsafe_code)]
+
+use std::marker::PhantomFn;
+
+struct Bar;
+struct Bar2;
+struct Bar3;
+
+#[allow(unsafe_code)]
+mod allowed_unsafe {
+    use std::marker::PhantomFn;
+    fn allowed() { unsafe {} }
+    unsafe fn also_allowed() {}
+    unsafe trait AllowedUnsafe : PhantomFn<Self> {}
+    unsafe impl AllowedUnsafe for super::Bar {}
+}
+
+macro_rules! unsafe_in_macro {
+    () => {
+        unsafe {} //~ ERROR: usage of an `unsafe` block
+    }
+}
+
+unsafe fn baz() {} //~ ERROR: declaration of an `unsafe` function
+unsafe trait Foo : PhantomFn<Self> {} //~ ERROR: declaration of an `unsafe` trait
+unsafe impl Foo for Bar {} //~ ERROR: implementation of an `unsafe` trait
+
+trait Baz {
+    unsafe fn baz(&self); //~ ERROR: declaration of an `unsafe` method
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl Baz for Bar {
+    unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+
+#[allow(unsafe_code)]
+trait A {
+    unsafe fn allowed_unsafe(&self);
+    unsafe fn allowed_unsafe_provided(&self) {}
+}
+
+#[allow(unsafe_code)]
+impl Baz for Bar2 {
+    unsafe fn baz(&self) {}
+    unsafe fn provided_override(&self) {}
+}
+
+impl Baz for Bar3 {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self) {}
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+#[allow(unsafe_code)]
+unsafe trait B {
+    fn dummy(&self) {}
+}
+
+trait C {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self);
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl C for Bar {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self) {}
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl C for Bar2 {
+    unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+trait D {
+    #[allow(unsafe_code)]
+    unsafe fn unsafe_provided(&self) {}
+}
+
+impl D for Bar {}
+
+fn main() {
+    unsafe {} //~ ERROR: usage of an `unsafe` block
+
+    unsafe_in_macro!()
+}
index f4740492651ae03e4cd15a1412f8d8a8887bfccd..c9ef2df8e1326f01f26bb275f40bde1ce2f4d29d 100644 (file)
@@ -29,7 +29,7 @@ impl S {
 
     // Cause an error. It shouldn't have any macro backtrace frames.
     fn bar(&self) { }
-    fn bar(&self) { } //~ ERROR duplicate definition
+    fn bar(&self) { } //~ ERROR duplicate method
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/move-in-guard-1.rs b/src/test/compile-fail/move-in-guard-1.rs
new file mode 100644 (file)
index 0000000..5d29d0e
--- /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.
+
+#![feature(box_syntax)]
+
+pub fn main() {
+    let x = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, _) if take(x) => (),
+        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/compile-fail/move-in-guard-2.rs b/src/test/compile-fail/move-in-guard-2.rs
new file mode 100644 (file)
index 0000000..23af257
--- /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.
+
+#![feature(box_syntax)]
+
+pub fn main() {
+    let x = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, _) |
+        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
index 2fb097f111db47f98727566112fc8e35047c49f0..526750257d2785c81f52b11599084aebf589cd16 100644 (file)
 mod foo {
     mod baz {
         struct Test;
-        impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Add for Test {} //~ ERROR: use of undeclared trait
+        impl Clone for Test {} //~ ERROR: use of undeclared trait
+        impl Iterator for Test {} //~ ERROR: use of undeclared trait
+        impl ToString for Test {} //~ ERROR: use of undeclared trait
+        impl Writer for Test {} //~ ERROR: use of undeclared trait
 
         fn foo() {
             drop(2) //~ ERROR: unresolved name
@@ -30,11 +30,11 @@ fn foo() {
     }
 
     struct Test;
-    impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+    impl Add for Test {} //~ ERROR: use of undeclared trait
+    impl Clone for Test {} //~ ERROR: use of undeclared trait
+    impl Iterator for Test {} //~ ERROR: use of undeclared trait
+    impl ToString for Test {} //~ ERROR: use of undeclared trait
+    impl Writer for Test {} //~ ERROR: use of undeclared trait
 
     fn foo() {
         drop(2) //~ ERROR: unresolved name
@@ -45,11 +45,11 @@ fn qux() {
     #[no_implicit_prelude]
     mod qux_inner {
         struct Test;
-        impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Add for Test {} //~ ERROR: use of undeclared trait
+        impl Clone for Test {} //~ ERROR: use of undeclared trait
+        impl Iterator for Test {} //~ ERROR: use of undeclared trait
+        impl ToString for Test {} //~ ERROR: use of undeclared trait
+        impl Writer for Test {} //~ ERROR: use of undeclared trait
 
         fn foo() {
             drop(2) //~ ERROR: unresolved name
index c0f7bea25b57ad88fddc5f218e6c75bd06fa1cdb..c4bcd33b93bd0beb67f68e1bf121553ec12432c6 100644 (file)
 // fail with the same error message).
 
 struct Test;
-impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl Add for Test {} //~ ERROR: use of undeclared trait
+impl Clone for Test {} //~ ERROR: use of undeclared trait
+impl Iterator for Test {} //~ ERROR: use of undeclared trait
+impl ToString for Test {} //~ ERROR: use of undeclared trait
+impl Writer for Test {} //~ ERROR: use of undeclared trait
 
 fn main() {
     drop(2) //~ ERROR: unresolved name
diff --git a/src/test/compile-fail/object-safety-by-value-self-use.rs b/src/test/compile-fail/object-safety-by-value-self-use.rs
new file mode 100644 (file)
index 0000000..1b20a90
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that while a trait with by-value self is object-safe, we
+// can't actually invoke it from an object (yet...?).
+
+#![feature(rustc_attrs)]
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+fn use_bar(t: Box<Bar>) {
+    t.bar() //~ ERROR cannot move a value of type Bar
+}
+
+fn main() { }
+
index 5ebcc8516ca0516610c34ab2d470b2674c8c7136..976717249e8eb2400fe6e307b625bd0fc8e73e18 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that we correctly prevent users from making trait objects
-// from traits with a `fn(self)` method.
+// Check that a trait with by-value self is considered object-safe.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
 
 trait Bar {
     fn bar(self);
@@ -19,29 +21,35 @@ trait Baz {
     fn baz(self: Self);
 }
 
+trait Quux {
+    // Legal because of the where clause:
+    fn baz(self: Self) where Self : Sized;
+}
+
 fn make_bar<T:Bar>(t: &T) -> &Bar {
-    t
-        //~^ ERROR `Bar` is not object-safe
-        //~| NOTE method `bar` has a receiver type of `Self`
+    t // legal
 }
 
 fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
-    t as &Bar
-        //~^ ERROR `Bar` is not object-safe
-        //~| NOTE method `bar` has a receiver type of `Self`
+    t as &Bar // legal
 }
 
 fn make_baz<T:Baz>(t: &T) -> &Baz {
-    t
-        //~^ ERROR `Baz` is not object-safe
-        //~| NOTE method `baz` has a receiver type of `Self`
+    t // legal
 }
 
 fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
-    t as &Baz
-        //~^ ERROR `Baz` is not object-safe
-        //~| NOTE method `baz` has a receiver type of `Self`
+    t as &Baz // legal
+}
+
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
 }
 
-fn main() {
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
 }
index 0ca706404c1f309028b36775d7d3d16daa237841..fd20accfa1e6b562bd319e86b3a987a86baefcaf 100644 (file)
@@ -9,12 +9,18 @@
 // except according to those terms.
 
 // Check that we correctly prevent users from making trait objects
-// from traits with generic methods.
+// from traits with generic methods, unless `where Self : Sized` is
+// present.
 
 trait Bar {
     fn bar<T>(&self, t: T);
 }
 
+trait Quux {
+    fn bar<T>(&self, t: T)
+        where Self : Sized;
+}
+
 fn make_bar<T:Bar>(t: &T) -> &Bar {
     t
         //~^ ERROR `Bar` is not object-safe
@@ -27,5 +33,13 @@ fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
         //~| NOTE method `bar` has generic type parameters
 }
 
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
 fn main() {
 }
index df0f44c1391580898084e7484bf3d06e75686225..b546774ccbd8cae8deb49bb638bf3e8fa886fac1 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 // Check that we correctly prevent users from making trait objects
-// form traits that make use of `Self` in an argument or return position.
+// form traits that make use of `Self` in an argument or return
+// position, unless `where Self : Sized` is present..
 
 trait Bar {
     fn bar(&self, x: &Self);
@@ -19,6 +20,10 @@ trait Baz {
     fn bar(&self) -> Self;
 }
 
+trait Quux {
+    fn get(&self, s: &Self) -> Self where Self : Sized;
+}
+
 fn make_bar<T:Bar>(t: &T) -> &Bar {
     t
         //~^ ERROR `Bar` is not object-safe
@@ -43,5 +48,13 @@ fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
         //~| NOTE method `bar` references the `Self` type in its arguments or return type
 }
 
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
 fn main() {
 }
index ffc21a5ce612326c9ef5e895a6526628679a841c..55f3b995336534c5e7cf8e9424ceb167bf2387b5 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
 
 //~^^^^^^^^^^ ERROR overflow
 //
-// We also get a second error message at the top of file (dummy
-// span). This is not helpful, but also kind of annoying to prevent,
-// so for now just live with it, since we also get a second message
-// that is more helpful.
+// We get an error message at the top of file (dummy span).
+// This is not helpful, but also kind of annoying to prevent,
+// so for now just live with it.
 
 enum Nil {NilValue}
 struct Cons<T> {head:isize, tail:T}
@@ -28,9 +27,8 @@ fn dot(&self, other:Cons<T>) -> isize {
 }
 fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
   match n {    0 => {first.dot(second)}
-      //~^ ERROR: reached the recursion limit during monomorphization
-      // Error message should be here. It should be a type error
-      // to instantiate `test` at a type other than T. (See #4287)
+      // FIXME(#4287) Error message should be here. It should be
+      // a type error to instantiate `test` at a type other than T.
     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
   }
 }
index 6cd984c071a0c1d444d61e2b02634965bfc77231..e8bc11317f2aadbd597b1a58228d0a61be3505a1 100644 (file)
@@ -47,4 +47,7 @@ fn main() {
     //~^^^^ ERROR overflow evaluating
     //~^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
     //~^^^^^^ NOTE required by `is_send`
+    //~^^^^^^^ ERROR overflow evaluating
+    //~^^^^^^^^ NOTE consider adding a `#![recursion_limit="20"]` attribute to your crate
+    //~^^^^^^^^^ NOTE required by `is_send`
 }
index 0d0dc0a05d12ad1f006745501e5b043deb476d8d..3983a84f6ad1795a8d0ffac46710870b32d3d3cd 100644 (file)
 
 
 trait NewTrait : SomeNonExistentTrait {}
-//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait`
+//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
 
 impl SomeNonExistentTrait for isize {}
-//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait`
+//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
 
 fn f<T:SomeNonExistentTrait>() {}
-//~^ ERROR attempt to bound type parameter with a nonexistent trait `SomeNonExistentTrait`
+//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
 
diff --git a/src/test/compile-fail/retslot-cast.rs b/src/test/compile-fail/retslot-cast.rs
new file mode 100644 (file)
index 0000000..fafae0c
--- /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.
+
+#![feature(rustc_attrs)]
+#![allow(warnings)]
+
+pub fn fail(x: Option<& (Iterator+Send)>) -> Option<&Iterator> {
+    // This call used to trigger an LLVM assertion because the return slot had type
+    // "Option<&Iterator>"* instead of "Option<&(Iterator+Send)>"*
+    inner(x)
+}
+
+pub fn inner(x: Option<& (Iterator+Send)>) -> Option<&(Iterator+Send)> {
+    x
+}
+
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
diff --git a/src/test/compile-fail/send-is-not-static-std-sync-2.rs b/src/test/compile-fail/send-is-not-static-std-sync-2.rs
new file mode 100644 (file)
index 0000000..d9d3706
--- /dev/null
@@ -0,0 +1,46 @@
+// 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.
+
+// basic tests to see that certain "obvious" errors are caught by
+// these types no longer requiring `'static` (RFC 458)
+
+#![allow(dead_code)]
+
+use std::sync::{Mutex, RwLock, mpsc};
+
+fn mutex() {
+    let lock = {
+        let x = 1;
+        Mutex::new(&x) //~ ERROR does not live long enough
+    };
+
+    let _dangling = *lock.lock().unwrap();
+}
+
+fn rwlock() {
+    let lock = {
+        let x = 1;
+        RwLock::new(&x) //~ ERROR does not live long enough
+    };
+    let _dangling = *lock.read().unwrap();
+}
+
+fn channel() {
+    let (_tx, rx) = {
+        let x = 1;
+        let (tx, rx) = mpsc::channel();
+        let _ = tx.send(&x); //~ ERROR does not live long enough
+        (tx, rx)
+    };
+
+    let _dangling = rx.recv();
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/send-is-not-static-std-sync.rs b/src/test/compile-fail/send-is-not-static-std-sync.rs
new file mode 100644 (file)
index 0000000..8ec2fe8
--- /dev/null
@@ -0,0 +1,56 @@
+// 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.
+
+// basic tests to see that certain "obvious" errors are caught by
+// these types no longer requiring `'static` (RFC 458)
+
+#![allow(dead_code)]
+
+use std::sync::{Mutex, RwLock, mpsc};
+
+fn mutex() {
+    let x = 1;
+    let y = Box::new(1);
+    let lock = Mutex::new(&x);
+    *lock.lock().unwrap() = &*y;
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        *lock.lock().unwrap() = &z; //~ ERROR does not live long enough
+    }
+}
+
+fn rwlock() {
+    let x = 1;
+    let y = Box::new(1);
+    let lock = RwLock::new(&x);
+    *lock.write().unwrap() = &*y;
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        *lock.write().unwrap() = &z; //~ ERROR does not live long enough
+    }
+}
+
+fn channel() {
+    let x = 1;
+    let y = Box::new(1);
+    let (tx, rx) = mpsc::channel();
+
+    tx.send(&x).unwrap();
+    tx.send(&*y);
+    drop(y); //~ ERROR cannot move out
+    {
+        let z = 2;
+        tx.send(&z).unwrap(); //~ ERROR does not live long enough
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/suggest-private-fields.rs b/src/test/compile-fail/suggest-private-fields.rs
new file mode 100644 (file)
index 0000000..3064849
--- /dev/null
@@ -0,0 +1,36 @@
+// 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:struct-field-privacy.rs
+
+extern crate "struct-field-privacy" as xc;
+
+use xc::B;
+
+struct A {
+    pub a: u32,
+    b: u32,
+}
+
+fn main () {
+    // external crate struct
+    let k = B {
+        aa: 20, //~ ERROR structure `struct-field-privacy::B` has no field named `aa`
+        //~^ HELP did you mean `a`?
+        bb: 20, //~ ERROR structure `struct-field-privacy::B` has no field named `bb`
+    };
+    // local crate struct
+    let l = A {
+        aa: 20, //~ ERROR structure `A` has no field named `aa`
+        //~^ HELP did you mean `a`?
+        bb: 20, //~ ERROR structure `A` has no field named `bb`
+        //~^ HELP did you mean `b`?
+    };
+}
diff --git a/src/test/compile-fail/syntaxt-default-trait-impls.rs b/src/test/compile-fail/syntaxt-default-trait-impls.rs
new file mode 100644 (file)
index 0000000..a33cd0e
--- /dev/null
@@ -0,0 +1,18 @@
+// 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(optin_builtin_traits)]
+
+trait MyDefaultImpl {}
+
+impl<T> MyDefaultImpl for .. {}
+//~^ ERROR default trait implementations are not allowed to have genercis
+
+fn main() {}
diff --git a/src/test/compile-fail/trait-impl-2.rs b/src/test/compile-fail/trait-impl-2.rs
deleted file mode 100644 (file)
index 303e3d9..0000000
+++ /dev/null
@@ -1,24 +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.
-
-// Test calling methods on an impl for a bare trait. This test checks trait impls
-// must be in the same module as the trait.
-
-mod Foo {
-    trait T {}
-}
-
-mod Bar {
-    impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same
-        fn foo(&self) {}
-    }
-}
-
-fn main() {}
index 28d20483c7e7bcc498d4580c91eb1542e4374d4e..969b6398fdb10d787ed9ef456c64273afc92ade3 100644 (file)
@@ -14,7 +14,7 @@ mod a {
 trait A {
 }
 
-impl A for a { //~ERROR found module name used as a type
+impl A for a { //~ ERROR use of undeclared type name `a`
 }
 
 fn main() {
index e621d77a65c8d37a11700abea70b0c91b9a600a1..3aec23a55b8118e9f4766c28ed7c5d2c9e02e5d5 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-tidy-linelength
-
-impl<T> Option<T> { //~ERROR inherent implementations are not allowed for types not defined in the current module
+impl<T> Option<T> {
+//~^ ERROR cannot associate methods with a type outside the crate the type is defined in
     pub fn foo(&self) { }
 }
 
index d8b3176787c040b1f75efdc2b741c05686522092..b09b10ffa0aad9dc22572e47f9348b44d7d7e7ac 100644 (file)
@@ -18,4 +18,5 @@ fn main() {
     10.dup::<i32>(); //~ ERROR does not take type parameters
     10.blah::<i32, i32>(); //~ ERROR incorrect number of type parameters
     (box 10 as Box<bar>).dup(); //~ ERROR cannot convert to a trait object
+    //~^ ERROR the trait `bar` is not implemented for the type `bar`
 }
diff --git a/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs b/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs
new file mode 100644 (file)
index 0000000..fb6c43a
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+fn foo1<T:Copy<U>, U>(x: T) {}
+//~^ ERROR: wrong number of type arguments: expected 0, found 1
+
+trait Trait: Copy<Send> {}
+//~^ ERROR: wrong number of type arguments: expected 0, found 1
+
+struct MyStruct1<T: Copy<T>>;
+//~^ ERROR wrong number of type arguments: expected 0, found 1
+
+struct MyStruct2<'a, T: Copy<'a>>;
+//~^ ERROR: wrong number of lifetime parameters: expected 0, found 1
+
+fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
+//~^ ERROR: wrong number of type arguments: expected 0, found 1
+//~^^ ERROR: wrong number of lifetime parameters: expected 0, found 1
+
+fn main() {
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs b/src/test/compile-fail/typeck-default-trait-impl-assoc-type.rs
new file mode 100644 (file)
index 0000000..8a9d537
--- /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.
+
+// Test that we do not consider associated types to be sendable without
+// some applicable trait bound (and we don't ICE).
+
+trait Trait {
+    type AssocType;
+    fn dummy(&self) { }
+}
+fn bar<T:Trait+Send>() {
+    is_send::<T::AssocType>(); //~ ERROR not implemented
+}
+
+fn is_send<T:Send>() {
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types-2.rs
new file mode 100644 (file)
index 0000000..0f3453d
--- /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.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait MyTrait: MarkerTrait {}
+
+impl MyTrait for .. {}
+
+struct MyS;
+
+struct MyS2;
+
+impl !MyTrait for MyS2 {}
+
+fn is_mytrait<T: MyTrait>() {}
+
+fn main() {
+    is_mytrait::<MyS>();
+
+    is_mytrait::<(MyS2, MyS)>();
+    //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2`
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs b/src/test/compile-fail/typeck-default-trait-impl-constituent-types.rs
new file mode 100644 (file)
index 0000000..524f467
--- /dev/null
@@ -0,0 +1,35 @@
+// 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(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait MyTrait: MarkerTrait {}
+
+impl MyTrait for .. {}
+impl<T> !MyTrait for *mut T {}
+
+struct MyS;
+
+struct MyS2;
+
+impl !MyTrait for MyS2 {}
+
+struct MyS3;
+
+fn is_mytrait<T: MyTrait>() {}
+
+fn main() {
+    is_mytrait::<MyS>();
+
+    is_mytrait::<MyS2>();
+    //~^ ERROR the trait `MyTrait` is not implemented for the type `MyS2`
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-send.rs
new file mode 100644 (file)
index 0000000..db4d1fe
--- /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.
+
+#![feature(optin_builtin_traits)]
+
+struct MySendable {
+   t: *mut u8
+}
+
+unsafe impl Send for MySendable {}
+
+struct MyNotSendable {
+   t: *mut u8
+}
+
+impl !Send for MyNotSendable {}
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<MySendable>();
+    is_send::<MyNotSendable>();
+    //~^ ERROR the trait `core::marker::Send` is not implemented for the type `MyNotSendable`
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs b/src/test/compile-fail/typeck-default-trait-impl-negation-sync.rs
new file mode 100644 (file)
index 0000000..d613589
--- /dev/null
@@ -0,0 +1,50 @@
+// 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
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Managed;
+use std::cell::UnsafeCell;
+
+struct MySync {
+   t: *mut u8
+}
+
+unsafe impl Sync for MySync {}
+
+struct MyNotSync {
+   t: *mut u8
+}
+
+impl !Sync for MyNotSync {}
+
+struct MyTypeWUnsafe {
+   t: UnsafeCell<u8>
+}
+
+struct MyTypeManaged {
+   t: Managed
+}
+
+fn is_sync<T: Sync>() {}
+
+fn main() {
+    is_sync::<MySync>();
+    is_sync::<MyNotSync>();
+    //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `MyNotSync`
+
+    is_sync::<MyTypeWUnsafe>();
+    //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<u8>`
+
+    is_sync::<MyTypeManaged>();
+    //~^ ERROR the trait `core::marker::Sync` is not implemented for the type `core::marker::Managed`
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-negation.rs b/src/test/compile-fail/typeck-default-trait-impl-negation.rs
new file mode 100644 (file)
index 0000000..a1ca0e3
--- /dev/null
@@ -0,0 +1,44 @@
+// 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(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait MyTrait: MarkerTrait {}
+
+impl MyTrait for .. {}
+
+unsafe trait MyUnsafeTrait: MarkerTrait {}
+
+unsafe impl MyUnsafeTrait for .. {}
+
+struct ThisImplsTrait;
+
+impl !MyUnsafeTrait for ThisImplsTrait {}
+
+
+struct ThisImplsUnsafeTrait;
+
+impl !MyTrait for ThisImplsUnsafeTrait {}
+
+fn is_my_trait<T: MyTrait>() {}
+fn is_my_unsafe_trait<T: MyUnsafeTrait>() {}
+
+fn main() {
+    is_my_trait::<ThisImplsTrait>();
+    is_my_trait::<ThisImplsUnsafeTrait>();
+    //~^ ERROR the trait `MyTrait` is not implemented for the type `ThisImplsUnsafeTrait`
+
+    is_my_unsafe_trait::<ThisImplsTrait>();
+    //~^ ERROR the trait `MyUnsafeTrait` is not implemented for the type `ThisImplsTrait`
+
+    is_my_unsafe_trait::<ThisImplsUnsafeTrait>();
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs b/src/test/compile-fail/typeck-default-trait-impl-outside-crate.rs
new file mode 100644 (file)
index 0000000..10ba8c7
--- /dev/null
@@ -0,0 +1,18 @@
+// 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
+
+#![feature(optin_builtin_traits)]
+
+impl Copy for .. {}
+//~^ ERROR cannot create default implementations for traits outside the crate they're defined in; define a new trait instead.
+
+fn main() {}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-precedence.rs b/src/test/compile-fail/typeck-default-trait-impl-precedence.rs
new file mode 100644 (file)
index 0000000..4006eb2
--- /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 declaring that `&T` is `Defaulted` if `T:Signed` implies
+// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
+// other words, the `..` impl only applies if there are no existing
+// impls whose types unify.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait Defaulted : MarkerTrait { }
+impl Defaulted for .. { }
+impl<'a,T:Signed> Defaulted for &'a T { }
+impl<'a,T:Signed> Defaulted for &'a mut T { }
+fn is_defaulted<T:Defaulted>() { }
+
+trait Signed : MarkerTrait { }
+impl Signed for i32 { }
+
+fn main() {
+    is_defaulted::<&'static i32>();
+    is_defaulted::<&'static u32>();
+    //~^ ERROR the trait `Signed` is not implemented for the type `u32`
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-send-param.rs b/src/test/compile-fail/typeck-default-trait-impl-send-param.rs
new file mode 100644 (file)
index 0000000..185e9dc
--- /dev/null
@@ -0,0 +1,21 @@
+// 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 do not consider parameter types to be sendable without
+// an explicit trait bound.
+
+fn foo<T>() {
+    is_send::<T>() //~ ERROR not implemented
+}
+
+fn is_send<T:Send>() {
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/typeck-default-trait-impl-superregion.rs b/src/test/compile-fail/typeck-default-trait-impl-superregion.rs
new file mode 100644 (file)
index 0000000..4a6a77a
--- /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 when a `..` impl applies, we also check that any
+// supertrait conditions are met.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait MyTrait : 'static {}
+
+impl MyTrait for .. {}
+
+fn foo<T:MyTrait>() { }
+
+fn bar<'a>() {
+    foo::<&'a ()>(); //~ ERROR does not fulfill the required lifetime
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs b/src/test/compile-fail/typeck-default-trait-impl-supertrait.rs
new file mode 100644 (file)
index 0000000..7f24058
--- /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.
+
+// Test that when a `..` impl applies, we also check that any
+// supertrait conditions are met.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait NotImplemented: MarkerTrait { }
+
+trait MyTrait : NotImplemented {}
+
+impl MyTrait for .. {}
+
+fn foo<T:MyTrait>() { bar::<T>() }
+
+fn bar<T:NotImplemented>() { }
+
+fn main() {
+    foo::<i32>(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i32`
+    bar::<i64>(); //~ ERROR the trait `NotImplemented` is not implemented for the type `i64`
+}
diff --git a/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs b/src/test/compile-fail/typeck-default-trait-impl-trait-where-clause.rs
new file mode 100644 (file)
index 0000000..c970aaa
--- /dev/null
@@ -0,0 +1,47 @@
+// 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
+
+// Test that when a `..` impl applies, we also check that any
+// supertrait conditions are met.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::MarkerTrait;
+
+trait NotImplemented: MarkerTrait { }
+
+trait MyTrait: MarkerTrait
+    where Option<Self> : NotImplemented
+{}
+
+impl NotImplemented for i32 {}
+
+impl MyTrait for .. {}
+
+fn foo<T:MyTrait>() {
+    bar::<Option<T>>()
+    //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<T>`
+    //
+    // This should probably typecheck. This is #20671.
+}
+
+fn bar<T:NotImplemented>() { }
+
+fn test() {
+    bar::<Option<i32>>();
+    //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
+}
+
+fn main() {
+    foo::<i32>();
+    //~^ ERROR the trait `NotImplemented` is not implemented for the type `core::option::Option<i32>`
+}
index 557fb2f4f8833ff18f775a5c654841ebf9760fcf..57a394dc7f1ec746847641673a6ac0ef8fcf126c 100644 (file)
@@ -17,6 +17,6 @@ fn dummy(&self) { }
 }
 
 impl !TestTrait for TestType {}
-//~^ ERROR  negative impls are currently allowed just for `Send` and `Sync`
+//~^ ERROR negative impls are only allowed for traits with default impls (e.g., `Send` and `Sync`)
 
 fn main() {}
index f4e18265fd9901b528653a777f77ea31f6a55226..b3fe178dc455e83b0d8c40f7092b57cbee1090fd 100644 (file)
@@ -12,5 +12,5 @@
 
 fn main() {
     <String as IntoCow>::into_cow("foo".to_string());
-    //~^ ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR too few type parameters provided: expected 1 parameter(s)
 }
index 12f62d805e15a8235d47b5df91fbf50768fadd11..f28bf7acadd371240b0c3b3c1b77fa885ed95554 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(unboxed_closures)]
 
-fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR nonexistent trait `Nonexist`
+fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist`
 
 type Typedef = isize;
 
diff --git a/src/test/compile-fail/unsafe_no_drop_flag-gate.rs b/src/test/compile-fail/unsafe_no_drop_flag-gate.rs
new file mode 100644 (file)
index 0000000..542698f
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+pub struct T;
+
+#[unsafe_no_drop_flag]
+//~^ ERROR unsafe_no_drop_flag has unstable semantics and may be removed
+pub struct S {
+    pub x: T,
+}
+
+impl Drop for S {
+    fn drop(&mut self) {}
+}
+
+pub fn main() {}
index d8a82d8fbf0467863cf201616693610afce9c8db..1998f8ab15529e5cc110fcd28462a8e6ab0d4b74 100644 (file)
@@ -18,7 +18,7 @@ struct Number {
     n: i64
 }
 
-impl fmt::String for Number {
+impl fmt::Display for Number {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.n)
     }
index 2a97155dd2efb878eebba9b619663ceaf824553c..49d8622976bb2dfd43159d1ee1ce01c9d764591b 100644 (file)
@@ -11,7 +11,7 @@
 use Trait::foo;
 //~^ ERROR `foo` is not directly importable
 use Foo::new;
-//~^ ERROR `new` is not directly importable
+//~^ ERROR unresolved import `Foo::new`. Not a module `Foo`
 
 pub trait Trait {
     fn foo();
index 70c7d42feb53f063c3094c815a97ec25034b9b94..a2e780d49b8eaac9e5f89cd0debfe19937bacf4b 100644 (file)
@@ -8,4 +8,4 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-impl Foo; //~ ERROR expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `;`
+impl Foo; //~ ERROR expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `;`
diff --git a/src/test/parse-fail/issue-22647.rs b/src/test/parse-fail/issue-22647.rs
new file mode 100644 (file)
index 0000000..5de8627
--- /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.
+
+fn main() {
+    let caller<F> = |f: F|  //~ ERROR unexpected token: `<`
+    where F: Fn() -> i32
+    {
+        let x = f();
+        println!("Y {}",x);
+        return x;
+    };
+
+    caller(bar_handler);
+}
+
+fn bar_handler() -> i32 {
+    5
+}
diff --git a/src/test/parse-fail/issue-22712.rs b/src/test/parse-fail/issue-22712.rs
new file mode 100644 (file)
index 0000000..abc9e59
--- /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.
+
+struct Foo<B> {
+    buffer: B
+}
+
+fn bar() {
+    let Foo<Vec<u8>>  //~ ERROR unexpected token: `<`
+}
+
+fn main() {}
index f182eb8fa5ba6bb7f77f84e7eb80f39245500773..a8b2fa4e115be10543f9b86b77a8409115a6e048 100644 (file)
@@ -13,7 +13,7 @@ struct S {
 }
 
 impl Cmp, ToString for S {
-//~^ ERROR: expected one of `(`, `+`, `::`, `<`, `for`, `where`, or `{`, found `,`
+//~^ ERROR: expected one of `(`, `+`, `..`, `::`, `<`, `for`, `where`, or `{`, found `,`
   fn eq(&&other: S) { false }
   fn to_string(&self) -> String { "hi".to_string() }
 }
index e8f9ed4d2cfc8d760da40f213ef332a7043c8552..8febbf8309ea78cb046705b4c04ad9d3c7d5b0be 100644 (file)
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 
 fn main() {
-    let x: Box<Show+> = box 3 as Box<Show+>;
+    let x: Box<Debug+> = box 3 as Box<Debug+>;
     //~^ ERROR at least one type parameter bound must be specified
     //~^^ ERROR at least one type parameter bound must be specified
 }
-
index a034352c4a69457e8f6cf49c31f13ac20819f90a..51447b225763b258258fcfc33efa992fcabc5a76 100644 (file)
@@ -13,7 +13,9 @@ trait Foo {
 
 struct Bar;
 
-impl Foo + Owned for Bar { //~ ERROR not a trait
+impl Foo + Owned for Bar {
+//~^ ERROR not a trait
+//~^^ ERROR expected one of `..`, `where`, or `{`, found `Bar`
 }
 
 fn main() { }
diff --git a/src/test/pretty/default-trait-impl.rs b/src/test/pretty/default-trait-impl.rs
new file mode 100644 (file)
index 0000000..d148bb1
--- /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.
+
+#![feature(optin_builtin_traits)]
+
+// pp-exact
+
+use std::marker::MarkerTrait;
+
+trait MyTrait: MarkerTrait { }
+
+impl MyTrait for .. { }
+
+pub fn main() { }
index bee4a120d5909fd2b0f375c81518071f9c986d03..51c6b14e1deedb01fed39975d73f22ed15b113cf 100644 (file)
@@ -22,12 +22,12 @@ digraph block {
     N3 -> N4;
     N4 -> N5;
     N5 -> N6;
-    N6 -> N8;
-    N8 -> N9;
+    N6 -> N9;
     N9 -> N10;
     N10 -> N11;
     N11 -> N12;
-    N12 -> N13;
+    N12 -> N8;
+    N8 -> N13;
     N13 -> N14;
     N14 -> N15;
     N15 -> N7;
index 76e66513515622c71406b246e371b26feab9e3bc..fb7d2ad97bd5f553277f80ae09dfcba4cbd3f1bd 100644 (file)
@@ -32,16 +32,16 @@ digraph block {
     N6 -> N7;
     N7 -> N8;
     N8 -> N9;
-    N9 -> N11;
-    N11 -> N12;
-    N12 -> N13;
+    N9 -> N12;
+    N12 -> N11;
+    N11 -> N13;
     N13 -> N14;
     N14 -> N15;
     N15 -> N10;
-    N11 -> N16;
-    N16 -> N17;
+    N9 -> N17;
     N17 -> N18;
-    N18 -> N19;
+    N18 -> N16;
+    N16 -> N19;
     N19 -> N20;
     N20 -> N21;
     N21 -> N22;
diff --git a/src/test/run-make/rustdoc-extern-default-method/Makefile b/src/test/run-make/rustdoc-extern-default-method/Makefile
new file mode 100644 (file)
index 0000000..ffc4a08
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all: lib.rs ext.rs
+       $(HOST_RPATH_ENV) $(RUSTC) ext.rs
+       $(HOST_RPATH_ENV) $(RUSTDOC) -L $(TMPDIR) -w html -o $(TMPDIR)/doc lib.rs
+       $(HTMLDOCCK) $(TMPDIR)/doc lib.rs
diff --git a/src/test/run-make/rustdoc-extern-default-method/ext.rs b/src/test/run-make/rustdoc-extern-default-method/ext.rs
new file mode 100644 (file)
index 0000000..8615627
--- /dev/null
@@ -0,0 +1,21 @@
+// 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="lib"]
+
+pub trait Trait {
+    fn provided(&self) {}
+}
+
+pub struct Struct;
+
+impl Trait for Struct {
+    fn provided(&self) {}
+}
diff --git a/src/test/run-make/rustdoc-extern-default-method/lib.rs b/src/test/run-make/rustdoc-extern-default-method/lib.rs
new file mode 100644 (file)
index 0000000..df92764
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+extern crate ext;
+
+// @count lib/struct.Struct.html '//*[@id="method.provided"]' 1
+pub use ext::Struct;
index 5d6e629ffc1d1627dccc0be3042322042e096d0f..3d57a2263e1ef188994635c0ad1698b81b04d4db 100644 (file)
@@ -10,3 +10,6 @@ all:
        cp foo.rs $(TMPDIR)/+foo+bar
        $(RUSTC) $(TMPDIR)/+foo+bar 2>&1 \
                | grep "invalid character.*in crate name:"
+       cp foo.rs $(TMPDIR)/-foo.rs
+       $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \
+               | grep "crate name cannot start with a hyphen:"
diff --git a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
new file mode 100644 (file)
index 0000000..2243e00
--- /dev/null
@@ -0,0 +1,107 @@
+// 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.
+
+// Various uses of `T::Item` syntax where the bound that supplies
+// `Item` originates in a where-clause, not the declaration of
+// `T`. Issue #20300.
+
+use std::marker::{MarkerTrait, PhantomData};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+use std::sync::atomic::Ordering::SeqCst;
+
+static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
+
+// Preamble.
+trait Trait : MarkerTrait { type Item; }
+struct Struct;
+impl Trait for Struct {
+    type Item = u32;
+}
+
+// Where-clause attached on the method which declares `T`.
+struct A;
+impl A {
+    fn foo<T>(_x: T::Item) where T: Trait {
+        COUNTER.fetch_add(1, SeqCst);
+    }
+}
+
+// Where-clause attached on the method to a parameter from the struct.
+struct B<T>(PhantomData<T>);
+impl<T> B<T> {
+    fn foo(_x: T::Item) where T: Trait {
+        COUNTER.fetch_add(10, SeqCst);
+    }
+}
+
+// Where-clause attached to free fn.
+fn c<T>(_: T::Item) where T : Trait {
+    COUNTER.fetch_add(100, SeqCst);
+}
+
+// Where-clause attached to defaulted and non-defaulted trait method.
+trait AnotherTrait {
+    fn method<T>(&self, _: T::Item) where T: Trait;
+    fn default_method<T>(&self, _: T::Item) where T: Trait {
+        COUNTER.fetch_add(1000, SeqCst);
+    }
+}
+struct D;
+impl AnotherTrait for D {
+    fn method<T>(&self, _: T::Item) where T: Trait {
+        COUNTER.fetch_add(10000, SeqCst);
+    }
+}
+
+// Where-clause attached to trait and impl containing the method.
+trait YetAnotherTrait<T>
+    where T : Trait
+{
+    fn method(&self, _: T::Item);
+    fn default_method(&self, _: T::Item) {
+        COUNTER.fetch_add(100000, SeqCst);
+    }
+}
+struct E<T>(PhantomData<T>);
+impl<T> YetAnotherTrait<T> for E<T>
+    where T : Trait
+{
+    fn method(&self, _: T::Item) {
+        COUNTER.fetch_add(1000000, SeqCst);
+    }
+}
+
+// Where-clause attached to inherent impl containing the method.
+struct F<T>(PhantomData<T>);
+impl<T> F<T> where T : Trait {
+    fn method(&self, _: T::Item) {
+        COUNTER.fetch_add(10000000, SeqCst);
+    }
+}
+
+// Where-clause attached to struct.
+#[allow(dead_code)]
+struct G<T> where T : Trait {
+    data: T::Item,
+    phantom: PhantomData<T>,
+}
+
+fn main() {
+    A::foo::<Struct>(22);
+    B::<Struct>::foo(22);
+    c::<Struct>(22);
+    D.method::<Struct>(22);
+    D.default_method::<Struct>(22);
+    E(PhantomData::<Struct>).method(22);
+    E(PhantomData::<Struct>).default_method(22);
+    F(PhantomData::<Struct>).method(22);
+    G::<Struct> { data: 22, phantom: PhantomData };
+    assert_eq!(COUNTER.load(SeqCst), 11111111);
+}
index 652f21c2ae3f829aeaff85b54ab1871492d9656c..d2e9bc2efe7279c10a0a00d7c25b6b1522aea5d1 100644 (file)
@@ -23,5 +23,5 @@ pub fn main() {
     let mut v = vec!(1);
     v.push_val(2);
     v.push_val(3);
-    assert_eq!(v, vec!(1, 2, 3));
+    assert_eq!(v, [1, 2, 3]);
 }
index b7aa2989ac5820466348e361385130bfb5a8ae98..48129f2b6ddc3ebe2b1251bca6e41085c305bc45 100644 (file)
@@ -11,7 +11,7 @@
 // Test that freezing an `&mut` pointer while referent is
 // frozen is legal.
 //
-// Example from src/middle/borrowck/doc.rs
+// Example from src/librustc_borrowck/borrowck/README.md
 
 fn foo<'a>(mut t0: &'a mut int,
            mut t1: &'a mut int) {
index 575c32baeac24782509cec1adde66b5fe4b377af..daff321efcfd9d39299fb7c03e35b30934635d8c 100644 (file)
@@ -54,7 +54,7 @@ fn cat(in_x : uint, in_y : int, in_name: String) -> cat {
     }
 }
 
-impl fmt::String for cat {
+impl fmt::Display for cat {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.name)
     }
index f87f2e07c9de0f0ee2507023a37286cb905f3bee..2473b4b674e5784a1fcf94cd65253014952ac748 100644 (file)
@@ -22,5 +22,5 @@ fn bar(v: &mut [uint]) {
 pub fn main() {
     let mut the_vec = vec!(1, 2, 3, 100);
     bar(&mut the_vec);
-    assert_eq!(the_vec, vec!(100, 3, 2, 1));
+    assert_eq!(the_vec, [100, 3, 2, 1]);
 }
index 4f97e6a20815d0014f06a8581abac69b50d8f69e..ea09bb3904de6b950f027f95b9094bd885ed66ef 100644 (file)
@@ -18,5 +18,5 @@ fn bar(v: &mut [uint]) {
 pub fn main() {
     let mut the_vec = vec!(1, 2, 3, 100);
     bar(&mut the_vec);
-    assert_eq!(the_vec, vec!(100, 3, 2, 1));
+    assert_eq!(the_vec, [100, 3, 2, 1]);
 }
index 04a69bbf3a2bc1b1748db4324e605c193f1804f4..b16b033c22fccafc6854593e9f4cbb553a63cb98 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that an impl for homogeneous pairs does not conflict with a
diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs
deleted file mode 100644 (file)
index dce1203..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(macro_rules)]
-
-use std::borrow::{Cow, IntoCow};
-use std::collections::BitVec;
-use std::default::Default;
-use std::iter::FromIterator;
-use std::ops::Add;
-use std::option::IntoIter as OptionIter;
-use std::rand::Rand;
-use std::rand::XorShiftRng as DummyRng;
-// FIXME the glob std::prelude::*; import of Vec is missing non-static inherent methods.
-use std::vec::Vec;
-
-#[derive(PartialEq, Eq)]
-struct Newt<T>(T);
-
-fn id<T>(x: T) -> T { x }
-fn eq<T: Eq>(a: T, b: T) -> bool { a == b }
-fn u8_as_i8(x: u8) -> i8 { x as i8 }
-fn odd(x: uint) -> bool { x % 2 == 1 }
-fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
-
-trait Size: Sized {
-    fn size() -> uint { std::mem::size_of::<Self>() }
-}
-impl<T> Size for T {}
-
-macro_rules! tests {
-    ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
-        const C: $ty = $expr;
-        static S: $ty = $expr;
-        assert!(eq(C($($test),*), $expr($($test),*)));
-        assert!(eq(S($($test),*), $expr($($test),*)));
-        assert!(eq(C($($test),*), S($($test),*)));
-    })+})
-}
-
-tests! {
-    // Free function.
-    id, fn(int) -> int, (5);
-    id::<int>, fn(int) -> int, (5);
-
-    // Enum variant constructor.
-    Some, fn(int) -> Option<int>, (5);
-    Some::<int>, fn(int) -> Option<int>, (5);
-
-    // Tuple struct constructor.
-    Newt, fn(int) -> Newt<int>, (5);
-    Newt::<int>, fn(int) -> Newt<int>, (5);
-
-    // Inherent static methods.
-    Vec::new, fn() -> Vec<()>, ();
-    Vec::<()>::new, fn() -> Vec<()>, ();
-    Vec::with_capacity, fn(uint) -> Vec<()>, (5);
-    Vec::<()>::with_capacity, fn(uint) -> Vec<()>, (5);
-    BitVec::from_fn, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd);
-    BitVec::from_fn::<fn(uint) -> bool>, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd);
-
-    // Inherent non-static method.
-    Vec::map_in_place, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>, (vec![b'f', b'o', b'o'], u8_as_i8);
-    Vec::map_in_place::<i8, fn(u8) -> i8>, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>,
-        (vec![b'f', b'o', b'o'], u8_as_i8);
-    // FIXME these break with "type parameter might not appear here pointing at `<u8>`.
-    // Vec::<u8>::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
-    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
-    // Vec::<u8>::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
-    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
-
-    // Trait static methods.
-    <bool as Size>::size, fn() -> uint, ();
-    Default::default, fn() -> int, ();
-    <int as Default>::default, fn() -> int, ();
-    Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-    <int as Rand>::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-    Rand::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-    <int as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-
-    // Trait non-static methods.
-    Clone::clone, fn(&int) -> int, (&5);
-    <int as Clone>::clone, fn(&int) -> int, (&5);
-    FromIterator::from_iter, fn(OptionIter<int>) -> Vec<int>, (Some(5).into_iter());
-    <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    <Vec<int> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    <Vec<int> as FromIterator<_>>::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    Add::add, fn(i32, i32) -> i32, (5, 6);
-    <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
-    <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
-    <String as IntoCow<_>>::into_cow, fn(String) -> Cow<'static, str>,
-        ("foo".to_string());
-    <String as IntoCow<'static, _>>::into_cow, fn(String) -> Cow<'static, str>,
-        ("foo".to_string());
-}
diff --git a/src/test/run-pass/cycle-generic-bound.rs b/src/test/run-pass/cycle-generic-bound.rs
new file mode 100644 (file)
index 0000000..2388a56
--- /dev/null
@@ -0,0 +1,18 @@
+// 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 #15477. This test just needs to compile.
+
+use std::marker::PhantomFn;
+
+trait Chromosome<X: Chromosome<i32>> : PhantomFn<(Self,X)> {
+}
+
+fn main() { }
diff --git a/src/test/run-pass/cycle-trait-type-trait.rs b/src/test/run-pass/cycle-trait-type-trait.rs
new file mode 100644 (file)
index 0000000..6e16e68
--- /dev/null
@@ -0,0 +1,23 @@
+// 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 a case where a supertrait references a type that references
+// the original trait. This poses no problem at the moment.
+
+trait Chromosome: Get<Struct<i32>> {
+}
+
+trait Get<A> {
+    fn get(&self) -> A;
+}
+
+struct Struct<C:Chromosome> { c: C }
+
+fn main() { }
index 30d6b934fa277a06b83e8bd7792bf218f741df18..eb66423f1c7a7f0543678616f498aefae01f156d 100644 (file)
@@ -26,6 +26,9 @@ mod hello;
 #[cfg(target_os = "dragonfly")]
 mod hello;
 
+#[cfg(target_os = "bitrig")]
+mod hello;
+
 #[cfg(target_os = "android")]
 mod hello;
 
index 0e1ab73c02d088ff73e275d7dd42998778e952d7..5d68a25a14ada73433012e8a3a13ccdf1c9c04f0 100644 (file)
@@ -9,13 +9,14 @@
 // except according to those terms.
 
 use std::env::*;
+use std::path::PathBuf;
 
 #[cfg(unix)]
 fn main() {
     let oldhome = var("HOME");
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 
     remove_var("HOME");
     if cfg!(target_os = "android") {
@@ -36,14 +37,14 @@ fn main() {
     assert!(home_dir().is_some());
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 
     remove_var("HOME");
 
     set_var("USERPROFILE", "/home/MountainView");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 
     set_var("HOME", "/home/MountainView");
     set_var("USERPROFILE", "/home/PaloAlto");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 }
diff --git a/src/test/run-pass/extern-methods.rs b/src/test/run-pass/extern-methods.rs
new file mode 100644 (file)
index 0000000..8fe69e4
--- /dev/null
@@ -0,0 +1,38 @@
+// 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::marker::MarkerTrait;
+
+trait A : MarkerTrait {
+    extern "fastcall" fn test1(i: i32);
+    extern fn test2(i: i32);
+}
+
+struct S;
+impl S {
+    extern "stdcall" fn test3(i: i32) {
+        assert_eq!(i, 3);
+    }
+}
+
+impl A for S {
+    extern "fastcall" fn test1(i: i32) {
+        assert_eq!(i, 1);
+    }
+    extern fn test2(i: i32) {
+        assert_eq!(i, 2);
+    }
+}
+
+fn main() {
+    <S as A>::test1(1);
+    <S as A>::test2(2);
+    S::test3(3);
+}
index 7f84efcdd5de8862cd5d26eb93381ce1819838d9..010f54dd55934ea53c425066dd4bb67dde200c85 100644 (file)
@@ -24,5 +24,5 @@ fn map_<U, F>(x: &Vec<T> , mut f: F) -> Vec<U> where F: FnMut(&T) -> U {
 }
 
 pub fn main() {
-    assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), vec!(2,3,4));
+    assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), [2,3,4]);
 }
diff --git a/src/test/run-pass/impl-inherent-non-conflict.rs b/src/test/run-pass/impl-inherent-non-conflict.rs
new file mode 100644 (file)
index 0000000..663ed24
--- /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.
+
+// Ensure that an user-defined type admits multiple inherent methods
+// with the same name, which can be called on values that have a
+// precise enough type to allow distinguishing between the methods.
+
+struct Foo<T>(T);
+
+impl Foo<usize> {
+    fn bar(&self) -> i32 { self.0 as i32 }
+}
+
+impl Foo<isize> {
+    fn bar(&self) -> i32 { -(self.0 as i32) }
+}
+
+fn main() {
+    let foo_u = Foo::<usize>(5);
+    assert_eq!(foo_u.bar(), 5);
+
+    let foo_i = Foo::<isize>(3);
+    assert_eq!(foo_i.bar(), -3);
+}
diff --git a/src/test/run-pass/impl-inherent-prefer-over-trait.rs b/src/test/run-pass/impl-inherent-prefer-over-trait.rs
new file mode 100644 (file)
index 0000000..3031228
--- /dev/null
@@ -0,0 +1,38 @@
+// 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.
+
+struct Foo;
+
+trait Trait {
+    fn bar(&self);
+}
+
+// Inherent impls should be preferred over trait ones.
+impl Foo {
+    fn bar(&self) {}
+}
+
+impl Trait {
+    fn baz(_: &Foo) {}
+}
+
+impl Trait for Foo {
+    fn bar(&self) { panic!("wrong method called!") }
+}
+
+fn main() {
+    Foo.bar();
+    Foo::bar(&Foo);
+    <Foo>::bar(&Foo);
+
+    // Should work even if Trait::baz doesn't exist.
+    // N.B: `<Trait>::bar` would be ambiguous.
+    <Trait>::baz(&Foo);
+}
diff --git a/src/test/run-pass/impl-not-adjacent-to-type.rs b/src/test/run-pass/impl-not-adjacent-to-type.rs
new file mode 100644 (file)
index 0000000..c1dc68b
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+mod foo {
+    pub struct Point {
+        pub x: i32,
+        pub y: i32,
+    }
+}
+
+impl foo::Point {
+    fn x(&self) -> i32 { self.x }
+}
+
+fn main() {
+    assert_eq!((foo::Point { x: 1, y: 3}).x(), 1);
+}
index f852bac404861a8d9683e3fa47c2c7412a773837..4b0e9168e19bd35fac2a431dfc0dab09508aaf19 100644 (file)
@@ -42,6 +42,18 @@ pub fn main() {
     }
 }
 
+#[cfg(target_os = "bitrig")]
+mod m {
+    #[main]
+    #[cfg(target_arch = "x86_64")]
+    pub fn main() {
+        unsafe {
+            assert_eq!(::rusti::pref_align_of::<u64>(), 8u);
+            assert_eq!(::rusti::min_align_of::<u64>(), 8u);
+        }
+    }
+}
+
 #[cfg(target_os = "windows")]
 mod m {
     #[main]
diff --git a/src/test/run-pass/issue-12729.rs b/src/test/run-pass/issue-12729.rs
new file mode 100644 (file)
index 0000000..09c0c86
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Foo;
+
+mod bar {
+    use Foo;
+
+    impl Foo {
+        fn baz(&self) {}
+    }
+}
+fn main() {}
+
index aa176d5b0f04197fa482b9a929f3df414a539fc4..d995ecc492e3477f65d3ac466c4d30e8e00d100c 100644 (file)
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 // 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.
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::slice::SliceExt;
-use std::old_io::{fs, USER_RWX};
-use std::process;
+// no-prefer-dynamic
+
+#![feature(fs, process, env, path, rand)]
+
 use std::env;
-use std::old_path::BytesContainer;
+use std::fs;
+use std::process;
 use std::rand::random;
+use std::str;
 
 fn main() {
     // If we're the child, make sure we were invoked correctly
@@ -34,21 +35,20 @@ fn main() {
 fn test() {
     // If we're the parent, copy our own binary to a new directory.
     let my_path = env::current_exe().unwrap();
-    let my_dir  = my_path.dir_path();
+    let my_dir  = my_path.parent().unwrap();
 
     let random_u32: u32 = random();
-    let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}",
-                                                  random_u32)));
-    fs::mkdir(&child_dir, USER_RWX).unwrap();
+    let child_dir = my_dir.join(&format!("issue-15149-child-{}", random_u32));
+    fs::create_dir(&child_dir).unwrap();
 
-    let child_path = child_dir.join(format!("mytest{}",
-                                            env::consts::EXE_SUFFIX));
+    let child_path = child_dir.join(&format!("mytest{}",
+                                             env::consts::EXE_SUFFIX));
     fs::copy(&my_path, &child_path).unwrap();
 
     // Append the new directory to our own PATH.
     let path = {
         let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap()).collect();
-        paths.push(child_dir.clone());
+        paths.push(child_dir.to_path_buf());
         env::join_paths(paths.iter()).unwrap()
     };
 
@@ -58,9 +58,9 @@ fn test() {
 
     assert!(child_output.status.success(),
             format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
-                    child_output.stdout.container_as_str().unwrap(),
-                    child_output.stderr.container_as_str().unwrap()));
+                    str::from_utf8(&child_output.stdout).unwrap(),
+                    str::from_utf8(&child_output.stderr).unwrap()));
 
-    fs::rmdir_recursive(&child_dir).unwrap();
+    fs::remove_dir_all(&child_dir).unwrap();
 
 }
index 3bab78ab0df9f0ca3959ff1ea010a0f9a5ff0b0b..92d8dfa2cf9a975bc306078ebdfeebe5267c1f63 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::old_io::{process, Command};
+use std::process::Command;
 use std::env;
 
 fn main() {
@@ -22,10 +22,8 @@ fn main() {
 }
 
 fn test() {
-    let status = Command::new(env::current_exe().unwrap())
+    let status = Command::new(&env::current_exe().unwrap())
                          .arg("foo").arg("")
-                         .stdout(process::InheritFd(1))
-                         .stderr(process::InheritFd(2))
                          .status().unwrap();
     assert!(status.success());
 }
index 4d20e6360ad4fdda2654b0047b475e37b2fcdaac..ba107dd2cf9a2457b8b41db94e66834b9b56847f 100644 (file)
@@ -8,14 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-windows currently windows requires UTF-8 for spawning processes
-
-use std::old_io::Command;
-use std::env;
-
+#[cfg(unix)]
 fn main() {
+    use std::process::Command;
+    use std::env;
+    use std::os::unix::prelude::*;
+    use std::ffi::OsStr;
+
     if env::args().len() == 1 {
-        assert!(Command::new(env::current_exe().unwrap()).arg(b"\xff")
+        assert!(Command::new(&env::current_exe().unwrap())
+                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
                         .status().unwrap().success())
     }
 }
+
+#[cfg(windows)]
+fn main() {}
diff --git a/src/test/run-pass/issue-22356.rs b/src/test/run-pass/issue-22356.rs
new file mode 100644 (file)
index 0000000..7c0ab11
--- /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.
+
+use std::marker::{PhantomData, PhantomFn};
+
+pub struct Handle<T, I>(T, I);
+
+impl<T, I> Handle<T, I> {
+    pub fn get_info(&self) -> &I {
+        let Handle(_, ref info) = *self;
+        info
+    }
+}
+
+pub struct BufferHandle<D: Device, T> {
+    raw: RawBufferHandle<D>,
+    _marker: PhantomData<T>,
+}
+
+impl<D: Device, T> BufferHandle<D, T> {
+    pub fn get_info(&self) -> &String {
+        self.raw.get_info()
+    }
+}
+
+pub type RawBufferHandle<D: Device> = Handle<<D as Device>::Buffer, String>;
+
+pub trait Device: PhantomFn<Self> {
+    type Buffer;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/issue-22426.rs b/src/test/run-pass/issue-22426.rs
new file mode 100644 (file)
index 0000000..b1c8f9c
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+fn main() {
+  match 42 {
+    x if x < 7 => (),
+    _ => ()
+  }
+}
diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs
new file mode 100644 (file)
index 0000000..1ecdd39
--- /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.
+
+use std::{fs, net};
+
+fn assert_both<T: Send + Sync>() {}
+
+fn main() {
+    assert_both::<fs::File>();
+    assert_both::<fs::Metadata>();
+    assert_both::<fs::ReadDir>();
+    assert_both::<fs::DirEntry>();
+    assert_both::<fs::WalkDir>();
+    assert_both::<fs::OpenOptions>();
+    assert_both::<fs::Permissions>();
+
+    assert_both::<net::TcpStream>();
+    assert_both::<net::TcpListener>();
+    assert_both::<net::UdpSocket>();
+    assert_both::<net::SocketAddr>();
+    assert_both::<net::IpAddr>();
+}
index 754412ea949381c7059b1a6d6472d9f7a76d2489..3f1a1c75d8a78c077fad6d1c1fceb651c5be0e82 100644 (file)
@@ -24,6 +24,6 @@ pub fn main() {
     let mut table = HashMap::new();
     table.insert("one".to_string(), 1);
     table.insert("two".to_string(), 2);
-    assert!(check_strs(&format!("{:?}", table), "HashMap {\"one\": 1, \"two\": 2}") ||
-            check_strs(&format!("{:?}", table), "HashMap {\"two\": 2, \"one\": 1}"));
+    assert!(check_strs(&format!("{:?}", table), "{\"one\": 1, \"two\": 2}") ||
+            check_strs(&format!("{:?}", table), "{\"two\": 2, \"one\": 1}"));
 }
index f4b85e03eaeac031dfb37f2e8de0f9cb7effcdbe..be4d475229591bc7c5b178dc6f2b5c2eef25c53e 100644 (file)
@@ -101,7 +101,7 @@ fn add_pt(&mut self, x: int, y: int) {
 
 // Allows AsciiArt to be converted to a string using the libcore ToString trait.
 // Note that the %s fmt! specifier will not call this automatically.
-impl fmt::String for AsciiArt {
+impl fmt::Display for AsciiArt {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Convert each line into a string.
         let lines = self.lines.iter()
diff --git a/src/test/run-pass/issue-7607-2.rs b/src/test/run-pass/issue-7607-2.rs
new file mode 100644 (file)
index 0000000..c52051f
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod a {
+    pub struct Foo { a: usize }
+}
+
+pub mod b {
+    use a::Foo;
+    impl Foo {
+        fn bar(&self) { }
+    }
+}
+
+pub fn main() { }
+
+
index 350ec68a7d1495347ffe02ba11595b627cdb5ef9..6f5ded6c475b6f3f058a094b52767753e5baa242 100644 (file)
@@ -10,7 +10,6 @@
 
 // aux-build:lang-item-public.rs
 // ignore-android
-// ignore-windows #13361
 
 #![feature(lang_items, start, no_std)]
 #![no_std]
@@ -37,7 +36,7 @@
 #[link(name = "c")]
 extern {}
 
-#[cfg(target_os = "openbsd")]
+#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
 #[link(name = "c")]
 extern {}
 
index 457c0a35fd70f9a963fccd81f224b1dff69f41cf..0d563f1a714c350cecbf0f18523c9a2c7fa993ad 100644 (file)
@@ -44,11 +44,11 @@ fn transform(x: Option<int>) -> Option<String> {
 pub fn main() {
     assert_eq!(transform(Some(10)), Some("11".to_string()));
     assert_eq!(transform(None), None);
-    assert!((vec!("hi".to_string()))
+    assert_eq!((vec!("hi".to_string()))
         .bind(|x| vec!(x.clone(), format!("{}!", x)) )
-        .bind(|x| vec!(x.clone(), format!("{}?", x)) ) ==
-        vec!("hi".to_string(),
-             "hi?".to_string(),
-             "hi!".to_string(),
-             "hi!?".to_string()));
+        .bind(|x| vec!(x.clone(), format!("{}?", x)) ),
+        ["hi".to_string(),
+         "hi?".to_string(),
+         "hi!".to_string(),
+         "hi!?".to_string()]);
 }
diff --git a/src/test/run-pass/move-guard-const.rs b/src/test/run-pass/move-guard-const.rs
new file mode 100644 (file)
index 0000000..64c4f1f
--- /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.
+
+#![feature(box_syntax)]
+
+fn main() {
+    let x = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (2, 1) if take(x) => (),
+        (1, 2) if take(x) => (),
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/run-pass/object-safety-sized-self-by-value-self.rs b/src/test/run-pass/object-safety-sized-self-by-value-self.rs
new file mode 100644 (file)
index 0000000..ae09233
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that a trait is still object-safe (and usable) if it has
+// methods with by-value self so long as they require `Self : Sized`.
+
+trait Counter {
+    fn tick(&mut self) -> u32;
+    fn get(self) -> u32 where Self : Sized;
+}
+
+struct CCounter {
+    c: u32
+}
+
+impl Counter for CCounter {
+    fn tick(&mut self) -> u32 { self.c += 1; self.c }
+    fn get(self) -> u32 where Self : Sized { self.c }
+}
+
+fn tick1<C:Counter>(mut c: C) -> u32 {
+    tick2(&mut c);
+    c.get()
+}
+
+fn tick2(c: &mut Counter) {
+    tick3(c);
+}
+
+fn tick3<C:?Sized+Counter>(c: &mut C) {
+    c.tick();
+    c.tick();
+}
+
+fn main() {
+    let mut c = CCounter { c: 0 };
+    let value = tick1(c);
+    assert_eq!(value, 2);
+}
diff --git a/src/test/run-pass/object-safety-sized-self-generic-method.rs b/src/test/run-pass/object-safety-sized-self-generic-method.rs
new file mode 100644 (file)
index 0000000..1a42c4b
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that a trait is still object-safe (and usable) if it has
+// generic methods so long as they require `Self : Sized`.
+
+trait Counter {
+    fn tick(&mut self) -> u32;
+    fn with<F:FnOnce(u32)>(&self, f: F) where Self : Sized;
+}
+
+struct CCounter {
+    c: u32
+}
+
+impl Counter for CCounter {
+    fn tick(&mut self) -> u32 { self.c += 1; self.c }
+    fn with<F:FnOnce(u32)>(&self, f: F) { f(self.c); }
+}
+
+fn tick1<C:Counter>(c: &mut C) {
+    tick2(c);
+    c.with(|i| ());
+}
+
+fn tick2(c: &mut Counter) {
+    tick3(c);
+}
+
+fn tick3<C:?Sized+Counter>(c: &mut C) {
+    c.tick();
+    c.tick();
+}
+
+fn main() {
+    let mut c = CCounter { c: 0 };
+    tick1(&mut c);
+    assert_eq!(c.tick(), 3);
+}
diff --git a/src/test/run-pass/object-safety-sized-self-return-Self.rs b/src/test/run-pass/object-safety-sized-self-return-Self.rs
new file mode 100644 (file)
index 0000000..7f075bb
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that a trait is still object-safe (and usable) if it has
+// methods that return `Self` so long as they require `Self : Sized`.
+
+trait Counter {
+    fn new() -> Self where Self : Sized;
+    fn tick(&mut self) -> u32;
+}
+
+struct CCounter {
+    c: u32
+}
+
+impl Counter for CCounter {
+    fn new() -> CCounter { CCounter { c: 0 } }
+    fn tick(&mut self) -> u32 { self.c += 1; self.c }
+}
+
+fn preticked<C:Counter>() -> C {
+    let mut c: C = Counter::new();
+    tick(&mut c);
+    c
+}
+
+fn tick(c: &mut Counter) {
+    tick_generic(c);
+}
+
+fn tick_generic<C:?Sized+Counter>(c: &mut C) {
+    c.tick();
+    c.tick();
+}
+
+fn main() {
+    let mut c = preticked::<CCounter>();
+    tick(&mut c);
+    assert_eq!(c.tick(), 5);
+}
index f574259c375fc86886bda5882c28f1987479e760..41bf7fe2dfa637eab39b708d7949e7024d80cce9 100644 (file)
@@ -12,6 +12,7 @@
 //ignore-freebsd
 //ignore-ios
 //ignore-dragonfly
+//ignore-bitrig
 
 #![feature(asm)]
 
index 948c4d064d723ef7f9302e763324853c13a14b39..e4c7f4ef095222bdc2f64cc2d7ba9bfe63c00066 100644 (file)
@@ -13,6 +13,7 @@
 //ignore-freebsd
 //ignore-ios
 //ignore-dragonfly
+//ignore-bitrig
 
 #![feature(asm)]
 
index cf23a1a0f25b29bba539818075ae1b2596d9279c..835b4c40f5ca76c5b48cb55a598453a9e9ac5dfe 100644 (file)
@@ -55,6 +55,15 @@ pub fn size() -> uint { 16_usize }
     }
 }
 
+#[cfg(target_os = "bitrig")]
+mod m {
+    #[cfg(target_arch = "x86_64")]
+    pub mod m {
+        pub fn align() -> uint { 8u }
+        pub fn size() -> uint { 16u }
+    }
+}
+
 #[cfg(target_os = "windows")]
 mod m {
     #[cfg(target_arch = "x86")]
index f0b6a505929c66e9a67bcb6ec08034c3fbdcd4a9..b159b128333f0e39aea8386d3c20679d53825240 100644 (file)
@@ -14,6 +14,7 @@
 // aux-build:sepcomp_lib.rs
 // compile-flags: -C lto
 // no-prefer-dynamic
+// ignore-android FIXME #18800
 
 extern crate sepcomp_lib;
 use sepcomp_lib::a::one;
diff --git a/src/test/run-pass/std-sync-right-kind-impls.rs b/src/test/run-pass/std-sync-right-kind-impls.rs
new file mode 100644 (file)
index 0000000..d2d72ed
--- /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.
+
+use std::sync;
+
+fn assert_both<T: Sync + Send>() {}
+
+fn main() {
+    assert_both::<sync::StaticMutex>();
+    assert_both::<sync::StaticCondvar>();
+    assert_both::<sync::StaticRwLock>();
+    assert_both::<sync::Mutex<()>>();
+    assert_both::<sync::Condvar>();
+    assert_both::<sync::RwLock<()>>();
+    assert_both::<sync::Semaphore>();
+    assert_both::<sync::Barrier>();
+    assert_both::<sync::Arc<()>>();
+    assert_both::<sync::Weak<()>>();
+    assert_both::<sync::Once>();
+}
diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs
new file mode 100644 (file)
index 0000000..6d29d5f
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(unused_mut)]
+#![feature(collections)]
+
+extern crate collections;
+
+use collections::BinaryHeap;
+use collections::{BitSet, BitVec};
+use collections::{BTreeMap, BTreeSet};
+use collections::EnumSet;
+use collections::LinkedList;
+use collections::Vec;
+use collections::VecDeque;
+use collections::VecMap;
+
+use collections::Bound::Included;
+use collections::enum_set::CLike;
+use std::mem;
+
+fn is_sync<T>(_: T) where T: Sync {}
+fn is_send<T>(_: T) where T: Send {}
+
+macro_rules! all_sync_send {
+    ($ctor:expr, $($iter:ident),+) => ({
+        $(
+            let mut x = $ctor;
+            is_sync(x.$iter());
+            let mut y = $ctor;
+            is_send(y.$iter());
+        )+
+    })
+}
+
+macro_rules! is_sync_send {
+    ($ctor:expr, $iter:ident($($param:expr),+)) => ({
+        let mut x = $ctor;
+        is_sync(x.$iter($( $param ),+));
+        let mut y = $ctor;
+        is_send(y.$iter($( $param ),+));
+    })
+}
+
+fn main() {
+    // The iterator "generator" list should exhaust what corresponding
+    // implementations have where `Sync` and `Send` semantics apply.
+    all_sync_send!(BinaryHeap::<usize>::new(), iter, drain, into_iter);
+
+    all_sync_send!(BitVec::new(), iter);
+
+    all_sync_send!(BitSet::new(), iter);
+    is_sync_send!(BitSet::new(), union(&BitSet::new()));
+    is_sync_send!(BitSet::new(), intersection(&BitSet::new()));
+    is_sync_send!(BitSet::new(), difference(&BitSet::new()));
+    is_sync_send!(BitSet::new(), symmetric_difference(&BitSet::new()));
+
+    all_sync_send!(BTreeMap::<usize, usize>::new(), iter, iter_mut, into_iter, keys, values);
+    is_sync_send!(BTreeMap::<usize, usize>::new(), range(Included(&0), Included(&9)));
+    is_sync_send!(BTreeMap::<usize, usize>::new(), range_mut(Included(&0), Included(&9)));
+
+    all_sync_send!(BTreeSet::<usize>::new(), iter, into_iter);
+    is_sync_send!(BTreeSet::<usize>::new(), range(Included(&0), Included(&9)));
+    is_sync_send!(BTreeSet::<usize>::new(), difference(&BTreeSet::<usize>::new()));
+    is_sync_send!(BTreeSet::<usize>::new(), symmetric_difference(&BTreeSet::<usize>::new()));
+    is_sync_send!(BTreeSet::<usize>::new(), intersection(&BTreeSet::<usize>::new()));
+    is_sync_send!(BTreeSet::<usize>::new(), union(&BTreeSet::<usize>::new()));
+
+    all_sync_send!(LinkedList::<usize>::new(), iter, iter_mut, into_iter);
+
+    #[derive(Copy)]
+    #[repr(usize)]
+    #[allow(dead_code)]
+    enum Foo { A, B, C }
+    impl CLike for Foo {
+        fn to_usize(&self) -> usize {
+            *self as usize
+        }
+
+        fn from_usize(v: usize) -> Foo {
+            unsafe { mem::transmute(v) }
+        }
+    }
+    all_sync_send!(EnumSet::<Foo>::new(), iter);
+
+    all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, drain, into_iter);
+
+    all_sync_send!(VecMap::<usize>::new(), iter, iter_mut, drain, into_iter, keys, values);
+
+    all_sync_send!(Vec::<usize>::new(), into_iter, drain);
+}
index dea7f99fcbace35c6da7c123fb882f683c0583db..61d6d3fdd3b717dd08c9753588096038b02033ca 100644 (file)
@@ -2,6 +2,6 @@
 
 {
     assert!(file!().ends_with("includeme.fragment"));
-    assert!(line!() == 5_usize);
+    assert!(line!() == 5u32);
     format!("victory robot {}", line!())
 }
index 349a676a433e366eceb45021cb10186a2f22453a..ddd8cd8be3d5c00f84287e96521660282eeff7be 100644 (file)
@@ -23,7 +23,7 @@ macro_rules! indirect_line { () => ( line!() ) }
 
 pub fn main() {
     assert_eq!(line!(), 25);
-    //assert!((column!() == 11));
+    assert!((column!() == 4u32));
     assert_eq!(indirect_line!(), 27);
     assert!((file!().ends_with("syntax-extension-source-utils.rs")));
     assert_eq!(stringify!((2*3) + 5).to_string(), "( 2 * 3 ) + 5".to_string());
index 5f4b18df6e16b983f103a0fda7958b83c1648c6c..0dedf621a4f2887f0f6205142239e505e9e638bf 100644 (file)
@@ -44,9 +44,9 @@ fn bar<U:to_str,T:map<U>>(x: T) -> Vec<String> {
 }
 
 pub fn main() {
-    assert_eq!(foo(vec!(1)), vec!("hi".to_string()));
-    assert_eq!(bar::<int, Vec<int> >(vec!(4, 5)), vec!("4".to_string(), "5".to_string()));
+    assert_eq!(foo(vec!(1)), ["hi".to_string()]);
+    assert_eq!(bar::<int, Vec<int> >(vec!(4, 5)), ["4".to_string(), "5".to_string()]);
     assert_eq!(bar::<String, Vec<String> >(vec!("x".to_string(), "y".to_string())),
-               vec!("x".to_string(), "y".to_string()));
-    assert_eq!(bar::<(), Vec<()>>(vec!(())), vec!("()".to_string()));
+               ["x".to_string(), "y".to_string()]);
+    assert_eq!(bar::<(), Vec<()>>(vec!(())), ["()".to_string()]);
 }
diff --git a/src/test/run-pass/trait-impl-2.rs b/src/test/run-pass/trait-impl-2.rs
new file mode 100644 (file)
index 0000000..abc35bc
--- /dev/null
@@ -0,0 +1,23 @@
+// 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.
+
+pub mod Foo {
+    pub trait Trait {
+        fn foo(&self);
+    }
+}
+
+mod Bar {
+    impl<'a> ::Foo::Trait+'a {
+        fn bar(&self) { self.foo() }
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/ufcs-polymorphic-paths.rs b/src/test/run-pass/ufcs-polymorphic-paths.rs
new file mode 100644 (file)
index 0000000..29b1c8f
--- /dev/null
@@ -0,0 +1,132 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(macro_rules)]
+
+use std::borrow::{Cow, IntoCow};
+use std::collections::BitVec;
+use std::default::Default;
+use std::iter::FromIterator;
+use std::ops::Add;
+use std::option::IntoIter as OptionIter;
+use std::rand::Rand;
+use std::rand::XorShiftRng as DummyRng;
+// FIXME the glob std::prelude::*; import of Vec is missing non-static inherent methods.
+use std::vec::Vec;
+
+#[derive(PartialEq, Eq)]
+struct Newt<T>(T);
+
+fn id<T>(x: T) -> T { x }
+fn eq<T: Eq>(a: T, b: T) -> bool { a == b }
+fn u8_as_i8(x: u8) -> i8 { x as i8 }
+fn odd(x: usize) -> bool { x % 2 == 1 }
+fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
+
+trait Size: Sized {
+    fn size() -> usize { std::mem::size_of::<Self>() }
+}
+impl<T> Size for T {}
+
+macro_rules! tests {
+    ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
+        const C: $ty = $expr;
+        static S: $ty = $expr;
+        assert!(eq(C($($test),*), $expr($($test),*)));
+        assert!(eq(S($($test),*), $expr($($test),*)));
+        assert!(eq(C($($test),*), S($($test),*)));
+    })+})
+}
+
+tests! {
+    // Free function.
+    id, fn(i32) -> i32, (5);
+    id::<i32>, fn(i32) -> i32, (5);
+
+    // Enum variant constructor.
+    Some, fn(i32) -> Option<i32>, (5);
+    Some::<i32>, fn(i32) -> Option<i32>, (5);
+
+    // Tuple struct constructor.
+    Newt, fn(i32) -> Newt<i32>, (5);
+    Newt::<i32>, fn(i32) -> Newt<i32>, (5);
+
+    // Inherent static methods.
+    Vec::new, fn() -> Vec<()>, ();
+    Vec::<()>::new, fn() -> Vec<()>, ();
+    <Vec<()>>::new, fn() -> Vec<()>, ();
+    Vec::with_capacity, fn(usize) -> Vec<()>, (5);
+    Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5);
+    <Vec<()>>::with_capacity, fn(usize) -> Vec<()>, (5);
+    BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd);
+    BitVec::from_fn::<fn(usize) -> bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd);
+
+    // Inherent non-static method.
+    Vec::map_in_place, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>, (vec![b'f', b'o', b'o'], u8_as_i8);
+    Vec::map_in_place::<i8, fn(u8) -> i8>, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>,
+        (vec![b'f', b'o', b'o'], u8_as_i8);
+    // FIXME these break with "type parameter might not appear here pointing at `<u8>`.
+    // Vec::<u8>::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
+    // Vec::<u8>::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
+
+    // Trait static methods.
+    bool::size, fn() -> usize, ();
+    <bool>::size, fn() -> usize, ();
+    <bool as Size>::size, fn() -> usize, ();
+
+    Default::default, fn() -> i32, ();
+    i32::default, fn() -> i32, ();
+    <i32>::default, fn() -> i32, ();
+    <i32 as Default>::default, fn() -> i32, ();
+
+    Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32>::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32 as Rand>::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    Rand::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    i32::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32>::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32 as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+
+    // Trait non-static methods.
+    Clone::clone, fn(&i32) -> i32, (&5);
+    i32::clone, fn(&i32) -> i32, (&5);
+    <i32>::clone, fn(&i32) -> i32, (&5);
+    <i32 as Clone>::clone, fn(&i32) -> i32, (&5);
+
+    FromIterator::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+    Vec::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+    <Vec<_>>::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+    <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+    <Vec<i32> as FromIterator<_>>::from_iter, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+    FromIterator::from_iter::<OptionIter<i32>>, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+    <Vec<i32> as FromIterator<_>>::from_iter::<OptionIter<i32>>, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+
+    Add::add, fn(i32, i32) -> i32, (5, 6);
+    i32::add, fn(i32, i32) -> i32, (5, 6);
+    <i32>::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
+
+    String::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+    <String>::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+    <String as IntoCow<_>>::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+    <String as IntoCow<'static, _>>::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+}
index 087ef5dcf05e4a08bc529f342eb174f596269434..1401fe7470b0a1d71f0772e2d9217414625cdbde 100644 (file)
@@ -18,5 +18,5 @@ fn f<F: FnMut()>(mut f: F) {
 fn main() {
     let mut v: Vec<_> = vec![];
     f(|| v.push(0));
-    assert_eq!(v, vec![0]);
+    assert_eq!(v, [0]);
 }
index 52c09aadfbd7b17a34afa25a7472359f27d0677d..449e500edbe846345be09cb01ef50404d9f6aef9 100644 (file)
@@ -37,7 +37,8 @@ fn f(tx: Sender<bool>) {
 
 pub fn main() {
     let (tx, rx) = channel();
-    let _t = thread::spawn(move|| f(tx.clone()));
+    let t = thread::spawn(move|| f(tx.clone()));
     println!("hiiiiiiiii");
     assert!(rx.recv().unwrap());
+    drop(t.join());
 }
index d38b6e79eba66bccffd5632e441f5c9c345e31d4..4d90f71c830ba6db56bf83758047fb6119f50d78 100644 (file)
@@ -19,5 +19,6 @@ fn f() {
 }
 
 pub fn main() {
-    let _t = thread::spawn(f);
+    let t = thread::spawn(f);
+    drop(t.join());
 }
index 5dd0a5522c639b4feee382f758cd4f0ed1bcfcd3..dea58c8e86fbb8cbc1e2f6708c48d2fb6c770f1b 100644 (file)
@@ -34,6 +34,7 @@ pub fn main() {
           target_os = "linux",
           target_os = "freebsd",
           target_os = "dragonfly",
+          target_os = "bitrig",
           target_os = "openbsd",
           target_os = "android"))]
 pub fn main() { }