]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #40780 - aidanhs:aphs-cache-git-modules, r=alexcrichton
authorCorey Farwell <coreyf@rwell.org>
Wed, 29 Mar 2017 20:53:29 +0000 (16:53 -0400)
committerGitHub <noreply@github.com>
Wed, 29 Mar 2017 20:53:29 +0000 (16:53 -0400)
Attempt to cache git modules

Partial resolution of #40772, appveyor remains to be done once travis looks like it's working ok.

The approach in this PR is based on the `--reference` flag to `git-clone`/`git-submodule --update` and is a compromise based on the current limitations of the tools we're using.

The ideal would be:
1. have a cached pristine copy of rust-lang/rust master in `$HOME/rustsrc` with all submodules initialised
2. clone the PR branch with `git clone --recurse-submodules --reference $HOME/rustsrc git@github.com:rust-lang/rust.git`

This would (in the nonexistent ideal world) use the pristine copy as an object cache for the top level repo and all submodules, transferring over the network only the changes on the branch. Unfortunately, a) there is no way to manually control the initial clone with travis and b) even if there was, cloned submodules don't use the submodules of the reference as an object cache. So the steps we end up with are:

1. have a cached pristine copy of rust-lang/rust master in `$HOME/rustsrc` with all submodules initialised
2. have a cloned PR branch
3. extract the path of each submodule, and explicitly `git submodule update --init --reference $HOME/rustsrc/$module $module` (i.e. point directly to the location of the pristine submodule repo) for each one

I've also taken some care to make this forward compatible, both for adding and removing submodules.

r? @alexcrichton

389 files changed:
.gitmodules
.travis.yml
CONTRIBUTING.md
appveyor.yml
cargo
src/Cargo.lock
src/bootstrap/bin/rustdoc.rs
src/bootstrap/check.rs
src/ci/docker/armhf-gnu/Dockerfile
src/ci/docker/cross/Dockerfile
src/ci/docker/dist-android/Dockerfile
src/ci/docker/dist-arm-linux/Dockerfile
src/ci/docker/dist-armv7-aarch64-linux/Dockerfile
src/ci/docker/dist-freebsd/Dockerfile
src/ci/docker/dist-fuchsia/Dockerfile
src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile
src/ci/docker/dist-mips-linux/Dockerfile
src/ci/docker/dist-mips64-linux/Dockerfile
src/ci/docker/dist-powerpc-linux/Dockerfile
src/ci/docker/dist-powerpc64-linux/Dockerfile
src/ci/docker/dist-s390x-linux-netbsd/Dockerfile
src/ci/docker/dist-s390x-linux-netbsd/build-netbsd-toolchain.sh
src/ci/docker/dist-x86-linux/Dockerfile
src/ci/docker/dist-x86_64-musl/Dockerfile
src/ci/docker/emscripten/Dockerfile
src/ci/docker/emscripten/build-emscripten.sh
src/ci/docker/i686-gnu-nopt/Dockerfile
src/ci/docker/i686-gnu/Dockerfile
src/ci/docker/x86_64-gnu-aux/Dockerfile
src/ci/docker/x86_64-gnu-debug/Dockerfile
src/ci/docker/x86_64-gnu-distcheck/Dockerfile
src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
src/ci/docker/x86_64-gnu-incremental/Dockerfile
src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
src/ci/docker/x86_64-gnu-nopt/Dockerfile
src/ci/docker/x86_64-gnu/Dockerfile
src/doc/book
src/doc/nomicon
src/doc/reference
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/alloc.md [new file with mode: 0644]
src/doc/unstable-book/src/as-unsafe-cell.md [new file with mode: 0644]
src/doc/unstable-book/src/ascii-ctype.md [new file with mode: 0644]
src/doc/unstable-book/src/binary-heap-extras.md [new file with mode: 0644]
src/doc/unstable-book/src/binary-heap-peek-mut-pop.md [new file with mode: 0644]
src/doc/unstable-book/src/borrow-state.md [new file with mode: 0644]
src/doc/unstable-book/src/box-heap.md [new file with mode: 0644]
src/doc/unstable-book/src/c-void-variant.md [new file with mode: 0644]
src/doc/unstable-book/src/catch-expr.md [new file with mode: 0644]
src/doc/unstable-book/src/char-escape-debug.md [new file with mode: 0644]
src/doc/unstable-book/src/closure-to-fn-coercion.md [new file with mode: 0644]
src/doc/unstable-book/src/coerce-unsized.md [new file with mode: 0644]
src/doc/unstable-book/src/collection-placement.md [new file with mode: 0644]
src/doc/unstable-book/src/collections-range.md [new file with mode: 0644]
src/doc/unstable-book/src/collections.md [new file with mode: 0644]
src/doc/unstable-book/src/command-envs.md [new file with mode: 0644]
src/doc/unstable-book/src/compiler-builtins-lib.md [new file with mode: 0644]
src/doc/unstable-book/src/concat-idents-macro.md [new file with mode: 0644]
src/doc/unstable-book/src/core-char-ext.md [new file with mode: 0644]
src/doc/unstable-book/src/core-float.md [new file with mode: 0644]
src/doc/unstable-book/src/core-intrinsics.md [new file with mode: 0644]
src/doc/unstable-book/src/core-panic.md [new file with mode: 0644]
src/doc/unstable-book/src/core-private-bignum.md [new file with mode: 0644]
src/doc/unstable-book/src/core-private-diy-float.md [new file with mode: 0644]
src/doc/unstable-book/src/core-slice-ext.md [new file with mode: 0644]
src/doc/unstable-book/src/core-str-ext.md [new file with mode: 0644]
src/doc/unstable-book/src/dec2flt.md [new file with mode: 0644]
src/doc/unstable-book/src/decode-utf8.md [new file with mode: 0644]
src/doc/unstable-book/src/derive-clone-copy.md [new file with mode: 0644]
src/doc/unstable-book/src/derive-eq.md [new file with mode: 0644]
src/doc/unstable-book/src/discriminant-value.md [new file with mode: 0644]
src/doc/unstable-book/src/enumset.md [new file with mode: 0644]
src/doc/unstable-book/src/error-type-id.md [new file with mode: 0644]
src/doc/unstable-book/src/exact-size-is-empty.md [new file with mode: 0644]
src/doc/unstable-book/src/fd-read.md [new file with mode: 0644]
src/doc/unstable-book/src/fd.md [new file with mode: 0644]
src/doc/unstable-book/src/field-init-shorthand.md [deleted file]
src/doc/unstable-book/src/fixed-size-array.md [new file with mode: 0644]
src/doc/unstable-book/src/float-extras.md [new file with mode: 0644]
src/doc/unstable-book/src/flt2dec.md [new file with mode: 0644]
src/doc/unstable-book/src/fmt-flags-align.md [new file with mode: 0644]
src/doc/unstable-book/src/fmt-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/fn-traits.md [new file with mode: 0644]
src/doc/unstable-book/src/fnbox.md [new file with mode: 0644]
src/doc/unstable-book/src/fused.md [new file with mode: 0644]
src/doc/unstable-book/src/future-atomic-orderings.md [new file with mode: 0644]
src/doc/unstable-book/src/get-type-id.md [new file with mode: 0644]
src/doc/unstable-book/src/heap-api.md [new file with mode: 0644]
src/doc/unstable-book/src/i128.md [new file with mode: 0644]
src/doc/unstable-book/src/inclusive-range-syntax.md
src/doc/unstable-book/src/inclusive-range.md [new file with mode: 0644]
src/doc/unstable-book/src/int-error-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/integer-atomics.md [new file with mode: 0644]
src/doc/unstable-book/src/into-boxed-c-str.md [new file with mode: 0644]
src/doc/unstable-book/src/into-boxed-os-str.md [new file with mode: 0644]
src/doc/unstable-book/src/into-boxed-path.md [new file with mode: 0644]
src/doc/unstable-book/src/io-error-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/io.md [new file with mode: 0644]
src/doc/unstable-book/src/ip.md [new file with mode: 0644]
src/doc/unstable-book/src/is-unique.md [new file with mode: 0644]
src/doc/unstable-book/src/iter-rfind.md [new file with mode: 0644]
src/doc/unstable-book/src/libstd-io-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/libstd-sys-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/libstd-thread-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/linked-list-extras.md [new file with mode: 0644]
src/doc/unstable-book/src/lookup-host.md [new file with mode: 0644]
src/doc/unstable-book/src/map-entry-recover-keys.md [new file with mode: 0644]
src/doc/unstable-book/src/mpsc-select.md [new file with mode: 0644]
src/doc/unstable-book/src/n16.md [new file with mode: 0644]
src/doc/unstable-book/src/never-type-impls.md [new file with mode: 0644]
src/doc/unstable-book/src/nonzero.md [new file with mode: 0644]
src/doc/unstable-book/src/once-poison.md [new file with mode: 0644]
src/doc/unstable-book/src/oom.md [new file with mode: 0644]
src/doc/unstable-book/src/option-entry.md [new file with mode: 0644]
src/doc/unstable-book/src/osstring-shrink-to-fit.md [new file with mode: 0644]
src/doc/unstable-book/src/panic-abort.md [new file with mode: 0644]
src/doc/unstable-book/src/panic-unwind.md [new file with mode: 0644]
src/doc/unstable-book/src/pattern.md [new file with mode: 0644]
src/doc/unstable-book/src/peek.md [new file with mode: 0644]
src/doc/unstable-book/src/placement-in.md [new file with mode: 0644]
src/doc/unstable-book/src/placement-new-protocol.md [new file with mode: 0644]
src/doc/unstable-book/src/print.md [new file with mode: 0644]
src/doc/unstable-book/src/proc-macro-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/process-try-wait.md [new file with mode: 0644]
src/doc/unstable-book/src/pub-restricted.md [new file with mode: 0644]
src/doc/unstable-book/src/question-mark-carrier.md [new file with mode: 0644]
src/doc/unstable-book/src/rand.md [new file with mode: 0644]
src/doc/unstable-book/src/range-contains.md [new file with mode: 0644]
src/doc/unstable-book/src/raw.md [new file with mode: 0644]
src/doc/unstable-book/src/rc-would-unwrap.md [new file with mode: 0644]
src/doc/unstable-book/src/retain-hash-collection.md [new file with mode: 0644]
src/doc/unstable-book/src/rt.md [new file with mode: 0644]
src/doc/unstable-book/src/rustc-private.md [new file with mode: 0644]
src/doc/unstable-book/src/rustdoc.md [new file with mode: 0644]
src/doc/unstable-book/src/sanitizer-runtime-lib.md [new file with mode: 0644]
src/doc/unstable-book/src/set-stdio.md [new file with mode: 0644]
src/doc/unstable-book/src/shared.md [new file with mode: 0644]
src/doc/unstable-book/src/sip-hash-13.md [new file with mode: 0644]
src/doc/unstable-book/src/slice-concat-ext.md [new file with mode: 0644]
src/doc/unstable-book/src/slice-get-slice.md [new file with mode: 0644]
src/doc/unstable-book/src/sort-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/static-recursion.md [deleted file]
src/doc/unstable-book/src/step-by.md [new file with mode: 0644]
src/doc/unstable-book/src/step-trait.md [new file with mode: 0644]
src/doc/unstable-book/src/str-escape.md [new file with mode: 0644]
src/doc/unstable-book/src/str-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/thread-id.md [new file with mode: 0644]
src/doc/unstable-book/src/thread-local-internals.md [new file with mode: 0644]
src/doc/unstable-book/src/thread-local-state.md [new file with mode: 0644]
src/doc/unstable-book/src/trusted-len.md [new file with mode: 0644]
src/doc/unstable-book/src/try-from.md [new file with mode: 0644]
src/doc/unstable-book/src/unicode.md [new file with mode: 0644]
src/doc/unstable-book/src/unique.md [new file with mode: 0644]
src/doc/unstable-book/src/unsize.md [new file with mode: 0644]
src/doc/unstable-book/src/update-panic-count.md [new file with mode: 0644]
src/doc/unstable-book/src/utf8-error-error-len.md [new file with mode: 0644]
src/doc/unstable-book/src/vec-remove-item.md [new file with mode: 0644]
src/doc/unstable-book/src/windows-c.md [new file with mode: 0644]
src/doc/unstable-book/src/windows-handle.md [new file with mode: 0644]
src/doc/unstable-book/src/windows-net.md [new file with mode: 0644]
src/doc/unstable-book/src/windows-stdio.md [new file with mode: 0644]
src/doc/unstable-book/src/zero-one.md [new file with mode: 0644]
src/grammar/verify.rs
src/libcollections/btree/map.rs
src/libcollections/linked_list.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/vec.rs
src/libcollectionstest/vec.rs
src/libcore/char.rs
src/libcore/cmp.rs
src/libcore/iter/traits.rs
src/libcore/num/dec2flt/algorithm.rs
src/libcore/ops.rs
src/libcore/result.rs
src/libcore/slice/sort.rs
src/libcore/str/mod.rs
src/libgraphviz/lib.rs
src/liblibc
src/liblog/Cargo.toml [deleted file]
src/liblog/directive.rs [deleted file]
src/liblog/lib.rs [deleted file]
src/liblog/macros.rs [deleted file]
src/librustc/Cargo.toml
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/dep_tracking_map.rs
src/librustc/dep_graph/edges.rs
src/librustc/dep_graph/shadow.rs
src/librustc/diagnostics.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/ich/fingerprint.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/higher_ranked/mod.rs
src/librustc/lint/context.rs
src/librustc/middle/cstore.rs
src/librustc/middle/dead.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/mir/mod.rs
src/librustc/traits/object_safety.rs
src/librustc/ty/adjustment.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc_back/Cargo.toml
src/librustc_borrowck/Cargo.toml
src/librustc_borrowck/borrowck/fragments.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_borrowck/graphviz.rs
src/librustc_const_eval/Cargo.toml
src/librustc_const_eval/_match.rs
src/librustc_const_eval/check_match.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/accumulate_vec.rs
src/librustc_data_structures/base_n.rs
src/librustc_data_structures/blake2b.rs
src/librustc_data_structures/indexed_set.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_incremental/Cargo.toml
src/librustc_incremental/persist/file_format.rs
src/librustc_lint/Cargo.toml
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_llvm/build.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/locator.rs
src/librustc_metadata/schema.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/build/scope.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/type_check.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_passes/Cargo.toml
src/librustc_plugin/load.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/Cargo.toml
src/librustc_save_analysis/csv_dumper.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/abi.rs
src/librustc_trans/adt.rs
src/librustc_trans/asm.rs
src/librustc_trans/back/archive.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/rpath.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/symbol_names.rs
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/builder.rs
src/librustc_trans/context.rs
src/librustc_trans/mir/analyze.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/monomorphize.rs
src/librustc_typeck/Cargo.toml
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/builtin.rs
src/librustc_typeck/coherence/inherent.rs [deleted file]
src/librustc_typeck/coherence/inherent_impls.rs [new file with mode: 0644]
src/librustc_typeck/coherence/inherent_impls_overlap.rs [new file with mode: 0644]
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/diagnostics.rs
src/librustdoc/Cargo.toml
src/librustdoc/build.rs [deleted file]
src/librustdoc/clean/inline.rs
src/librustdoc/core.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/visit_ast.rs
src/libstd/ascii.rs
src/libstd/collections/hash/table.rs
src/libstd/io/cursor.rs
src/libstd/io/mod.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/net/mod.rs
src/libstd/net/parser.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/os/raw.rs
src/libstd/process.rs
src/libstd/sync/once.rs
src/libstd/sys/unix/ext/net.rs
src/libstd/sys/unix/process/process_common.rs
src/libstd/sys/unix/process/process_unix.rs
src/libstd/sys/windows/process.rs
src/libstd/sys/windows/stdio.rs
src/libstd/sys_common/net.rs
src/libstd_unicode/char.rs
src/libsyntax/Cargo.toml
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/libsyntax/symbol.rs
src/libsyntax/test.rs
src/libsyntax_ext/Cargo.toml
src/llvm
src/rt/hoedown [deleted submodule]
src/rustc/rustdoc.rs
src/rustllvm/llvm-rebuild-trigger
src/test/compile-fail/augmented-assignments.rs
src/test/compile-fail/borrowck/borrowck-issue-14498.rs
src/test/compile-fail/imports/shadow_builtin_macros.rs [new file with mode: 0644]
src/test/compile-fail/issue-10176.rs [new file with mode: 0644]
src/test/compile-fail/issue-33819.rs
src/test/compile-fail/issue-40000.rs [new file with mode: 0644]
src/test/compile-fail/issue-40749.rs [new file with mode: 0644]
src/test/compile-fail/issue-40845.rs [new file with mode: 0644]
src/test/compile-fail/issue-5500.rs [new file with mode: 0644]
src/test/compile-fail/mut-suggestion.rs
src/test/compile-fail/object-safety-supertrait-mentions-Self.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs
src/test/compile-fail/static-lifetime-bound.rs [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/logging_right_crate.rs [deleted file]
src/test/run-pass-fulldeps/conditional-debug-macro-off.rs [deleted file]
src/test/run-pass-fulldeps/logging-enabled-debug.rs [deleted file]
src/test/run-pass-fulldeps/logging-enabled.rs [deleted file]
src/test/run-pass-fulldeps/logging-right-crate.rs [deleted file]
src/test/run-pass-fulldeps/logging-separate-lines.rs [deleted file]
src/test/run-pass-fulldeps/rust-log-filter.rs [deleted file]
src/test/run-pass-fulldeps/switch-stdout.rs [new file with mode: 0644]
src/test/run-pass/auxiliary/llvm_pr32379.rs [new file with mode: 0644]
src/test/run-pass/conditional-debug-macro-on.rs
src/test/run-pass/inference-changes-39485.rs [deleted file]
src/test/run-pass/issue-15763.rs
src/test/run-pass/issue-16671.rs
src/test/run-pass/issue-39984.rs [new file with mode: 0644]
src/test/run-pass/issue-40770.rs [new file with mode: 0644]
src/test/run-pass/llvm-pr32379.rs [new file with mode: 0644]
src/test/run-pass/project-defer-unification.rs
src/test/ui/codemap_tests/huge_multispan_highlight.stderr
src/test/ui/did_you_mean/issue-31424.stderr
src/test/ui/did_you_mean/issue-35937.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-35937.stderr [new file with mode: 0644]
src/test/ui/did_you_mean/issue-38147-2.stderr
src/test/ui/did_you_mean/issue-38147-3.stderr
src/test/ui/did_you_mean/issue-39544.rs
src/test/ui/did_you_mean/issue-39544.stderr
src/test/ui/did_you_mean/issue-40823.rs [new file with mode: 0644]
src/test/ui/did_you_mean/issue-40823.stderr [new file with mode: 0644]
src/test/ui/pub/pub-restricted-error-fn.rs [new file with mode: 0644]
src/test/ui/pub/pub-restricted-error-fn.stderr [new file with mode: 0644]
src/test/ui/pub/pub-restricted-error.rs [new file with mode: 0644]
src/test/ui/pub/pub-restricted-error.stderr [new file with mode: 0644]
src/test/ui/pub/pub-restricted-non-path.rs [new file with mode: 0644]
src/test/ui/pub/pub-restricted-non-path.stderr [new file with mode: 0644]
src/test/ui/pub/pub-restricted.rs [new file with mode: 0644]
src/test/ui/pub/pub-restricted.stderr [new file with mode: 0644]
src/test/ui/span/borrowck-borrow-overloaded-auto-deref-mut.stderr
src/test/ui/span/borrowck-borrow-overloaded-deref-mut.stderr
src/test/ui/span/borrowck-object-mutability.stderr
src/tools/compiletest/Cargo.toml
src/tools/compiletest/src/procsrv.rs
src/tools/error_index_generator/main.rs

index d2e1fb868a9990b1ed81bfdda3c23f3ce78b09f9..53d17874924093c298f0f111f1c4c4d680c68f55 100644 (file)
@@ -5,10 +5,6 @@
 [submodule "src/compiler-rt"]
        path = src/compiler-rt
        url = https://github.com/rust-lang/compiler-rt.git
-[submodule "src/rt/hoedown"]
-       path = src/rt/hoedown
-       url = https://github.com/rust-lang/hoedown.git
-       branch = rust-2015-09-21-do-not-delete
 [submodule "src/jemalloc"]
        path = src/jemalloc
        url = https://github.com/rust-lang/jemalloc.git
index 51e4440d5874712524b67da53d711db6bbd2f7f0..83e837e2d7690afd4e6458442b4d1545a6b937d4 100644 (file)
@@ -52,7 +52,7 @@ matrix:
       os: osx
       osx_image: xcode8.2
       install: &osx_install_sccache >
-        travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-apple-darwin &&
+        travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-apple-darwin &&
           chmod +x /usr/local/bin/sccache &&
         travis_retry curl -o /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
           chmod +x /usr/local/bin/stamp
@@ -154,9 +154,21 @@ after_failure:
       echo "#### Build failed; Disk usage after running script:";
       df -h;
       du . | sort -nr | head -n100
+
+  # One of these is the linux sccache log, one is the OSX sccache log. Instead
+  # of worrying about what system we are just cat both. One of these commands
+  # will fail but that's ok, they'll both get executed.
   - cat obj/tmp/sccache.log
   - cat /tmp/sccache.log
 
+  # Random attempt at debugging currently. Just poking around in here to see if
+  # anything shows up.
+  - ls $HOME/Library/Logs/DiagnosticReports/
+
+  # attempt to debug anything killed by the oom killer on linux, just to see if
+  # it happened
+  - dmesg | grep -i kill
+
 # Save tagged docker images we created and load them if they're available
 # Travis saves caches whether the build failed or not, nuke rustsrc if
 # the failure was while updating it (as it may be in an bad state)
index f921fb2c94233efa196d6ef16ebc271dc2a813a5..0314a5dfd8d02a5b283d317ef83cadad445fd8ce 100644 (file)
@@ -311,9 +311,13 @@ To save @bors some work, and to get small changes through more quickly, when
 the other rollup-eligible patches too, and they'll get tested and merged at
 the same time.
 
-To find documentation-related issues, sort by the [A-docs label][adocs].
+To find documentation-related issues, sort by the [T-doc label][tdoc].
 
-[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs
+[tdoc]: https://github.com/rust-lang/rust/issues?q=is%3Aopen%20is%3Aissue%20label%3AT-doc
+
+You can find documentation style guidelines in [RFC 1574][rfc1574].
+
+[rfc1574]: https://github.com/rust-lang/rfcs/blob/master/text/1574-more-api-documentation-conventions.md#appendix-a-full-conventions-text
 
 In many cases, you don't need a full `./x.py doc`. You can use `rustdoc` directly
 to check small fixes. For example, `rustdoc src/doc/reference.md` will render
index 48983513147eb758318e96b91022868c812c8dd5..fa599a00c4de349144f9acb15252afd477fdb533 100644 (file)
@@ -45,14 +45,14 @@ environment:
   - MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja
     SCRIPT: python x.py test
-    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
-    MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
+    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
+    MINGW_ARCHIVE: i686-6.2.0-release-win32-dwarf-rt_v5-rev1.7z
     MINGW_DIR: mingw32
   - MSYS_BITS: 64
     SCRIPT: python x.py test
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-ninja
-    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
-    MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
+    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
+    MINGW_ARCHIVE: x86_64-6.2.0-release-win32-seh-rt_v5-rev1.7z
     MINGW_DIR: mingw64
 
   # 32/64 bit MSVC and GNU deployment
@@ -70,15 +70,15 @@ environment:
   - MSYS_BITS: 32
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-ninja
     SCRIPT: python x.py dist
-    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
-    MINGW_ARCHIVE: i686-4.9.2-release-win32-dwarf-rt_v4-rev4.7z
+    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
+    MINGW_ARCHIVE: i686-6.2.0-release-win32-dwarf-rt_v5-rev1.7z
     MINGW_DIR: mingw32
     DEPLOY: 1
   - MSYS_BITS: 64
     SCRIPT: python x.py dist
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-ninja
-    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci
-    MINGW_ARCHIVE: x86_64-4.9.2-release-win32-seh-rt_v4-rev4.7z
+    MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
+    MINGW_ARCHIVE: x86_64-6.2.0-release-win32-seh-rt_v5-rev1.7z
     MINGW_DIR: mingw64
     DEPLOY: 1
 
@@ -115,8 +115,8 @@ install:
   - set PATH=C:\Python27;%PATH%
 
   # Download and install sccache
-  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-pc-windows-msvc
-  - mv 2017-03-16-sccache-x86_64-pc-windows-msvc sccache.exe
+  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-pc-windows-msvc
+  - mv 2017-03-24-sccache-x86_64-pc-windows-msvc sccache.exe
   - set PATH=%PATH%;%CD%
 
   # Download and install ninja
@@ -184,6 +184,7 @@ deploy:
     on:
       branch: auto
       DEPLOY: 1
+    max_error_retry: 5
 
   # This provider is the same as the one above except that it has a slightly
   # different upload directory and a slightly different trigger
@@ -200,6 +201,7 @@ deploy:
     on:
       branch: auto
       DEPLOY_ALT: 1
+    max_error_retry: 5
 
 # init:
 #   - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
diff --git a/cargo b/cargo
index c995e9eb5acf3976ae8674a0dc6d9e958053d9fd..4e95c6b41eca3388f54dd5f7787366ad2df637b5 160000 (submodule)
--- a/cargo
+++ b/cargo
@@ -1 +1 @@
-Subproject commit c995e9eb5acf3976ae8674a0dc6d9e958053d9fd
+Subproject commit 4e95c6b41eca3388f54dd5f7787366ad2df637b5
index 9ae894061a6762d0af21dde50427de153f6bfc6c..a9021dc34e207438edb537e673f3511c461aa7b9 100644 (file)
@@ -8,7 +8,7 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -27,7 +27,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "bitflags"
-version = "0.8.0"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -75,7 +75,7 @@ dependencies = [
  "build_helper 0.1.0",
  "cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -104,12 +104,12 @@ version = "0.1.0"
 
 [[package]]
 name = "clap"
-version = "2.21.1"
+version = "2.22.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -122,7 +122,7 @@ name = "cmake"
 version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -140,14 +140,14 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "compiletest"
 version = "0.0.0"
 dependencies = [
- "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -162,14 +162,6 @@ name = "dtoa"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "env_logger"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "env_logger"
 version = "0.4.2"
@@ -196,7 +188,7 @@ name = "flate"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -205,7 +197,7 @@ version = "0.0.0"
 
 [[package]]
 name = "gcc"
-version = "0.3.44"
+version = "0.3.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -223,10 +215,10 @@ version = "0.0.0"
 
 [[package]]
 name = "handlebars"
-version = "0.25.1"
+version = "0.25.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -251,7 +243,7 @@ dependencies = [
 
 [[package]]
 name = "lazy_static"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -270,10 +262,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "linkchecker"
 version = "0.1.0"
 
-[[package]]
-name = "log"
-version = "0.0.0"
-
 [[package]]
 name = "log"
 version = "0.3.7"
@@ -284,9 +272,9 @@ name = "mdbook"
 version = "0.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -370,6 +358,14 @@ dependencies = [
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "pulldown-cmark"
+version = "0.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "qemu-test-client"
 version = "0.1.0"
@@ -395,7 +391,7 @@ name = "regex"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -428,7 +424,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -439,7 +435,7 @@ dependencies = [
  "arena 0.0.0",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_math 0.0.0",
@@ -479,7 +475,7 @@ dependencies = [
 name = "rustc_back"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "syntax 0.0.0",
 ]
@@ -493,7 +489,7 @@ name = "rustc_borrowck"
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -508,7 +504,7 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
@@ -530,7 +526,7 @@ dependencies = [
 name = "rustc_data_structures"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
 ]
 
@@ -539,8 +535,9 @@ name = "rustc_driver"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro_plugin 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
@@ -579,7 +576,7 @@ name = "rustc_incremental"
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
@@ -591,7 +588,7 @@ dependencies = [
 name = "rustc_lint"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_eval 0.0.0",
@@ -604,7 +601,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
 ]
 
@@ -623,7 +620,7 @@ name = "rustc_metadata"
 version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
@@ -642,7 +639,7 @@ name = "rustc_mir"
 version = "0.0.0"
 dependencies = [
  "graphviz 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_bitflags 0.0.0",
  "rustc_const_eval 0.0.0",
@@ -666,7 +663,7 @@ dependencies = [
 name = "rustc_passes"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_const_eval 0.0.0",
  "rustc_const_math 0.0.0",
@@ -705,7 +702,7 @@ name = "rustc_resolve"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_errors 0.0.0",
  "syntax 0.0.0",
@@ -716,7 +713,7 @@ dependencies = [
 name = "rustc_save_analysis"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -730,7 +727,7 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
@@ -762,7 +759,7 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "fmt_macros 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_eval 0.0.0",
@@ -780,8 +777,10 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "build_helper 0.1.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.0.0",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_eval 0.0.0",
@@ -828,7 +827,7 @@ dependencies = [
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -857,7 +856,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "syntax"
 version = "0.0.0"
 dependencies = [
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -870,7 +869,7 @@ name = "syntax_ext"
 version = "0.0.0"
 dependencies = [
  "fmt_macros 0.0.0",
- "log 0.0.0",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_errors 0.0.0",
  "syntax 0.0.0",
@@ -988,23 +987,22 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
+"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
 "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
 "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
-"checksum bitflags 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e1ab483fc81a8143faa7203c4a3c02888ebd1a782e37e41fa34753ba9a162"
-"checksum clap 2.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "74a80f603221c9cd9aa27a28f52af452850051598537bb6b359c38a7d61e5cda"
+"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
+"checksum clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e17a4a72ffea176f77d6e2db609c6c919ef221f23862c9915e687fb54d833485"
 "checksum cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "d18d68987ed4c516dcc3e7913659bfa4076f5182eea4a7e0038bb060953e76ac"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
-"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum gcc 0.3.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a32cd40070d7611ab76343dcb3204b2bb28c8a9450989a83a3d590248142f439"
+"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
-"checksum handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b2249f6f0dc5a3bb2b3b1a8f797dfccbc4b053344d773d654ad565e51427d335"
+"checksum handlebars 0.25.2 (registry+https://github.com/rust-lang/crates.io-index)" = "663e1728d8037fb0d4e13bcd1b1909fb5d913690a9929eb385922df157c2ff8f"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc"
+"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
 "checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
 "checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
 "checksum mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "06a68e8738e42b38a02755d3ce5fa12d559e17acb238e4326cbc3cc056e65280"
@@ -1013,6 +1011,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
+"checksum pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9ab1e588ef8efd702c7ed9d2bd774db5e6f4d878bb5a1a9f371828fbdff6973"
 "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
 "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
index e9ca430f1582b4723529255bb17cfb7309fc4d36..3a1a9c3e40d66066b708f48e2de876d38d7fa702 100644 (file)
@@ -40,6 +40,14 @@ fn main() {
         .arg(sysroot)
         .env(bootstrap::util::dylib_path_var(),
              env::join_paths(&dylib_path).unwrap());
+
+    // Pass the `rustbuild` feature flag to crates which rustbuild is
+    // building. See the comment in bootstrap/lib.rs where this env var is
+    // set for more details.
+    if env::var_os("RUSTBUILD_UNSTABLE").is_some() {
+        cmd.arg("--cfg").arg("rustbuild");
+    }
+
     std::process::exit(match cmd.status() {
         Ok(s) => s.code().unwrap_or(1),
         Err(e) => panic!("\n\nfailed to run {:?}: {}\n\n", cmd, e),
index 40cdb9242df15b2fec93cee92f272d31e4ec5849..f8f641060c442674f4d7b9a03b8d8bcde5008fec 100644 (file)
@@ -586,7 +586,7 @@ fn android_copy_libs(build: &Build, compiler: &Compiler, target: &str) {
                       .arg(ADB_TEST_DIR));
 
     let target_dir = format!("{}/{}", ADB_TEST_DIR, target);
-    build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir[..]]));
+    build.run(Command::new("adb").args(&["shell", "mkdir", &target_dir]));
 
     for f in t!(build.sysroot_libdir(compiler, target).read_dir()) {
         let f = t!(f);
index a3e74adbb3672f3d85169b394717415581ea02e8..933562c79e5821837b8fae00fa23bc908d750900 100644 (file)
@@ -74,7 +74,7 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static
 RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 72675bc9a446c9ce259e467d8577fdb06f527c5f..8dc02ab522c21bf9604a500048734714fc33faa6 100644 (file)
@@ -22,7 +22,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 031ad0ddcd4e6ab057c4abe9cc135ea8782f746b..44d6863bf0bbdc8430f7cab91cd0c289f41e63a6 100644 (file)
@@ -32,7 +32,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV TARGETS=arm-linux-androideabi
index ae439f5b30f29b09d306d36f202b86a06b71aba6..7facc52390ff4a294b1f5111a46cfe340dc7614b 100644 (file)
@@ -27,10 +27,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
-      chmod +x /usr/local/bin/sccache
-
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
     dpkg -i dumb-init_*.deb && \
     rm dumb-init_*.deb
@@ -65,6 +61,10 @@ RUN ./build-toolchains.sh
 
 USER root
 
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
 ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabi/bin
 ENV PATH=$PATH:/x-tools/arm-unknown-linux-gnueabihf/bin
 
index 7f3c55225878066d8ec60ec8e6eb8e5813619cbd..369e5a7dffe2a8048c84023e861a322a280a0194 100644 (file)
@@ -27,10 +27,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
-      chmod +x /usr/local/bin/sccache
-
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
     dpkg -i dumb-init_*.deb && \
     rm dumb-init_*.deb
@@ -66,6 +62,10 @@ RUN ./build-toolchains.sh
 
 USER root
 
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
 ENV PATH=$PATH:/x-tools/aarch64-unknown-linux-gnueabi/bin
 ENV PATH=$PATH:/x-tools/armv7-unknown-linux-gnueabihf/bin
 
index deee78847bbf633de27be0c0e5b528df2fa3f6c2..633f58ea474b4eccc623af0cd2d03e29fa1b622d 100644 (file)
@@ -26,7 +26,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV \
index de8ed3378eb1622527387c980544cdf8c91ddfcb..ed37a9e842e227a9219599bf00b70e947a8c90d5 100644 (file)
@@ -29,7 +29,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV \
index f19860405b02c06fa3131ac39c8d1df60666719c..d88ec7aab34643da663133c818c5bfadf58f7f1c 100644 (file)
@@ -26,7 +26,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV RUST_CONFIGURE_ARGS \
index 8de9b6abddd6ff6aad85f811ad0168ff9aae326a..938c53ae48837d057b653cced3a47d190b2b0b03 100644 (file)
@@ -18,7 +18,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 134f475f82d6e7a02eed7f689922e5d73b707f0a..45de8100b4f27f9f3aed69d309e70a678e4840b3 100644 (file)
@@ -18,7 +18,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 1c61714adbd2aa06dc8485799e34f7430656aff6..c1e5e863ae06c3b710900cdc6f03d81dbb9d4596 100644 (file)
@@ -27,10 +27,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
-      chmod +x /usr/local/bin/sccache
-
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
     dpkg -i dumb-init_*.deb && \
     rm dumb-init_*.deb
@@ -66,6 +62,10 @@ RUN ./build-powerpc-toolchain.sh
 
 USER root
 
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
 ENV PATH=$PATH:/x-tools/powerpc-unknown-linux-gnu/bin
 
 ENV \
index 975ae1d3ec9c1b710f5c3f14b81101528109013b..7413c327323e5072aca0e34050286b13a552eebd 100644 (file)
@@ -25,11 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   wget \
   xz-utils \
   libssl-dev \
-  pkg-config
-
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
-      chmod +x /usr/local/bin/sccache
+ pkg-config
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
     dpkg -i dumb-init_*.deb && \
@@ -70,6 +66,10 @@ RUN apt-get install -y --no-install-recommends rpm2cpio cpio
 COPY build-powerpc64le-toolchain.sh /tmp/
 RUN ./build-powerpc64le-toolchain.sh
 
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
 ENV PATH=$PATH:/x-tools/powerpc64-unknown-linux-gnu/bin
 
 ENV \
index fd67f185162d9def159f516b394ea25daa84ad10..4180006690fc902c76eb19eda0b3cf9c91d62edb 100644 (file)
@@ -27,10 +27,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   libssl-dev \
   pkg-config
 
-RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
-      chmod +x /usr/local/bin/sccache
-
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
     dpkg -i dumb-init_*.deb && \
     rm dumb-init_*.deb
@@ -64,17 +60,21 @@ COPY patches/ /tmp/patches/
 COPY s390x-linux-gnu.config build-s390x-toolchain.sh /tmp/
 RUN ./build-s390x-toolchain.sh
 
-USER root
-
 COPY build-netbsd-toolchain.sh /tmp/
 RUN ./build-netbsd-toolchain.sh
 
-ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin
+USER root
+
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
+ENV PATH=$PATH:/x-tools/s390x-ibm-linux-gnu/bin:/x-tools/x86_64-unknown-netbsd/bin
 
 ENV \
-    AR_x86_64_unknown_netbsd=x86_64-unknown-netbsd-ar \
-    CC_x86_64_unknown_netbsd=x86_64-unknown-netbsd-gcc \
-    CXX_x86_64_unknown_netbsd=x86_64-unknown-netbsd-g++ \
+    AR_x86_64_unknown_netbsd=x86_64--netbsd-ar \
+    CC_x86_64_unknown_netbsd=x86_64--netbsd-gcc-sysroot \
+    CXX_x86_64_unknown_netbsd=x86_64--netbsd-g++-sysroot \
     CC_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-gcc \
     AR_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-ar \
     CXX_s390x_unknown_linux_gnu=s390x-ibm-linux-gnu-g++
index 654b458ea409e01335ebe1816ab6b40a58991761..ea335a249736c703296840774638e609961625c1 100755 (executable)
 
 set -ex
 
-BINUTILS=2.25.1
-GCC=5.3.0
-
-# First up, build binutils
-mkdir binutils
-cd binutils
-curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.bz2 | tar xjf -
-mkdir binutils-build
-cd binutils-build
-../binutils-$BINUTILS/configure \
-  --target=x86_64-unknown-netbsd
-make -j10
-make install
-cd ../..
-rm -rf binutils
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  rm /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
 
-# Next, download the NetBSD libc and relevant header files
 mkdir netbsd
-# originally from:
-# https://ftp.netbsd.org/pub/NetBSD/NetBSD-7.0/amd64/binary/sets/base.tgz
-curl https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-16-netbsd-base.tgz | \
-  tar xzf - -C netbsd ./usr/include ./usr/lib ./lib
-# originally from:
-# https://ftp.netbsd.org/pub/NetBSD/NetBSD-7.0/amd64/binary/sets/comp.tgz
-curl https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-16-netbsd-comp.tgz | \
-  tar xzf - -C netbsd ./usr/include ./usr/lib
-
-dst=/usr/local/x86_64-unknown-netbsd
-cp -r netbsd/usr/include $dst
-cp netbsd/usr/lib/crt0.o $dst/lib
-cp netbsd/usr/lib/crti.o $dst/lib
-cp netbsd/usr/lib/crtn.o $dst/lib
-cp netbsd/usr/lib/crtbeginS.o $dst/lib
-cp netbsd/usr/lib/crtendS.o $dst/lib
-cp netbsd/usr/lib/crtbegin.o $dst/lib
-cp netbsd/usr/lib/crtend.o $dst/lib
-cp netbsd/usr/lib/gcrt0.o $dst/lib
-cp netbsd/usr/lib/libc.a $dst/lib
-cp netbsd/usr/lib/libc_p.a $dst/lib
-cp netbsd/usr/lib/libc_pic.a $dst/lib
-cp netbsd/lib/libc.so.12.193.1 $dst/lib
-cp netbsd/lib/libutil.so.7.21 $dst/lib
-cp netbsd/usr/lib/libm.a $dst/lib
-cp netbsd/usr/lib/libm_p.a $dst/lib
-cp netbsd/usr/lib/libm_pic.a $dst/lib
-cp netbsd/lib/libm.so.0.11 $dst/lib
-cp netbsd/usr/lib/librt.so.1.1 $dst/lib
-cp netbsd/usr/lib/libpthread.a $dst/lib
-cp netbsd/usr/lib/libpthread_p.a $dst/lib
-cp netbsd/usr/lib/libpthread_pic.a $dst/lib
-cp netbsd/usr/lib/libpthread.so.1.2 $dst/lib
-
-ln -s libc.so.12.193.1 $dst/lib/libc.so
-ln -s libc.so.12.193.1 $dst/lib/libc.so.12
-ln -s libm.so.0.11 $dst/lib/libm.so
-ln -s libm.so.0.11 $dst/lib/libm.so.0
-ln -s libutil.so.7.21 $dst/lib/libutil.so
-ln -s libutil.so.7.21 $dst/lib/libutil.so.7
-ln -s libpthread.so.1.2 $dst/lib/libpthread.so
-ln -s libpthread.so.1.2 $dst/lib/libpthread.so.1
-ln -s librt.so.1.1 $dst/lib/librt.so
-
-rm -rf netbsd
-
-# Finally, download and build gcc to target NetBSD
-mkdir gcc
-cd gcc
-curl https://ftp.gnu.org/gnu/gcc/gcc-$GCC/gcc-$GCC.tar.bz2 | tar xjf -
-cd gcc-$GCC
-./contrib/download_prerequisites
-
-# Originally from
-# ftp://ftp.netbsd.org/pub/pkgsrc/pkgsrc-2016Q4/pkgsrc/lang/gcc5/patches/patch-libstdc%2B%2B-v3_config_os_bsd_netbsd_ctype__base.h
-PATCHES="https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-13-netbsd-patch1.patch"
-
-# Originally from
-# ftp://ftp.netbsd.org/pub/pkgsrc/pkgsrc-2016Q4/pkgsrc/lang/gcc5/patches/patch-libstdc%2B%2B-v3_config_os_bsd_netbsd_ctype__configure__char.cc
-PATCHES="$PATCHES https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-01-13-netbsd-patch2.patch"
-
-for patch in $PATCHES; do
-  curl $patch | patch -Np0
-done
-
-mkdir ../gcc-build
-cd ../gcc-build
-../gcc-$GCC/configure                            \
-  --enable-languages=c,c++                       \
-  --target=x86_64-unknown-netbsd                 \
-  --disable-libcilkrts                           \
-  --disable-multilib                             \
-  --disable-nls                                  \
-  --disable-libgomp                              \
-  --disable-libquadmath                          \
-  --disable-libssp                               \
-  --disable-libvtv                               \
-  --disable-libcilkrt                            \
-  --disable-libada                               \
-  --disable-libsanitizer                         \
-  --disable-libquadmath-support                  \
-  --disable-lto
-make -j10
-make install
+cd netbsd
+
+mkdir -p /x-tools/x86_64-unknown-netbsd/sysroot
+
+URL=https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
+
+# Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/source/sets/*.tgz
+curl $URL/2017-03-17-netbsd-src.tgz | tar xzf -
+curl $URL/2017-03-17-netbsd-gnusrc.tgz | tar xzf -
+curl $URL/2017-03-17-netbsd-sharesrc.tgz | tar xzf -
+curl $URL/2017-03-17-netbsd-syssrc.tgz | tar xzf -
+
+# Originally from ftp://ftp.netbsd.org/pub/NetBSD/NetBSD-$BSD/amd64/binary/sets/*.tgz
+curl $URL/2017-03-17-netbsd-base.tgz | \
+  tar xzf - -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib ./lib
+curl $URL/2017-03-17-netbsd-comp.tgz | \
+  tar xzf - -C /x-tools/x86_64-unknown-netbsd/sysroot ./usr/include ./usr/lib
+
+cd usr/src
+
+# The options, in order, do the following
+# * this is an unpriviledged build
+# * output to a predictable location
+# * disable various uneeded stuff
+MKUNPRIVED=yes TOOLDIR=/x-tools/x86_64-unknown-netbsd \
+MKSHARE=no MKDOC=no MKHTML=no MKINFO=no MKKMOD=no MKLINT=no MKMAN=no MKNLS=no MKPROFILE=no \
+hide_output ./build.sh -j10 -m amd64 tools
 
 cd ../..
-rm -rf gcc
+
+rm -rf usr
+
+cat > /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-gcc-sysroot <<'EOF'
+#!/bin/bash
+exec /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-gcc --sysroot=/x-tools/x86_64-unknown-netbsd/sysroot "$@"
+EOF
+
+cat > /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-g++-sysroot <<'EOF'
+#!/bin/bash
+exec /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-g++ --sysroot=/x-tools/x86_64-unknown-netbsd/sysroot "$@"
+EOF
+
+GCC_SHA1=`sha1sum -b /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-gcc | cut -d' ' -f1`
+GPP_SHA1=`sha1sum -b /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-g++ | cut -d' ' -f1`
+
+echo "# $GCC_SHA1" >> /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-gcc-sysroot
+echo "# $GPP_SHA1" >> /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-g++-sysroot
+
+chmod +x /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-gcc-sysroot
+chmod +x /x-tools/x86_64-unknown-netbsd/bin/x86_64--netbsd-g++-sysroot
index cd4c81912dff5a6ca37e3086305cabaf20e3cde5..18c7a4d2b3e7f54306fd5dba0f4e9056d6a927d7 100644 (file)
@@ -76,7 +76,7 @@ RUN curl -Lo /rustroot/dumb-init \
 ENTRYPOINT ["/rustroot/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV HOSTS=i686-unknown-linux-gnu
index 151552331c86caa98d0bad090c8d8087852beece..085aa351659905c2af0da4113bd96c7d4a19207f 100644 (file)
@@ -26,7 +26,7 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 ENV RUST_CONFIGURE_ARGS \
index e8eb151a0784c842654f32eb3e0e397b02253d97..77cf54a19a7fd9ee510066f3a9ed19a9aa0f4b16 100644 (file)
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   lib32stdc++6
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 88bf583007ce53f296b5a2405dac1174025d94a9..e39767357ad6301a56f463ec24d49a0ab7e97181 100755 (executable)
@@ -29,7 +29,24 @@ exit 1
 }
 
 curl https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz | \
-      tar xzf -
+    tar xzf -
+
+# Some versions of the EMSDK archive have their contents in .emsdk-portable
+# and others in emsdk_portable. Make sure the EMSDK ends up in a fixed path.
+if [ -d emsdk-portable ]; then
+    mv emsdk-portable emsdk_portable
+fi
+
+if [ ! -d emsdk_portable ]; then
+    echo "ERROR: Invalid emsdk archive. Dumping working directory." >&2
+    ls -l
+    exit 1
+fi
+
+# Some versions of the EMSDK set the permissions of the root directory to
+# 0700. Ensure the directory is readable by all users.
+chmod 755 emsdk_portable
+
 source emsdk_portable/emsdk_env.sh
 hide_output emsdk update
 hide_output emsdk install --build=Release sdk-tag-1.37.1-32bit
index aca4bfb546d2fb8a01dd343ba1c80ce5d87934a1..c84cf56e4e858bdaf788b30371b8fc00a672099b 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 2664307b09b3085d7c7a553d2682aa6601371040..f4bb9083b85827ece5f152af18aaa1a4009761f7 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index fdc8221ad250d68448c50cb7c6c913f6c93440f7..68184c65cf17ffcf75ac8728c2d4de0a5889f279 100644 (file)
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index dae7fac3890d8d7fcd396692f99f40dedc652262..6320a806fc301d3b7d9b7afd29d409ec46fcfc6e 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 05ff4847ecc1dfe31b5e8e36a15269eb55f70f64..180f53ec33f31f173ebd1dcd230ebf44272cda40 100644 (file)
@@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   pkg-config
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 176b1f0a857db98375884debdc41604e8e60d1a3..4500fc0f642deec293c20ca4c7e68e6514a1a9ca 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 216b2d9a65624f98660cabc855862443a18d4b49..ad1227fa581f9ca745e74752d23333ab8b3b65eb 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index d91e05e2b2dfffeb419f1db01778e610ede4500f..f1240201805718819fed02848b084ba7debbb263 100644 (file)
@@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index d79b07efab525200edf8b76865b7a0f55cc74d39..fa9707d1a7352c9f54d1b7bcd91acf4ba79639a0 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 71ed9ab943a0a101c2f3cc6ee5851bdf63ae6d8e..e5d89034dbe4268b6e46dcdf6dae3d914bbd591e 100644 (file)
@@ -14,7 +14,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils
 
 RUN curl -o /usr/local/bin/sccache \
-      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-16-sccache-x86_64-unknown-linux-musl && \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-24-sccache-x86_64-unknown-linux-musl && \
       chmod +x /usr/local/bin/sccache
 
 RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
index 9bd223ca406b1170a24942d6474f9e8a56f4a420..a2c56870d4dc589237102cc5e0fe7b9ebd0d14a1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 9bd223ca406b1170a24942d6474f9e8a56f4a420
+Subproject commit a2c56870d4dc589237102cc5e0fe7b9ebd0d14a1
index d08fe97d12b41c1ed8cc7701e545864132783941..616b98444ff4eb5260deee95ee3e090dfd98b947 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d08fe97d12b41c1ed8cc7701e545864132783941
+Subproject commit 616b98444ff4eb5260deee95ee3e090dfd98b947
index 516549972d61c8946542d1a34afeae97167ff77b..acedc32cacae80cf2f4925753a4ce7f7ffd7c86a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 516549972d61c8946542d1a34afeae97167ff77b
+Subproject commit acedc32cacae80cf2f4925753a4ce7f7ffd7c86a
index 456c76d43a6ece8d318d19adb2347806ddd80c42..fe491d7f9018ef5fff1d0c2cd78a5d55744be79f 100644 (file)
 - [abi_vectorcall](abi-vectorcall.md)
 - [abi_x86_interrupt](abi-x86-interrupt.md)
 - [advanced_slice_patterns](advanced-slice-patterns.md)
+- [alloc](alloc.md)
 - [alloc_jemalloc](alloc-jemalloc.md)
 - [alloc_system](alloc-system.md)
 - [allocator](allocator.md)
 - [allow_internal_unstable](allow-internal-unstable.md)
+- [as_unsafe_cell](as-unsafe-cell.md)
+- [ascii_ctype](ascii-ctype.md)
 - [asm](asm.md)
 - [associated_consts](associated-consts.md)
 - [associated_type_defaults](associated-type-defaults.md)
 - [attr_literals](attr-literals.md)
+- [binary_heap_extras](binary-heap-extras.md)
+- [binary_heap_peek_mut_pop](binary-heap-peek-mut-pop.md)
+- [borrow_state](borrow-state.md)
+- [box_heap](box-heap.md)
 - [box_patterns](box-patterns.md)
 - [box_syntax](box-syntax.md)
+- [c_void_variant](c-void-variant.md)
+- [catch_expr](catch-expr.md)
 - [cfg_target_feature](cfg-target-feature.md)
 - [cfg_target_has_atomic](cfg-target-has-atomic.md)
 - [cfg_target_thread_local](cfg-target-thread-local.md)
 - [cfg_target_vendor](cfg-target-vendor.md)
+- [char_escape_debug](char-escape-debug.md)
+- [closure_to_fn_coercion](closure-to-fn-coercion.md)
+- [coerce_unsized](coerce-unsized.md)
+- [collection_placement](collection-placement.md)
+- [collections](collections.md)
+- [collections_range](collections-range.md)
+- [command_envs](command-envs.md)
 - [compiler_builtins](compiler-builtins.md)
+- [compiler_builtins_lib](compiler-builtins-lib.md)
 - [concat_idents](concat-idents.md)
+- [concat_idents_macro](concat-idents-macro.md)
 - [conservative_impl_trait](conservative-impl-trait.md)
 - [const_fn](const-fn.md)
 - [const_indexing](const-indexing.md)
+- [core_char_ext](core-char-ext.md)
+- [core_float](core-float.md)
+- [core_intrinsics](core-intrinsics.md)
+- [core_panic](core-panic.md)
+- [core_private_bignum](core-private-bignum.md)
+- [core_private_diy_float](core-private-diy-float.md)
+- [core_slice_ext](core-slice-ext.md)
+- [core_str_ext](core-str-ext.md)
 - [custom_attribute](custom-attribute.md)
 - [custom_derive](custom-derive.md)
+- [dec2flt](dec2flt.md)
+- [decode_utf8](decode-utf8.md)
 - [default_type_parameter_fallback](default-type-parameter-fallback.md)
+- [derive_clone_copy](derive-clone-copy.md)
+- [derive_eq](derive-eq.md)
+- [discriminant_value](discriminant-value.md)
 - [drop_types_in_const](drop-types-in-const.md)
 - [dropck_eyepatch](dropck-eyepatch.md)
 - [dropck_parametricity](dropck-parametricity.md)
+- [enumset](enumset.md)
+- [error_type_id](error-type-id.md)
+- [exact_size_is_empty](exact-size-is-empty.md)
 - [exclusive_range_pattern](exclusive-range-pattern.md)
-- [field_init_shorthand](field-init-shorthand.md)
+- [fd](fd.md)
+- [fd_read](fd-read.md)
+- [fixed_size_array](fixed-size-array.md)
+- [float_extras](float-extras.md)
+- [flt2dec](flt2dec.md)
+- [fmt_flags_align](fmt-flags-align.md)
+- [fmt_internals](fmt-internals.md)
+- [fn_traits](fn-traits.md)
+- [fnbox](fnbox.md)
 - [fundamental](fundamental.md)
+- [fused](fused.md)
+- [future_atomic_orderings](future-atomic-orderings.md)
 - [generic_param_attrs](generic-param-attrs.md)
+- [get_type_id](get-type-id.md)
+- [heap_api](heap-api.md)
+- [i128](i128.md)
 - [i128_type](i128-type.md)
+- [inclusive_range](inclusive-range.md)
 - [inclusive_range_syntax](inclusive-range-syntax.md)
+- [int_error_internals](int-error-internals.md)
+- [integer_atomics](integer-atomics.md)
+- [into_boxed_c_str](into-boxed-c-str.md)
+- [into_boxed_os_str](into-boxed-os-str.md)
+- [into_boxed_path](into-boxed-path.md)
 - [intrinsics](intrinsics.md)
+- [io](io.md)
+- [io_error_internals](io-error-internals.md)
+- [ip](ip.md)
+- [is_unique](is-unique.md)
+- [iter_rfind](iter-rfind.md)
 - [lang_items](lang-items.md)
+- [libstd_io_internals](libstd-io-internals.md)
+- [libstd_sys_internals](libstd-sys-internals.md)
+- [libstd_thread_internals](libstd-thread-internals.md)
 - [link_args](link-args.md)
 - [link_cfg](link-cfg.md)
 - [link_llvm_intrinsics](link-llvm-intrinsics.md)
 - [linkage](linkage.md)
+- [linked_list_extras](linked-list-extras.md)
 - [log_syntax](log-syntax.md)
+- [lookup_host](lookup-host.md)
 - [loop_break_value](loop-break-value.md)
 - [macro_reexport](macro-reexport.md)
 - [main](main.md)
+- [map_entry_recover_keys](map-entry-recover-keys.md)
+- [mpsc_select](mpsc-select.md)
+- [n16](n16.md)
 - [naked_functions](naked-functions.md)
 - [needs_allocator](needs-allocator.md)
 - [needs_panic_runtime](needs-panic-runtime.md)
 - [never_type](never-type.md)
+- [never_type_impls](never-type-impls.md)
 - [no_core](no-core.md)
 - [no_debug](no-debug.md)
 - [non_ascii_idents](non-ascii-idents.md)
+- [nonzero](nonzero.md)
 - [omit_gdb_pretty_printer_section](omit-gdb-pretty-printer-section.md)
 - [on_unimplemented](on-unimplemented.md)
+- [once_poison](once-poison.md)
+- [oom](oom.md)
 - [optin_builtin_traits](optin-builtin-traits.md)
+- [option_entry](option-entry.md)
+- [osstring_shrink_to_fit](osstring-shrink-to-fit.md)
+- [panic_abort](panic-abort.md)
 - [panic_runtime](panic-runtime.md)
+- [panic_unwind](panic-unwind.md)
+- [pattern](pattern.md)
+- [peek](peek.md)
+- [placement_in](placement-in.md)
 - [placement_in_syntax](placement-in-syntax.md)
+- [placement_new_protocol](placement-new-protocol.md)
 - [platform_intrinsics](platform-intrinsics.md)
 - [plugin](plugin.md)
 - [plugin_registrar](plugin-registrar.md)
 - [prelude_import](prelude-import.md)
+- [print](print.md)
 - [proc_macro](proc-macro.md)
+- [proc_macro_internals](proc-macro-internals.md)
+- [process_try_wait](process-try-wait.md)
+- [pub_restricted](pub-restricted.md)
+- [question_mark_carrier](question-mark-carrier.md)
 - [quote](quote.md)
+- [rand](rand.md)
+- [range_contains](range-contains.md)
+- [raw](raw.md)
+- [rc_would_unwrap](rc-would-unwrap.md)
 - [relaxed_adts](relaxed-adts.md)
 - [repr_simd](repr-simd.md)
+- [retain_hash_collection](retain-hash-collection.md)
+- [rt](rt.md)
 - [rustc_attrs](rustc-attrs.md)
 - [rustc_diagnostic_macros](rustc-diagnostic-macros.md)
+- [rustc_private](rustc-private.md)
+- [rustdoc](rustdoc.md)
 - [rvalue_static_promotion](rvalue-static-promotion.md)
 - [sanitizer_runtime](sanitizer-runtime.md)
+- [sanitizer_runtime_lib](sanitizer-runtime-lib.md)
+- [set_stdio](set-stdio.md)
+- [shared](shared.md)
 - [simd](simd.md)
 - [simd_ffi](simd-ffi.md)
+- [sip_hash_13](sip-hash-13.md)
+- [slice_concat_ext](slice-concat-ext.md)
+- [slice_get_slice](slice-get-slice.md)
 - [slice_patterns](slice-patterns.md)
+- [sort_internals](sort-internals.md)
 - [sort_unstable](sort-unstable.md)
 - [specialization](specialization.md)
 - [staged_api](staged-api.md)
 - [start](start.md)
 - [static_nobundle](static-nobundle.md)
-- [static_recursion](static-recursion.md)
+- [step_by](step-by.md)
+- [step_trait](step-trait.md)
 - [stmt_expr_attributes](stmt-expr-attributes.md)
+- [str_escape](str-escape.md)
+- [str_internals](str-internals.md)
 - [struct_field_attributes](struct-field-attributes.md)
 - [structural_match](structural-match.md)
 - [target_feature](target-feature.md)
 - [test](test.md)
+- [thread_id](thread-id.md)
 - [thread_local](thread-local.md)
+- [thread_local_internals](thread-local-internals.md)
+- [thread_local_state](thread-local-state.md)
 - [trace_macros](trace-macros.md)
+- [trusted_len](trusted-len.md)
+- [try_from](try-from.md)
 - [type_ascription](type-ascription.md)
 - [unboxed_closures](unboxed-closures.md)
+- [unicode](unicode.md)
+- [unique](unique.md)
+- [unsize](unsize.md)
 - [untagged_unions](untagged-unions.md)
 - [unwind_attributes](unwind-attributes.md)
+- [update_panic_count](update-panic-count.md)
 - [use_extern_macros](use-extern-macros.md)
+- [utf8_error_error_len](utf8-error-error-len.md)
+- [vec_remove_item](vec-remove-item.md)
+- [windows_c](windows-c.md)
+- [windows_handle](windows-handle.md)
+- [windows_net](windows-net.md)
+- [windows_stdio](windows-stdio.md)
 - [windows_subsystem](windows-subsystem.md)
+- [zero_one](zero-one.md)
diff --git a/src/doc/unstable-book/src/alloc.md b/src/doc/unstable-book/src/alloc.md
new file mode 100644 (file)
index 0000000..47eeb08
--- /dev/null
@@ -0,0 +1,7 @@
+# `alloc`
+
+The tracking issue for this feature is: [#27783]
+
+[#27783]: https://github.com/rust-lang/rust/issues/27783
+
+------------------------
diff --git a/src/doc/unstable-book/src/as-unsafe-cell.md b/src/doc/unstable-book/src/as-unsafe-cell.md
new file mode 100644 (file)
index 0000000..79d7a7c
--- /dev/null
@@ -0,0 +1,7 @@
+# `as_unsafe_cell`
+
+The tracking issue for this feature is: [#27708]
+
+[#27708]: https://github.com/rust-lang/rust/issues/27708
+
+------------------------
diff --git a/src/doc/unstable-book/src/ascii-ctype.md b/src/doc/unstable-book/src/ascii-ctype.md
new file mode 100644 (file)
index 0000000..e253b4d
--- /dev/null
@@ -0,0 +1,5 @@
+# `ascii_ctype`
+
+The tracking issue for this feature is: [#39658]
+
+[#39658]: https://github.com/rust-lang/rust/issues/39658
diff --git a/src/doc/unstable-book/src/binary-heap-extras.md b/src/doc/unstable-book/src/binary-heap-extras.md
new file mode 100644 (file)
index 0000000..aa535f3
--- /dev/null
@@ -0,0 +1,7 @@
+# `binary_heap_extras`
+
+The tracking issue for this feature is: [#28147]
+
+[#28147]: https://github.com/rust-lang/rust/issues/28147
+
+------------------------
diff --git a/src/doc/unstable-book/src/binary-heap-peek-mut-pop.md b/src/doc/unstable-book/src/binary-heap-peek-mut-pop.md
new file mode 100644 (file)
index 0000000..f3863ab
--- /dev/null
@@ -0,0 +1,7 @@
+# `binary_heap_peek_mut_pop`
+
+The tracking issue for this feature is: [#38863]
+
+[#38863]: https://github.com/rust-lang/rust/issues/38863
+
+------------------------
diff --git a/src/doc/unstable-book/src/borrow-state.md b/src/doc/unstable-book/src/borrow-state.md
new file mode 100644 (file)
index 0000000..304b8df
--- /dev/null
@@ -0,0 +1,7 @@
+# `borrow_state`
+
+The tracking issue for this feature is: [#27733]
+
+[#27733]: https://github.com/rust-lang/rust/issues/27733
+
+------------------------
diff --git a/src/doc/unstable-book/src/box-heap.md b/src/doc/unstable-book/src/box-heap.md
new file mode 100644 (file)
index 0000000..0f3f01b
--- /dev/null
@@ -0,0 +1,7 @@
+# `box_heap`
+
+The tracking issue for this feature is: [#27779]
+
+[#27779]: https://github.com/rust-lang/rust/issues/27779
+
+------------------------
diff --git a/src/doc/unstable-book/src/c-void-variant.md b/src/doc/unstable-book/src/c-void-variant.md
new file mode 100644 (file)
index 0000000..a2fdc99
--- /dev/null
@@ -0,0 +1,5 @@
+# `c_void_variant`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/catch-expr.md b/src/doc/unstable-book/src/catch-expr.md
new file mode 100644 (file)
index 0000000..44eb2a6
--- /dev/null
@@ -0,0 +1,7 @@
+# `catch_expr`
+
+The tracking issue for this feature is: [#31436]
+
+[#31436]: https://github.com/rust-lang/rust/issues/31436
+
+------------------------
diff --git a/src/doc/unstable-book/src/char-escape-debug.md b/src/doc/unstable-book/src/char-escape-debug.md
new file mode 100644 (file)
index 0000000..21aa486
--- /dev/null
@@ -0,0 +1,7 @@
+# `char_escape_debug`
+
+The tracking issue for this feature is: [#35068]
+
+[#35068]: https://github.com/rust-lang/rust/issues/35068
+
+------------------------
diff --git a/src/doc/unstable-book/src/closure-to-fn-coercion.md b/src/doc/unstable-book/src/closure-to-fn-coercion.md
new file mode 100644 (file)
index 0000000..4e3b735
--- /dev/null
@@ -0,0 +1,7 @@
+# `closure_to_fn_coercion`
+
+The tracking issue for this feature is: [#39817]
+
+[#39817]: https://github.com/rust-lang/rust/issues/39817
+
+------------------------
diff --git a/src/doc/unstable-book/src/coerce-unsized.md b/src/doc/unstable-book/src/coerce-unsized.md
new file mode 100644 (file)
index 0000000..078d3fa
--- /dev/null
@@ -0,0 +1,7 @@
+# `coerce_unsized`
+
+The tracking issue for this feature is: [#27732]
+
+[#27732]: https://github.com/rust-lang/rust/issues/27732
+
+------------------------
diff --git a/src/doc/unstable-book/src/collection-placement.md b/src/doc/unstable-book/src/collection-placement.md
new file mode 100644 (file)
index 0000000..268ca6e
--- /dev/null
@@ -0,0 +1,7 @@
+# `collection_placement`
+
+The tracking issue for this feature is: [#30172]
+
+[#30172]: https://github.com/rust-lang/rust/issues/30172
+
+------------------------
diff --git a/src/doc/unstable-book/src/collections-range.md b/src/doc/unstable-book/src/collections-range.md
new file mode 100644 (file)
index 0000000..ea4f999
--- /dev/null
@@ -0,0 +1,7 @@
+# `collections_range`
+
+The tracking issue for this feature is: [#30877]
+
+[#30877]: https://github.com/rust-lang/rust/issues/30877
+
+------------------------
diff --git a/src/doc/unstable-book/src/collections.md b/src/doc/unstable-book/src/collections.md
new file mode 100644 (file)
index 0000000..5c93783
--- /dev/null
@@ -0,0 +1,5 @@
+# `collections`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/command-envs.md b/src/doc/unstable-book/src/command-envs.md
new file mode 100644 (file)
index 0000000..0ab89e2
--- /dev/null
@@ -0,0 +1,7 @@
+# `command_envs`
+
+The tracking issue for this feature is: [#38526]
+
+[#38526]: https://github.com/rust-lang/rust/issues/38526
+
+------------------------
diff --git a/src/doc/unstable-book/src/compiler-builtins-lib.md b/src/doc/unstable-book/src/compiler-builtins-lib.md
new file mode 100644 (file)
index 0000000..8986b96
--- /dev/null
@@ -0,0 +1,5 @@
+# `compiler_builtins_lib`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/concat-idents-macro.md b/src/doc/unstable-book/src/concat-idents-macro.md
new file mode 100644 (file)
index 0000000..ac2fdd4
--- /dev/null
@@ -0,0 +1,7 @@
+# `concat_idents_macro`
+
+The tracking issue for this feature is: [#29599]
+
+[#29599]: https://github.com/rust-lang/rust/issues/29599
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-char-ext.md b/src/doc/unstable-book/src/core-char-ext.md
new file mode 100644 (file)
index 0000000..d37d6b5
--- /dev/null
@@ -0,0 +1,7 @@
+# `core_char_ext`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-float.md b/src/doc/unstable-book/src/core-float.md
new file mode 100644 (file)
index 0000000..194b260
--- /dev/null
@@ -0,0 +1,7 @@
+# `core_float`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-intrinsics.md b/src/doc/unstable-book/src/core-intrinsics.md
new file mode 100644 (file)
index 0000000..28ad352
--- /dev/null
@@ -0,0 +1,5 @@
+# `core_intrinsics`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-panic.md b/src/doc/unstable-book/src/core-panic.md
new file mode 100644 (file)
index 0000000..c197588
--- /dev/null
@@ -0,0 +1,5 @@
+# `core_panic`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-private-bignum.md b/src/doc/unstable-book/src/core-private-bignum.md
new file mode 100644 (file)
index 0000000..f85811c
--- /dev/null
@@ -0,0 +1,5 @@
+# `core_private_bignum`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-private-diy-float.md b/src/doc/unstable-book/src/core-private-diy-float.md
new file mode 100644 (file)
index 0000000..8465921
--- /dev/null
@@ -0,0 +1,5 @@
+# `core_private_diy_float`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-slice-ext.md b/src/doc/unstable-book/src/core-slice-ext.md
new file mode 100644 (file)
index 0000000..c50d44a
--- /dev/null
@@ -0,0 +1,7 @@
+# `core_slice_ext`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
diff --git a/src/doc/unstable-book/src/core-str-ext.md b/src/doc/unstable-book/src/core-str-ext.md
new file mode 100644 (file)
index 0000000..08c68f1
--- /dev/null
@@ -0,0 +1,7 @@
+# `core_str_ext`
+
+The tracking issue for this feature is: [#32110]
+
+[#32110]: https://github.com/rust-lang/rust/issues/32110
+
+------------------------
diff --git a/src/doc/unstable-book/src/dec2flt.md b/src/doc/unstable-book/src/dec2flt.md
new file mode 100644 (file)
index 0000000..311ab4a
--- /dev/null
@@ -0,0 +1,5 @@
+# `dec2flt`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/decode-utf8.md b/src/doc/unstable-book/src/decode-utf8.md
new file mode 100644 (file)
index 0000000..b96854e
--- /dev/null
@@ -0,0 +1,7 @@
+# `decode_utf8`
+
+The tracking issue for this feature is: [#27783]
+
+[#27783]: https://github.com/rust-lang/rust/issues/27783
+
+------------------------
diff --git a/src/doc/unstable-book/src/derive-clone-copy.md b/src/doc/unstable-book/src/derive-clone-copy.md
new file mode 100644 (file)
index 0000000..cc60391
--- /dev/null
@@ -0,0 +1,5 @@
+# `derive_clone_copy`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/derive-eq.md b/src/doc/unstable-book/src/derive-eq.md
new file mode 100644 (file)
index 0000000..68a275f
--- /dev/null
@@ -0,0 +1,5 @@
+# `derive_eq`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/discriminant-value.md b/src/doc/unstable-book/src/discriminant-value.md
new file mode 100644 (file)
index 0000000..2f99f5e
--- /dev/null
@@ -0,0 +1,7 @@
+# `discriminant_value`
+
+The tracking issue for this feature is: [#24263]
+
+[#24263]: https://github.com/rust-lang/rust/issues/24263
+
+------------------------
diff --git a/src/doc/unstable-book/src/enumset.md b/src/doc/unstable-book/src/enumset.md
new file mode 100644 (file)
index 0000000..24c8d8f
--- /dev/null
@@ -0,0 +1,7 @@
+# `enumset`
+
+The tracking issue for this feature is: [#37966]
+
+[#37966]: https://github.com/rust-lang/rust/issues/37966
+
+------------------------
diff --git a/src/doc/unstable-book/src/error-type-id.md b/src/doc/unstable-book/src/error-type-id.md
new file mode 100644 (file)
index 0000000..be7a3ff
--- /dev/null
@@ -0,0 +1,7 @@
+# `error_type_id`
+
+The tracking issue for this feature is: [#27745]
+
+[#27745]: https://github.com/rust-lang/rust/issues/27745
+
+------------------------
diff --git a/src/doc/unstable-book/src/exact-size-is-empty.md b/src/doc/unstable-book/src/exact-size-is-empty.md
new file mode 100644 (file)
index 0000000..200ec38
--- /dev/null
@@ -0,0 +1,7 @@
+# `exact_size_is_empty`
+
+The tracking issue for this feature is: [#35428]
+
+[#35428]: https://github.com/rust-lang/rust/issues/35428
+
+------------------------
diff --git a/src/doc/unstable-book/src/fd-read.md b/src/doc/unstable-book/src/fd-read.md
new file mode 100644 (file)
index 0000000..e78d433
--- /dev/null
@@ -0,0 +1,5 @@
+# `fd_read`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/fd.md b/src/doc/unstable-book/src/fd.md
new file mode 100644 (file)
index 0000000..0414244
--- /dev/null
@@ -0,0 +1,5 @@
+# `fd`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/field-init-shorthand.md b/src/doc/unstable-book/src/field-init-shorthand.md
deleted file mode 100644 (file)
index e737dba..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# `field_init_shorthand`
-
-The tracking issue for this feature is: [#37340]
-
-[#37340]: https://github.com/rust-lang/rust/issues/37340
-
-------------------------
-
-
-
diff --git a/src/doc/unstable-book/src/fixed-size-array.md b/src/doc/unstable-book/src/fixed-size-array.md
new file mode 100644 (file)
index 0000000..9e24e6a
--- /dev/null
@@ -0,0 +1,7 @@
+# `fixed_size_array`
+
+The tracking issue for this feature is: [#27778]
+
+[#27778]: https://github.com/rust-lang/rust/issues/27778
+
+------------------------
diff --git a/src/doc/unstable-book/src/float-extras.md b/src/doc/unstable-book/src/float-extras.md
new file mode 100644 (file)
index 0000000..ff2d20a
--- /dev/null
@@ -0,0 +1,7 @@
+# `float_extras`
+
+The tracking issue for this feature is: [#27752]
+
+[#27752]: https://github.com/rust-lang/rust/issues/27752
+
+------------------------
diff --git a/src/doc/unstable-book/src/flt2dec.md b/src/doc/unstable-book/src/flt2dec.md
new file mode 100644 (file)
index 0000000..15e62a3
--- /dev/null
@@ -0,0 +1,5 @@
+# `flt2dec`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/fmt-flags-align.md b/src/doc/unstable-book/src/fmt-flags-align.md
new file mode 100644 (file)
index 0000000..755263b
--- /dev/null
@@ -0,0 +1,7 @@
+# `fmt_flags_align`
+
+The tracking issue for this feature is: [#27726]
+
+[#27726]: https://github.com/rust-lang/rust/issues/27726
+
+------------------------
diff --git a/src/doc/unstable-book/src/fmt-internals.md b/src/doc/unstable-book/src/fmt-internals.md
new file mode 100644 (file)
index 0000000..7cbe3c8
--- /dev/null
@@ -0,0 +1,5 @@
+# `fmt_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/fn-traits.md b/src/doc/unstable-book/src/fn-traits.md
new file mode 100644 (file)
index 0000000..3942cda
--- /dev/null
@@ -0,0 +1,7 @@
+# `fn_traits`
+
+The tracking issue for this feature is: [#29625]
+
+[#29625]: https://github.com/rust-lang/rust/issues/29625
+
+------------------------
diff --git a/src/doc/unstable-book/src/fnbox.md b/src/doc/unstable-book/src/fnbox.md
new file mode 100644 (file)
index 0000000..a9b74d4
--- /dev/null
@@ -0,0 +1,7 @@
+# `fnbox`
+
+The tracking issue for this feature is: [#28796]
+
+[#28796]: https://github.com/rust-lang/rust/issues/28796
+
+------------------------
diff --git a/src/doc/unstable-book/src/fused.md b/src/doc/unstable-book/src/fused.md
new file mode 100644 (file)
index 0000000..460555b
--- /dev/null
@@ -0,0 +1,7 @@
+# `fused`
+
+The tracking issue for this feature is: [#35602]
+
+[#35602]: https://github.com/rust-lang/rust/issues/35602
+
+------------------------
diff --git a/src/doc/unstable-book/src/future-atomic-orderings.md b/src/doc/unstable-book/src/future-atomic-orderings.md
new file mode 100644 (file)
index 0000000..40c2ef2
--- /dev/null
@@ -0,0 +1,5 @@
+# `future_atomic_orderings`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/get-type-id.md b/src/doc/unstable-book/src/get-type-id.md
new file mode 100644 (file)
index 0000000..afdb030
--- /dev/null
@@ -0,0 +1,7 @@
+# `get_type_id`
+
+The tracking issue for this feature is: [#27745]
+
+[#27745]: https://github.com/rust-lang/rust/issues/27745
+
+------------------------
diff --git a/src/doc/unstable-book/src/heap-api.md b/src/doc/unstable-book/src/heap-api.md
new file mode 100644 (file)
index 0000000..01404e4
--- /dev/null
@@ -0,0 +1,7 @@
+# `heap_api`
+
+The tracking issue for this feature is: [#27700]
+
+[#27700]: https://github.com/rust-lang/rust/issues/27700
+
+------------------------
diff --git a/src/doc/unstable-book/src/i128.md b/src/doc/unstable-book/src/i128.md
new file mode 100644 (file)
index 0000000..a1a7ce8
--- /dev/null
@@ -0,0 +1,7 @@
+# `i128`
+
+The tracking issue for this feature is: [#35118]
+
+[#35118]: https://github.com/rust-lang/rust/issues/35118
+
+------------------------
index 74d85536399d72f93096fce8091cb67d6167ddbe..255445c318dca7c830e4e325df5155715259ba44 100644 (file)
@@ -6,5 +6,15 @@ The tracking issue for this feature is: [#28237]
 
 ------------------------
 
+To get a range that goes from 0 to 10 and includes the value 10, you
+can write `0...10`:
 
+```rust
+#![feature(inclusive_range_syntax)]
 
+fn main() {
+    for i in 0...10 {
+        println!("{}", i);
+    }
+}
+```
diff --git a/src/doc/unstable-book/src/inclusive-range.md b/src/doc/unstable-book/src/inclusive-range.md
new file mode 100644 (file)
index 0000000..2e88e20
--- /dev/null
@@ -0,0 +1,7 @@
+# `inclusive_range`
+
+The tracking issue for this feature is: [#28237]
+
+[#28237]: https://github.com/rust-lang/rust/issues/28237
+
+------------------------
diff --git a/src/doc/unstable-book/src/int-error-internals.md b/src/doc/unstable-book/src/int-error-internals.md
new file mode 100644 (file)
index 0000000..402e4fa
--- /dev/null
@@ -0,0 +1,5 @@
+# `int_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/integer-atomics.md b/src/doc/unstable-book/src/integer-atomics.md
new file mode 100644 (file)
index 0000000..50db9fd
--- /dev/null
@@ -0,0 +1,7 @@
+# `integer_atomics`
+
+The tracking issue for this feature is: [#32976]
+
+[#32976]: https://github.com/rust-lang/rust/issues/32976
+
+------------------------
diff --git a/src/doc/unstable-book/src/into-boxed-c-str.md b/src/doc/unstable-book/src/into-boxed-c-str.md
new file mode 100644 (file)
index 0000000..0d94b4f
--- /dev/null
@@ -0,0 +1,7 @@
+# `into_boxed_c_str`
+
+The tracking issue for this feature is: [#40380]
+
+[#40380]: https://github.com/rust-lang/rust/issues/40380
+
+------------------------
diff --git a/src/doc/unstable-book/src/into-boxed-os-str.md b/src/doc/unstable-book/src/into-boxed-os-str.md
new file mode 100644 (file)
index 0000000..7636e20
--- /dev/null
@@ -0,0 +1,7 @@
+# `into_boxed_os_str`
+
+The tracking issue for this feature is: [#into_boxed_os_str]
+
+[#into_boxed_os_str]: https://github.com/rust-lang/rust/issues/40380
+
+------------------------
diff --git a/src/doc/unstable-book/src/into-boxed-path.md b/src/doc/unstable-book/src/into-boxed-path.md
new file mode 100644 (file)
index 0000000..754c604
--- /dev/null
@@ -0,0 +1,7 @@
+# `into_boxed_path`
+
+The tracking issue for this feature is: [#40380]
+
+[#40380]: https://github.com/rust-lang/rust/issues/40380
+
+------------------------
diff --git a/src/doc/unstable-book/src/io-error-internals.md b/src/doc/unstable-book/src/io-error-internals.md
new file mode 100644 (file)
index 0000000..5bee18d
--- /dev/null
@@ -0,0 +1,5 @@
+# `io_error_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/io.md b/src/doc/unstable-book/src/io.md
new file mode 100644 (file)
index 0000000..ed6cae2
--- /dev/null
@@ -0,0 +1,7 @@
+# `io`
+
+The tracking issue for this feature is: [#27802]
+
+[#27802]: https://github.com/rust-lang/rust/issues/27802
+
+------------------------
diff --git a/src/doc/unstable-book/src/ip.md b/src/doc/unstable-book/src/ip.md
new file mode 100644 (file)
index 0000000..7e7d52a
--- /dev/null
@@ -0,0 +1,7 @@
+# `ip`
+
+The tracking issue for this feature is: [#27709]
+
+[#27709]: https://github.com/rust-lang/rust/issues/27709
+
+------------------------
diff --git a/src/doc/unstable-book/src/is-unique.md b/src/doc/unstable-book/src/is-unique.md
new file mode 100644 (file)
index 0000000..6070006
--- /dev/null
@@ -0,0 +1,7 @@
+# `is_unique`
+
+The tracking issue for this feature is: [#28356]
+
+[#28356]: https://github.com/rust-lang/rust/issues/28356
+
+------------------------
diff --git a/src/doc/unstable-book/src/iter-rfind.md b/src/doc/unstable-book/src/iter-rfind.md
new file mode 100644 (file)
index 0000000..4447144
--- /dev/null
@@ -0,0 +1,7 @@
+# `iter_rfind`
+
+The tracking issue for this feature is: [#39480]
+
+[#39480]: https://github.com/rust-lang/rust/issues/39480
+
+------------------------
diff --git a/src/doc/unstable-book/src/libstd-io-internals.md b/src/doc/unstable-book/src/libstd-io-internals.md
new file mode 100644 (file)
index 0000000..8bcc276
--- /dev/null
@@ -0,0 +1,5 @@
+# `libstd_io_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/libstd-sys-internals.md b/src/doc/unstable-book/src/libstd-sys-internals.md
new file mode 100644 (file)
index 0000000..1b53faa
--- /dev/null
@@ -0,0 +1,5 @@
+# `libstd_sys_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/libstd-thread-internals.md b/src/doc/unstable-book/src/libstd-thread-internals.md
new file mode 100644 (file)
index 0000000..b682d12
--- /dev/null
@@ -0,0 +1,5 @@
+# `libstd_thread_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/linked-list-extras.md b/src/doc/unstable-book/src/linked-list-extras.md
new file mode 100644 (file)
index 0000000..be3b96a
--- /dev/null
@@ -0,0 +1,7 @@
+# `linked_list_extras`
+
+The tracking issue for this feature is: [#27794]
+
+[#27794]: https://github.com/rust-lang/rust/issues/27794
+
+------------------------
diff --git a/src/doc/unstable-book/src/lookup-host.md b/src/doc/unstable-book/src/lookup-host.md
new file mode 100644 (file)
index 0000000..b60e7a0
--- /dev/null
@@ -0,0 +1,7 @@
+# `lookup_host`
+
+The tracking issue for this feature is: [#27705]
+
+[#27705]: https://github.com/rust-lang/rust/issues/27705
+
+------------------------
diff --git a/src/doc/unstable-book/src/map-entry-recover-keys.md b/src/doc/unstable-book/src/map-entry-recover-keys.md
new file mode 100644 (file)
index 0000000..2d15aa0
--- /dev/null
@@ -0,0 +1,5 @@
+# `map_entry_recover_keys`
+
+The tracking issue for this feature is: [#34285]
+
+[#34285]: https://github.com/rust-lang/rust/issues/34285
diff --git a/src/doc/unstable-book/src/mpsc-select.md b/src/doc/unstable-book/src/mpsc-select.md
new file mode 100644 (file)
index 0000000..1405b6c
--- /dev/null
@@ -0,0 +1,5 @@
+# `mpsc_select`
+
+The tracking issue for this feature is: [#27800]
+
+[#27800]: https://github.com/rust-lang/rust/issues/27800
diff --git a/src/doc/unstable-book/src/n16.md b/src/doc/unstable-book/src/n16.md
new file mode 100644 (file)
index 0000000..e556ada
--- /dev/null
@@ -0,0 +1,5 @@
+# `n16`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/never-type-impls.md b/src/doc/unstable-book/src/never-type-impls.md
new file mode 100644 (file)
index 0000000..4063cd0
--- /dev/null
@@ -0,0 +1,7 @@
+# `never_type_impls`
+
+The tracking issue for this feature is: [#35121]
+
+[#35121]: https://github.com/rust-lang/rust/issues/35121
+
+------------------------
diff --git a/src/doc/unstable-book/src/nonzero.md b/src/doc/unstable-book/src/nonzero.md
new file mode 100644 (file)
index 0000000..f200f8e
--- /dev/null
@@ -0,0 +1,7 @@
+# `nonzero`
+
+The tracking issue for this feature is: [#27730]
+
+[#27730]: https://github.com/rust-lang/rust/issues/27730
+
+------------------------
diff --git a/src/doc/unstable-book/src/once-poison.md b/src/doc/unstable-book/src/once-poison.md
new file mode 100644 (file)
index 0000000..3c16caf
--- /dev/null
@@ -0,0 +1,7 @@
+# `once_poison`
+
+The tracking issue for this feature is: [#33577]
+
+[#33577]: https://github.com/rust-lang/rust/issues/33577
+
+------------------------
diff --git a/src/doc/unstable-book/src/oom.md b/src/doc/unstable-book/src/oom.md
new file mode 100644 (file)
index 0000000..908caeb
--- /dev/null
@@ -0,0 +1,7 @@
+# `oom`
+
+The tracking issue for this feature is: [#27700]
+
+[#27700]: https://github.com/rust-lang/rust/issues/27700
+
+------------------------
diff --git a/src/doc/unstable-book/src/option-entry.md b/src/doc/unstable-book/src/option-entry.md
new file mode 100644 (file)
index 0000000..edb4efc
--- /dev/null
@@ -0,0 +1,7 @@
+# `option_entry`
+
+The tracking issue for this feature is: [#39288]
+
+[#39288]: https://github.com/rust-lang/rust/issues/39288
+
+------------------------
diff --git a/src/doc/unstable-book/src/osstring-shrink-to-fit.md b/src/doc/unstable-book/src/osstring-shrink-to-fit.md
new file mode 100644 (file)
index 0000000..21dc7d0
--- /dev/null
@@ -0,0 +1,7 @@
+# `osstring_shrink_to_fit`
+
+The tracking issue for this feature is: [#40421]
+
+[#40421]: https://github.com/rust-lang/rust/issues/40421
+
+------------------------
diff --git a/src/doc/unstable-book/src/panic-abort.md b/src/doc/unstable-book/src/panic-abort.md
new file mode 100644 (file)
index 0000000..07a9576
--- /dev/null
@@ -0,0 +1,7 @@
+# `panic_abort`
+
+The tracking issue for this feature is: [#32837]
+
+[#32837]: https://github.com/rust-lang/rust/issues/32837
+
+------------------------
diff --git a/src/doc/unstable-book/src/panic-unwind.md b/src/doc/unstable-book/src/panic-unwind.md
new file mode 100644 (file)
index 0000000..840e492
--- /dev/null
@@ -0,0 +1,7 @@
+# `panic_unwind`
+
+The tracking issue for this feature is: [#32837]
+
+[#32837]: https://github.com/rust-lang/rust/issues/32837
+
+------------------------
diff --git a/src/doc/unstable-book/src/pattern.md b/src/doc/unstable-book/src/pattern.md
new file mode 100644 (file)
index 0000000..e76ee6b
--- /dev/null
@@ -0,0 +1,7 @@
+# `pattern`
+
+The tracking issue for this feature is: [#27721]
+
+[#27721]: https://github.com/rust-lang/rust/issues/27721
+
+------------------------
diff --git a/src/doc/unstable-book/src/peek.md b/src/doc/unstable-book/src/peek.md
new file mode 100644 (file)
index 0000000..c42b4e9
--- /dev/null
@@ -0,0 +1,7 @@
+# `peek`
+
+The tracking issue for this feature is: [#38980]
+
+[#38980]: https://github.com/rust-lang/rust/issues/38980
+
+------------------------
diff --git a/src/doc/unstable-book/src/placement-in.md b/src/doc/unstable-book/src/placement-in.md
new file mode 100644 (file)
index 0000000..6ff010b
--- /dev/null
@@ -0,0 +1,7 @@
+# `placement_in`
+
+The tracking issue for this feature is: [#27779]
+
+[#27779]: https://github.com/rust-lang/rust/issues/27779
+
+------------------------
diff --git a/src/doc/unstable-book/src/placement-new-protocol.md b/src/doc/unstable-book/src/placement-new-protocol.md
new file mode 100644 (file)
index 0000000..d53225f
--- /dev/null
@@ -0,0 +1,7 @@
+# `placement_new_protocol`
+
+The tracking issue for this feature is: [#27779]
+
+[#27779]: https://github.com/rust-lang/rust/issues/27779
+
+------------------------
diff --git a/src/doc/unstable-book/src/print.md b/src/doc/unstable-book/src/print.md
new file mode 100644 (file)
index 0000000..dc25cb2
--- /dev/null
@@ -0,0 +1,5 @@
+# `print`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/proc-macro-internals.md b/src/doc/unstable-book/src/proc-macro-internals.md
new file mode 100644 (file)
index 0000000..ea087c0
--- /dev/null
@@ -0,0 +1,7 @@
+# `proc_macro_internals`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
diff --git a/src/doc/unstable-book/src/process-try-wait.md b/src/doc/unstable-book/src/process-try-wait.md
new file mode 100644 (file)
index 0000000..3593b64
--- /dev/null
@@ -0,0 +1,7 @@
+# `process_try_wait`
+
+The tracking issue for this feature is: [#38903]
+
+[#38903]: https://github.com/rust-lang/rust/issues/38903
+
+------------------------
diff --git a/src/doc/unstable-book/src/pub-restricted.md b/src/doc/unstable-book/src/pub-restricted.md
new file mode 100644 (file)
index 0000000..6b1e88b
--- /dev/null
@@ -0,0 +1,7 @@
+# `pub_restricted`
+
+The tracking issue for this feature is: [#32409]
+
+[#38356]: https://github.com/rust-lang/rust/issues/32409
+
+------------------------
diff --git a/src/doc/unstable-book/src/question-mark-carrier.md b/src/doc/unstable-book/src/question-mark-carrier.md
new file mode 100644 (file)
index 0000000..56154ac
--- /dev/null
@@ -0,0 +1,7 @@
+# `question_mark_carrier`
+
+The tracking issue for this feature is: [#31436]
+
+[#31436]: https://github.com/rust-lang/rust/issues/31436
+
+------------------------
diff --git a/src/doc/unstable-book/src/rand.md b/src/doc/unstable-book/src/rand.md
new file mode 100644 (file)
index 0000000..d0229d9
--- /dev/null
@@ -0,0 +1,5 @@
+# `rand`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/range-contains.md b/src/doc/unstable-book/src/range-contains.md
new file mode 100644 (file)
index 0000000..ac4581f
--- /dev/null
@@ -0,0 +1,7 @@
+# `range_contains`
+
+The tracking issue for this feature is: [#32311]
+
+[#32311]: https://github.com/rust-lang/rust/issues/32311
+
+------------------------
diff --git a/src/doc/unstable-book/src/raw.md b/src/doc/unstable-book/src/raw.md
new file mode 100644 (file)
index 0000000..d7caf22
--- /dev/null
@@ -0,0 +1,7 @@
+# `raw`
+
+The tracking issue for this feature is: [#27751]
+
+[#27751]: https://github.com/rust-lang/rust/issues/27751
+
+------------------------
diff --git a/src/doc/unstable-book/src/rc-would-unwrap.md b/src/doc/unstable-book/src/rc-would-unwrap.md
new file mode 100644 (file)
index 0000000..462387d
--- /dev/null
@@ -0,0 +1,5 @@
+# `rc_would_unwrap`
+
+The tracking issue for this feature is: [#28356]
+
+[#28356]: https://github.com/rust-lang/rust/issues/28356
diff --git a/src/doc/unstable-book/src/retain-hash-collection.md b/src/doc/unstable-book/src/retain-hash-collection.md
new file mode 100644 (file)
index 0000000..c9ba5ac
--- /dev/null
@@ -0,0 +1,7 @@
+# `retain_hash_collection`
+
+The tracking issue for this feature is: [#36648]
+
+[#36648]: https://github.com/rust-lang/rust/issues/36648
+
+------------------------
diff --git a/src/doc/unstable-book/src/rt.md b/src/doc/unstable-book/src/rt.md
new file mode 100644 (file)
index 0000000..007acc2
--- /dev/null
@@ -0,0 +1,5 @@
+# `rt`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/rustc-private.md b/src/doc/unstable-book/src/rustc-private.md
new file mode 100644 (file)
index 0000000..2453475
--- /dev/null
@@ -0,0 +1,7 @@
+# `rustc_private`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
diff --git a/src/doc/unstable-book/src/rustdoc.md b/src/doc/unstable-book/src/rustdoc.md
new file mode 100644 (file)
index 0000000..c7491ab
--- /dev/null
@@ -0,0 +1,7 @@
+# `rustdoc`
+
+The tracking issue for this feature is: [#27812]
+
+[#27812]: https://github.com/rust-lang/rust/issues/27812
+
+------------------------
diff --git a/src/doc/unstable-book/src/sanitizer-runtime-lib.md b/src/doc/unstable-book/src/sanitizer-runtime-lib.md
new file mode 100644 (file)
index 0000000..82ae67f
--- /dev/null
@@ -0,0 +1,5 @@
+# `sanitizer_runtime_lib`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/set-stdio.md b/src/doc/unstable-book/src/set-stdio.md
new file mode 100644 (file)
index 0000000..7dbdcda
--- /dev/null
@@ -0,0 +1,5 @@
+# `set_stdio`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/shared.md b/src/doc/unstable-book/src/shared.md
new file mode 100644 (file)
index 0000000..b79d121
--- /dev/null
@@ -0,0 +1,7 @@
+# `shared`
+
+The tracking issue for this feature is: [#27730]
+
+[#27730]: https://github.com/rust-lang/rust/issues/27730
+
+------------------------
diff --git a/src/doc/unstable-book/src/sip-hash-13.md b/src/doc/unstable-book/src/sip-hash-13.md
new file mode 100644 (file)
index 0000000..8f69c3a
--- /dev/null
@@ -0,0 +1,7 @@
+# `sip_hash_13`
+
+The tracking issue for this feature is: [#34767]
+
+[#34767]: https://github.com/rust-lang/rust/issues/34767
+
+------------------------
diff --git a/src/doc/unstable-book/src/slice-concat-ext.md b/src/doc/unstable-book/src/slice-concat-ext.md
new file mode 100644 (file)
index 0000000..9ba2de5
--- /dev/null
@@ -0,0 +1,7 @@
+# `slice_concat_ext`
+
+The tracking issue for this feature is: [#27747]
+
+[#27747]: https://github.com/rust-lang/rust/issues/27747
+
+------------------------
diff --git a/src/doc/unstable-book/src/slice-get-slice.md b/src/doc/unstable-book/src/slice-get-slice.md
new file mode 100644 (file)
index 0000000..57e2c14
--- /dev/null
@@ -0,0 +1,7 @@
+# `slice_get_slice`
+
+The tracking issue for this feature is: [#35729]
+
+[#35729]: https://github.com/rust-lang/rust/issues/35729
+
+------------------------
diff --git a/src/doc/unstable-book/src/sort-internals.md b/src/doc/unstable-book/src/sort-internals.md
new file mode 100644 (file)
index 0000000..6f2385e
--- /dev/null
@@ -0,0 +1,5 @@
+# `sort_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/static-recursion.md b/src/doc/unstable-book/src/static-recursion.md
deleted file mode 100644 (file)
index d419ea4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# `static_recursion`
-
-The tracking issue for this feature is: [#29719]
-
-[#29719]: https://github.com/rust-lang/rust/issues/29719
-
-------------------------
-
-
-
diff --git a/src/doc/unstable-book/src/step-by.md b/src/doc/unstable-book/src/step-by.md
new file mode 100644 (file)
index 0000000..b649496
--- /dev/null
@@ -0,0 +1,7 @@
+# `step_by`
+
+The tracking issue for this feature is: [#27741]
+
+[#27741]: https://github.com/rust-lang/rust/issues/27741
+
+------------------------
diff --git a/src/doc/unstable-book/src/step-trait.md b/src/doc/unstable-book/src/step-trait.md
new file mode 100644 (file)
index 0000000..e53ca13
--- /dev/null
@@ -0,0 +1,7 @@
+# `step_trait`
+
+The tracking issue for this feature is: [#27741]
+
+[#27741]: https://github.com/rust-lang/rust/issues/27741
+
+------------------------
diff --git a/src/doc/unstable-book/src/str-escape.md b/src/doc/unstable-book/src/str-escape.md
new file mode 100644 (file)
index 0000000..61e31c8
--- /dev/null
@@ -0,0 +1,7 @@
+# `str_escape`
+
+The tracking issue for this feature is: [#27791]
+
+[#27791]: https://github.com/rust-lang/rust/issues/27791
+
+------------------------
diff --git a/src/doc/unstable-book/src/str-internals.md b/src/doc/unstable-book/src/str-internals.md
new file mode 100644 (file)
index 0000000..af8ef05
--- /dev/null
@@ -0,0 +1,5 @@
+# `str_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/thread-id.md b/src/doc/unstable-book/src/thread-id.md
new file mode 100644 (file)
index 0000000..af3ea99
--- /dev/null
@@ -0,0 +1,7 @@
+# `thread_id`
+
+The tracking issue for this feature is: [#21507]
+
+[#21507]: https://github.com/rust-lang/rust/issues/21507
+
+------------------------
diff --git a/src/doc/unstable-book/src/thread-local-internals.md b/src/doc/unstable-book/src/thread-local-internals.md
new file mode 100644 (file)
index 0000000..e1cdcc3
--- /dev/null
@@ -0,0 +1,5 @@
+# `thread_local_internals`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/thread-local-state.md b/src/doc/unstable-book/src/thread-local-state.md
new file mode 100644 (file)
index 0000000..113c1e9
--- /dev/null
@@ -0,0 +1,7 @@
+# `thread_local_state`
+
+The tracking issue for this feature is: [#27716]
+
+[#27716]: https://github.com/rust-lang/rust/issues/27716
+
+------------------------
diff --git a/src/doc/unstable-book/src/trusted-len.md b/src/doc/unstable-book/src/trusted-len.md
new file mode 100644 (file)
index 0000000..80213cf
--- /dev/null
@@ -0,0 +1,7 @@
+# `trusted_len`
+
+The tracking issue for this feature is: [#37572]
+
+[#37572]: https://github.com/rust-lang/rust/issues/37572
+
+------------------------
diff --git a/src/doc/unstable-book/src/try-from.md b/src/doc/unstable-book/src/try-from.md
new file mode 100644 (file)
index 0000000..d763caf
--- /dev/null
@@ -0,0 +1,7 @@
+# `try_from`
+
+The tracking issue for this feature is: [#33417]
+
+[#33417]: https://github.com/rust-lang/rust/issues/33417
+
+------------------------
diff --git a/src/doc/unstable-book/src/unicode.md b/src/doc/unstable-book/src/unicode.md
new file mode 100644 (file)
index 0000000..9fecec2
--- /dev/null
@@ -0,0 +1,7 @@
+# `unicode`
+
+The tracking issue for this feature is: [#27783]
+
+[#27783]: https://github.com/rust-lang/rust/issues/27783
+
+------------------------
diff --git a/src/doc/unstable-book/src/unique.md b/src/doc/unstable-book/src/unique.md
new file mode 100644 (file)
index 0000000..99a3490
--- /dev/null
@@ -0,0 +1,7 @@
+# `unique`
+
+The tracking issue for this feature is: [#27730]
+
+[#27730]: https://github.com/rust-lang/rust/issues/27730
+
+------------------------
diff --git a/src/doc/unstable-book/src/unsize.md b/src/doc/unstable-book/src/unsize.md
new file mode 100644 (file)
index 0000000..92807e2
--- /dev/null
@@ -0,0 +1,7 @@
+# `unsize`
+
+The tracking issue for this feature is: [#27732]
+
+[#27732]: https://github.com/rust-lang/rust/issues/27732
+
+------------------------
diff --git a/src/doc/unstable-book/src/update-panic-count.md b/src/doc/unstable-book/src/update-panic-count.md
new file mode 100644 (file)
index 0000000..d315647
--- /dev/null
@@ -0,0 +1,5 @@
+# `update_panic_count`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/utf8-error-error-len.md b/src/doc/unstable-book/src/utf8-error-error-len.md
new file mode 100644 (file)
index 0000000..1c14a5a
--- /dev/null
@@ -0,0 +1,7 @@
+# `utf8_error_error_len`
+
+The tracking issue for this feature is: [#40494]
+
+[#40494]: https://github.com/rust-lang/rust/issues/40494
+
+------------------------
diff --git a/src/doc/unstable-book/src/vec-remove-item.md b/src/doc/unstable-book/src/vec-remove-item.md
new file mode 100644 (file)
index 0000000..2b8c9f0
--- /dev/null
@@ -0,0 +1,7 @@
+# `vec_remove_item`
+
+The tracking issue for this feature is: [#40062]
+
+[#40062]: https://github.com/rust-lang/rust/issues/40062
+
+------------------------
diff --git a/src/doc/unstable-book/src/windows-c.md b/src/doc/unstable-book/src/windows-c.md
new file mode 100644 (file)
index 0000000..3f833eb
--- /dev/null
@@ -0,0 +1,5 @@
+# `windows_c`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/windows-handle.md b/src/doc/unstable-book/src/windows-handle.md
new file mode 100644 (file)
index 0000000..f47a842
--- /dev/null
@@ -0,0 +1,5 @@
+# `windows_handle`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/windows-net.md b/src/doc/unstable-book/src/windows-net.md
new file mode 100644 (file)
index 0000000..174960d
--- /dev/null
@@ -0,0 +1,5 @@
+# `windows_net`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/windows-stdio.md b/src/doc/unstable-book/src/windows-stdio.md
new file mode 100644 (file)
index 0000000..4d36144
--- /dev/null
@@ -0,0 +1,5 @@
+# `windows_stdio`
+
+This feature is internal to the Rust compiler and is not intended for general use.
+
+------------------------
diff --git a/src/doc/unstable-book/src/zero-one.md b/src/doc/unstable-book/src/zero-one.md
new file mode 100644 (file)
index 0000000..4d1cf38
--- /dev/null
@@ -0,0 +1,7 @@
+# `zero_one`
+
+The tracking issue for this feature is: [#27739]
+
+[#27739]: https://github.com/rust-lang/rust/issues/27739
+
+------------------------
index 919fc98e438c52a0ceb21bf41f38d2fecd48a274..bd28a63c5f4dfb947edce379ac569c3c1af43519 100644 (file)
@@ -196,7 +196,7 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>, surrogate_
     let toknum = &s[content_end + 3 .. toknum_end];
 
     let not_found = format!("didn't find token {:?} in the map", toknum);
-    let proto_tok = tokens.get(toknum).expect(&not_found[..]);
+    let proto_tok = tokens.get(toknum).expect(&not_found);
 
     let nm = Symbol::intern(content);
 
@@ -304,14 +304,14 @@ fn next(r: &mut lexer::StringReader) -> TokenAndSpan {
     let mut token_file = File::open(&Path::new(&args.next().unwrap())).unwrap();
     let mut token_list = String::new();
     token_file.read_to_string(&mut token_list).unwrap();
-    let token_map = parse_token_list(&token_list[..]);
+    let token_map = parse_token_list(&token_list);
 
     let stdin = std::io::stdin();
     let lock = stdin.lock();
     let lines = lock.lines();
     let antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().trim(),
                                                        &token_map,
-                                                       &surrogate_pairs_pos[..],
+                                                       &surrogate_pairs_pos,
                                                        has_bom));
 
     for antlr_tok in antlr_tokens {
index bed216ba3d111b83dd10fac0657854d2de7c08b1..dcacef4f0f0d5f301cb189c1647693659e2fc393 100644 (file)
@@ -141,8 +141,7 @@ pub struct BTreeMap<K, V> {
 unsafe impl<#[may_dangle] K, #[may_dangle] V> Drop for BTreeMap<K, V> {
     fn drop(&mut self) {
         unsafe {
-            for _ in ptr::read(self).into_iter() {
-            }
+            drop(ptr::read(self).into_iter());
         }
     }
 }
index f58c87b801f552852d2f7c4392971eeaf2d18c3c..8f0488f69369e5d905c18c906e1cfa5c459e34f0 100644 (file)
@@ -1376,7 +1376,7 @@ fn test_send() {
         thread::spawn(move || {
                 check_links(&n);
                 let a: &[_] = &[&1, &2, &3];
-                assert_eq!(a, &n.iter().collect::<Vec<_>>()[..]);
+                assert_eq!(a, &*n.iter().collect::<Vec<_>>());
             })
             .join()
             .ok()
index d3723ace9efb332f4349be1bf37e62b3878cf55c..f7451f574ffa3b131a29f4f1afd8eb9230204539 100644 (file)
@@ -1162,7 +1162,7 @@ pub fn sort_by_key<B, F>(&mut self, mut f: F)
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is based on Orson Peters' [pdqsort][pattern-defeating quicksort],
+    /// The current algorithm is based on Orson Peters' [pattern-defeating quicksort][pdqsort],
     /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
     /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
     /// heapsort on degenerate inputs.
@@ -1199,7 +1199,7 @@ pub fn sort_unstable(&mut self)
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is based on Orson Peters' [pdqsort][pattern-defeating quicksort],
+    /// The current algorithm is based on Orson Peters' [pattern-defeating quicksort][pdqsort],
     /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
     /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
     /// heapsort on degenerate inputs.
@@ -1239,7 +1239,7 @@ pub fn sort_unstable_by<F>(&mut self, compare: F)
     ///
     /// # Current implementation
     ///
-    /// The current algorithm is based on Orson Peters' [pdqsort][pattern-defeating quicksort],
+    /// The current algorithm is based on Orson Peters' [pattern-defeating quicksort][pdqsort],
     /// which is a quicksort variant designed to be very fast on certain kinds of patterns,
     /// sometimes achieving linear time. It is randomized but deterministic, and falls back to
     /// heapsort on degenerate inputs.
index 8abc9ca7e9fe87b19ee29c632480122bda4a7853..219e818f7d7385123e2eacdab699b19b655c8b6e 100644 (file)
 
 //! Unicode string slices.
 //!
+//! The `&str` type is one of the two main string types, the other being `String`.
+//! Unlike its `String` counterpart, its contents are borrowed.
+//!
+//! # Basic Usage
+//!
+//! A basic string declaration of `&str` type:
+//!
+//! ```
+//! let hello_world = "Hello, World!";
+//! ```
+//!
+//! Here we have declared a string literal, also known as a string slice.
+//! String literals have a static lifetime, which means the string `hello_world`
+//! is guaranteed to be valid for the duration of the entire program.
+//! We can explicitly specify `hello_world`'s lifetime as well:
+//!
+//! ```
+//! let hello_world: &'static str = "Hello, world!";
+//! ```
+//!
 //! *[See also the `str` primitive type](../../std/primitive.str.html).*
 
-
 #![stable(feature = "rust1", since = "1.0.0")]
 
 // Many of the usings in this module are only used in the test configuration.
index 7b408af13aa2f4b435ad64beed14b0871dd77b8e..56b60a3e00341b6b4eb6605b65d16d3350e0c2b5 100644 (file)
@@ -1563,7 +1563,7 @@ fn deref_mut(&mut self) -> &mut [T] {
 impl<T> FromIterator<T> for Vec<T> {
     #[inline]
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Vec<T> {
-        <Self as SpecExtend<_, _>>::from_iter(iter.into_iter())
+        <Self as SpecExtend<T, I::IntoIter>>::from_iter(iter.into_iter())
     }
 }
 
@@ -1631,7 +1631,7 @@ fn into_iter(mut self) -> slice::IterMut<'a, T> {
 impl<T> Extend<T> for Vec<T> {
     #[inline]
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
-        self.spec_extend(iter.into_iter())
+        <Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
     }
 }
 
@@ -1662,7 +1662,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
                 vector
             }
         };
-        vector.spec_extend(iterator);
+        <Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
         vector
     }
 
@@ -1674,7 +1674,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
 impl<T, I> SpecExtend<T, I> for Vec<T>
     where I: TrustedLen<Item=T>,
 {
-    fn from_iter(iterator: I) -> Self {
+    default fn from_iter(iterator: I) -> Self {
         let mut vector = Vec::new();
         vector.spec_extend(iterator);
         vector
@@ -1706,6 +1706,27 @@ fn spec_extend(&mut self, iterator: I) {
     }
 }
 
+impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
+    fn from_iter(iterator: IntoIter<T>) -> Self {
+        // A common case is passing a vector into a function which immediately
+        // re-collects into a vector. We can short circuit this if the IntoIter
+        // has not been advanced at all.
+        if *iterator.buf == iterator.ptr as *mut T {
+            unsafe {
+                let vec = Vec::from_raw_parts(*iterator.buf as *mut T,
+                                              iterator.len(),
+                                              iterator.cap);
+                mem::forget(iterator);
+                vec
+            }
+        } else {
+            let mut vector = Vec::new();
+            vector.spec_extend(iterator);
+            vector
+        }
+    }
+}
+
 impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>
     where I: Iterator<Item=&'a T>,
           T: Clone,
index 06d70800d392560e8c99e44fd65edc878c95a114..63df0eb73050971b86dad86fe7e4814f53d23d32 100644 (file)
@@ -680,3 +680,19 @@ fn mkpanic() -> usize { panic!() }
     let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { vec.place_back() <- mkpanic(); }));
     assert_eq!(vec.len(), 3);
 }
+
+#[test]
+fn from_into_inner() {
+    let vec = vec![1, 2, 3];
+    let ptr = vec.as_ptr();
+    let vec = vec.into_iter().collect::<Vec<_>>();
+    assert_eq!(vec, [1, 2, 3]);
+    assert_eq!(vec.as_ptr(), ptr);
+
+    let ptr = &vec[1] as *const _;
+    let mut it = vec.into_iter();
+    it.next().unwrap();
+    let vec = it.collect::<Vec<_>>();
+    assert_eq!(vec, [2, 3]);
+    assert!(ptr != vec.as_ptr());
+}
index 19e69ca296d8f4ea5221c0d9a6b45fb5e7f0c4f8..b27c801cf89d5d26f3d74ba331a3b0e497e5ddc5 100644 (file)
@@ -187,7 +187,7 @@ fn from(c: char) -> Self {
 /// with the character encoding that IANA calls ISO-8859-1.
 /// This encoding is compatible with ASCII.
 ///
-/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hypen),
+/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
 /// which leaves some "blanks", byte values that are not assigned to any character.
 /// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
 ///
index 7db35359a1f7d427433a69d9a100f8a5587bfc1b..dc2398b22acec67e6dbd98f1c94a9698a266c4ef 100644 (file)
@@ -322,6 +322,41 @@ pub fn then_with<F: FnOnce() -> Ordering>(self, f: F) -> Ordering {
     }
 }
 
+/// A helper struct for reverse ordering.
+///
+/// This struct is a helper to be used with functions like `Vec::sort_by_key` and
+/// can be used to reverse order a part of a key.
+///
+/// Example usage:
+///
+/// ```
+/// #![feature(reverse_cmp_key)]
+/// use std::cmp::Reverse;
+///
+/// let mut v = vec![1, 2, 3, 4, 5, 6];
+/// v.sort_by_key(|&num| (num > 3, Reverse(num)));
+/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
+/// ```
+#[derive(PartialEq, Eq, Debug)]
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+pub struct Reverse<T>(pub T);
+
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+impl<T: PartialOrd> PartialOrd for Reverse<T> {
+    #[inline]
+    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
+        other.0.partial_cmp(&self.0)
+    }
+}
+
+#[unstable(feature = "reverse_cmp_key", issue = "40893")]
+impl<T: Ord> Ord for Reverse<T> {
+    #[inline]
+    fn cmp(&self, other: &Reverse<T>) -> Ordering {
+        other.0.cmp(&self.0)
+    }
+}
+
 /// Trait for types that form a [total order](https://en.wikipedia.org/wiki/Total_order).
 ///
 /// An order is a total order if it is (for all `a`, `b` and `c`):
index 3415b0eea9bd01519090bdd9c20567e906eb2819..34f14ef53f8935e890f6459472aa02c971cbf677 100644 (file)
@@ -536,9 +536,9 @@ fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
 /// #     }
 /// # }
 /// impl ExactSizeIterator for Counter {
-///     // We already have the number of iterations, so we can use it directly.
+///     // We can easily calculate the remaining number of iterations.
 ///     fn len(&self) -> usize {
-///         self.count
+///         5 - self.count
 ///     }
 /// }
 ///
@@ -546,7 +546,7 @@ fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
 ///
 /// let counter = Counter::new();
 ///
-/// assert_eq!(0, counter.len());
+/// assert_eq!(5, counter.len());
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ExactSizeIterator: Iterator {
index 604bc7c10dea0aedaa886e976f1c63e392314fce..60dab943a3acfa094b93b275162bacc294610b78 100644 (file)
@@ -141,7 +141,7 @@ pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Opt
 ///
 /// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation
 /// of `10^e` (in the same floating point format). This is often enough to get the correct result.
-/// However, when the result is close to halfway between two adjecent (ordinary) floats, the
+/// However, when the result is close to halfway between two adjacent (ordinary) floats, the
 /// compound rounding error from multiplying two approximation means the result may be off by a
 /// few bits. When this happens, the iterative Algorithm R fixes things up.
 ///
@@ -392,7 +392,7 @@ fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
     //
     // Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding
     // on their own. When they are equal and the remainder is non-zero, the value still
-    // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainer
+    // needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
     // is zero, we have a half-to-even situation.
     let bits = x.bit_length();
     let lsb = bits - T::sig_bits() as usize;
index 686cc21eba1a0aafca8436250d940dc4ead374d6..d203b68c0dfd57fd1e8461968bf607a9089de01c 100644 (file)
@@ -196,7 +196,7 @@ pub trait Drop {
     fn drop(&mut self);
 }
 
-/// The `Add` trait is used to specify the functionality of `+`.
+/// The addition operator `+`.
 ///
 /// # Examples
 ///
@@ -269,7 +269,7 @@ fn add(self, other: $t) -> $t { self + other }
 
 add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Sub` trait is used to specify the functionality of `-`.
+/// The subtraction operator `-`.
 ///
 /// # Examples
 ///
@@ -342,7 +342,7 @@ fn sub(self, other: $t) -> $t { self - other }
 
 sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Mul` trait is used to specify the functionality of `*`.
+/// The multiplication operator `*`.
 ///
 /// # Examples
 ///
@@ -464,7 +464,7 @@ fn mul(self, other: $t) -> $t { self * other }
 
 mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Div` trait is used to specify the functionality of `/`.
+/// The division operator `/`.
 ///
 /// # Examples
 ///
@@ -609,7 +609,7 @@ fn div(self, other: $t) -> $t { self / other }
 
 div_impl_float! { f32 f64 }
 
-/// The `Rem` trait is used to specify the functionality of `%`.
+/// The remainder operator `%`.
 ///
 /// # Examples
 ///
@@ -689,7 +689,7 @@ fn rem(self, other: $t) -> $t { self % other }
 
 rem_impl_float! { f32 f64 }
 
-/// The `Neg` trait is used to specify the functionality of unary `-`.
+/// The unary negation operator `-`.
 ///
 /// # Examples
 ///
@@ -768,7 +768,7 @@ macro_rules! neg_impl_unsigned {
 // neg_impl_unsigned! { usize u8 u16 u32 u64 }
 neg_impl_numeric! { isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `Not` trait is used to specify the functionality of unary `!`.
+/// The unary logical negation operator `!`.
 ///
 /// # Examples
 ///
@@ -826,7 +826,7 @@ fn not(self) -> $t { !self }
 
 not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitAnd` trait is used to specify the functionality of `&`.
+/// The bitwise AND operator `&`.
 ///
 /// # Examples
 ///
@@ -909,7 +909,7 @@ fn bitand(self, rhs: $t) -> $t { self & rhs }
 
 bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitOr` trait is used to specify the functionality of `|`.
+/// The bitwise OR operator `|`.
 ///
 /// # Examples
 ///
@@ -992,7 +992,7 @@ fn bitor(self, rhs: $t) -> $t { self | rhs }
 
 bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitXor` trait is used to specify the functionality of `^`.
+/// The bitwise XOR operator `^`.
 ///
 /// # Examples
 ///
@@ -1078,7 +1078,7 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
 
 bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `Shl` trait is used to specify the functionality of `<<`.
+/// The left shift operator `<<`.
 ///
 /// # Examples
 ///
@@ -1181,7 +1181,7 @@ macro_rules! shl_impl_all {
 
 shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
 
-/// The `Shr` trait is used to specify the functionality of `>>`.
+/// The right shift operator `>>`.
 ///
 /// # Examples
 ///
@@ -1284,7 +1284,7 @@ macro_rules! shr_impl_all {
 
 shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 
-/// The `AddAssign` trait is used to specify the functionality of `+=`.
+/// The addition assignment operator `+=`.
 ///
 /// # Examples
 ///
@@ -1340,7 +1340,7 @@ fn add_assign(&mut self, other: $t) { *self += other }
 
 add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `SubAssign` trait is used to specify the functionality of `-=`.
+/// The subtraction assignment operator `-=`.
 ///
 /// # Examples
 ///
@@ -1396,7 +1396,7 @@ fn sub_assign(&mut self, other: $t) { *self -= other }
 
 sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `MulAssign` trait is used to specify the functionality of `*=`.
+/// The multiplication assignment operator `*=`.
 ///
 /// # Examples
 ///
@@ -1441,7 +1441,7 @@ fn mul_assign(&mut self, other: $t) { *self *= other }
 
 mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `DivAssign` trait is used to specify the functionality of `/=`.
+/// The division assignment operator `/=`.
 ///
 /// # Examples
 ///
@@ -1485,7 +1485,7 @@ fn div_assign(&mut self, other: $t) { *self /= other }
 
 div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `RemAssign` trait is used to specify the functionality of `%=`.
+/// The remainder assignment operator `%=`.
 ///
 /// # Examples
 ///
@@ -1529,7 +1529,7 @@ fn rem_assign(&mut self, other: $t) { *self %= other }
 
 rem_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
 
-/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
+/// The bitwise AND assignment operator `&=`.
 ///
 /// # Examples
 ///
@@ -1615,7 +1615,7 @@ fn bitand_assign(&mut self, other: $t) { *self &= other }
 
 bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
+/// The bitwise OR assignment operator `|=`.
 ///
 /// # Examples
 ///
@@ -1659,7 +1659,7 @@ fn bitor_assign(&mut self, other: $t) { *self |= other }
 
 bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
+/// The bitwise XOR assignment operator `^=`.
 ///
 /// # Examples
 ///
@@ -1703,7 +1703,7 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other }
 
 bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
 
-/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
+/// The left shift assignment operator `<<=`.
 ///
 /// # Examples
 ///
@@ -1768,7 +1768,7 @@ macro_rules! shl_assign_impl_all {
 
 shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
 
-/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
+/// The right shift assignment operator `>>=`.
 ///
 /// # Examples
 ///
index 6ec8a37dfa4330042e62996c4b956f1a3b75a770..c46b0c1324de6e1987df9afd69382ec53275ebda 100644 (file)
@@ -838,10 +838,10 @@ impl<T: Default, E> Result<T, E> {
     ///
     /// assert_eq!(1909, good_year);
     /// assert_eq!(0, bad_year);
+    /// ```
     ///
     /// [`parse`]: ../../std/primitive.str.html#method.parse
     /// [`FromStr`]: ../../std/str/trait.FromStr.html
-    /// ```
     #[inline]
     #[stable(feature = "result_unwrap_or_default", since = "1.16.0")]
     pub fn unwrap_or_default(self) -> T {
index d13d537d99301781dd6aa246c4008d529354e320..3612ee65bca0dba78c5ad3fd35e51bbba3b3340e 100644 (file)
@@ -152,8 +152,8 @@ fn partial_insertion_sort<T, F>(v: &mut [T], is_less: &mut F) -> bool
 fn insertion_sort<T, F>(v: &mut [T], is_less: &mut F)
     where F: FnMut(&T, &T) -> bool
 {
-    for i in 2..v.len()+1 {
-        shift_tail(&mut v[..i], is_less);
+    for i in 1..v.len() {
+        shift_tail(&mut v[..i+1], is_less);
     }
 }
 
@@ -498,32 +498,40 @@ fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &mut F) -> usize
 #[cold]
 fn break_patterns<T>(v: &mut [T]) {
     let len = v.len();
-
     if len >= 8 {
-        // A random number will be taken modulo this one. The modulus is a power of two so that we
-        // can simply take bitwise "and", thus avoiding costly CPU operations.
-        let modulus = (len / 4).next_power_of_two();
-        debug_assert!(modulus >= 1 && modulus <= len / 2);
-
-        // Pseudorandom number generation from the "Xorshift RNGs" paper by George Marsaglia.
-        let mut random = len;
-        random ^= random << 13;
-        random ^= random >> 17;
-        random ^= random << 5;
-        random &= modulus - 1;
-        debug_assert!(random < len / 2);
-
-        // The first index.
-        let a = len / 4 * 2;
-        debug_assert!(a >= 1 && a < len - 2);
-
-        // The second index.
-        let b = len / 4 + random;
-        debug_assert!(b >= 1 && b < len - 2);
-
-        // Swap neighbourhoods of `a` and `b`.
+        // Pseudorandom number generator from the "Xorshift RNGs" paper by George Marsaglia.
+        let mut random = len as u32;
+        let mut gen_u32 = || {
+            random ^= random << 13;
+            random ^= random >> 17;
+            random ^= random << 5;
+            random
+        };
+        let mut gen_usize = || {
+            if mem::size_of::<usize>() <= 4 {
+                gen_u32() as usize
+            } else {
+                (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
+            }
+        };
+
+        // Take random numbers modulo this number.
+        // The number fits into `usize` because `len` is not greater than `isize::MAX`.
+        let modulus = len.next_power_of_two();
+
+        // Some pivot candidates will be in the nearby of this index. Let's randomize them.
+        let pos = len / 4 * 2;
+
         for i in 0..3 {
-            v.swap(a - 1 + i, b - 1 + i);
+            // Generate a random number modulo `len`. However, in order to avoid costly operations
+            // we first take it modulo a power of two, and then decrease by `len` until it fits
+            // into the range `[0, len - 1]`.
+            let mut other = gen_usize() & (modulus - 1);
+            while other >= len {
+                other -= len;
+            }
+
+            v.swap(pos - 1 + i, other);
         }
     }
 }
index dfb6936da6bda4d1f381aa9ef28dc208a3940850..0d66d0e93aa85a5344706486479c1658d07fec3c 100644 (file)
 /// [`from_str`]: #tymethod.from_str
 /// [`str`]: ../../std/primitive.str.html
 /// [`parse`]: ../../std/primitive.str.html#method.parse
+///
+/// # Examples
+///
+/// Basic implementation of `FromStr` on an example `Point` type:
+///
+/// ```
+/// use std::str::FromStr;
+/// use std::num::ParseIntError;
+///
+/// #[derive(Debug, PartialEq)]
+/// struct Point {
+///     x: i32,
+///     y: i32
+/// }
+///
+/// impl FromStr for Point {
+///     type Err = ParseIntError;
+///
+///     fn from_str(s: &str) -> Result<Self, Self::Err> {
+///         let coords: Vec<&str> = s.trim_matches(|p| p == '(' || p == ')' )
+///                                  .split(",")
+///                                  .collect();
+///
+///         let x_fromstr = coords[0].parse::<i32>()?;
+///         let y_fromstr = coords[1].parse::<i32>()?;
+///
+///         Ok(Point { x: x_fromstr, y: y_fromstr })
+///     }
+/// }
+///
+/// let p = Point::from_str("(1,2)");
+/// assert_eq!(p.unwrap(), Point{ x: 1, y: 2} )
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait FromStr: Sized {
     /// The associated error which can be returned from parsing.
@@ -101,7 +134,9 @@ fn from_str(s: &str) -> Result<bool, ParseBoolError> {
     }
 }
 
-/// An error returned when parsing a `bool` from a string fails.
+/// An error returned when parsing a `bool` using [`from_str`] fails
+///
+/// [`from_str`]: ../../std/primitive.bool.html#method.from_str
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ParseBoolError { _priv: () }
index 8e587ad211de80c3c2e50b5d9672a1e527690794..1b2c7775185f78d9dbf9e318236f8d3e4e5c0426 100644 (file)
@@ -554,7 +554,7 @@ fn escape_str(s: &str) -> String {
     pub fn to_dot_string(&self) -> String {
         match self {
             &LabelStr(ref s) => format!("\"{}\"", s.escape_default()),
-            &EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s[..])),
+            &EscStr(ref s) => format!("\"{}\"", LabelText::escape_str(&s)),
             &HtmlStr(ref s) => format!("<{}>", s),
         }
     }
@@ -587,7 +587,7 @@ pub fn suffix_line(self, suffix: LabelText) -> LabelText<'static> {
         let mut prefix = self.pre_escaped_content().into_owned();
         let suffix = suffix.pre_escaped_content();
         prefix.push_str(r"\n\n");
-        prefix.push_str(&suffix[..]);
+        prefix.push_str(&suffix);
         EscStr(prefix.into_cow())
     }
 }
@@ -878,7 +878,7 @@ impl<'a> Labeller<'a> for LabelledGraph {
         type Node = Node;
         type Edge = &'a Edge;
         fn graph_id(&'a self) -> Id<'a> {
-            Id::new(&self.name[..]).unwrap()
+            Id::new(self.name).unwrap()
         }
         fn node_id(&'a self, n: &Node) -> Id<'a> {
             id_name(n)
index 64d954c6a76e896fbf7ed5c17e77c40e388abe84..05a2d197356ef253dfd985166576619ac9b6947f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 64d954c6a76e896fbf7ed5c17e77c40e388abe84
+Subproject commit 05a2d197356ef253dfd985166576619ac9b6947f
diff --git a/src/liblog/Cargo.toml b/src/liblog/Cargo.toml
deleted file mode 100644 (file)
index 31a8624..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "log"
-version = "0.0.0"
-
-[lib]
-name = "log"
-path = "lib.rs"
-crate-type = ["dylib", "rlib"]
diff --git a/src/liblog/directive.rs b/src/liblog/directive.rs
deleted file mode 100644 (file)
index eb50d6e..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::ascii::AsciiExt;
-use std::cmp;
-
-#[derive(Debug, Clone)]
-pub struct LogDirective {
-    pub name: Option<String>,
-    pub level: u32,
-}
-
-pub const LOG_LEVEL_NAMES: [&'static str; 5] = ["ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
-
-/// Parse an individual log level that is either a number or a symbolic log level
-fn parse_log_level(level: &str) -> Option<u32> {
-    level.parse::<u32>()
-        .ok()
-        .or_else(|| {
-            let pos = LOG_LEVEL_NAMES.iter().position(|&name| name.eq_ignore_ascii_case(level));
-            pos.map(|p| p as u32 + 1)
-        })
-        .map(|p| cmp::min(p, ::MAX_LOG_LEVEL))
-}
-
-/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=1/foo")
-/// and return a vector with log directives.
-///
-/// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in
-/// std::).  Also supports string log levels of error, warn, info, and debug
-pub fn parse_logging_spec(spec: &str) -> (Vec<LogDirective>, Option<String>) {
-    let mut dirs = Vec::new();
-
-    let mut parts = spec.split('/');
-    let mods = parts.next();
-    let filter = parts.next();
-    if parts.next().is_some() {
-        println!("warning: invalid logging spec '{}', ignoring it (too many '/'s)",
-                 spec);
-        return (dirs, None);
-    }
-    if let Some(m) = mods {
-        for s in m.split(',') {
-            if s.is_empty() {
-                continue;
-            }
-            let mut parts = s.split('=');
-            let (log_level, name) =
-                match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) {
-                    (Some(part0), None, None) => {
-                        // if the single argument is a log-level string or number,
-                        // treat that as a global fallback
-                        match parse_log_level(part0) {
-                            Some(num) => (num, None),
-                            None => (::MAX_LOG_LEVEL, Some(part0)),
-                        }
-                    }
-                    (Some(part0), Some(""), None) => (::MAX_LOG_LEVEL, Some(part0)),
-                    (Some(part0), Some(part1), None) => {
-                        match parse_log_level(part1) {
-                            Some(num) => (num, Some(part0)),
-                            _ => {
-                                println!("warning: invalid logging spec '{}', ignoring it", part1);
-                                continue;
-                            }
-                        }
-                    }
-                    _ => {
-                        println!("warning: invalid logging spec '{}', ignoring it", s);
-                        continue;
-                    }
-                };
-            dirs.push(LogDirective {
-                name: name.map(str::to_owned),
-                level: log_level,
-            });
-        }
-    }
-
-    (dirs, filter.map(str::to_owned))
-}
-
-#[cfg(test)]
-mod tests {
-    use super::parse_logging_spec;
-
-    #[test]
-    fn parse_logging_spec_valid() {
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
-        assert_eq!(dirs.len(), 3);
-        assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
-        assert_eq!(dirs[0].level, 1);
-
-        assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
-        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);
-
-        assert_eq!(dirs[2].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[2].level, 4);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_logging_spec_invalid_crate() {
-        // test parse_logging_spec with multiple = in specification
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[0].level, 4);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_logging_spec_invalid_log_level() {
-        // test parse_logging_spec with 'noNumber' as log level
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[0].level, 4);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_logging_spec_string_log_level() {
-        // test parse_logging_spec with 'warn' as log level
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[0].level, ::WARN);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_logging_spec_empty_log_level() {
-        // test parse_logging_spec with '' as log level
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=wrong,crate2=");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_logging_spec_global() {
-        // test parse_logging_spec with no crate
-        let (dirs, filter) = parse_logging_spec("warn,crate2=4");
-        assert_eq!(dirs.len(), 2);
-        assert_eq!(dirs[0].name, None);
-        assert_eq!(dirs[0].level, 2);
-        assert_eq!(dirs[1].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[1].level, 4);
-        assert!(filter.is_none());
-    }
-
-    #[test]
-    fn parse_logging_spec_valid_filter() {
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4/abc");
-        assert_eq!(dirs.len(), 3);
-        assert_eq!(dirs[0].name, Some("crate1::mod1".to_owned()));
-        assert_eq!(dirs[0].level, 1);
-
-        assert_eq!(dirs[1].name, Some("crate1::mod2".to_owned()));
-        assert_eq!(dirs[1].level, ::MAX_LOG_LEVEL);
-
-        assert_eq!(dirs[2].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[2].level, 4);
-        assert!(filter.is_some() && filter.unwrap().to_owned() == "abc");
-    }
-
-    #[test]
-    fn parse_logging_spec_invalid_crate_filter() {
-        let (dirs, filter) = parse_logging_spec("crate1::mod1=1=2,crate2=4/a.c");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate2".to_owned()));
-        assert_eq!(dirs[0].level, 4);
-        assert!(filter.is_some() && filter.unwrap().to_owned() == "a.c");
-    }
-
-    #[test]
-    fn parse_logging_spec_empty_with_filter() {
-        let (dirs, filter) = parse_logging_spec("crate1/a*c");
-        assert_eq!(dirs.len(), 1);
-        assert_eq!(dirs[0].name, Some("crate1".to_owned()));
-        assert_eq!(dirs[0].level, ::MAX_LOG_LEVEL);
-        assert!(filter.is_some() && filter.unwrap().to_owned() == "a*c");
-    }
-}
diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs
deleted file mode 100644 (file)
index 057df64..0000000
+++ /dev/null
@@ -1,506 +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.
-
-//! Utilities for program-wide and customizable logging
-//!
-//! # Examples
-//!
-//! ```
-//! # #![feature(rustc_private)]
-//! #[macro_use] extern crate log;
-//!
-//! fn main() {
-//!     debug!("this is a debug {:?}", "message");
-//!     error!("this is printed by default");
-//!
-//!     if log_enabled!(log::INFO) {
-//!         let x = 3 * 4; // expensive computation
-//!         info!("the answer was: {:?}", x);
-//!     }
-//! }
-//! ```
-//!
-//! Assumes the binary is `main`:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=error ./main
-//! ERROR:main: this is printed by default
-//! ```
-//!
-//! ```{.bash}
-//! $ RUST_LOG=info ./main
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! ```{.bash}
-//! $ RUST_LOG=debug ./main
-//! DEBUG:main: this is a debug message
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! You can also set the log level on a per module basis:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=main=info ./main
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! And enable all logging:
-//!
-//! ```{.bash}
-//! $ RUST_LOG=main ./main
-//! DEBUG:main: this is a debug message
-//! ERROR:main: this is printed by default
-//! INFO:main: the answer was: 12
-//! ```
-//!
-//! # Logging Macros
-//!
-//! There are five macros that the logging subsystem uses:
-//!
-//! * `log!(level, ...)` - the generic logging macro, takes a level as a u32 and any
-//!                        related `format!` arguments
-//! * `debug!(...)` - a macro hard-wired to the log level of `DEBUG`
-//! * `info!(...)` - a macro hard-wired to the log level of `INFO`
-//! * `warn!(...)` - a macro hard-wired to the log level of `WARN`
-//! * `error!(...)` - a macro hard-wired to the log level of `ERROR`
-//!
-//! All of these macros use the same style of syntax as the `format!` syntax
-//! extension. Details about the syntax can be found in the documentation of
-//! `std::fmt` along with the Rust tutorial/manual.
-//!
-//! If you want to check at runtime if a given logging level is enabled (e.g. if the
-//! information you would want to log is expensive to produce), you can use the
-//! following macro:
-//!
-//! * `log_enabled!(level)` - returns true if logging of the given level is enabled
-//!
-//! # Enabling logging
-//!
-//! Log levels are controlled on a per-module basis, and by default all logging is
-//! disabled except for `error!` (a log level of 1). Logging is controlled via the
-//! `RUST_LOG` environment variable. The value of this environment variable is a
-//! comma-separated list of logging directives. A logging directive is of the form:
-//!
-//! ```text
-//! path::to::module=log_level
-//! ```
-//!
-//! The path to the module is rooted in the name of the crate it was compiled for,
-//! so if your program is contained in a file `hello.rs`, for example, to turn on
-//! logging for this file you would use a value of `RUST_LOG=hello`.
-//! Furthermore, this path is a prefix-search, so all modules nested in the
-//! specified module will also have logging enabled.
-//!
-//! The actual `log_level` is optional to specify. If omitted, all logging will be
-//! enabled. If specified, the it must be either a numeric in the range of 1-255, or
-//! it must be one of the strings `debug`, `error`, `info`, or `warn`. If a numeric
-//! is specified, then all logging less than or equal to that numeral is enabled.
-//! For example, if logging level 3 is active, error, warn, and info logs will be
-//! printed, but debug will be omitted.
-//!
-//! As the log level for a module is optional, the module to enable logging for is
-//! also optional. If only a `log_level` is provided, then the global log level for
-//! all modules is set to this value.
-//!
-//! Some examples of valid values of `RUST_LOG` are:
-//!
-//! * `hello` turns on all logging for the 'hello' module
-//! * `info` turns on all info logging
-//! * `hello=debug` turns on debug logging for 'hello'
-//! * `hello=3` turns on info logging for 'hello'
-//! * `hello,std::option` turns on hello, and std's option logging
-//! * `error,hello=warn` turn on global error logging and also warn for hello
-//!
-//! # Filtering results
-//!
-//! A RUST_LOG directive may include a string filter. The syntax is to append
-//! `/` followed by a string. Each message is checked against the string and is
-//! only logged if it contains the string. Note that the matching is done after
-//! formatting the log string but before adding any logging meta-data. There is
-//! a single filter for all modules.
-//!
-//! Some examples:
-//!
-//! * `hello/foo` turns on all logging for the 'hello' module where the log message
-//! includes 'foo'.
-//! * `info/f.o` turns on all info logging where the log message includes 'foo',
-//! 'f1o', 'fao', etc.
-//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
-//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
-//! * `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
-//!  hello. In both cases the log message must include a single digit number
-//!  followed by 'scopes'
-//!
-//! # Performance and Side Effects
-//!
-//! Each of these macros will expand to code similar to:
-//!
-//! ```rust,ignore
-//! if log_level <= my_module_log_level() {
-//!     ::log::log(log_level, format!(...));
-//! }
-//! ```
-//!
-//! What this means is that each of these macros are very cheap at runtime if
-//! they're turned off (just a load and an integer comparison). This also means that
-//! if logging is disabled, none of the components of the log will be executed.
-
-#![crate_name = "log"]
-#![unstable(feature = "rustc_private",
-            reason = "use the crates.io `log` library instead",
-            issue = "27812")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-       html_root_url = "https://doc.rust-lang.org/nightly/",
-       html_playground_url = "https://play.rust-lang.org/",
-       test(attr(deny(warnings))))]
-#![deny(missing_docs)]
-#![deny(warnings)]
-
-#![feature(staged_api)]
-
-use std::cell::RefCell;
-use std::fmt;
-use std::io::{self, Stderr};
-use std::io::prelude::*;
-use std::mem;
-use std::env;
-use std::slice;
-use std::sync::{Mutex, ONCE_INIT, Once};
-
-use directive::LOG_LEVEL_NAMES;
-
-#[macro_use]
-pub mod macros;
-
-mod directive;
-
-/// Maximum logging level of a module that can be specified. Common logging
-/// levels are found in the DEBUG/INFO/WARN/ERROR constants.
-pub const MAX_LOG_LEVEL: u32 = 255;
-
-/// The default logging level of a crate if no other is specified.
-const DEFAULT_LOG_LEVEL: u32 = 1;
-
-static mut LOCK: *mut Mutex<(Vec<directive::LogDirective>, Option<String>)> = 0 as *mut _;
-
-/// An unsafe constant that is the maximum logging level of any module
-/// specified. This is the first line of defense to determining whether a
-/// logging statement should be run.
-static mut LOG_LEVEL: u32 = MAX_LOG_LEVEL;
-
-/// Debug log level
-pub const DEBUG: u32 = 4;
-/// Info log level
-pub const INFO: u32 = 3;
-/// Warn log level
-pub const WARN: u32 = 2;
-/// Error log level
-pub const ERROR: u32 = 1;
-
-thread_local! {
-    static LOCAL_LOGGER: RefCell<Option<Box<Logger + Send>>> = {
-        RefCell::new(None)
-    }
-}
-
-/// A trait used to represent an interface to a thread-local logger. Each thread
-/// can have its own custom logger which can respond to logging messages
-/// however it likes.
-pub trait Logger {
-    /// Logs a single message described by the `record`.
-    fn log(&mut self, record: &LogRecord);
-}
-
-struct DefaultLogger {
-    handle: Stderr,
-}
-
-/// Wraps the log level with fmt implementations.
-#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
-pub struct LogLevel(pub u32);
-
-impl fmt::Display for LogLevel {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let LogLevel(level) = *self;
-        match LOG_LEVEL_NAMES.get(level as usize - 1) {
-            Some(ref name) => fmt::Display::fmt(name, fmt),
-            None => fmt::Display::fmt(&level, fmt),
-        }
-    }
-}
-
-impl Logger for DefaultLogger {
-    fn log(&mut self, record: &LogRecord) {
-        match writeln!(&mut self.handle,
-                       "{}:{}: {}",
-                       record.level,
-                       record.module_path,
-                       record.args) {
-            Err(e) => panic!("failed to log: {:?}", e),
-            Ok(()) => {}
-        }
-    }
-}
-
-impl Drop for DefaultLogger {
-    fn drop(&mut self) {
-        // FIXME(#12628): is panicking the right thing to do?
-        match self.handle.flush() {
-            Err(e) => panic!("failed to flush a logger: {:?}", e),
-            Ok(()) => {}
-        }
-    }
-}
-
-/// This function is called directly by the compiler when using the logging
-/// macros. This function does not take into account whether the log level
-/// specified is active or not, it will always log something if this method is
-/// called.
-///
-/// It is not recommended to call this function directly, rather it should be
-/// invoked through the logging family of macros.
-#[doc(hidden)]
-pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
-    // Test the literal string from args against the current filter, if there
-    // is one.
-    unsafe {
-        let filter = (*LOCK).lock().unwrap();
-        if let Some(ref filter) = filter.1 {
-            if !args.to_string().contains(filter) {
-                return;
-            }
-        }
-    }
-
-    // Completely remove the local logger from TLS in case anyone attempts to
-    // frob the slot while we're doing the logging. This will destroy any logger
-    // set during logging.
-    let logger = LOCAL_LOGGER.with(|s| s.borrow_mut().take());
-    let mut logger = logger.unwrap_or_else(|| Box::new(DefaultLogger { handle: io::stderr() }));
-    logger.log(&LogRecord {
-        level: LogLevel(level),
-        args: args,
-        file: loc.file,
-        module_path: loc.module_path,
-        line: loc.line,
-    });
-    set_logger(logger);
-}
-
-/// Getter for the global log level. This is a function so that it can be called
-/// safely
-#[doc(hidden)]
-#[inline(always)]
-pub fn log_level() -> u32 {
-    unsafe { LOG_LEVEL }
-}
-
-/// Replaces the thread-local logger with the specified logger, returning the old
-/// logger.
-pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> {
-    LOCAL_LOGGER.with(|slot| mem::replace(&mut *slot.borrow_mut(), Some(logger)))
-}
-
-/// A LogRecord is created by the logging macros, and passed as the only
-/// argument to Loggers.
-#[derive(Debug)]
-pub struct LogRecord<'a> {
-    /// The module path of where the LogRecord originated.
-    pub module_path: &'a str,
-
-    /// The LogLevel of this record.
-    pub level: LogLevel,
-
-    /// The arguments from the log line.
-    pub args: fmt::Arguments<'a>,
-
-    /// The file of where the LogRecord originated.
-    pub file: &'a str,
-
-    /// The line number of where the LogRecord originated.
-    pub line: u32,
-}
-
-#[doc(hidden)]
-#[derive(Copy, Clone)]
-pub struct LogLocation {
-    pub module_path: &'static str,
-    pub file: &'static str,
-    pub line: u32,
-}
-
-/// Tests whether a given module's name is enabled for a particular level of
-/// logging. This is the second layer of defense about determining whether a
-/// module's log statement should be emitted or not.
-#[doc(hidden)]
-pub fn mod_enabled(level: u32, module: &str) -> bool {
-    static INIT: Once = ONCE_INIT;
-    INIT.call_once(init);
-
-    // It's possible for many threads are in this function, only one of them
-    // will perform the global initialization, but all of them will need to check
-    // again to whether they should really be here or not. Hence, despite this
-    // check being expanded manually in the logging macro, this function checks
-    // the log level again.
-    if level > unsafe { LOG_LEVEL } {
-        return false;
-    }
-
-    // This assertion should never get tripped unless we're in an at_exit
-    // handler after logging has been torn down and a logging attempt was made.
-
-    unsafe {
-        let directives = (*LOCK).lock().unwrap();
-        enabled(level, module, directives.0.iter())
-    }
-}
-
-fn enabled(level: u32, module: &str, iter: slice::Iter<directive::LogDirective>) -> bool {
-    // Search for the longest match, the vector is assumed to be pre-sorted.
-    for directive in iter.rev() {
-        match directive.name {
-            Some(ref name) if !module.starts_with(&name[..]) => {}
-            Some(..) | None => return level <= directive.level,
-        }
-    }
-    level <= DEFAULT_LOG_LEVEL
-}
-
-/// Initialize logging for the current process.
-///
-/// This is not threadsafe at all, so initialization is performed through a
-/// `Once` primitive (and this function is called from that primitive).
-fn init() {
-    let (mut directives, filter) = match env::var("RUST_LOG") {
-        Ok(spec) => directive::parse_logging_spec(&spec[..]),
-        Err(..) => (Vec::new(), None),
-    };
-
-    // Sort the provided directives by length of their name, this allows a
-    // little more efficient lookup at runtime.
-    directives.sort_by(|a, b| {
-        let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0);
-        let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0);
-        alen.cmp(&blen)
-    });
-
-    let max_level = {
-        let max = directives.iter().max_by_key(|d| d.level);
-        max.map(|d| d.level).unwrap_or(DEFAULT_LOG_LEVEL)
-    };
-
-    unsafe {
-        LOG_LEVEL = max_level;
-
-        assert!(LOCK.is_null());
-        LOCK = Box::into_raw(Box::new(Mutex::new((directives, filter))));
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::enabled;
-    use directive::LogDirective;
-
-    #[test]
-    fn match_full_path() {
-        let dirs = [LogDirective {
-                        name: Some("crate2".to_string()),
-                        level: 3,
-                    },
-                    LogDirective {
-                        name: Some("crate1::mod1".to_string()),
-                        level: 2,
-                    }];
-        assert!(enabled(2, "crate1::mod1", dirs.iter()));
-        assert!(!enabled(3, "crate1::mod1", dirs.iter()));
-        assert!(enabled(3, "crate2", dirs.iter()));
-        assert!(!enabled(4, "crate2", dirs.iter()));
-    }
-
-    #[test]
-    fn no_match() {
-        let dirs = [LogDirective {
-                        name: Some("crate2".to_string()),
-                        level: 3,
-                    },
-                    LogDirective {
-                        name: Some("crate1::mod1".to_string()),
-                        level: 2,
-                    }];
-        assert!(!enabled(2, "crate3", dirs.iter()));
-    }
-
-    #[test]
-    fn match_beginning() {
-        let dirs = [LogDirective {
-                        name: Some("crate2".to_string()),
-                        level: 3,
-                    },
-                    LogDirective {
-                        name: Some("crate1::mod1".to_string()),
-                        level: 2,
-                    }];
-        assert!(enabled(3, "crate2::mod1", dirs.iter()));
-    }
-
-    #[test]
-    fn match_beginning_longest_match() {
-        let dirs = [LogDirective {
-                        name: Some("crate2".to_string()),
-                        level: 3,
-                    },
-                    LogDirective {
-                        name: Some("crate2::mod".to_string()),
-                        level: 4,
-                    },
-                    LogDirective {
-                        name: Some("crate1::mod1".to_string()),
-                        level: 2,
-                    }];
-        assert!(enabled(4, "crate2::mod1", dirs.iter()));
-        assert!(!enabled(4, "crate2", dirs.iter()));
-    }
-
-    #[test]
-    fn match_default() {
-        let dirs = [LogDirective {
-                        name: None,
-                        level: 3,
-                    },
-                    LogDirective {
-                        name: Some("crate1::mod1".to_string()),
-                        level: 2,
-                    }];
-        assert!(enabled(2, "crate1::mod1", dirs.iter()));
-        assert!(enabled(3, "crate2::mod2", dirs.iter()));
-    }
-
-    #[test]
-    fn zero_level() {
-        let dirs = [LogDirective {
-                        name: None,
-                        level: 3,
-                    },
-                    LogDirective {
-                        name: Some("crate1::mod1".to_string()),
-                        level: 0,
-                    }];
-        assert!(!enabled(1, "crate1::mod1", dirs.iter()));
-        assert!(enabled(3, "crate2::mod2", dirs.iter()));
-    }
-}
diff --git a/src/liblog/macros.rs b/src/liblog/macros.rs
deleted file mode 100644 (file)
index 803a2df..0000000
+++ /dev/null
@@ -1,205 +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.
-
-//! Logging macros
-
-/// The standard logging macro
-///
-/// This macro will generically log over a provided level (of type u32) with a
-/// format!-based argument list. See documentation in `std::fmt` for details on
-/// how to use the syntax.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-///     log!(log::WARN, "this is a warning {}", "message");
-///     log!(log::DEBUG, "this is a debug message");
-///     log!(6, "this is a custom logging level: {level}", level=6);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=warn ./main
-/// WARN:main: this is a warning message
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: this is a debug message
-/// WARN:main: this is a warning message
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=6 ./main
-/// DEBUG:main: this is a debug message
-/// WARN:main: this is a warning message
-/// 6:main: this is a custom logging level: 6
-/// ```
-#[macro_export]
-macro_rules! log {
-    ($lvl:expr, $($arg:tt)+) => ({
-        static LOC: ::log::LogLocation = ::log::LogLocation {
-            line: line!(),
-            file: file!(),
-            module_path: module_path!(),
-        };
-        let lvl = $lvl;
-        if log_enabled!(lvl) {
-            ::log::log(lvl, &LOC, format_args!($($arg)+))
-        }
-    })
-}
-
-/// A convenience macro for logging at the error log level.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-///     let error = 3;
-///     error!("the build has failed with error code: {}", error);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=error ./main
-/// ERROR:main: the build has failed with error code: 3
-/// ```
-///
-#[macro_export]
-macro_rules! error {
-    ($($arg:tt)*) => (log!(::log::ERROR, $($arg)*))
-}
-
-/// A convenience macro for logging at the warning log level.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-///     let code = 3;
-///     warn!("you may like to know that a process exited with: {}", code);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=warn ./main
-/// WARN:main: you may like to know that a process exited with: 3
-/// ```
-#[macro_export]
-macro_rules! warn {
-    ($($arg:tt)*) => (log!(::log::WARN, $($arg)*))
-}
-
-/// A convenience macro for logging at the info log level.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-///     let ret = 3;
-///     info!("this function is about to return: {}", ret);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=info ./main
-/// INFO:main: this function is about to return: 3
-/// ```
-#[macro_export]
-macro_rules! info {
-    ($($arg:tt)*) => (log!(::log::INFO, $($arg)*))
-}
-
-/// A convenience macro for logging at the debug log level. This macro will
-/// be omitted at compile time in an optimized build unless `-C debug-assertions`
-/// is passed to the compiler.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// fn main() {
-///     debug!("x = {x}, y = {y}", x=10, y=20);
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: x = 10, y = 20
-/// ```
-#[macro_export]
-macro_rules! debug {
-    ($($arg:tt)*) => (if cfg!(debug_assertions) { log!(::log::DEBUG, $($arg)*) })
-}
-
-/// A macro to test whether a log level is enabled for the current module.
-///
-/// # Examples
-///
-/// ```
-/// # #![feature(rustc_private)]
-/// #[macro_use] extern crate log;
-///
-/// struct Point { x: i32, y: i32 }
-/// fn some_expensive_computation() -> Point { Point { x: 1, y: 2 } }
-///
-/// fn main() {
-///     if log_enabled!(log::DEBUG) {
-///         let x = some_expensive_computation();
-///         debug!("x.x = {}, x.y = {}", x.x, x.y);
-///     }
-/// }
-/// ```
-///
-/// Assumes the binary is `main`:
-///
-/// ```{.bash}
-/// $ RUST_LOG=error ./main
-/// ```
-///
-/// ```{.bash}
-/// $ RUST_LOG=debug ./main
-/// DEBUG:main: x.x = 1, x.y = 2
-/// ```
-#[macro_export]
-macro_rules! log_enabled {
-    ($lvl:expr) => ({
-        let lvl = $lvl;
-        (lvl != ::log::DEBUG || cfg!(debug_assertions)) &&
-        lvl <= ::log::log_level() &&
-        ::log::mod_enabled(lvl, module_path!())
-    })
-}
index 5d53c60ad7fdc1072620abf156c939ae5dce7619..fa217acd9f9bf5e4eed1ea2feaede465f4450cbd 100644 (file)
@@ -12,7 +12,7 @@ crate-type = ["dylib"]
 arena = { path = "../libarena" }
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
-log = { path = "../liblog" }
+log = "0.3"
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
 rustc_const_math = { path = "../librustc_const_math" }
index 399af258e925167767be1ea6f3417141bfee6ae4..5aea2bcaa4f5c5fd5f4979df6ddb5183f4a9dcc5 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use hir::def_id::CrateNum;
 use std::fmt::Debug;
 use std::sync::Arc;
 
@@ -74,14 +75,13 @@ pub enum DepNode<D: Clone + Debug> {
     CoherenceCheckImpl(D),
     CoherenceOverlapCheck(D),
     CoherenceOverlapCheckSpecial(D),
-    CoherenceOverlapInherentCheck(D),
     CoherenceOrphanCheck(D),
     Variance,
     WfCheck(D),
     TypeckItemType(D),
     UnusedTraitCheck,
     CheckConst(D),
-    Privacy,
+    PrivacyAccessLevels(CrateNum),
     IntrinsicCheck(D),
     MatchCheck(D),
 
@@ -230,7 +230,7 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             CheckEntryFn => Some(CheckEntryFn),
             Variance => Some(Variance),
             UnusedTraitCheck => Some(UnusedTraitCheck),
-            Privacy => Some(Privacy),
+            PrivacyAccessLevels(k) => Some(PrivacyAccessLevels(k)),
             Reachability => Some(Reachability),
             DeadCheck => Some(DeadCheck),
             LateLintCheck => Some(LateLintCheck),
@@ -251,7 +251,6 @@ pub fn map_def<E, OP>(&self, mut op: OP) -> Option<DepNode<E>>
             CoherenceCheckImpl(ref d) => op(d).map(CoherenceCheckImpl),
             CoherenceOverlapCheck(ref d) => op(d).map(CoherenceOverlapCheck),
             CoherenceOverlapCheckSpecial(ref d) => op(d).map(CoherenceOverlapCheckSpecial),
-            CoherenceOverlapInherentCheck(ref d) => op(d).map(CoherenceOverlapInherentCheck),
             CoherenceOrphanCheck(ref d) => op(d).map(CoherenceOrphanCheck),
             WfCheck(ref d) => op(d).map(WfCheck),
             TypeckItemType(ref d) => op(d).map(TypeckItemType),
index 0f3108df9a822589aa4bba9743d8eaf77309a8c8..b6a2360211cac92610410d081de314d4c45a2148 100644 (file)
@@ -81,21 +81,6 @@ pub fn contains_key(&self, k: &M::Key) -> bool {
     pub fn keys(&self) -> Vec<M::Key> {
         self.map.keys().cloned().collect()
     }
-
-    /// Append `elem` to the vector stored for `k`, creating a new vector if needed.
-    /// This is considered a write to `k`.
-    ///
-    /// NOTE: Caution is required when using this method. You should
-    /// be sure that nobody is **reading from the vector** while you
-    /// are writing to it. Eventually, it'd be nice to remove this.
-    pub fn push<E: Clone>(&mut self, k: M::Key, elem: E)
-        where M: DepTrackingMapConfig<Value=Vec<E>>
-    {
-        self.write(&k);
-        self.map.entry(k)
-                .or_insert(Vec::new())
-                .push(elem);
-    }
 }
 
 impl<M: DepTrackingMapConfig> MemoizationMap for RefCell<DepTrackingMap<M>> {
index 8657a3e5a587899f80ebb536847bcb8f8a9a9f0c..5dbabcc923048482f8f06884ac3ec25c1ae7e82c 100644 (file)
@@ -101,11 +101,15 @@ pub fn pop_task(&mut self, key: DepNode<D>) {
     }
 
     /// Indicates that the current task `C` reads `v` by adding an
-    /// edge from `v` to `C`. If there is no current task, panics. If
-    /// you want to suppress this edge, use `ignore`.
+    /// edge from `v` to `C`. If there is no current task, has no
+    /// effect. Note that *reading* from tracked state is harmless if
+    /// you are not in a task; what is bad is *writing* to tracked
+    /// state (and leaking data that you read into a tracked task).
     pub fn read(&mut self, v: DepNode<D>) {
-        let source = self.make_node(v);
-        self.add_edge_from_current_node(|current| (source, current))
+        if self.current_node().is_some() {
+            let source = self.make_node(v);
+            self.add_edge_from_current_node(|current| (source, current))
+        }
     }
 
     /// Indicates that the current task `C` writes `v` by adding an
index 5d4190a8ae1a35bd76d35bab0e7641897ba25e5b..bedb6ff2771f064e468b5789a0ffb0a04b33fc85 100644 (file)
@@ -80,7 +80,13 @@ pub fn enqueue(&self, message: &DepMessage) {
 
             let mut stack = self.stack.borrow_mut();
             match *message {
-                DepMessage::Read(ref n) => self.check_edge(Some(Some(n)), top(&stack)),
+                // It is ok to READ shared state outside of a
+                // task. That can't do any harm (at least, the only
+                // way it can do harm is by leaking that data into a
+                // query or task, which would be a problem
+                // anyway). What would be bad is WRITING to that
+                // state.
+                DepMessage::Read(_) => { }
                 DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))),
                 DepMessage::PushTask(ref n) => stack.push(Some(n.clone())),
                 DepMessage::PushIgnore => stack.push(None),
@@ -116,7 +122,7 @@ fn check_edge(&self,
             (None, None) => unreachable!(),
 
             // nothing on top of the stack
-            (None, Some(n)) | (Some(n), None) => bug!("read/write of {:?} but no current task", n),
+            (None, Some(n)) | (Some(n), None) => bug!("write of {:?} but no current task", n),
 
             // this corresponds to an Ignore being top of the stack
             (Some(None), _) | (_, Some(None)) => (),
index 85b4ddcdd719099a90bd1cd25abc93827b32b7a2..5a0fbf8efb70778cc07954fe2c60d8436b1d7e0b 100644 (file)
@@ -1336,7 +1336,7 @@ trait SecondTrait : FirstTrait {
 
 E0398: r##"
 In Rust 1.3, the default object lifetime bounds are expected to change, as
-described in RFC #1156 [1]. You are getting a warning because the compiler
+described in [RFC 1156]. You are getting a warning because the compiler
 thinks it is possible that this change will cause a compilation error in your
 code. It is possible, though unlikely, that this is a false alarm.
 
@@ -1365,7 +1365,7 @@ fn foo<'a>(arg: &Box<SomeTrait+'a>) { ... }
 This explicitly states that you expect the trait object `SomeTrait` to contain
 references (with a maximum lifetime of `'a`).
 
-[1]: https://github.com/rust-lang/rfcs/pull/1156
+[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md
 "##,
 
 E0452: r##"
@@ -1771,6 +1771,7 @@ extern "C" fn foo(userdata: Box<i32>) {
 **item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`)
 is a function pointer, which is not zero-sized.
 This pattern should be rewritten. There are a few possible ways to do this:
+
 - change the original fn declaration to match the expected signature,
   and do the cast in the fn body (the prefered option)
 - cast the fn item fo a fn pointer before calling transmute, as shown here:
index 2ac1a036f99e1a996a85f60c1f653c0693474181..f9b740235f49e46534af00fd689dfbf1299af9a3 100644 (file)
@@ -907,6 +907,13 @@ fn lower_fn_decl(&mut self, decl: &FnDecl) -> P<hir::FnDecl> {
                 FunctionRetTy::Default(span) => hir::DefaultReturn(span),
             },
             variadic: decl.variadic,
+            has_implicit_self: decl.inputs.get(0).map_or(false, |arg| {
+                match arg.ty.node {
+                    TyKind::ImplicitSelf => true,
+                    TyKind::Rptr(_, ref mt) => mt.ty.node == TyKind::ImplicitSelf,
+                    _ => false
+                }
+            })
         })
     }
 
@@ -1900,57 +1907,45 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er)))
             }
             ExprKind::Range(ref e1, ref e2, lims) => {
-                fn make_struct(this: &mut LoweringContext,
-                               ast_expr: &Expr,
-                               path: &[&str],
-                               fields: &[(&str, &P<Expr>)]) -> hir::Expr {
-                    let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
-                                                         .collect::<Vec<_>>();
-                    let unstable_span = this.allow_internal_unstable("...", ast_expr.span);
-
-                    if fields.len() == 0 {
-                        this.expr_std_path(unstable_span, struct_path,
-                                           ast_expr.attrs.clone())
-                    } else {
-                        let fields = fields.into_iter().map(|&(s, e)| {
-                            let expr = P(this.lower_expr(&e));
-                            let unstable_span = this.allow_internal_unstable("...", e.span);
-                            this.field(Symbol::intern(s), expr, unstable_span)
-                        }).collect();
-                        let attrs = ast_expr.attrs.clone();
-
-                        this.expr_std_struct(unstable_span, struct_path, fields, None, attrs)
-                    }
-                }
-
                 use syntax::ast::RangeLimits::*;
 
-                return match (e1, e2, lims) {
-                    (&None,         &None,         HalfOpen) =>
-                        make_struct(self, e, &["RangeFull"], &[]),
-
-                    (&Some(ref e1), &None,         HalfOpen) =>
-                        make_struct(self, e, &["RangeFrom"],
-                                             &[("start", e1)]),
-
-                    (&None,         &Some(ref e2), HalfOpen) =>
-                        make_struct(self, e, &["RangeTo"],
-                                             &[("end", e2)]),
-
-                    (&Some(ref e1), &Some(ref e2), HalfOpen) =>
-                        make_struct(self, e, &["Range"],
-                                             &[("start", e1), ("end", e2)]),
-
-                    (&None,         &Some(ref e2), Closed)   =>
-                        make_struct(self, e, &["RangeToInclusive"],
-                                             &[("end", e2)]),
-
-                    (&Some(ref e1), &Some(ref e2), Closed)   =>
-                        make_struct(self, e, &["RangeInclusive", "NonEmpty"],
-                                             &[("start", e1), ("end", e2)]),
+                let (path, variant) = match (e1, e2, lims) {
+                    (&None, &None, HalfOpen) => ("RangeFull", None),
+                    (&Some(..), &None, HalfOpen) => ("RangeFrom", None),
+                    (&None, &Some(..), HalfOpen) => ("RangeTo", None),
+                    (&Some(..), &Some(..), HalfOpen) => ("Range", None),
+                    (&None, &Some(..), Closed) => ("RangeToInclusive", None),
+                    (&Some(..), &Some(..), Closed) => ("RangeInclusive", Some("NonEmpty")),
+                    (_, &None, Closed) =>
+                        panic!(self.diagnostic().span_fatal(
+                            e.span, "inclusive range with no end")),
+                };
 
-                    _ => panic!(self.diagnostic()
-                                    .span_fatal(e.span, "inclusive range with no end")),
+                let fields =
+                    e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e)))
+                    .map(|(s, e)| {
+                        let expr = P(self.lower_expr(&e));
+                        let unstable_span = self.allow_internal_unstable("...", e.span);
+                        self.field(Symbol::intern(s), expr, unstable_span)
+                    }).collect::<P<[hir::Field]>>();
+
+                let is_unit = fields.is_empty();
+                let unstable_span = self.allow_internal_unstable("...", e.span);
+                let struct_path =
+                    iter::once("ops").chain(iter::once(path)).chain(variant)
+                    .collect::<Vec<_>>();
+                let struct_path = self.std_path(unstable_span, &struct_path, is_unit);
+                let struct_path = hir::QPath::Resolved(None, P(struct_path));
+
+                return hir::Expr {
+                    id: self.lower_node_id(e.id),
+                    node: if is_unit {
+                        hir::ExprPath(struct_path)
+                    } else {
+                        hir::ExprStruct(struct_path, fields, None)
+                    },
+                    span: unstable_span,
+                    attrs: e.attrs.clone(),
                 };
             }
             ExprKind::Path(ref qself, ref path) => {
@@ -2613,17 +2608,6 @@ fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr
         P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
     }
 
-    fn expr_std_struct(&mut self,
-                       span: Span,
-                       components: &[&str],
-                       fields: hir::HirVec<hir::Field>,
-                       e: Option<P<hir::Expr>>,
-                       attrs: ThinVec<Attribute>) -> hir::Expr {
-        let path = self.std_path(span, components, false);
-        let qpath = hir::QPath::Resolved(None, P(path));
-        self.expr(span, hir::ExprStruct(qpath, fields, e), attrs)
-    }
-
     fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> hir::Expr {
         hir::Expr {
             id: self.next_id(),
index 583b3b848f30d88a7e572cc713233555a265f594..d7aa36b24f94279ba345399f7276a1e6fe609fff 100644 (file)
@@ -948,7 +948,7 @@ pub fn map_crate<'hir>(forest: &'hir mut Forest,
     intravisit::walk_crate(&mut collector, &forest.krate);
     let map = collector.map;
 
-    if log_enabled!(::log::DEBUG) {
+    if log_enabled!(::log::LogLevel::Debug) {
         // This only makes sense for ordered stores; note the
         // enumerate to count the number of entries.
         let (entries_less_1, _) = map.iter().filter(|&x| {
index 1c79a02d3da0e88d83f9b36511b09deb34bfc69d..27fa7487270885968948620ca571e64f7d849762 100644 (file)
@@ -159,6 +159,10 @@ impl Lifetime {
     pub fn is_elided(&self) -> bool {
         self.name == keywords::Invalid.name()
     }
+
+    pub fn is_static(&self) -> bool {
+        self.name == keywords::StaticLifetime.name()
+    }
 }
 
 /// A lifetime definition, eg `'a: 'b+'c+'d`
@@ -1379,6 +1383,9 @@ pub struct FnDecl {
     pub inputs: HirVec<P<Ty>>,
     pub output: FunctionRetTy,
     pub variadic: bool,
+    /// True if this function has an `self`, `&self` or `&mut self` receiver
+    /// (but not a `self: Xxx` one).
+    pub has_implicit_self: bool,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
index d296d8293fb0674010bb00d12ec012fdfaca0588..e760f7efc93d912645454213f9b42b5707836261 100644 (file)
@@ -55,7 +55,7 @@ pub fn to_hex(&self) -> String {
 impl Encodable for Fingerprint {
     #[inline]
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        for &byte in &self.0[..] {
+        for &byte in &self.0 {
             s.emit_u8(byte)?;
         }
         Ok(())
@@ -66,7 +66,7 @@ impl Decodable for Fingerprint {
     #[inline]
     fn decode<D: Decoder>(d: &mut D) -> Result<Fingerprint, D::Error> {
         let mut result = Fingerprint([0u8; FINGERPRINT_LENGTH]);
-        for byte in &mut result.0[..] {
+        for byte in &mut result.0 {
             *byte = d.read_u8()?;
         }
         Ok(result)
index 21139c8dde2a4b34b96c22becfc1b483728c9dfb..9fa2bc8a2a7a96f5290c4be26adaaccdc78b3918 100644 (file)
@@ -426,30 +426,26 @@ pub fn note_issue_32330(&self,
     {
         debug!("note_issue_32330: terr={:?}", terr);
         match *terr {
-            TypeError::RegionsInsufficientlyPolymorphic(_, &Region::ReVar(vid)) |
-            TypeError::RegionsOverlyPolymorphic(_, &Region::ReVar(vid)) => {
-                match self.region_vars.var_origin(vid) {
-                    RegionVariableOrigin::EarlyBoundRegion(_, _, Some(Issue32330 {
-                        fn_def_id,
-                        region_name
-                    })) => {
-                        diag.note(
-                            &format!("lifetime parameter `{0}` declared on fn `{1}` \
-                                      appears only in the return type, \
-                                      but here is required to be higher-ranked, \
-                                      which means that `{0}` must appear in both \
-                                      argument and return types",
-                                     region_name,
-                                     self.tcx.item_path_str(fn_def_id)));
-                        diag.note(
-                            &format!("this error is the result of a recent bug fix; \
-                                      for more information, see issue #33685 \
-                                      <https://github.com/rust-lang/rust/issues/33685>"));
-                    }
-                    _ => { }
-                }
+            TypeError::RegionsInsufficientlyPolymorphic(_, _, Some(box Issue32330 {
+                fn_def_id, region_name
+            })) |
+            TypeError::RegionsOverlyPolymorphic(_, _, Some(box Issue32330 {
+                fn_def_id, region_name
+            })) => {
+                diag.note(
+                    &format!("lifetime parameter `{0}` declared on fn `{1}` \
+                              appears only in the return type, \
+                              but here is required to be higher-ranked, \
+                              which means that `{0}` must appear in both \
+                              argument and return types",
+                             region_name,
+                             self.tcx.item_path_str(fn_def_id)));
+                diag.note(
+                    &format!("this error is the result of a recent bug fix; \
+                              for more information, see issue #33685 \
+                              <https://github.com/rust-lang/rust/issues/33685>"));
             }
-            _ => { }
+            _ => {}
         }
     }
 
index e919f025409c510a717458b4ea4d073c5ea83e8e..e3ffc99c0e9677bc667494e388492c2201369aa3 100644 (file)
@@ -15,6 +15,7 @@
             InferCtxt,
             LateBoundRegion,
             HigherRankedType,
+            RegionVariableOrigin,
             SubregionOrigin,
             SkolemizationMap};
 use super::combine::CombineFields;
@@ -656,14 +657,27 @@ pub fn leak_check(&self,
                        skol_br,
                        tainted_region);
 
+                let issue_32330 = if let &ty::ReVar(vid) = tainted_region {
+                    match self.region_vars.var_origin(vid) {
+                        RegionVariableOrigin::EarlyBoundRegion(_, _, issue_32330) => {
+                            issue_32330.map(Box::new)
+                        }
+                        _ => None
+                    }
+                } else {
+                    None
+                };
+
                 if overly_polymorphic {
                     debug!("Overly polymorphic!");
                     return Err(TypeError::RegionsOverlyPolymorphic(skol_br,
-                                                                   tainted_region));
+                                                                   tainted_region,
+                                                                   issue_32330));
                 } else {
                     debug!("Not as polymorphic!");
                     return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br,
-                                                                           tainted_region));
+                                                                           tainted_region,
+                                                                           issue_32330));
                 }
             }
         }
index 843f3a53f33e5c9500b9244563a13d138c605a78..20bf241a99906e3afe1a5196fb29718bc88f9cc1 100644 (file)
 use std::default::Default as StdDefault;
 use std::mem;
 use std::fmt;
-use std::ops::Deref;
 use syntax::attr;
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax_pos::{MultiSpan, Span};
+use syntax_pos::{DUMMY_SP, MultiSpan, Span};
 use errors::{self, Diagnostic, DiagnosticBuilder};
 use hir;
+use hir::def_id::LOCAL_CRATE;
 use hir::intravisit as hir_visit;
 use syntax::visit as ast_visit;
 
@@ -484,7 +484,7 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
                 Allow => bug!("earlier conditional return should handle Allow case")
             };
             let hyphen_case_lint_name = name.replace("_", "-");
-            if lint_flag_val.as_str().deref() == name {
+            if lint_flag_val.as_str() == name {
                 err.note(&format!("requested on the command line with `{} {}`",
                                   flag, hyphen_case_lint_name));
             } else {
@@ -495,7 +495,7 @@ pub fn raw_struct_lint<'a, S>(sess: &'a Session,
         },
         Node(lint_attr_name, src) => {
             def = Some(src);
-            if lint_attr_name.as_str().deref() != name {
+            if lint_attr_name.as_str() != name {
                 let level_str = level.as_str();
                 err.note(&format!("#[{}({})] implied by #[{}({})]",
                                   level_str, name, level_str, lint_attr_name));
@@ -1231,10 +1231,11 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
 /// Perform lint checking on a crate.
 ///
 /// Consumes the `lint_store` field of the `Session`.
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             access_levels: &AccessLevels) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck);
 
+    let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
+
     let krate = tcx.hir.krate();
 
     // We want to own the lint store, so move it out of the session.
index 225d6fc9bb2b211100ff6bdf65a9fc7a8018d26c..8bc0cf2577b5db05761ebbbf9a4b966875383605 100644 (file)
@@ -176,7 +176,6 @@ pub trait CrateStore {
     fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
-    fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;
 
     // trait info
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>;
@@ -255,8 +254,8 @@ fn maybe_get_item_body<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
     fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
-    fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 reexports: &def::ExportMap,
+    fn encode_metadata<'a, 'tcx>(&self,
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
                                  reachable: &NodeSet) -> Vec<u8>;
     fn metadata_encoding_version(&self) -> &[u8];
@@ -310,7 +309,6 @@ fn item_generics_cloned(&self, def: DefId) -> ty::Generics
         { bug!("item_generics_cloned") }
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
-    fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
 
     // trait info
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId> { vec![] }
@@ -412,10 +410,10 @@ fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
         { vec![] }
     fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
-    fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                           reexports: &def::ExportMap,
-                           link_meta: &LinkMeta,
-                           reachable: &NodeSet) -> Vec<u8> { vec![] }
+    fn encode_metadata<'a, 'tcx>(&self,
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 link_meta: &LinkMeta,
+                                 reachable: &NodeSet) -> Vec<u8> { vec![] }
     fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
 }
 
index cc6d6e88dee4ee068424be59d0d10ee853903fe1..8926ff5c1fbbb080dce5afbfe165418548395d66 100644 (file)
 use middle::privacy;
 use ty::{self, TyCtxt};
 use hir::def::Def;
-use hir::def_id::{DefId};
+use hir::def_id::{DefId, LOCAL_CRATE};
 use lint;
 use util::nodemap::FxHashSet;
 
 use syntax::{ast, codemap};
 use syntax::attr;
+use syntax::codemap::DUMMY_SP;
 use syntax_pos;
 
 // Any local node that may call something in its body block should be
@@ -592,9 +593,9 @@ fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
     }
 }
 
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             access_levels: &privacy::AccessLevels) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::DeadCheck);
+    let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
     let krate = tcx.hir.krate();
     let live_symbols = find_live(tcx, access_levels, krate);
     let mut visitor = DeadVisitor { tcx: tcx, live_symbols: live_symbols };
index 0cf53826dd4274998190b0e26c2a290f24553129..3b52e85e08e329c798316505a993f1ca9c267ba8 100644 (file)
@@ -194,76 +194,75 @@ pub struct cmt_<'tcx> {
 
 pub type cmt<'tcx> = Rc<cmt_<'tcx>>;
 
+pub enum ImmutabilityBlame<'tcx> {
+    ImmLocal(ast::NodeId),
+    ClosureEnv(ast::NodeId),
+    LocalDeref(ast::NodeId),
+    AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
+}
+
 impl<'tcx> cmt_<'tcx> {
-    pub fn get_def(&self) -> Option<ast::NodeId> {
-        match self.cat {
-            Categorization::Deref(ref cmt, ..) |
-            Categorization::Interior(ref cmt, _) |
-            Categorization::Downcast(ref cmt, _) => {
-                if let Categorization::Local(nid) = cmt.cat {
-                    Some(nid)
-                } else {
-                    None
-                }
+    fn resolve_field(&self, field_name: FieldName) -> (&'tcx ty::AdtDef, &'tcx ty::FieldDef)
+    {
+        let adt_def = self.ty.ty_adt_def().unwrap_or_else(|| {
+            bug!("interior cmt {:?} is not an ADT", self)
+        });
+        let variant_def = match self.cat {
+            Categorization::Downcast(_, variant_did) => {
+                adt_def.variant_with_id(variant_did)
             }
-            _ => None
-        }
+            _ => {
+                assert!(adt_def.is_univariant());
+                &adt_def.variants[0]
+            }
+        };
+        let field_def = match field_name {
+            NamedField(name) => variant_def.field_named(name),
+            PositionalField(idx) => &variant_def.fields[idx]
+        };
+        (adt_def, field_def)
     }
 
-    pub fn get_field(&self, name: ast::Name) -> Option<DefId> {
+    pub fn immutability_blame(&self) -> Option<ImmutabilityBlame<'tcx>> {
         match self.cat {
-            Categorization::Deref(ref cmt, ..) |
-            Categorization::Interior(ref cmt, _) |
-            Categorization::Downcast(ref cmt, _) => {
-                if let Categorization::Local(_) = cmt.cat {
-                    if let ty::TyAdt(def, _) = self.ty.sty {
-                        if def.is_struct() {
-                            return def.struct_variant().find_field_named(name).map(|x| x.did);
+            Categorization::Deref(ref base_cmt, _, BorrowedPtr(ty::ImmBorrow, _)) |
+            Categorization::Deref(ref base_cmt, _, Implicit(ty::ImmBorrow, _)) => {
+                // try to figure out where the immutable reference came from
+                match base_cmt.cat {
+                    Categorization::Local(node_id) =>
+                        Some(ImmutabilityBlame::LocalDeref(node_id)),
+                    Categorization::Interior(ref base_cmt, InteriorField(field_name)) => {
+                        let (adt_def, field_def) = base_cmt.resolve_field(field_name);
+                        Some(ImmutabilityBlame::AdtFieldDeref(adt_def, field_def))
+                    }
+                    Categorization::Upvar(Upvar { id, .. }) => {
+                        if let NoteClosureEnv(..) = self.note {
+                            Some(ImmutabilityBlame::ClosureEnv(id.closure_expr_id))
+                        } else {
+                            None
                         }
                     }
-                    None
-                } else {
-                    cmt.get_field(name)
+                    _ => None
                 }
             }
-            _ => None
-        }
-    }
-
-    pub fn get_field_name(&self) -> Option<ast::Name> {
-        match self.cat {
-            Categorization::Interior(_, ref ik) => {
-                if let InteriorKind::InteriorField(FieldName::NamedField(name)) = *ik {
-                    Some(name)
-                } else {
-                    None
-                }
+            Categorization::Local(node_id) => {
+                Some(ImmutabilityBlame::ImmLocal(node_id))
             }
-            Categorization::Deref(ref cmt, ..) |
-            Categorization::Downcast(ref cmt, _) => {
-                cmt.get_field_name()
+            Categorization::Rvalue(..) |
+            Categorization::Upvar(..) |
+            Categorization::Deref(.., UnsafePtr(..)) => {
+                // This should not be reachable up to inference limitations.
+                None
             }
-            _ => None,
-        }
-    }
-
-    pub fn get_arg_if_immutable(&self, map: &hir_map::Map) -> Option<ast::NodeId> {
-        match self.cat {
-            Categorization::Deref(ref cmt, ..) |
-            Categorization::Interior(ref cmt, _) |
-            Categorization::Downcast(ref cmt, _) => {
-                if let Categorization::Local(nid) = cmt.cat {
-                    if let ty::TyAdt(_, _) = self.ty.sty {
-                        if let ty::TyRef(_, ty::TypeAndMut{mutbl: MutImmutable, ..}) = cmt.ty.sty {
-                            return Some(nid);
-                        }
-                    }
-                    None
-                } else {
-                    cmt.get_arg_if_immutable(map)
-                }
+            Categorization::Interior(ref base_cmt, _) |
+            Categorization::Downcast(ref base_cmt, _) |
+            Categorization::Deref(ref base_cmt, _, _) => {
+                base_cmt.immutability_blame()
+            }
+            Categorization::StaticItem => {
+                // Do we want to do something here?
+                None
             }
-            _ => None
         }
     }
 }
@@ -1282,9 +1281,6 @@ pub enum Aliasability {
 #[derive(Copy, Clone, Debug)]
 pub enum AliasableReason {
     AliasableBorrowed,
-    AliasableClosure(ast::NodeId), // Aliasable due to capture Fn closure env
-    AliasableOther,
-    UnaliasableImmutable, // Created as needed upon seeing ImmutableUnique
     AliasableStatic,
     AliasableStaticMut,
 }
@@ -1324,23 +1320,13 @@ pub fn freely_aliasable(&self) -> Aliasability {
             Categorization::Deref(ref b, _, Implicit(ty::MutBorrow, _)) |
             Categorization::Deref(ref b, _, BorrowedPtr(ty::UniqueImmBorrow, _)) |
             Categorization::Deref(ref b, _, Implicit(ty::UniqueImmBorrow, _)) |
+            Categorization::Deref(ref b, _, Unique) |
             Categorization::Downcast(ref b, _) |
             Categorization::Interior(ref b, _) => {
                 // Aliasability depends on base cmt
                 b.freely_aliasable()
             }
 
-            Categorization::Deref(ref b, _, Unique) => {
-                let sub = b.freely_aliasable();
-                if b.mutbl.is_mutable() {
-                    // Aliasability depends on base cmt alone
-                    sub
-                } else {
-                    // Do not allow mutation through an immutable box.
-                    ImmutableUnique(Box::new(sub))
-                }
-            }
-
             Categorization::Rvalue(..) |
             Categorization::Local(..) |
             Categorization::Upvar(..) |
@@ -1356,13 +1342,9 @@ pub fn freely_aliasable(&self) -> Aliasability {
                 }
             }
 
-            Categorization::Deref(ref base, _, BorrowedPtr(ty::ImmBorrow, _)) |
-            Categorization::Deref(ref base, _, Implicit(ty::ImmBorrow, _)) => {
-                match base.cat {
-                    Categorization::Upvar(Upvar{ id, .. }) =>
-                        FreelyAliasable(AliasableClosure(id.closure_expr_id)),
-                    _ => FreelyAliasable(AliasableBorrowed)
-                }
+            Categorization::Deref(_, _, BorrowedPtr(ty::ImmBorrow, _)) |
+            Categorization::Deref(_, _, Implicit(ty::ImmBorrow, _)) => {
+                FreelyAliasable(AliasableBorrowed)
             }
         }
     }
index 4ec43e368a60dc9036e7ca96c9675ecbd3612c2e..b0e39442af98c9997f9885949d3b2e56e07d3178 100644 (file)
@@ -27,7 +27,9 @@
 use syntax::abi::Abi;
 use syntax::ast;
 use syntax::attr;
+use syntax::codemap::DUMMY_SP;
 use hir;
+use hir::def_id::LOCAL_CRATE;
 use hir::intravisit::{Visitor, NestedVisitorMap};
 use hir::itemlikevisit::ItemLikeVisitor;
 use hir::intravisit;
@@ -359,11 +361,11 @@ fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
     }
 }
 
-pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                access_levels: &privacy::AccessLevels)
-                                -> NodeSet {
+pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet {
     let _task = tcx.dep_graph.in_task(DepNode::Reachability);
 
+    let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
+
     let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
         *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib ||
         *ty == config::CrateTypeProcMacro
index 37749816eb153c725300a0eddba7f66cdc21b917..5094e28475b2640e9faea82e38e71fe28b91bba1 100644 (file)
@@ -29,7 +29,7 @@
 use syntax::attr;
 use syntax::ptr::P;
 use syntax::symbol::keywords;
-use syntax_pos::Span;
+use syntax_pos::{mk_sp, Span};
 use errors::DiagnosticBuilder;
 use util::nodemap::{NodeMap, NodeSet, FxHashSet, FxHashMap, DefIdMap};
 use rustc_back::slice;
@@ -434,7 +434,7 @@ fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
             self.resolve_elided_lifetimes(slice::ref_slice(lifetime_ref));
             return;
         }
-        if lifetime_ref.name == keywords::StaticLifetime.name() {
+        if lifetime_ref.is_static() {
             self.insert_lifetime(lifetime_ref, Region::Static);
             return;
         }
@@ -1434,7 +1434,7 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
             let lifetime_i = &lifetimes[i];
 
             for lifetime in lifetimes {
-                if lifetime.lifetime.name == keywords::StaticLifetime.name() {
+                if lifetime.lifetime.is_static() {
                     let lifetime = lifetime.lifetime;
                     let mut err = struct_span_err!(self.sess, lifetime.span, E0262,
                                   "invalid lifetime parameter name: `{}`", lifetime.name);
@@ -1464,7 +1464,17 @@ fn check_lifetime_defs(&mut self, old_scope: ScopeRef, lifetimes: &[hir::Lifetim
             self.check_lifetime_def_for_shadowing(old_scope, &lifetime_i.lifetime);
 
             for bound in &lifetime_i.bounds {
-                self.resolve_lifetime_ref(bound);
+                if !bound.is_static() {
+                    self.resolve_lifetime_ref(bound);
+                } else {
+                    self.insert_lifetime(bound, Region::Static);
+                    let full_span = mk_sp(lifetime_i.lifetime.span.lo, bound.span.hi);
+                    self.sess.struct_span_warn(full_span,
+                        &format!("unnecessary lifetime parameter `{}`", lifetime_i.lifetime.name))
+                        .help(&format!("you can use the `'static` lifetime directly, in place \
+                                        of `{}`", lifetime_i.lifetime.name))
+                        .emit();
+                }
             }
         }
     }
index 1fb537140257465eae43371f32b7b78eead2c4bf..4354ed6817ae96376db2640305c638b9f9567b34 100644 (file)
@@ -536,7 +536,7 @@ pub fn check_stability(self, def_id: DefId, id: NodeId, span: Span) {
                 if !self.stability.borrow().active_features.contains(feature) {
                     let msg = match *reason {
                         Some(ref r) => format!("use of unstable library feature '{}': {}",
-                                               &feature.as_str(), &r),
+                                               feature.as_str(), &r),
                         None => format!("use of unstable library feature '{}'", &feature)
                     };
                     emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span,
@@ -656,10 +656,11 @@ fn lookup_deprecation_uncached(self, id: DefId) -> Option<DeprecationEntry> {
 /// Given the list of enabled features that were not language features (i.e. that
 /// were expected to be library features), and the list of features used from
 /// libraries, identify activated features that don't exist and error about them.
-pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                 access_levels: &AccessLevels) {
+pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let sess = &tcx.sess;
 
+    let access_levels = &ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE);
+
     if tcx.stability.borrow().staged_api[&LOCAL_CRATE] && tcx.sess.features.borrow().staged_api {
         let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex);
         let krate = tcx.hir.krate();
index 9fdb86657769917bb49fa6c98830aed10d0d26ca..01dc7f51e29d9938c2b63e36086094414dd2dad8 100644 (file)
@@ -983,16 +983,16 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 }
 
 impl<'tcx> Operand<'tcx> {
-    pub fn item<'a>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
-                    def_id: DefId,
-                    substs: &'tcx Substs<'tcx>,
-                    span: Span)
-                    -> Self
-    {
+    pub fn function_handle<'a>(
+        tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+        def_id: DefId,
+        substs: &'tcx Substs<'tcx>,
+        span: Span,
+    ) -> Self {
         Operand::Constant(Constant {
             span: span,
             ty: tcx.item_type(def_id).subst(tcx, substs),
-            literal: Literal::Item { def_id, substs }
+            literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
         })
     }
 
index 2ebe0d459fab1453451b02f4bc7fd208224ac76b..7cd0b26940d9118284e3adcc03b35a3fda36972d 100644 (file)
@@ -46,7 +46,7 @@ pub fn error_msg(&self) -> Cow<'static, str> {
                 "the trait cannot require that `Self : Sized`".into(),
             ObjectSafetyViolation::SupertraitSelf =>
                 "the trait cannot use `Self` as a type parameter \
-                 in the supertrait listing".into(),
+                 in the supertraits or where-clauses".into(),
             ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
                 format!("method `{}` has no receiver", name).into(),
             ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
index 34977822bc69d8c8600105e7989ce5eed8e7c01f..d8ca30477205c53ccfcfd0e5bc61dab9c16828ae 100644 (file)
@@ -139,6 +139,21 @@ pub enum AutoBorrow<'tcx> {
     RawPtr(hir::Mutability),
 }
 
+/// Information for `CoerceUnsized` impls, storing information we
+/// have computed about the coercion.
+///
+/// This struct can be obtained via the `coerce_impl_info` query.
+/// Demanding this struct also has the side-effect of reporting errors
+/// for inappropriate impls.
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
+pub struct CoerceUnsizedInfo {
+    /// If this is a "custom coerce" impl, then what kind of custom
+    /// coercion is it? This applies to impls of `CoerceUnsized` for
+    /// structs, primarily, where we store a bit of info about which
+    /// fields need to be coerced.
+    pub custom_kind: Option<CustomCoerceUnsized>
+}
+
 #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
 pub enum CustomCoerceUnsized {
     /// Records the index of the field being coerced.
index 5543223105b444c37f5d8e512588661627c094a1..da56514ea82fbf9e485c3f1f761ff9253f9b54cc 100644 (file)
@@ -15,7 +15,7 @@
 use lint;
 use middle;
 use hir::TraitMap;
-use hir::def::Def;
+use hir::def::{Def, ExportMap};
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::map as hir_map;
 use hir::map::DisambiguatedDefPathData;
@@ -416,6 +416,9 @@ pub struct GlobalCtxt<'tcx> {
     /// is relevant; generated by resolve.
     pub trait_map: TraitMap,
 
+    /// Export map produced by name resolution.
+    pub export_map: ExportMap,
+
     pub named_region_map: resolve_lifetime::NamedRegionMap,
 
     pub region_maps: RegionMaps,
@@ -698,6 +701,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             region_maps: region_maps,
             variance_computed: Cell::new(false),
             trait_map: resolutions.trait_map,
+            export_map: resolutions.export_map,
             fulfilled_predicates: RefCell::new(fulfilled_predicates),
             hir: hir,
             maps: maps::Maps::new(dep_graph, providers),
index 5a696446b4bb6ea349abf18165ba1b0b269d557e..73d9c8b00ae472656765a3e2dd892df1b9720903 100644 (file)
@@ -39,8 +39,8 @@ pub enum TypeError<'tcx> {
     RegionsDoesNotOutlive(&'tcx Region, &'tcx Region),
     RegionsNotSame(&'tcx Region, &'tcx Region),
     RegionsNoOverlap(&'tcx Region, &'tcx Region),
-    RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region),
-    RegionsOverlyPolymorphic(BoundRegion, &'tcx Region),
+    RegionsInsufficientlyPolymorphic(BoundRegion, &'tcx Region, Option<Box<ty::Issue32330>>),
+    RegionsOverlyPolymorphic(BoundRegion, &'tcx Region, Option<Box<ty::Issue32330>>),
     Sorts(ExpectedFound<Ty<'tcx>>),
     IntMismatch(ExpectedFound<ty::IntVarValue>),
     FloatMismatch(ExpectedFound<ast::FloatTy>),
@@ -116,11 +116,11 @@ fn report_maybe_different(f: &mut fmt::Formatter,
             RegionsNoOverlap(..) => {
                 write!(f, "lifetimes do not intersect")
             }
-            RegionsInsufficientlyPolymorphic(br, _) => {
+            RegionsInsufficientlyPolymorphic(br, _, _) => {
                 write!(f, "expected bound lifetime parameter {}, \
                            found concrete lifetime", br)
             }
-            RegionsOverlyPolymorphic(br, _) => {
+            RegionsOverlyPolymorphic(br, _, _) => {
                 write!(f, "expected concrete lifetime, \
                            found bound lifetime parameter {}", br)
             }
@@ -253,15 +253,15 @@ pub fn note_and_explain_type_err(self,
                 self.note_and_explain_region(db, "...does not overlap ",
                                            region2, "");
             }
-            RegionsInsufficientlyPolymorphic(_, conc_region) => {
+            RegionsInsufficientlyPolymorphic(_, conc_region, _) => {
                 self.note_and_explain_region(db, "concrete lifetime that was found is ",
                                            conc_region, "");
             }
-            RegionsOverlyPolymorphic(_, &ty::ReVar(_)) => {
+            RegionsOverlyPolymorphic(_, &ty::ReVar(_), _) => {
                 // don't bother to print out the message below for
                 // inference variables, it's not very illuminating.
             }
-            RegionsOverlyPolymorphic(_, conc_region) => {
+            RegionsOverlyPolymorphic(_, conc_region, _) => {
                 self.note_and_explain_region(db, "expected concrete lifetime is ",
                                            conc_region, "");
             }
index 874e032bc46445490ffd30dd05b2fdf78e99dd42..38699105290551e97d7a344ca5d1ff75db8cf532 100644 (file)
@@ -202,7 +202,8 @@ fn push_impl_path<T>(self,
         } else {
             // for local crates, check whether type info is
             // available; typeck might not have completed yet
-            self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id)
+            self.maps.impl_trait_ref.borrow().contains_key(&impl_def_id) &&
+                self.maps.ty.borrow().contains_key(&impl_def_id)
         };
 
         if !use_types {
index ac8c38c7d585664d05d58efd4832d59e7a61e38e..4a183191cef29c70c82920b26f1873cf04e37c73 100644 (file)
 use dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig};
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use middle::const_val::ConstVal;
+use middle::privacy::AccessLevels;
 use mir;
-use ty::{self, Ty, TyCtxt};
+use session::CompileResult;
+use ty::{self, CrateInherentImpls, Ty, TyCtxt};
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::cell::{RefCell, RefMut};
@@ -176,9 +178,15 @@ fn describe(tcx: TyCtxt, (_, def_id): (CrateNum, DefId)) -> String {
     }
 }
 
-impl<'tcx> QueryDescription for queries::coherent_inherent_impls<'tcx> {
+impl<'tcx> QueryDescription for queries::crate_inherent_impls<'tcx> {
+    fn describe(_: TyCtxt, k: CrateNum) -> String {
+        format!("all inherent impls defined in crate `{:?}`", k)
+    }
+}
+
+impl<'tcx> QueryDescription for queries::crate_inherent_impls_overlap_check<'tcx> {
     fn describe(_: TyCtxt, _: CrateNum) -> String {
-        format!("coherence checking all inherent impls")
+        format!("check for overlap between inherent impls defined in this crate")
     }
 }
 
@@ -189,6 +197,19 @@ fn describe(tcx: TyCtxt, def: ty::InstanceDef<'tcx>) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::privacy_access_levels<'tcx> {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
+        format!("privacy access levels")
+    }
+}
+
+impl<'tcx> QueryDescription for queries::typeck_item_bodies<'tcx> {
+    fn describe(_: TyCtxt, _: CrateNum) -> String {
+        format!("type-checking all item bodies")
+    }
+}
+
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -368,7 +389,7 @@ fn default() -> Self {
     /// 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.
-    pub inherent_impls: InherentImpls(DefId) -> Vec<DefId>,
+    pub inherent_impls: InherentImpls(DefId) -> Rc<Vec<DefId>>,
 
     /// Maps from the def-id of a function/method or const/static
     /// to its MIR. Mutation is done at an item granularity to
@@ -393,19 +414,32 @@ fn default() -> Self {
     pub closure_type: ItemSignature(DefId) -> ty::PolyFnSig<'tcx>,
 
     /// Caches CoerceUnsized kinds for impls on custom types.
-    pub custom_coerce_unsized_kind: ItemSignature(DefId)
-        -> ty::adjustment::CustomCoerceUnsized,
+    pub coerce_unsized_info: ItemSignature(DefId)
+        -> ty::adjustment::CoerceUnsizedInfo,
+
+    pub typeck_item_bodies: typeck_item_bodies_dep_node(CrateNum) -> CompileResult,
 
     pub typeck_tables: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>,
 
     pub coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (),
 
-    pub coherent_inherent_impls: coherent_inherent_impls_dep_node(CrateNum) -> (),
+    /// Gets a complete map from all types to their inherent impls.
+    /// Not meant to be used directly outside of coherence.
+    /// (Defined only for LOCAL_CRATE)
+    pub crate_inherent_impls: crate_inherent_impls_dep_node(CrateNum) -> CrateInherentImpls,
+
+    /// Checks all types in the krate for overlap in their inherent impls. Reports errors.
+    /// Not meant to be used directly outside of coherence.
+    /// (Defined only for LOCAL_CRATE)
+    pub crate_inherent_impls_overlap_check: crate_inherent_impls_dep_node(CrateNum) -> (),
 
     /// Results of evaluating monomorphic constants embedded in
     /// other items, such as enum variant explicit discriminants.
     pub monomorphic_const_eval: MonomorphicConstEval(DefId) -> Result<ConstVal<'tcx>, ()>,
 
+    /// Performs the privacy check and computes "access levels".
+    pub privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Rc<AccessLevels>,
+
     pub mir_shims: mir_shim(ty::InstanceDef<'tcx>) -> &'tcx RefCell<mir::Mir<'tcx>>
 }
 
@@ -413,10 +447,14 @@ fn coherent_trait_dep_node((_, def_id): (CrateNum, DefId)) -> DepNode<DefId> {
     DepNode::CoherenceCheckTrait(def_id)
 }
 
-fn coherent_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
+fn crate_inherent_impls_dep_node(_: CrateNum) -> DepNode<DefId> {
     DepNode::Coherence
 }
 
 fn mir_shim(instance: ty::InstanceDef) -> DepNode<DefId> {
     instance.dep_node()
 }
+
+fn typeck_item_bodies_dep_node(_: CrateNum) -> DepNode<DefId> {
+    DepNode::TypeckBodiesKrate
+}
index c4192ffc697cecefaad97bae83db8aaddf5b5be1..6a4e7db21dd127d2d20bf57cb32a2517e4b1d0d1 100644 (file)
 
 use dep_graph::{self, DepNode};
 use hir::{map as hir_map, FreevarMap, TraitMap};
-use middle;
 use hir::def::{Def, CtorKind, ExportMap};
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
+use middle::privacy::AccessLevels;
 use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
 use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
@@ -31,7 +31,7 @@
 use ty::util::IntTypeExt;
 use ty::walk::TypeWalker;
 use util::common::MemoizationMap;
-use util::nodemap::{NodeSet, FxHashMap};
+use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
 
 use serialize::{self, Encodable, Encoder};
 use std::borrow::Cow;
 
 /// The complete set of all analyses described in this module. This is
 /// produced by the driver and fed to trans and later passes.
+///
+/// NB: These contents are being migrated into queries using the
+/// *on-demand* infrastructure.
 #[derive(Clone)]
 pub struct CrateAnalysis {
-    pub export_map: ExportMap,
-    pub access_levels: middle::privacy::AccessLevels,
+    pub access_levels: Rc<AccessLevels>,
     pub reachable: NodeSet,
     pub name: String,
     pub glob_map: Option<hir::GlobMap>,
@@ -122,6 +124,7 @@ pub struct Resolutions {
     pub freevars: FreevarMap,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
+    pub export_map: ExportMap,
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -2054,60 +2057,12 @@ pub fn trait_relevant_for_never(self, did: DefId) -> bool {
         })
     }
 
-    pub fn custom_coerce_unsized_kind(self, did: DefId) -> adjustment::CustomCoerceUnsized {
-        queries::custom_coerce_unsized_kind::get(self, DUMMY_SP, did)
+    pub fn coerce_unsized_info(self, did: DefId) -> adjustment::CoerceUnsizedInfo {
+        queries::coerce_unsized_info::get(self, DUMMY_SP, did)
     }
 
     pub fn associated_item(self, def_id: DefId) -> AssociatedItem {
-        if !def_id.is_local() {
-            return queries::associated_item::get(self, DUMMY_SP, def_id);
-        }
-
-        self.maps.associated_item.memoize(def_id, || {
-            // When the user asks for a given associated item, we
-            // always go ahead and convert all the associated items in
-            // the container. Note that we are also careful only to
-            // ever register a read on the *container* of the assoc
-            // item, not the assoc item itself. This prevents changes
-            // in the details of an item (for example, the type to
-            // which an associated type is bound) from contaminating
-            // those tasks that just need to scan the names of items
-            // and so forth.
-
-            let id = self.hir.as_local_node_id(def_id).unwrap();
-            let parent_id = self.hir.get_parent(id);
-            let parent_def_id = self.hir.local_def_id(parent_id);
-            let parent_item = self.hir.expect_item(parent_id);
-            match parent_item.node {
-                hir::ItemImpl(.., ref impl_trait_ref, _, ref impl_item_refs) => {
-                    for impl_item_ref in impl_item_refs {
-                        let assoc_item =
-                            self.associated_item_from_impl_item_ref(parent_def_id,
-                                                                    impl_trait_ref.is_some(),
-                                                                    impl_item_ref);
-                        self.maps.associated_item.borrow_mut()
-                            .insert(assoc_item.def_id, assoc_item);
-                    }
-                }
-
-                hir::ItemTrait(.., ref trait_item_refs) => {
-                    for trait_item_ref in trait_item_refs {
-                        let assoc_item =
-                            self.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
-                        self.maps.associated_item.borrow_mut()
-                            .insert(assoc_item.def_id, assoc_item);
-                    }
-                }
-
-                ref r => {
-                    panic!("unexpected container of associated items: {:?}", r)
-                }
-            }
-
-            // memoize wants us to return something, so return
-            // the one we generated for this def-id
-            *self.maps.associated_item.borrow().get(&def_id).unwrap()
-        })
+        queries::associated_item::get(self, DUMMY_SP, def_id)
     }
 
     fn associated_item_from_trait_item_ref(self,
@@ -2393,34 +2348,6 @@ pub fn trait_has_default_impl(self, trait_def_id: DefId) -> bool {
         def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
     }
 
-    /// Populates the type context with all the inherent implementations for
-    /// the given type if necessary.
-    pub fn populate_inherent_implementations_for_type_if_necessary(self,
-                                                                   span: Span,
-                                                                   type_id: DefId) {
-        if type_id.is_local() {
-            // Make sure coherence of inherent impls ran already.
-            ty::queries::coherent_inherent_impls::force(self, span, LOCAL_CRATE);
-            return
-        }
-
-        // The type is not local, hence we are reading this out of
-        // metadata and don't need to track edges.
-        let _ignore = self.dep_graph.in_ignore();
-
-        if self.populated_external_types.borrow().contains(&type_id) {
-            return
-        }
-
-        debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}",
-               type_id);
-
-        let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id);
-
-        self.maps.inherent_impls.borrow_mut().insert(type_id, inherent_impls);
-        self.populated_external_types.borrow_mut().insert(type_id);
-    }
-
     /// Populates the type context with all the implementations for the given
     /// trait if necessary.
     pub fn populate_implementations_for_trait_if_necessary(self, trait_id: DefId) {
@@ -2643,3 +2570,58 @@ pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
         }
     }
 }
+
+fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
+    -> AssociatedItem
+{
+    let id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let parent_id = tcx.hir.get_parent(id);
+    let parent_def_id = tcx.hir.local_def_id(parent_id);
+    let parent_item = tcx.hir.expect_item(parent_id);
+    match parent_item.node {
+        hir::ItemImpl(.., ref impl_trait_ref, _, ref impl_item_refs) => {
+            if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.node_id == id) {
+                let assoc_item =
+                    tcx.associated_item_from_impl_item_ref(parent_def_id,
+                                                            impl_trait_ref.is_some(),
+                                                            impl_item_ref);
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        hir::ItemTrait(.., ref trait_item_refs) => {
+            if let Some(trait_item_ref) = trait_item_refs.iter().find(|i| i.id.node_id == id) {
+                let assoc_item =
+                    tcx.associated_item_from_trait_item_ref(parent_def_id, trait_item_ref);
+                debug_assert_eq!(assoc_item.def_id, def_id);
+                return assoc_item;
+            }
+        }
+
+        ref r => {
+            panic!("unexpected container of associated items: {:?}", r)
+        }
+    }
+    panic!("associated item not found for def_id: {:?}", def_id);
+}
+
+pub fn provide(providers: &mut ty::maps::Providers) {
+    *providers = ty::maps::Providers {
+        associated_item,
+        ..*providers
+    };
+}
+
+
+/// A map for the local crate mapping each type to a vector of its
+/// inherent impls. This is not meant to be used outside of coherence;
+/// rather, you should request the vector for a specific type via
+/// `ty::queries::inherent_impls::get(def_id)` so as to minimize your
+/// dependencies (constructing this map requires touching the entire
+/// crate).
+#[derive(Clone, Debug)]
+pub struct CrateInherentImpls {
+    pub inherent_impls: DefIdMap<Rc<Vec<DefId>>>,
+}
+
index 49824e8a738d7a74e5a5204d31cfa1a5cbc6ef70..9126600e3f65393d2eff900e06bcbd077535be8d 100644 (file)
@@ -293,11 +293,13 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             RegionsNoOverlap(a, b) => {
                 return tcx.lift(&(a, b)).map(|(a, b)| RegionsNoOverlap(a, b))
             }
-            RegionsInsufficientlyPolymorphic(a, b) => {
-                return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b))
+            RegionsInsufficientlyPolymorphic(a, b, ref c) => {
+                let c = c.clone();
+                return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b, c))
             }
-            RegionsOverlyPolymorphic(a, b) => {
-                return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b))
+            RegionsOverlyPolymorphic(a, b, ref c) => {
+                let c = c.clone();
+                return tcx.lift(&b).map(|b| RegionsOverlyPolymorphic(a, b, c))
             }
             IntMismatch(x) => IntMismatch(x),
             FloatMismatch(x) => FloatMismatch(x),
index 85e861b405a9f8620b9480902e0208ce33666abd..730abc54568e1364e12747db4329b8caea0acd1d 100644 (file)
@@ -11,7 +11,7 @@ crate-type = ["dylib"]
 [dependencies]
 syntax = { path = "../libsyntax" }
 serialize = { path = "../libserialize" }
-log = { path = "../liblog" }
+log = "0.3"
 
 [features]
 jemalloc = []
index d53318f1768480674f384b513b06e281fda7ff82..af99c0e938724d95023ff8c3831fdbb6e3d44670 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 graphviz = { path = "../libgraphviz" }
index c0f681680a967b0350e27146d28486ae89a6c48b..b728d4d534516672e436312a336f40f627017943 100644 (file)
@@ -267,11 +267,11 @@ pub fn fixup_fragment_sets<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx
     // First, filter out duplicates
     moved.sort();
     moved.dedup();
-    debug!("fragments 1 moved: {:?}", path_lps(&moved[..]));
+    debug!("fragments 1 moved: {:?}", path_lps(&moved));
 
     assigned.sort();
     assigned.dedup();
-    debug!("fragments 1 assigned: {:?}", path_lps(&assigned[..]));
+    debug!("fragments 1 assigned: {:?}", path_lps(&assigned));
 
     // Second, build parents from the moved and assigned.
     for m in &moved {
@@ -291,14 +291,14 @@ pub fn fixup_fragment_sets<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx
 
     parents.sort();
     parents.dedup();
-    debug!("fragments 2 parents: {:?}", path_lps(&parents[..]));
+    debug!("fragments 2 parents: {:?}", path_lps(&parents));
 
     // Third, filter the moved and assigned fragments down to just the non-parents
-    moved.retain(|f| non_member(*f, &parents[..]));
-    debug!("fragments 3 moved: {:?}", path_lps(&moved[..]));
+    moved.retain(|f| non_member(*f, &parents));
+    debug!("fragments 3 moved: {:?}", path_lps(&moved));
 
-    assigned.retain(|f| non_member(*f, &parents[..]));
-    debug!("fragments 3 assigned: {:?}", path_lps(&assigned[..]));
+    assigned.retain(|f| non_member(*f, &parents));
+    debug!("fragments 3 assigned: {:?}", path_lps(&assigned));
 
     // Fourth, build the leftover from the moved, assigned, and parents.
     for m in &moved {
@@ -316,16 +316,16 @@ pub fn fixup_fragment_sets<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx
 
     unmoved.sort();
     unmoved.dedup();
-    debug!("fragments 4 unmoved: {:?}", frag_lps(&unmoved[..]));
+    debug!("fragments 4 unmoved: {:?}", frag_lps(&unmoved));
 
     // Fifth, filter the leftover fragments down to its core.
     unmoved.retain(|f| match *f {
         AllButOneFrom(_) => true,
-        Just(mpi) => non_member(mpi, &parents[..]) &&
-            non_member(mpi, &moved[..]) &&
-            non_member(mpi, &assigned[..])
+        Just(mpi) => non_member(mpi, &parents) &&
+            non_member(mpi, &moved) &&
+            non_member(mpi, &assigned)
     });
-    debug!("fragments 5 unmoved: {:?}", frag_lps(&unmoved[..]));
+    debug!("fragments 5 unmoved: {:?}", frag_lps(&unmoved));
 
     // Swap contents back in.
     fragments.unmoved_fragments = unmoved;
index 28b6c7a13f1713cb2c4bea107725d2e80cc4081a..cedb9e1cd1cfffc6c1b0df1b98cc60dcd6ec0982 100644 (file)
@@ -188,14 +188,6 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
             // user knows what they're doing in these cases.
             Ok(())
         }
-        (mc::Aliasability::ImmutableUnique(_), ty::MutBorrow) => {
-            bccx.report_aliasability_violation(
-                        borrow_span,
-                        loan_cause,
-                        mc::AliasableReason::UnaliasableImmutable,
-                        cmt);
-            Err(())
-        }
         (mc::Aliasability::FreelyAliasable(alias_cause), ty::UniqueImmBorrow) |
         (mc::Aliasability::FreelyAliasable(alias_cause), ty::MutBorrow) => {
             bccx.report_aliasability_violation(
@@ -510,4 +502,3 @@ pub fn report_potential_errors(&self) {
         self.move_error_collector.report_potential_errors(self.bccx);
     }
 }
-
index 20d495976b05f47a8c1ece2b23566775f8fee3bd..0915c57b588eb1a7c2c33b091682fd4fce4790e7 100644 (file)
@@ -34,6 +34,7 @@
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization as mc;
 use rustc::middle::mem_categorization::Categorization;
+use rustc::middle::mem_categorization::ImmutabilityBlame;
 use rustc::middle::region;
 use rustc::ty::{self, TyCtxt};
 
@@ -112,7 +113,7 @@ fn borrowck_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, body_id: hir::BodyId) {
                                                  &flowed_moves.move_data,
                                                  owner_id);
 
-    check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans[..], body);
+    check_loans::check_loans(bccx, &loan_dfcx, &flowed_moves, &all_loans, body);
 }
 
 fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
@@ -659,12 +660,10 @@ pub fn span_err_with_code<S: Into<MultiSpan>>(&self, s: S, msg: &str, code: &str
         self.tcx.sess.span_err_with_code(s, msg, code);
     }
 
-    pub fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
+    fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
         let span = err.span.clone();
-        let mut immutable_field = None;
-        let mut local_def = None;
 
-        let msg = &match err.code {
+        let msg = match err.code {
             err_mutbl => {
                 let descr = match err.cmt.note {
                     mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => {
@@ -700,27 +699,6 @@ pub fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
                     BorrowViolation(euv::AutoUnsafe) |
                     BorrowViolation(euv::ForLoop) |
                     BorrowViolation(euv::MatchDiscriminant) => {
-                        // Check for this field's definition to see if it is an immutable reference
-                        // and suggest making it mutable if that is the case.
-                        immutable_field = err.cmt.get_field_name()
-                            .and_then(|name| err.cmt.get_field(name))
-                            .and_then(|did| self.tcx.hir.as_local_node_id(did))
-                            .and_then(|nid| {
-                                if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(nid) {
-                                    return self.suggest_mut_for_immutable(&field.ty)
-                                        .map(|msg| (self.tcx.hir.span(nid), msg));
-                                }
-                                None
-                            });
-                        local_def = err.cmt.get_def()
-                            .and_then(|nid| {
-                                if !self.tcx.hir.is_argument(nid) {
-                                    Some(self.tcx.hir.span(nid))
-                                } else {
-                                    None
-                                }
-                            });
-
                         format!("cannot borrow {} as mutable", descr)
                     }
                     BorrowViolation(euv::ClosureInvocation) => {
@@ -746,16 +724,7 @@ pub fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> {
             }
         };
 
-        let mut db = self.struct_span_err(span, msg);
-        if let Some((span, msg)) = immutable_field {
-            db.span_label(span, &msg);
-        }
-        if let Some(let_span) = local_def {
-            if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
-                db.span_label(let_span, &format!("consider changing this to `mut {}`", snippet));
-            }
-        }
-        db
+        self.struct_span_err(span, &msg)
     }
 
     pub fn report_aliasability_violation(&self,
@@ -788,55 +757,49 @@ pub fn report_aliasability_violation(&self,
             }
         };
 
-        let mut err = match cause {
-            mc::AliasableOther => {
-                struct_span_err!(
-                    self.tcx.sess, span, E0385,
-                    "{} in an aliasable location", prefix)
-            }
-            mc::AliasableReason::UnaliasableImmutable => {
-                struct_span_err!(
-                    self.tcx.sess, span, E0386,
-                    "{} in an immutable container", prefix)
+        match cause {
+            mc::AliasableStatic |
+            mc::AliasableStaticMut => {
+                // This path cannot occur. It happens when we have an
+                // `&mut` or assignment to a static. But in the case
+                // of `static X`, we get a mutability violation first,
+                // and never get here. In the case of `static mut X`,
+                // that is unsafe and hence the aliasability error is
+                // ignored.
+                span_bug!(span, "aliasability violation for static `{}`", prefix)
             }
-            mc::AliasableClosure(id) => {
+            mc::AliasableBorrowed => {}
+        };
+        let blame = cmt.immutability_blame();
+        let mut err = match blame {
+            Some(ImmutabilityBlame::ClosureEnv(id)) => {
                 let mut err = struct_span_err!(
                     self.tcx.sess, span, E0387,
                     "{} in a captured outer variable in an `Fn` closure", prefix);
-                if let BorrowViolation(euv::ClosureCapture(_)) = kind {
+
+                // FIXME: the distinction between these 2 messages looks wrong.
+                let help = if let BorrowViolation(euv::ClosureCapture(_)) = kind {
                     // The aliasability violation with closure captures can
                     // happen for nested closures, so we know the enclosing
                     // closure incorrectly accepts an `Fn` while it needs to
                     // be `FnMut`.
-                    span_help!(&mut err, self.tcx.hir.span(id),
-                           "consider changing this to accept closures that implement `FnMut`");
+                    "consider changing this to accept closures that implement `FnMut`"
+
                 } else {
-                    span_help!(&mut err, self.tcx.hir.span(id),
-                           "consider changing this closure to take self by mutable reference");
-                }
+                    "consider changing this closure to take self by mutable reference"
+                };
+                err.span_help(self.tcx.hir.span(id), help);
                 err
             }
-            mc::AliasableStatic |
-            mc::AliasableStaticMut => {
-                // This path cannot occur. It happens when we have an
-                // `&mut` or assignment to a static. But in the case
-                // of `static X`, we get a mutability violation first,
-                // and never get here. In the case of `static mut X`,
-                // that is unsafe and hence the aliasability error is
-                // ignored.
-                span_bug!(span, "aliasability violation for static `{}`", prefix)
-            }
-            mc::AliasableBorrowed => {
-                let mut e = struct_span_err!(
+            _ =>  {
+                let mut err = struct_span_err!(
                     self.tcx.sess, span, E0389,
                     "{} in a `&` reference", prefix);
-                e.span_label(span, &"assignment into an immutable reference");
-                if let Some(nid) = cmt.get_arg_if_immutable(&self.tcx.hir) {
-                    self.immutable_argument_should_be_mut(nid, &mut e);
-                }
-                e
+                err.span_label(span, &"assignment into an immutable reference");
+                err
             }
         };
+        self.note_immutability_blame(&mut err, blame);
 
         if is_closure {
             err.help("closures behind references must be called via `&mut`");
@@ -845,49 +808,124 @@ pub fn report_aliasability_violation(&self,
     }
 
     /// Given a type, if it is an immutable reference, return a suggestion to make it mutable
-    fn suggest_mut_for_immutable(&self, pty: &hir::Ty) -> Option<String> {
+    fn suggest_mut_for_immutable(&self, pty: &hir::Ty, is_implicit_self: bool) -> Option<String> {
         // Check wether the argument is an immutable reference
+        debug!("suggest_mut_for_immutable({:?}, {:?})", pty, is_implicit_self);
         if let hir::TyRptr(lifetime, hir::MutTy {
             mutbl: hir::Mutability::MutImmutable,
             ref ty
         }) = pty.node {
             // Account for existing lifetimes when generating the message
-            if !lifetime.is_elided() {
-                if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(ty.span) {
-                    if let Ok(lifetime_snippet) = self.tcx.sess.codemap()
-                        .span_to_snippet(lifetime.span) {
-                            return Some(format!("use `&{} mut {}` here to make mutable",
-                                                lifetime_snippet,
-                                                snippet));
-                    }
-                }
-            } else if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(pty.span) {
-                if snippet.starts_with("&") {
-                    return Some(format!("use `{}` here to make mutable",
-                                        snippet.replace("&", "&mut ")));
-                }
+            let pointee_snippet = match self.tcx.sess.codemap().span_to_snippet(ty.span) {
+                Ok(snippet) => snippet,
+                _ => return None
+            };
+
+            let lifetime_snippet = if !lifetime.is_elided() {
+                format!("{} ", match self.tcx.sess.codemap().span_to_snippet(lifetime.span) {
+                    Ok(lifetime_snippet) => lifetime_snippet,
+                    _ => return None
+                })
             } else {
-                bug!("couldn't find a snippet for span: {:?}", pty.span);
-            }
+                String::new()
+            };
+            Some(format!("use `&{}mut {}` here to make mutable",
+                         lifetime_snippet,
+                         if is_implicit_self { "self" } else { &*pointee_snippet }))
+        } else {
+            None
         }
-        None
     }
 
-    fn immutable_argument_should_be_mut(&self, nid: ast::NodeId, db: &mut DiagnosticBuilder) {
-        let parent = self.tcx.hir.get_parent_node(nid);
+    fn local_binding_mode(&self, node_id: ast::NodeId) -> hir::BindingMode {
+        let pat = match self.tcx.hir.get(node_id) {
+            hir_map::Node::NodeLocal(pat) => pat,
+            node => bug!("bad node for local: {:?}", node)
+        };
+
+        match pat.node {
+            hir::PatKind::Binding(mode, ..) => mode,
+            _ => bug!("local is not a binding: {:?}", pat)
+        }
+    }
+
+    fn local_ty(&self, node_id: ast::NodeId) -> (Option<&hir::Ty>, bool) {
+        let parent = self.tcx.hir.get_parent_node(node_id);
         let parent_node = self.tcx.hir.get(parent);
 
         // The parent node is like a fn
         if let Some(fn_like) = FnLikeNode::from_node(parent_node) {
             // `nid`'s parent's `Body`
             let fn_body = self.tcx.hir.body(fn_like.body());
-            // Get the position of `nid` in the arguments list
-            let arg_pos = fn_body.arguments.iter().position(|arg| arg.pat.id == nid);
+            // Get the position of `node_id` in the arguments list
+            let arg_pos = fn_body.arguments.iter().position(|arg| arg.pat.id == node_id);
             if let Some(i) = arg_pos {
                 // The argument's `Ty`
-                let arg_ty = &fn_like.decl().inputs[i];
-                if let Some(msg) = self.suggest_mut_for_immutable(&arg_ty) {
-                    db.span_label(arg_ty.span, &msg);
+                (Some(&fn_like.decl().inputs[i]),
+                 i == 0 && fn_like.decl().has_implicit_self)
+            } else {
+                (None, false)
+            }
+        } else {
+            (None, false)
+        }
+    }
+
+    fn note_immutability_blame(&self,
+                               db: &mut DiagnosticBuilder,
+                               blame: Option<ImmutabilityBlame>) {
+        match blame {
+            None => {}
+            Some(ImmutabilityBlame::ClosureEnv(_)) => {}
+            Some(ImmutabilityBlame::ImmLocal(node_id)) => {
+                let let_span = self.tcx.hir.span(node_id);
+                if let hir::BindingMode::BindByValue(..) = self.local_binding_mode(node_id) {
+                    if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
+                        let (_, is_implicit_self) = self.local_ty(node_id);
+                        if is_implicit_self && snippet != "self" {
+                            // avoid suggesting `mut &self`.
+                            return
+                        }
+                        db.span_label(
+                            let_span,
+                            &format!("consider changing this to `mut {}`", snippet)
+                        );
+                    }
+                }
+            }
+            Some(ImmutabilityBlame::LocalDeref(node_id)) => {
+                let let_span = self.tcx.hir.span(node_id);
+                match self.local_binding_mode(node_id) {
+                    hir::BindingMode::BindByRef(..) => {
+                        let snippet = self.tcx.sess.codemap().span_to_snippet(let_span);
+                        if let Ok(snippet) = snippet {
+                            db.span_label(
+                                let_span,
+                                &format!("consider changing this to `{}`",
+                                         snippet.replace("ref ", "ref mut "))
+                            );
+                        }
+                    }
+                    hir::BindingMode::BindByValue(..) => {
+                        if let (Some(local_ty), is_implicit_self) = self.local_ty(node_id) {
+                            if let Some(msg) =
+                                 self.suggest_mut_for_immutable(local_ty, is_implicit_self) {
+                                db.span_label(local_ty.span, &msg);
+                            }
+                        }
+                    }
+                }
+            }
+            Some(ImmutabilityBlame::AdtFieldDeref(_, field)) => {
+                let node_id = match self.tcx.hir.as_local_node_id(field.did) {
+                    Some(node_id) => node_id,
+                    None => return
+                };
+
+                if let hir_map::Node::NodeField(ref field) = self.tcx.hir.get(node_id) {
+                    if let Some(msg) = self.suggest_mut_for_immutable(&field.ty, false) {
+                        db.span_label(field.ty.span, &msg);
+                    }
                 }
             }
         }
@@ -941,10 +979,13 @@ fn region_end_span(&self, region: &'tcx ty::Region) -> Option<Span> {
         }
     }
 
-    pub fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>) {
+    fn note_and_explain_bckerr(&self, db: &mut DiagnosticBuilder, err: BckError<'tcx>) {
         let error_span = err.span.clone();
         match err.code {
-            err_mutbl => self.note_and_explain_mutbl_error(db, &err, &error_span),
+            err_mutbl => {
+                self.note_and_explain_mutbl_error(db, &err, &error_span);
+                self.note_immutability_blame(db, err.cmt.immutability_blame());
+            }
             err_out_of_scope(super_scope, sub_scope, cause) => {
                 let (value_kind, value_msg) = match err.cmt.cat {
                     mc::Categorization::Rvalue(..) =>
@@ -1096,13 +1137,6 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
             _ => {
                 if let Categorization::Deref(..) = err.cmt.cat {
                     db.span_label(*error_span, &"cannot borrow as mutable");
-                    if let Some(local_id) = err.cmt.get_arg_if_immutable(&self.tcx.hir) {
-                        self.immutable_argument_should_be_mut(local_id, db);
-                    } else if let Categorization::Deref(ref inner_cmt, ..) = err.cmt.cat {
-                        if let Categorization::Local(local_id) = inner_cmt.cat {
-                            self.immutable_argument_should_be_mut(local_id, db);
-                        }
-                    }
                 } else if let Categorization::Local(local_id) = err.cmt.cat {
                     let span = self.tcx.hir.span(local_id);
                     if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
@@ -1110,14 +1144,6 @@ fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckErro
                             db.span_label(*error_span, &format!("cannot reborrow mutably"));
                             db.span_label(*error_span, &format!("try removing `&mut` here"));
                         } else {
-                            if snippet.starts_with("ref ") {
-                                db.span_label(span, &format!("use `{}` here to make mutable",
-                                                             snippet.replace("ref ", "ref mut ")));
-                            } else if snippet != "self" {
-                                db.span_label(span,
-                                              &format!("use `mut {}` here to make mutable",
-                                                       snippet));
-                            }
                             db.span_label(*error_span, &format!("cannot borrow mutably"));
                         }
                     } else {
index db4a1701e976b9ec4f9ff1506c05265986157675..bfd342a9f213465a9e52b7630bce4e85672cd8e0 100644 (file)
@@ -198,7 +198,7 @@ fn main() {
 ```
 "##,
 
-E0386: r##"
+/*E0386: r##"
 This error occurs when an attempt is made to mutate the target of a mutable
 reference stored inside an immutable container.
 
@@ -228,7 +228,7 @@ fn main() {
 let y: Box<Cell<_>> = Box::new(Cell::new(x));
 y.set(2);
 ```
-"##,
+"##,*/
 
 E0387: r##"
 This error occurs when an attempt is made to mutate or mutably reference data
@@ -1117,6 +1117,6 @@ fn main() {
 }
 
 register_diagnostics! {
-    E0385, // {} in an aliasable location
+//    E0385, // {} in an aliasable location
     E0524, // two closures require unique access to `..` at the same time
 }
index 0da9525efd8566e53520961e8b4addd8e9231a94..e3a2bfa392738586fe06cd374082d3222c6bf50d 100644 (file)
@@ -88,7 +88,7 @@ fn build_set<O:DataFlowOperator, F>(&self,
                 set.push_str(", ");
             }
             let loan_str = self.borrowck_ctxt.loan_path_to_string(&lp);
-            set.push_str(&loan_str[..]);
+            set.push_str(&loan_str);
             saw_some = true;
             true
         });
index 780b2c16a32ecefc5bd556d2a88b6409b9246554..907410f74dca4f268697e32d036a606894924996 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 arena = { path = "../libarena" }
-log = { path = "../liblog" }
+log = "0.3"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
index 53a7e87292818d773a7af3dfcd859d0b8467adcd..c1dc5f5f7a2b8d10e0f5a99565480dfab83f9993 100644 (file)
@@ -680,10 +680,10 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
     }).collect();
     let wild_patterns: Vec<_> = wild_patterns_owned.iter().collect();
     let matrix = Matrix(m.iter().flat_map(|r| {
-        specialize(cx, &r[..], &ctor, &wild_patterns)
+        specialize(cx, &r, &ctor, &wild_patterns)
     }).collect());
     match specialize(cx, v, &ctor, &wild_patterns) {
-        Some(v) => match is_useful(cx, &matrix, &v[..], witness) {
+        Some(v) => match is_useful(cx, &matrix, &v, witness) {
             UsefulWithWitness(witnesses) => UsefulWithWitness(
                 witnesses.into_iter()
                     .map(|witness| witness.apply_constructor(cx, &ctor, lty))
index e2b9f174ff0c200a6e174347d0e85cf5c7239fff..9d55281d019d9ee579a4d755e47b6303d674ec04 100644 (file)
@@ -311,7 +311,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         for &(pat, hir_pat) in pats {
             let v = vec![pat];
 
-            match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
+            match is_useful(cx, &seen, &v, LeaveOutWitness) {
                 NotUseful => {
                     match source {
                         hir::MatchSource::IfLetDesugar { .. } => {
index e2e16059d98718c534335bf277927d4cb35c7853..343b1ed68b80431cb3e734dff8adc4764073cd87 100644 (file)
@@ -9,5 +9,5 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 serialize = { path = "../libserialize" }
index d4bd9e707fdcb9780a618a6ba30151061b479109..c03c2890ba34c6cb4723c3eb00ed514a8bf2e5a5 100644 (file)
@@ -91,8 +91,8 @@ impl<A: Array> Deref for AccumulateVec<A> {
     type Target = [A::Element];
     fn deref(&self) -> &Self::Target {
         match *self {
-            AccumulateVec::Array(ref v) => &v[..],
-            AccumulateVec::Heap(ref v) => &v[..],
+            AccumulateVec::Array(ref v) => v,
+            AccumulateVec::Heap(ref v) => v,
         }
     }
 }
@@ -100,8 +100,8 @@ fn deref(&self) -> &Self::Target {
 impl<A: Array> DerefMut for AccumulateVec<A> {
     fn deref_mut(&mut self) -> &mut [A::Element] {
         match *self {
-            AccumulateVec::Array(ref mut v) => &mut v[..],
-            AccumulateVec::Heap(ref mut v) => &mut v[..],
+            AccumulateVec::Array(ref mut v) => v,
+            AccumulateVec::Heap(ref mut v) => v,
         }
     }
 }
index 4359581a897f57153df7e6179f8bb9f4ba553548..cf54229fa7f52e59130cbd39c43ee7656c90d1f4 100644 (file)
@@ -48,7 +48,7 @@ pub fn encode(n: u64, base: u64) -> String {
 #[test]
 fn test_encode() {
     fn test(n: u64, base: u64) {
-        assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base)[..], base as u32));
+        assert_eq!(Ok(n), u64::from_str_radix(&encode(n, base), base as u32));
     }
 
     for base in 2..37 {
index 31492e2621945dd292d556f556fd61d4a3d36fb6..9d97a83f693c32f7cb528def5b49ff3ac47f1178 100644 (file)
@@ -35,7 +35,7 @@ pub struct Blake2bCtx {
 impl ::std::fmt::Debug for Blake2bCtx {
     fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
         try!(write!(fmt, "hash: "));
-        for v in &self.h[..] {
+        for v in &self.h {
             try!(write!(fmt, "{:x}", v));
         }
         Ok(())
index 2e9e054e97eafe7dd0172d5f116710d65f1c7669..572ce98d3ae8e30a0f19a8b9a69b887c9873eb3e 100644 (file)
@@ -91,13 +91,13 @@ unsafe fn from_slice_mut(s: &mut [Word]) -> &mut Self {
 impl<T: Idx> Deref for IdxSetBuf<T> {
     type Target = IdxSet<T>;
     fn deref(&self) -> &IdxSet<T> {
-        unsafe { IdxSet::from_slice(&self.bits[..]) }
+        unsafe { IdxSet::from_slice(&self.bits) }
     }
 }
 
 impl<T: Idx> DerefMut for IdxSetBuf<T> {
     fn deref_mut(&mut self) -> &mut IdxSet<T> {
-        unsafe { IdxSet::from_slice_mut(&mut self.bits[..]) }
+        unsafe { IdxSet::from_slice_mut(&mut self.bits) }
     }
 }
 
@@ -135,11 +135,11 @@ pub fn contains(&self, elem: &T) -> bool {
     }
 
     pub fn words(&self) -> &[Word] {
-        &self.bits[..]
+        &self.bits
     }
 
     pub fn words_mut(&mut self) -> &mut [Word] {
-        &mut self.bits[..]
+        &mut self.bits
     }
 
     pub fn clone_from(&mut self, other: &IdxSet<T>) {
index caa5c8b7e00581562638ea76af04f39571305455..5b5113caa8e8c0dd9d68e7e8078b71991efa107e 100644 (file)
@@ -11,7 +11,8 @@ crate-type = ["dylib"]
 [dependencies]
 arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
-log = { path = "../liblog" }
+log = { version = "0.3", features = ["release_max_level_info"] }
+env_logger = { version = "0.4", default-features = false }
 proc_macro_plugin = { path = "../libproc_macro_plugin" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
index 5d600270626cb0ebc9c65ab9b32d58697233b2e4..4873b21c548740f98480346794ea5abc76309c64 100644 (file)
@@ -48,6 +48,7 @@
 use std::io::{self, Write};
 use std::iter;
 use std::path::{Path, PathBuf};
+use std::rc::Rc;
 use syntax::{ast, diagnostics, visit};
 use syntax::attr;
 use syntax::ext::base::ExtCtxt;
@@ -198,13 +199,13 @@ macro_rules! controller_entry_point {
 
             result?;
 
-            if log_enabled!(::log::INFO) {
+            if log_enabled!(::log::LogLevel::Info) {
                 println!("Pre-trans");
                 tcx.print_debug_stats();
             }
             let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map);
 
-            if log_enabled!(::log::INFO) {
+            if log_enabled!(::log::LogLevel::Info) {
                 println!("Post-trans");
                 tcx.print_debug_stats();
             }
@@ -257,10 +258,7 @@ fn keep_hygiene_data(sess: &Session) -> bool {
 }
 
 fn keep_ast(sess: &Session) -> bool {
-    sess.opts.debugging_opts.keep_ast ||
-    sess.opts.debugging_opts.save_analysis ||
-    sess.opts.debugging_opts.save_analysis_csv ||
-    sess.opts.debugging_opts.save_analysis_api
+    sess.opts.debugging_opts.keep_ast || ::save_analysis(sess)
 }
 
 /// The name used for source code that doesn't originate in a file
@@ -807,18 +805,18 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         expanded_crate: krate,
         defs: resolver.definitions,
         analysis: ty::CrateAnalysis {
-            export_map: resolver.export_map,
-            access_levels: AccessLevels::default(),
+            access_levels: Rc::new(AccessLevels::default()),
             reachable: NodeSet(),
             name: crate_name.to_string(),
             glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
         },
         resolutions: Resolutions {
             freevars: resolver.freevars,
+            export_map: resolver.export_map,
             trait_map: resolver.trait_map,
             maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
         },
-        hir_forest: hir_forest
+        hir_forest: hir_forest,
     })
 }
 
@@ -888,7 +886,9 @@ macro_rules! try_with_f {
 
     let mut local_providers = ty::maps::Providers::default();
     mir::provide(&mut local_providers);
+    rustc_privacy::provide(&mut local_providers);
     typeck::provide(&mut local_providers);
+    ty::provide(&mut local_providers);
 
     let mut extern_providers = ty::maps::Providers::default();
     cstore::provide(&mut extern_providers);
@@ -930,9 +930,7 @@ macro_rules! try_with_f {
              || consts::check_crate(tcx));
 
         analysis.access_levels =
-            time(time_passes, "privacy checking", || {
-                rustc_privacy::check_crate(tcx, &analysis.export_map)
-            });
+            time(time_passes, "privacy checking", || rustc_privacy::check_crate(tcx));
 
         time(time_passes,
              "intrinsic checking",
@@ -999,19 +997,15 @@ macro_rules! try_with_f {
         analysis.reachable =
             time(time_passes,
                  "reachability checking",
-                 || reachable::find_reachable(tcx, &analysis.access_levels));
+                 || reachable::find_reachable(tcx));
 
-        time(time_passes, "death checking", || {
-            middle::dead::check_crate(tcx, &analysis.access_levels);
-        });
+        time(time_passes, "death checking", || middle::dead::check_crate(tcx));
 
         time(time_passes, "unused lib feature checking", || {
-            stability::check_unused_or_stable_features(tcx, &analysis.access_levels)
+            stability::check_unused_or_stable_features(tcx)
         });
 
-        time(time_passes,
-             "lint checking",
-             || lint::check_crate(tcx, &analysis.access_levels));
+        time(time_passes, "lint checking", || lint::check_crate(tcx));
 
         // The above three passes generate errors w/o aborting
         if sess.err_count() > 0 {
index 62d75126557284b806dcdf173c991fedf7c14bbb..c90dde3a5f6e0232694ae37dec7e11e70c91b446 100644 (file)
@@ -35,6 +35,7 @@
 extern crate arena;
 extern crate getopts;
 extern crate graphviz;
+extern crate env_logger;
 extern crate libc;
 extern crate rustc;
 extern crate rustc_back;
@@ -66,6 +67,7 @@
 
 use rustc_resolve as resolve;
 use rustc_save_analysis as save;
+use rustc_save_analysis::DumpHandler;
 use rustc_trans::back::link;
 use rustc_trans::back::write::{create_target_machine, RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
 use rustc::dep_graph::DepGraph;
@@ -232,7 +234,7 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>)
 // Extract input (string or file and optional path) from matches.
 fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> {
     if free_matches.len() == 1 {
-        let ifile = &free_matches[0][..];
+        let ifile = &free_matches[0];
         if ifile == "-" {
             let mut src = String::new();
             io::stdin().read_to_string(&mut src).unwrap();
@@ -506,8 +508,9 @@ fn build_controller(&mut self,
                                         state.expanded_crate.unwrap(),
                                         state.analysis.unwrap(),
                                         state.crate_name.unwrap(),
-                                        state.out_dir,
-                                        save_analysis_format(state.session))
+                                        DumpHandler::new(save_analysis_format(state.session),
+                                                         state.out_dir,
+                                                         state.crate_name.unwrap()))
                 });
             };
             control.after_analysis.run_callback_on_error = true;
@@ -799,7 +802,7 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
         for lint in lints {
             let name = lint.name_lower().replace("_", "-");
             println!("    {}  {:7.7}  {}",
-                     padded(&name[..]),
+                     padded(&name),
                      lint.default_level.as_str(),
                      lint.desc);
         }
@@ -837,7 +840,7 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec<lint::LintId>, bool)>)
                          .map(|x| x.to_string().replace("_", "-"))
                          .collect::<Vec<String>>()
                          .join(", ");
-            println!("    {}  {}", padded(&name[..]), desc);
+            println!("    {}  {}", padded(&name), desc);
         }
         println!("\n");
     };
@@ -944,7 +947,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
                                                  .into_iter()
                                                  .map(|x| x.opt_group)
                                                  .collect();
-    let matches = match getopts::getopts(&args[..], &all_groups) {
+    let matches = match getopts::getopts(&args, &all_groups) {
         Ok(m) => m,
         Err(f) => early_error(ErrorOutputType::default(), &f.to_string()),
     };
@@ -1083,7 +1086,7 @@ fn flush(&mut self) -> io::Result<()> {
                       format!("we would appreciate a bug report: {}", BUG_REPORT_URL)];
             for note in &xs {
                 handler.emit(&MultiSpan::new(),
-                             &note[..],
+                             &note,
                              errors::Level::Note);
             }
             if match env::var_os("RUST_BACKTRACE") {
@@ -1127,6 +1130,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
 }
 
 pub fn main() {
+    env_logger::init().unwrap();
     let result = run(|| run_compiler(&env::args().collect::<Vec<_>>(),
                                      &mut RustcDefaultCalls,
                                      None,
index 6cd97e9559885048ac4f6905ecc257b5bf45e545..18dc504ca8aa913568bbf5fd48fae2c8ff5728db 100644 (file)
@@ -589,7 +589,7 @@ fn all_matching_node_ids<'a, 'hir>(&'a self,
                                        -> NodesMatchingUII<'a, 'hir> {
         match *self {
             ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()),
-            ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])),
+            ItemViaPath(ref parts) => NodesMatchingSuffix(map.nodes_matching_suffix(&parts)),
         }
     }
 
@@ -600,7 +600,7 @@ fn to_one_node_id(self, user_option: &str, sess: &Session, map: &hir_map::Map) -
                                   user_option,
                                   self.reconstructed_input(),
                                   is_wrong_because);
-            sess.fatal(&message[..])
+            sess.fatal(&message)
         };
 
         let mut saw_node = ast::DUMMY_NODE_ID;
@@ -771,7 +771,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
     fn expand_err_details(r: io::Result<()>) -> io::Result<()> {
         r.map_err(|ioerr| {
             io::Error::new(io::ErrorKind::Other,
-                           &format!("graphviz::render failed: {}", ioerr)[..])
+                           format!("graphviz::render failed: {}", ioerr))
         })
     }
 }
index 9568cc3d6de0e35c8cc00fce917dc91b73e344c0..af2416f787ea4669e693fa0162bca977c6ac7ece 100644 (file)
@@ -289,7 +289,7 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
 
     pub fn t_param(&self, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        self.infcx.tcx.mk_param(index, Symbol::intern(&name[..]))
+        self.infcx.tcx.mk_param(index, Symbol::intern(&name))
     }
 
     pub fn re_early_bound(&self, index: u32, name: &'static str) -> &'tcx ty::Region {
index e3ee7527545042211481ecf9d36f6e228c23f0bc..7bf2efa4b885f8eef332581957e4a84f795f75c8 100644 (file)
@@ -13,6 +13,6 @@ graphviz = { path = "../libgraphviz" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 serialize = { path = "../libserialize" }
-log = { path = "../liblog" }
+log = "0.3"
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index b67caa6750a81b59de426b5923fb98199345a6e7..5c20f65274f54ffbcd86a5323b3bb704dbe328fb 100644 (file)
@@ -99,9 +99,9 @@ pub fn read_file(sess: &Session, path: &Path) -> io::Result<Option<Vec<u8>>> {
         let rustc_version_str_len = rustc_version_str_len[0] as usize;
         let mut buffer = Vec::with_capacity(rustc_version_str_len);
         buffer.resize(rustc_version_str_len, 0);
-        file.read_exact(&mut buffer[..])?;
+        file.read_exact(&mut buffer)?;
 
-        if &buffer[..] != rustc_version().as_bytes() {
+        if buffer != rustc_version().as_bytes() {
             report_format_mismatch(sess, path, "Different compiler version");
             return Ok(None);
         }
index 4d5c0d7ba0ae1130f253a8e05113c9078ed202e3..c3c5461ff7c506a612d45564e01aa6b8a8a41938 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_eval = { path = "../librustc_const_eval" }
index 353b86820c405e3811d9f438cc5a55cd797fdeea..c4220e9a0d3dc1420022e6a7b5b2a3c1ff9c8c98 100644 (file)
@@ -88,7 +88,7 @@ fn to_camel_case(s: &str) -> String {
             } else {
                 format!("{} `{}` should have a camel case name such as `{}`", sort, name, c)
             };
-            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
+            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m);
         }
     }
 }
index f0276f90f274d6d99ffa2f37b88512c1481a2b37..0ee9d4a42c7f81a26c15efdb0a37ab3eb5af6b45 100644 (file)
@@ -334,7 +334,7 @@ fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
             attr.check_name("doc") &&
             match attr.meta_item_list() {
                 None => false,
-                Some(l) => attr::list_contains_name(&l[..], "hidden"),
+                Some(l) => attr::list_contains_name(&l, "hidden"),
             }
         });
         self.doc_hidden_stack.push(doc_hidden);
index abba8afd9da8699f33f5a4691fd4ede7a5477619..86bf209ccf8c8d92c5c841f684f356f869293b20 100644 (file)
@@ -146,7 +146,7 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
             ty::TyBool => return,
             ty::TyAdt(def, _) => {
                 let attrs = cx.tcx.get_attrs(def.did);
-                check_must_use(cx, &attrs[..], s.span)
+                check_must_use(cx, &attrs, s.span)
             }
             _ => false,
         };
index b74bccb70593f7517e5d5a5838a78b11300359f1..2b945e0a3afaff2f8e7d8ffe10335be2e719bbea 100644 (file)
@@ -131,10 +131,16 @@ fn main() {
         if is_crossed && flag.starts_with("-m") {
             continue;
         }
+
+        // -Wdate-time is not supported by the netbsd cross compiler
+        if is_crossed && target.contains("netbsd") && flag.contains("date-time") {
+            continue;
+        }
+
         cfg.flag(flag);
     }
 
-    for component in &components[..] {
+    for component in &components {
         let mut flag = String::from("-DLLVM_COMPONENT_");
         flag.push_str(&component.to_uppercase());
         cfg.flag(&flag);
@@ -167,7 +173,7 @@ fn main() {
     if !is_crossed {
         cmd.arg("--system-libs");
     }
-    cmd.args(&components[..]);
+    cmd.args(&components);
 
     for lib in output(&mut cmd).split_whitespace() {
         let name = if lib.starts_with("-l") {
@@ -227,16 +233,21 @@ fn main() {
         }
     }
 
-    // OpenBSD has a particular C++ runtime library name
+    let llvm_static_stdcpp = env::var_os("LLVM_STATIC_STDCPP");
+
     let stdcppname = if target.contains("openbsd") {
+        // OpenBSD has a particular C++ runtime library name
         "estdc++"
+    } else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {
+        // NetBSD uses a separate library when relocation is required
+        "stdc++_pic"
     } else {
         "stdc++"
     };
 
     // C++ runtime library
     if !target.contains("msvc") {
-        if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") {
+        if let Some(s) = llvm_static_stdcpp {
             assert!(!cxxflags.contains("stdlib=libc++"));
             let path = PathBuf::from(s);
             println!("cargo:rustc-link-search=native={}",
index 6f7f03ca216b9a3c83543c1448358e278f962285..e8b906092730e5cbee6f873daa302fd57eaf46a6 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 flate = { path = "../libflate" }
-log = { path = "../liblog" }
+log = "0.3"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
index fcdb968dc06152ceca6c81d41140876336ab79f8..04a8b88f8a594a694537722cfda51677330f75f6 100644 (file)
@@ -669,7 +669,7 @@ pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
                                   name,
                                   config::host_triple(),
                                   self.sess.opts.target_triple);
-            span_fatal!(self.sess, span, E0456, "{}", &message[..]);
+            span_fatal!(self.sess, span, E0456, "{}", &message);
         }
 
         let root = ekrate.metadata.get_root();
@@ -1058,7 +1058,7 @@ fn postprocess(&mut self, krate: &ast::Crate) {
         self.inject_allocator_crate();
         self.inject_panic_runtime(krate);
 
-        if log_enabled!(log::INFO) {
+        if log_enabled!(log::LogLevel::Info) {
             dump_crates(&self.cstore);
         }
 
index 2a67b79eaa52e6022ef699ee90fcbad76e91380c..3e9b6a6226ab507d7f7087251b31f75fa6bdf9ea 100644 (file)
@@ -88,9 +88,9 @@ pub fn provide<$lt>(providers: &mut Providers<$lt>) {
     }
     associated_item => { cdata.get_associated_item(def_id.index) }
     impl_trait_ref => { cdata.get_impl_trait(def_id.index, tcx) }
-    custom_coerce_unsized_kind => {
-        cdata.get_custom_coerce_unsized_kind(def_id.index).unwrap_or_else(|| {
-            bug!("custom_coerce_unsized_kind: `{:?}` is missing its kind", def_id);
+    coerce_unsized_info => {
+        cdata.get_coerce_unsized_info(def_id.index).unwrap_or_else(|| {
+            bug!("coerce_unsized_info: `{:?}` is missing its info", def_id);
         })
     }
     mir => {
@@ -109,6 +109,7 @@ pub fn provide<$lt>(providers: &mut Providers<$lt>) {
     typeck_tables => { cdata.item_body_tables(def_id.index, tcx) }
     closure_kind => { cdata.closure_kind(def_id.index) }
     closure_type => { cdata.closure_ty(def_id.index, tcx) }
+    inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
 }
 
 impl CrateStore for cstore::CStore {
@@ -162,12 +163,6 @@ fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>
         self.get_crate_data(did.krate).get_fn_arg_names(did.index)
     }
 
-    fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>
-    {
-        self.dep_graph.read(DepNode::MetaData(def_id));
-        self.get_crate_data(def_id.krate).get_inherent_implementations_for_type(def_id.index)
-    }
-
     fn implementations_of_trait(&self, filter: Option<DefId>) -> Vec<DefId>
     {
         if let Some(def_id) = filter {
@@ -496,12 +491,12 @@ fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>
         self.do_extern_mod_stmt_cnum(emod_id)
     }
 
-    fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                 reexports: &def::ExportMap,
+    fn encode_metadata<'a, 'tcx>(&self,
+                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  link_meta: &LinkMeta,
                                  reachable: &NodeSet) -> Vec<u8>
     {
-        encoder::encode_metadata(tcx, self, reexports, link_meta, reachable)
+        encoder::encode_metadata(tcx, self, link_meta, reachable)
     }
 
     fn metadata_encoding_version(&self) -> &[u8]
index 6ccdf8092f210491c856774bb92ea632ccaf91bc..3de1e3442c69ddb6c0ecf63f8a31df8062bbad8d 100644 (file)
@@ -643,10 +643,10 @@ pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity {
         self.get_impl_data(id).polarity
     }
 
-    pub fn get_custom_coerce_unsized_kind(&self,
-                                          id: DefIndex)
-                                          -> Option<ty::adjustment::CustomCoerceUnsized> {
-        self.get_impl_data(id).coerce_unsized_kind
+    pub fn get_coerce_unsized_info(&self,
+                                   id: DefIndex)
+                                   -> Option<ty::adjustment::CoerceUnsizedInfo> {
+        self.get_impl_data(id).coerce_unsized_info
     }
 
     pub fn get_impl_trait(&self,
index 044ed529ef74cfa50c96f36683172d5a04999174..38d774992a55111b8d901b75a5d192730f76ba38 100644 (file)
@@ -13,7 +13,6 @@
 use schema::*;
 
 use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary};
-use rustc::hir::def;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId};
 use rustc::hir::map::definitions::DefPathTable;
 use rustc::middle::dependency_format::Linkage;
@@ -48,7 +47,6 @@
 pub struct EncodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Encoder<'a>,
     pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    reexports: &'a def::ExportMap,
     link_meta: &'a LinkMeta,
     cstore: &'a cstore::CStore,
     exported_symbols: &'a NodeSet,
@@ -306,7 +304,7 @@ fn encode_info_for_mod(&mut self,
         let def_id = tcx.hir.local_def_id(id);
 
         let data = ModData {
-            reexports: match self.reexports.get(&id) {
+            reexports: match tcx.export_map.get(&id) {
                 Some(exports) if *vis == hir::Public => self.lazy_seq_ref(exports),
                 _ => LazySeq::empty(),
             },
@@ -695,7 +693,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                 let data = ImplData {
                     polarity: hir::ImplPolarity::Positive,
                     parent_impl: None,
-                    coerce_unsized_kind: None,
+                    coerce_unsized_info: None,
                     trait_ref: tcx.impl_trait_ref(def_id).map(|trait_ref| self.lazy(&trait_ref)),
                 };
 
@@ -715,13 +713,21 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) ->
                     None
                 };
 
+                // if this is an impl of `CoerceUnsized`, create its
+                // "unsized info", else just store None
+                let coerce_unsized_info =
+                    trait_ref.and_then(|t| {
+                        if Some(t.def_id) == tcx.lang_items.coerce_unsized_trait() {
+                            Some(ty::queries::coerce_unsized_info::get(tcx, item.span, def_id))
+                        } else {
+                            None
+                        }
+                    });
+
                 let data = ImplData {
                     polarity: polarity,
                     parent_impl: parent,
-                    coerce_unsized_kind: tcx.maps.custom_coerce_unsized_kind
-                        .borrow()
-                        .get(&def_id)
-                        .cloned(),
+                    coerce_unsized_info: coerce_unsized_info,
                     trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)),
                 };
 
@@ -920,14 +926,14 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) {
                 self.encode_fields(def_id);
             }
             hir::ItemImpl(..) => {
-                for &trait_item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
+                for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(trait_item_def_id,
                                 EncodeContext::encode_info_for_impl_item,
                                 trait_item_def_id);
                 }
             }
             hir::ItemTrait(..) => {
-                for &item_def_id in &self.tcx.associated_item_def_ids(def_id)[..] {
+                for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() {
                     self.record(item_def_id,
                                 EncodeContext::encode_info_for_trait_item,
                                 item_def_id);
@@ -1423,7 +1429,6 @@ fn encode_crate_root(&mut self) -> Lazy<CrateRoot> {
 
 pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cstore: &cstore::CStore,
-                                 reexports: &def::ExportMap,
                                  link_meta: &LinkMeta,
                                  exported_symbols: &NodeSet)
                                  -> Vec<u8> {
@@ -1437,7 +1442,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut ecx = EncodeContext {
             opaque: opaque::Encoder::new(&mut cursor),
             tcx: tcx,
-            reexports: reexports,
             link_meta: link_meta,
             cstore: cstore,
             exported_symbols: exported_symbols,
index a6771083fc34eaf438313e920cbc78707a569ba2..e8bc8b01652a62a5c71161b6b8e489a21ea21a6f 100644 (file)
@@ -477,15 +477,15 @@ fn find_library_crate(&mut self) -> Option<Library> {
                 Some(file) => file,
             };
             let (hash, found_kind) =
-                if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
+                if file.starts_with(&rlib_prefix) && file.ends_with(".rlib") {
                     (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
-                } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") {
+                } else if file.starts_with(&rlib_prefix) && file.ends_with(".rmeta") {
                     (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
                 } else if file.starts_with(&dylib_prefix) &&
                                              file.ends_with(&dypair.1) {
                     (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib)
                 } else {
-                    if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
+                    if file.starts_with(&staticlib_prefix) && file.ends_with(&staticpair.1) {
                         staticlibs.push(CrateMismatch {
                             path: path.to_path_buf(),
                             got: "static".to_string(),
index 4a20913d0b3fd19e16cef779f1817c42880f1a81..abb482a50ebc2621487e53fb43c3af4c5e8f7b73 100644 (file)
@@ -285,7 +285,9 @@ pub struct TraitData<'tcx> {
 pub struct ImplData<'tcx> {
     pub polarity: hir::ImplPolarity,
     pub parent_impl: Option<DefId>,
-    pub coerce_unsized_kind: Option<ty::adjustment::CustomCoerceUnsized>,
+
+    /// This is `Some` only for impls of `CoerceUnsized`.
+    pub coerce_unsized_info: Option<ty::adjustment::CoerceUnsizedInfo>,
     pub trait_ref: Option<Lazy<ty::TraitRef<'tcx>>>,
 }
 
index 531be0b6ae9f5f620528982f7edf7f829b7f7bb0..6e42e02d5109b6c5e1fd1ea83ec8d55c244ea379 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 graphviz = { path = "../libgraphviz" }
-log = { path = "../liblog" }
+log = "0.3"
 rustc = { path = "../librustc" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
index 1de5b9218564fdb73a96682b9fb3dc291c540392..dd4190a412dacd7fee78db5870c406133a12fd9d 100644 (file)
@@ -89,6 +89,7 @@
 use build::{BlockAnd, BlockAndExtension, Builder, CFG};
 use rustc::middle::region::{CodeExtent, CodeExtentData};
 use rustc::middle::lang_items;
+use rustc::middle::const_val::ConstVal;
 use rustc::ty::subst::{Kind, Subst};
 use rustc::ty::{Ty, TyCtxt};
 use rustc::mir::*;
@@ -784,9 +785,8 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         func: Operand::Constant(Constant {
             span: data.span,
             ty: tcx.item_type(free_func).subst(tcx, substs),
-            literal: Literal::Item {
-                def_id: free_func,
-                substs: substs
+            literal: Literal::Value {
+                value: ConstVal::Function(free_func, substs),
             }
         }),
         args: vec![Operand::Consume(data.value.clone())],
index da58a1ed1f49b2a90c5f72b1fd4f7da63cd0b9b5..44858a98e36f963f0c597ae971b00968ea00bda1 100644 (file)
@@ -714,9 +714,8 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         ty: callee.ty,
         span: expr.span,
         kind: ExprKind::Literal {
-            literal: Literal::Item {
-                def_id: callee.def_id,
-                substs: callee.substs,
+            literal: Literal::Value {
+                value: ConstVal::Function(callee.def_id, callee.substs),
             },
         },
     }
@@ -743,14 +742,24 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                      -> ExprKind<'tcx> {
     let substs = cx.tables().node_id_item_substs(expr.id)
         .unwrap_or_else(|| cx.tcx.intern_substs(&[]));
-    let def_id = match def {
+    match def {
         // A regular function, constructor function or a constant.
         Def::Fn(def_id) |
         Def::Method(def_id) |
         Def::StructCtor(def_id, CtorKind::Fn) |
-        Def::VariantCtor(def_id, CtorKind::Fn) |
+        Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
+            literal: Literal::Value {
+                value: ConstVal::Function(def_id, substs),
+            },
+        },
+
         Def::Const(def_id) |
-        Def::AssociatedConst(def_id) => def_id,
+        Def::AssociatedConst(def_id) => ExprKind::Literal {
+            literal: Literal::Item {
+                def_id: def_id,
+                substs: substs,
+            },
+        },
 
         Def::StructCtor(def_id, CtorKind::Const) |
         Def::VariantCtor(def_id, CtorKind::Const) => {
@@ -758,7 +767,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 // A unit struct/variant which is used as a value.
                 // We return a completely different ExprKind here to account for this special case.
                 ty::TyAdt(adt_def, substs) => {
-                    return ExprKind::Adt {
+                    ExprKind::Adt {
                         adt_def: adt_def,
                         variant_index: adt_def.variant_index_with_id(def_id),
                         substs: substs,
@@ -770,17 +779,11 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             }
         }
 
-        Def::Static(node_id, _) => return ExprKind::StaticRef { id: node_id },
+        Def::Static(node_id, _) => ExprKind::StaticRef { id: node_id },
 
-        Def::Local(..) | Def::Upvar(..) => return convert_var(cx, expr, def),
+        Def::Local(..) | Def::Upvar(..) => convert_var(cx, expr, def),
 
         _ => span_bug!(expr.span, "def `{:?}` not yet implemented", def),
-    };
-    ExprKind::Literal {
-        literal: Literal::Item {
-            def_id: def_id,
-            substs: substs,
-        },
     }
 }
 
index c555ce1ab9c425de7e8c749a8c1a67826f6af472..3eef5d83b8ba0504f2e8946c4f4b5179aeb0bfe7 100644 (file)
@@ -132,9 +132,8 @@ pub fn trait_method(&mut self,
                 let method_ty = self.tcx.item_type(item.def_id);
                 let method_ty = method_ty.subst(self.tcx, substs);
                 return (method_ty,
-                        Literal::Item {
-                            def_id: item.def_id,
-                            substs: substs,
+                        Literal::Value {
+                            value: ConstVal::Function(item.def_id, substs),
                         });
             }
         }
index 26d5b7fd38ab080b09552e520bb5764ea154d7f1..63d20be88feee70eb623fd9c9b8fe13f1e2b7538 100644 (file)
@@ -12,6 +12,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::infer;
 use rustc::middle::region::ROOT_CODE_EXTENT;
+use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
 use rustc::ty::{self, Ty};
@@ -335,7 +336,9 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
             Operand::Constant(Constant {
                 span: span,
                 ty: tcx.item_type(def_id).subst(tcx, param_env.free_substs),
-                literal: Literal::Item { def_id, substs: param_env.free_substs },
+                literal: Literal::Value {
+                    value: ConstVal::Function(def_id, param_env.free_substs),
+                },
             }),
             vec![rcvr]
         )
index e998665e035365056fafe6065ce5b694b4371980..ba42804c9262f0c92f776453399528e4e6d0443a 100644 (file)
@@ -568,11 +568,6 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
                 });
             }
             Operand::Constant(ref constant) => {
-                // Only functions and methods can have these types.
-                if let ty::TyFnDef(..) = constant.ty.sty {
-                    return;
-                }
-
                 if let Literal::Item { def_id, substs } = constant.literal {
                     // Don't peek inside generic (associated) constants.
                     if substs.types().next().is_some() {
index f98bb73c504dcfb00e44a5247f184ee4b930e3f5..3d604affbfea9ce0e24f33c5f02069dab9896e46 100644 (file)
@@ -15,6 +15,7 @@
 use rustc::traits::{self, Reveal};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
+use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::tcx::LvalueTy;
 use rustc::mir::transform::{MirPass, MirSource, Pass};
@@ -526,7 +527,9 @@ fn check_call_inputs(&mut self,
     fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
         match operand {
             &Operand::Constant(Constant {
-                literal: Literal::Item { def_id, .. }, ..
+                literal: Literal::Value {
+                    value: ConstVal::Function(def_id, _), ..
+                }, ..
             }) => {
                 Some(def_id) == self.tcx().lang_items.box_free_fn()
             }
index d0f142ad7d7a87b7a81fb7fc905cc957426bee77..ccbc6700d89c1bc3c314d5d3d8acf9a4434cc299 100644 (file)
@@ -525,8 +525,8 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Option<Basi
             }],
             terminator: Some(Terminator {
                 kind: TerminatorKind::Call {
-                    func: Operand::item(tcx, drop_fn.def_id, substs,
-                                        self.source_info.span),
+                    func: Operand::function_handle(tcx, drop_fn.def_id, substs,
+                                                   self.source_info.span),
                     args: vec![Operand::Consume(Lvalue::Local(ref_lvalue))],
                     destination: Some((unit_temp, succ)),
                     cleanup: unwind,
@@ -629,7 +629,7 @@ fn unelaborated_free_block<'a>(
         let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
 
         let call = TerminatorKind::Call {
-            func: Operand::item(tcx, free_func, substs, self.source_info.span),
+            func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
             args: vec![Operand::Consume(self.lvalue.clone())],
             destination: Some((unit_temp, target)),
             cleanup: None
index cc710e0ac3563772aa88214d498e9d12488f992d..d2560c2f8203f0557957ea0bbb968fbaa127bba3 100644 (file)
@@ -9,10 +9,10 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 rustc = { path = "../librustc" }
 rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rustc_errors = { path = "../librustc_errors" }
\ No newline at end of file
+rustc_errors = { path = "../librustc_errors" }
index 1bfc445fca98d72ca4f7c8f03a92b63dda875fc1..efe9963cecc7300a955394726544c1af4130cc4a 100644 (file)
@@ -126,19 +126,19 @@ fn dylink_registrar(&mut self,
             // inside this crate, so continue would spew "macro undefined"
             // errors
             Err(err) => {
-                self.sess.span_fatal(span, &err[..])
+                self.sess.span_fatal(span, &err)
             }
         };
 
         unsafe {
             let registrar =
-                match lib.symbol(&symbol[..]) {
+                match lib.symbol(&symbol) {
                     Ok(registrar) => {
                         mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
                     }
                     // again fatal if we can't register macros
                     Err(err) => {
-                        self.sess.span_fatal(span, &err[..])
+                        self.sess.span_fatal(span, &err)
                     }
                 };
 
index e32ec25a7e8f77857f40bf5242a5529ad17096e2..64821f5d44bf495d4126bc25516121db4720d933 100644 (file)
@@ -17,6 +17,7 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
+#![cfg_attr(stage0, feature(field_init_shorthand))]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 
-use rustc::dep_graph::DepNode;
 use rustc::hir::{self, PatKind};
-use rustc::hir::def::{self, Def};
-use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
+use rustc::hir::def::Def;
+use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::DeepVisitor;
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 use rustc::middle::privacy::{AccessLevel, AccessLevels};
 use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
 use rustc::ty::fold::TypeVisitor;
+use rustc::ty::maps::Providers;
 use rustc::util::nodemap::NodeSet;
 use syntax::ast;
-use syntax_pos::Span;
+use syntax_pos::{DUMMY_SP, Span};
 
 use std::cmp;
 use std::mem::replace;
+use std::rc::Rc;
 
 pub mod diagnostics;
 
@@ -71,7 +73,6 @@ fn visit_vis(&mut self, vis: &'tcx hir::Visibility) {
 
 struct EmbargoVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    export_map: &'a def::ExportMap,
 
     // Accessibility levels for reachable nodes
     access_levels: AccessLevels,
@@ -324,7 +325,7 @@ fn visit_mod(&mut self, m: &'tcx hir::Mod, _sp: Span, id: ast::NodeId) {
         // This code is here instead of in visit_item so that the
         // crate module gets processed as well.
         if self.prev_level.is_some() {
-            if let Some(exports) = self.export_map.get(&id) {
+            if let Some(exports) = self.tcx.export_map.get(&id) {
                 for export in exports {
                     if let Some(node_id) = self.tcx.hir.as_local_node_id(export.def.def_id()) {
                         self.update(node_id, Some(AccessLevel::Exported));
@@ -1204,10 +1205,23 @@ fn visit_expr(&mut self, _: &'tcx hir::Expr) {}
     fn visit_pat(&mut self, _: &'tcx hir::Pat) {}
 }
 
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                             export_map: &def::ExportMap)
-                             -> AccessLevels {
-    let _task = tcx.dep_graph.in_task(DepNode::Privacy);
+pub fn provide(providers: &mut Providers) {
+    *providers = Providers {
+        privacy_access_levels,
+        ..*providers
+    };
+}
+
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Rc<AccessLevels> {
+    tcx.dep_graph.with_ignore(|| { // FIXME
+        ty::queries::privacy_access_levels::get(tcx, DUMMY_SP, LOCAL_CRATE)
+    })
+}
+
+fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   krate: CrateNum)
+                                   -> Rc<AccessLevels> {
+    assert_eq!(krate, LOCAL_CRATE);
 
     let krate = tcx.hir.krate();
 
@@ -1226,7 +1240,6 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // items which are reachable from external crates based on visibility.
     let mut visitor = EmbargoVisitor {
         tcx: tcx,
-        export_map: export_map,
         access_levels: Default::default(),
         prev_level: Some(AccessLevel::Public),
         changed: false,
@@ -1270,7 +1283,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
     }
 
-    visitor.access_levels
+    Rc::new(visitor.access_levels)
 }
 
 __build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }
index 5ce4c74e735fd6fb11015095554c5777730d2878..0968ea31b754f9e7b2d0e47f5ccd871156483204 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 syntax = { path = "../libsyntax" }
 rustc = { path = "../librustc" }
 arena = { path = "../libarena" }
index c33d5b9b6e16bb14bb4980039c00deac67c22c5c..86e0d0039d1a7c4a517308a66177409be5516995 100644 (file)
@@ -539,7 +539,7 @@ fn legacy_import_macro(&mut self,
                            binding: &'a NameBinding<'a>,
                            span: Span,
                            allow_shadowing: bool) {
-        if self.builtin_macros.insert(name, binding).is_some() && !allow_shadowing {
+        if self.global_macros.insert(name, binding).is_some() && !allow_shadowing {
             let msg = format!("`{}` is already in scope", name);
             let note =
                 "macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560)";
index 8f6b1b8971e5b9ffb1967dbb72629227735966fe..2c2babf0a66535724b080ec1d8913c210f98eacd 100644 (file)
@@ -890,19 +890,23 @@ fn foo(f: i32, g: i32) {} // ok!
 E0422: r##"
 You are trying to use an identifier that is either undefined or not a struct.
 Erroneous code example:
-``` compile_fail,E0422
+
+```compile_fail,E0422
 fn main () {
     let x = Foo { x: 1, y: 2 };
 }
 ```
+
 In this case, `Foo` is undefined, so it inherently isn't anything, and
 definitely not a struct.
+
 ```compile_fail
 fn main () {
     let foo = 1;
     let x = foo { x: 1, y: 2 };
 }
 ```
+
 In this case, `foo` is defined, but is not a struct, so Rust can't use it as
 one.
 "##,
index f832e0f9a4811146e7f83cb2e57b1396b29b2de2..0466e76475da3d1f05069ec0b24edccf45500de3 100644 (file)
@@ -75,7 +75,7 @@
 use std::rc::Rc;
 
 use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver};
-use macros::{InvocationData, LegacyBinding, LegacyScope};
+use macros::{InvocationData, LegacyBinding, LegacyScope, MacroBinding};
 
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
@@ -922,6 +922,10 @@ fn is_trait(&self) -> bool {
     fn is_local(&self) -> bool {
         self.normal_ancestor_id.is_local()
     }
+
+    fn nearest_item_scope(&'a self) -> Module<'a> {
+        if self.is_trait() { self.parent.unwrap() } else { self }
+    }
 }
 
 impl<'a> fmt::Debug for ModuleData<'a> {
@@ -1174,7 +1178,7 @@ pub struct Resolver<'a> {
 
     crate_loader: &'a mut CrateLoader,
     macro_names: FxHashSet<Name>,
-    builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
+    global_macros: FxHashMap<Name, &'a NameBinding<'a>>,
     lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
     macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
     macro_defs: FxHashMap<Mark, DefId>,
@@ -1372,7 +1376,7 @@ pub fn new(session: &'a Session,
 
             crate_loader: crate_loader,
             macro_names: FxHashSet(),
-            builtin_macros: FxHashMap(),
+            global_macros: FxHashMap(),
             lexical_macro_resolutions: Vec::new(),
             macro_map: FxHashMap(),
             macro_exports: Vec::new(),
@@ -2429,9 +2433,9 @@ fn resolve_qpath_anywhere(&mut self,
                 };
             }
         }
-        let is_builtin = self.builtin_macros.get(&path[0].name).cloned()
+        let is_global = self.global_macros.get(&path[0].name).cloned()
             .map(|binding| binding.get_macro(self).kind() == MacroKind::Bang).unwrap_or(false);
-        if primary_ns != MacroNS && (is_builtin || self.macro_names.contains(&path[0].name)) {
+        if primary_ns != MacroNS && (is_global || self.macro_names.contains(&path[0].name)) {
             // Return some dummy definition, it's enough for error reporting.
             return Some(
                 PathResolution::new(Def::Macro(DefId::local(CRATE_DEF_INDEX), MacroKind::Bang))
@@ -2566,6 +2570,7 @@ fn resolve_path(&mut self,
                 self.resolve_ident_in_module(module, ident, ns, false, record_used)
             } else if opt_ns == Some(MacroNS) {
                 self.resolve_lexical_macro_path_segment(ident, ns, record_used)
+                    .map(MacroBinding::binding)
             } else {
                 match self.resolve_ident_in_lexical_scope(ident, ns, record_used) {
                     Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
@@ -3223,7 +3228,7 @@ fn report_errors(&mut self) {
             };
             let msg1 = format!("`{}` could refer to the name {} here", name, participle(b1));
             let msg2 = format!("`{}` could also refer to the name {} here", name, participle(b2));
-            let note = if !lexical && b1.is_glob_import() {
+            let note = if b1.expansion == Mark::root() || !lexical && b1.is_glob_import() {
                 format!("consider adding an explicit import of `{}` to disambiguate", name)
             } else if let Def::Macro(..) = b1.def() {
                 format!("macro-expanded {} do not shadow",
@@ -3243,11 +3248,15 @@ fn report_errors(&mut self) {
                 let msg = format!("`{}` is ambiguous", name);
                 self.session.add_lint(lint::builtin::LEGACY_IMPORTS, id, span, msg);
             } else {
-                self.session.struct_span_err(span, &format!("`{}` is ambiguous", name))
-                    .span_note(b1.span, &msg1)
-                    .span_note(b2.span, &msg2)
-                    .note(&note)
-                    .emit();
+                let mut err =
+                    self.session.struct_span_err(span, &format!("`{}` is ambiguous", name));
+                err.span_note(b1.span, &msg1);
+                match b2.def() {
+                    Def::Macro(..) if b2.span == DUMMY_SP =>
+                        err.note(&format!("`{}` is also a builtin macro", name)),
+                    _ => err.span_note(b2.span, &msg2),
+                };
+                err.note(&note).emit();
             }
         }
 
@@ -3361,14 +3370,13 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
         if self.proc_macro_enabled { return; }
 
         for attr in attrs {
-            let name = unwrap_or!(attr.name(), continue);
-            let maybe_binding = self.builtin_macros.get(&name).cloned().or_else(|| {
-                let ident = Ident::with_empty_ctxt(name);
-                self.resolve_lexical_macro_path_segment(ident, MacroNS, None).ok()
-            });
-
-            if let Some(binding) = maybe_binding {
-                if let SyntaxExtension::AttrProcMacro(..) = *binding.get_macro(self) {
+            if attr.path.segments.len() > 1 {
+                continue
+            }
+            let ident = attr.path.segments[0].identifier;
+            let result = self.resolve_lexical_macro_path_segment(ident, MacroNS, None);
+            if let Ok(binding) = result {
+                if let SyntaxExtension::AttrProcMacro(..) = *binding.binding().get_macro(self) {
                     attr::mark_known(attr);
 
                     let msg = "attribute procedural macros are experimental";
@@ -3376,7 +3384,7 @@ fn check_proc_macro_attrs(&mut self, attrs: &[ast::Attribute]) {
 
                     feature_err(&self.session.parse_sess, feature,
                                 attr.span, GateIssue::Language, msg)
-                        .span_note(binding.span, "procedural macro imported here")
+                        .span_note(binding.span(), "procedural macro imported here")
                         .emit();
                 }
             }
index 99fc1c142f6815fd2cc097699e3fd0be0e02cd2b..05f30f039c8f0649dd3eaf3bab6fc28c909219ee 100644 (file)
@@ -81,11 +81,29 @@ pub struct LegacyBinding<'a> {
     pub span: Span,
 }
 
+#[derive(Copy, Clone)]
 pub enum MacroBinding<'a> {
     Legacy(&'a LegacyBinding<'a>),
+    Global(&'a NameBinding<'a>),
     Modern(&'a NameBinding<'a>),
 }
 
+impl<'a> MacroBinding<'a> {
+    pub fn span(self) -> Span {
+        match self {
+            MacroBinding::Legacy(binding) => binding.span,
+            MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding.span,
+        }
+    }
+
+    pub fn binding(self) -> &'a NameBinding<'a> {
+        match self {
+            MacroBinding::Global(binding) | MacroBinding::Modern(binding) => binding,
+            MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"),
+        }
+    }
+}
+
 impl<'a> base::Resolver for Resolver<'a> {
     fn next_node_id(&mut self) -> ast::NodeId {
         self.session.next_node_id()
@@ -154,7 +172,6 @@ fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark
             expansion: mark,
         };
         expansion.visit_with(&mut visitor);
-        self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
         invocation.expansion.set(visitor.legacy_scope);
     }
 
@@ -171,7 +188,7 @@ fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
             vis: ty::Visibility::Invisible,
             expansion: Mark::root(),
         });
-        self.builtin_macros.insert(ident.name, binding);
+        self.global_macros.insert(ident.name, binding);
     }
 
     fn resolve_imports(&mut self) {
@@ -189,7 +206,7 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
                 attr::mark_known(&attrs[i]);
             }
 
-            match self.builtin_macros.get(&name).cloned() {
+            match self.global_macros.get(&name).cloned() {
                 Some(binding) => match *binding.get_macro(self) {
                     MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
                         return Some(attrs.remove(i))
@@ -221,7 +238,7 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
                     }
                     let trait_name = traits[j].segments[0].identifier.name;
                     let legacy_name = Symbol::intern(&format!("derive_{}", trait_name));
-                    if !self.builtin_macros.contains_key(&legacy_name) {
+                    if !self.global_macros.contains_key(&legacy_name) {
                         continue
                     }
                     let span = traits.remove(j).span;
@@ -372,27 +389,27 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
                     Err(Determinacy::Determined)
                 },
             };
-            self.current_module.macro_resolutions.borrow_mut()
+            self.current_module.nearest_item_scope().macro_resolutions.borrow_mut()
                 .push((path.into_boxed_slice(), span));
             return def;
         }
 
         let name = path[0].name;
-        let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) {
-            Some(MacroBinding::Legacy(binding)) => Ok(Def::Macro(binding.def_id, MacroKind::Bang)),
-            Some(MacroBinding::Modern(binding)) => Ok(binding.def_ignoring_ambiguity()),
-            None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
-                Ok(binding) => Ok(binding.def_ignoring_ambiguity()),
-                Err(Determinacy::Undetermined) if !force =>
-                    return Err(Determinacy::Undetermined),
+        let legacy_resolution = self.resolve_legacy_scope(&invocation.legacy_scope, name, false);
+        let result = if let Some(MacroBinding::Legacy(binding)) = legacy_resolution {
+            Ok(Def::Macro(binding.def_id, MacroKind::Bang))
+        } else {
+            match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
+                Ok(binding) => Ok(binding.binding().def_ignoring_ambiguity()),
+                Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
                 Err(_) => {
                     self.found_unresolved_macro = true;
                     Err(Determinacy::Determined)
                 }
-            },
+            }
         };
 
-        self.current_module.legacy_macro_resolutions.borrow_mut()
+        self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
             .push((scope, path[0], span, kind));
 
         result
@@ -403,42 +420,56 @@ pub fn resolve_lexical_macro_path_segment(&mut self,
                                               ident: Ident,
                                               ns: Namespace,
                                               record_used: Option<Span>)
-                                              -> Result<&'a NameBinding<'a>, Determinacy> {
-        let mut module = self.current_module;
-        let mut potential_expanded_shadower: Option<&NameBinding> = None;
+                                              -> Result<MacroBinding<'a>, Determinacy> {
+        let mut module = Some(self.current_module);
+        let mut potential_illegal_shadower = Err(Determinacy::Determined);
+        let determinacy =
+            if record_used.is_some() { Determinacy::Determined } else { Determinacy::Undetermined };
         loop {
-            // Since expanded macros may not shadow the lexical scope (enforced below),
-            // we can ignore unresolved invocations (indicated by the penultimate argument).
-            match self.resolve_ident_in_module(module, ident, ns, true, record_used) {
+            let result = if let Some(module) = module {
+                // Since expanded macros may not shadow the lexical scope and
+                // globs may not shadow global macros (both enforced below),
+                // we resolve with restricted shadowing (indicated by the penultimate argument).
+                self.resolve_ident_in_module(module, ident, ns, true, record_used)
+                    .map(MacroBinding::Modern)
+            } else {
+                self.global_macros.get(&ident.name).cloned().ok_or(determinacy)
+                    .map(MacroBinding::Global)
+            };
+
+            match result.map(MacroBinding::binding) {
                 Ok(binding) => {
                     let span = match record_used {
                         Some(span) => span,
-                        None => return Ok(binding),
+                        None => return result,
                     };
-                    match potential_expanded_shadower {
-                        Some(shadower) if shadower.def() != binding.def() => {
+                    if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
+                        if shadower.def() != binding.def() {
                             let name = ident.name;
                             self.ambiguity_errors.push(AmbiguityError {
                                 span: span, name: name, b1: shadower, b2: binding, lexical: true,
                                 legacy: false,
                             });
-                            return Ok(shadower);
+                            return potential_illegal_shadower;
                         }
-                        _ if binding.expansion == Mark::root() => return Ok(binding),
-                        _ => potential_expanded_shadower = Some(binding),
+                    }
+                    if binding.expansion != Mark::root() ||
+                       (binding.is_glob_import() && module.unwrap().def().is_some()) {
+                        potential_illegal_shadower = result;
+                    } else {
+                        return result;
                     }
                 },
                 Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
                 Err(Determinacy::Determined) => {}
             }
 
-            match module.kind {
-                ModuleKind::Block(..) => module = module.parent.unwrap(),
-                ModuleKind::Def(..) => return match potential_expanded_shadower {
-                    Some(binding) => Ok(binding),
-                    None if record_used.is_some() => Err(Determinacy::Determined),
-                    None => Err(Determinacy::Undetermined),
+            module = match module {
+                Some(module) => match module.kind {
+                    ModuleKind::Block(..) => module.parent,
+                    ModuleKind::Def(..) => None,
                 },
+                None => return potential_illegal_shadower,
             }
         }
     }
@@ -488,11 +519,11 @@ pub fn resolve_legacy_scope(&mut self,
 
         let binding = if let Some(binding) = binding {
             MacroBinding::Legacy(binding)
-        } else if let Some(binding) = self.builtin_macros.get(&name).cloned() {
+        } else if let Some(binding) = self.global_macros.get(&name).cloned() {
             if !self.use_extern_macros {
                 self.record_use(Ident::with_empty_ctxt(name), MacroNS, binding, DUMMY_SP);
             }
-            MacroBinding::Modern(binding)
+            MacroBinding::Global(binding)
         } else {
             return None;
         };
@@ -524,21 +555,15 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
             let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
             let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
             match (legacy_resolution, resolution) {
-                (Some(legacy_resolution), Ok(resolution)) => {
-                    let (legacy_span, participle) = match legacy_resolution {
-                        MacroBinding::Modern(binding)
-                            if binding.def() == resolution.def() => continue,
-                        MacroBinding::Modern(binding) => (binding.span, "imported"),
-                        MacroBinding::Legacy(binding) => (binding.span, "defined"),
-                    };
-                    let msg1 = format!("`{}` could refer to the macro {} here", ident, participle);
+                (Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
+                    let msg1 = format!("`{}` could refer to the macro defined here", ident);
                     let msg2 = format!("`{}` could also refer to the macro imported here", ident);
                     self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
-                        .span_note(legacy_span, &msg1)
-                        .span_note(resolution.span, &msg2)
+                        .span_note(legacy_binding.span, &msg1)
+                        .span_note(binding.span, &msg2)
                         .emit();
                 },
-                (Some(MacroBinding::Modern(binding)), Err(_)) => {
+                (Some(MacroBinding::Global(binding)), Ok(MacroBinding::Global(_))) => {
                     self.record_use(ident, MacroNS, binding, span);
                     self.err_if_macro_use_proc_macro(ident.name, span, binding);
                 },
@@ -567,11 +592,11 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
             find_best_match_for_name(self.macro_names.iter(), name, None)
         } else {
             None
-        // Then check builtin macros.
+        // Then check global macros.
         }.or_else(|| {
             // FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
-            let builtin_macros = self.builtin_macros.clone();
-            let names = builtin_macros.iter().filter_map(|(name, binding)| {
+            let global_macros = self.global_macros.clone();
+            let names = global_macros.iter().filter_map(|(name, binding)| {
                 if binding.get_macro(self).kind() == kind {
                     Some(name)
                 } else {
index 2f4ac12cd7363bf2604c8d738206947802300f27..43654c8ce6f6875b13aa5009fabec257024ae784 100644 (file)
@@ -145,7 +145,7 @@ pub fn resolve_ident_in_module(&mut self,
                                    module: Module<'a>,
                                    ident: Ident,
                                    ns: Namespace,
-                                   ignore_unresolved_invocations: bool,
+                                   restricted_shadowing: bool,
                                    record_used: Option<Span>)
                                    -> Result<&'a NameBinding<'a>, Determinacy> {
         self.populate_module_if_necessary(module);
@@ -158,9 +158,8 @@ pub fn resolve_ident_in_module(&mut self,
             if let Some(binding) = resolution.binding {
                 if let Some(shadowed_glob) = resolution.shadows_glob {
                     let name = ident.name;
-                    // If we ignore unresolved invocations, we must forbid
-                    // expanded shadowing to avoid time travel.
-                    if ignore_unresolved_invocations &&
+                    // Forbid expanded shadowing to avoid time travel.
+                    if restricted_shadowing &&
                        binding.expansion != Mark::root() &&
                        ns != MacroNS && // In MacroNS, `try_define` always forbids this shadowing
                        binding.def() != shadowed_glob.def() {
@@ -215,7 +214,7 @@ pub fn resolve_ident_in_module(&mut self,
         }
 
         let no_unresolved_invocations =
-            ignore_unresolved_invocations || module.unresolved_invocations.borrow().is_empty();
+            restricted_shadowing || module.unresolved_invocations.borrow().is_empty();
         match resolution.binding {
             // In `MacroNS`, expanded bindings do not shadow (enforced in `try_define`).
             Some(binding) if no_unresolved_invocations || ns == MacroNS =>
@@ -225,6 +224,9 @@ pub fn resolve_ident_in_module(&mut self,
         }
 
         // Check if the globs are determined
+        if restricted_shadowing && module.def().is_some() {
+            return Err(Determined);
+        }
         for directive in module.globs.borrow().iter() {
             if self.is_accessible(directive.vis.get()) {
                 if let Some(module) = directive.imported_module.get() {
index 06c5150fd13ade909458604075f3dcacd69a2b9c..07a5c266fc026798a23251015f1ed319788da744 100644 (file)
@@ -9,7 +9,7 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 rustc = { path = "../librustc" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index 59340ae87ee5da6e607b7e48ce976efd988b9228..4bab135ff12f70db54b2a65ef5007de61d07dcea 100644 (file)
@@ -423,7 +423,7 @@ fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
 
     let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from(v))));
     strs.fold(String::new(), |mut s, ss| {
-        s.push_str(&ss[..]);
+        s.push_str(&ss);
         s
     })
 }
index acc877d3947758fb20a222e51c2f6a896fe5c3e4..2d1e12bf0a10dfd379e4d90488a6f915a9059d9e 100644 (file)
 use data::{self, VariableKind};
 use dump::Dump;
 
-pub struct JsonDumper<'b, W: Write + 'b> {
-    output: &'b mut W,
+pub struct JsonDumper<O: DumpOutput> {
     result: Analysis,
+    output: O,
 }
 
-impl<'b, W: Write> JsonDumper<'b, W> {
-    pub fn new(writer: &'b mut W) -> JsonDumper<'b, W> {
-        JsonDumper { output: writer, result: Analysis::new() }
-    }
+pub trait DumpOutput {
+    fn dump(&mut self, result: &Analysis);
 }
 
-impl<'b, W: Write> Drop for JsonDumper<'b, W> {
-    fn drop(&mut self) {
-        if let Err(_) = write!(self.output, "{}", as_json(&self.result)) {
+pub struct WriteOutput<'b, W: Write + 'b> {
+    output: &'b mut W,
+}
+
+impl<'b, W: Write> DumpOutput for WriteOutput<'b, W> {
+    fn dump(&mut self, result: &Analysis) {
+        if let Err(_) = write!(self.output, "{}", as_json(&result)) {
             error!("Error writing output");
         }
     }
 }
 
+pub struct CallbackOutput<'b> {
+    callback: &'b mut FnMut(&Analysis),
+}
+
+impl<'b> DumpOutput for CallbackOutput<'b> {
+    fn dump(&mut self, result: &Analysis) {
+        (self.callback)(result)
+    }
+}
+
+impl<'b, W: Write> JsonDumper<WriteOutput<'b, W>> {
+    pub fn new(writer: &'b mut W) -> JsonDumper<WriteOutput<'b, W>> {
+        JsonDumper { output: WriteOutput { output: writer }, result: Analysis::new() }
+    }
+}
+
+impl<'b> JsonDumper<CallbackOutput<'b>> {
+    pub fn with_callback(callback: &'b mut FnMut(&Analysis)) -> JsonDumper<CallbackOutput<'b>> {
+        JsonDumper { output: CallbackOutput { callback: callback }, result: Analysis::new() }
+    }
+}
+
+impl<O: DumpOutput> Drop for JsonDumper<O> {
+    fn drop(&mut self) {
+        self.output.dump(&self.result);
+    }
+}
+
 macro_rules! impl_fn {
     ($fn_name: ident, $data_type: ident, $bucket: ident) => {
         fn $fn_name(&mut self, data: $data_type) {
@@ -49,7 +79,7 @@ fn $fn_name(&mut self, data: $data_type) {
     }
 }
 
-impl<'b, W: Write + 'b> Dump for JsonDumper<'b, W> {
+impl<'b, O: DumpOutput + 'b> Dump for JsonDumper<O> {
     fn crate_prelude(&mut self, data: CratePreludeData) {
         self.result.prelude = Some(data)
     }
index 5e2b1df9d34f89451f28737760f2f4648dc487bc..e5c04f6b61ec297643bb9cd1726fb33bcff8b115 100644 (file)
@@ -48,6 +48,7 @@
 use rustc::hir::map::Node;
 use rustc::hir::def_id::DefId;
 use rustc::session::config::CrateType::CrateTypeExecutable;
+use rustc::session::Session;
 use rustc::ty::{self, TyCtxt};
 
 use std::env;
@@ -866,55 +867,131 @@ fn extension(&self) -> &'static str {
     }
 }
 
-pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
-                               krate: &ast::Crate,
-                               analysis: &'l ty::CrateAnalysis,
-                               cratename: &str,
-                               odir: Option<&Path>,
-                               format: Format) {
-    let _ignore = tcx.dep_graph.in_ignore();
+/// Defines what to do with the results of saving the analysis.
+pub trait SaveHandler {
+    fn save<'l, 'tcx>(&mut self,
+                      save_ctxt: SaveContext<'l, 'tcx>,
+                      krate: &ast::Crate,
+                      cratename: &str);
+}
 
-    assert!(analysis.glob_map.is_some());
+/// Dump the save-analysis results to a file.
+pub struct DumpHandler<'a> {
+    format: Format,
+    odir: Option<&'a Path>,
+    cratename: String
+}
 
-    info!("Dumping crate {}", cratename);
+impl<'a> DumpHandler<'a> {
+    pub fn new(format: Format, odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
+        DumpHandler {
+            format: format,
+            odir: odir,
+            cratename: cratename.to_owned()
+        }
+    }
 
-    // find a path to dump our data to
-    let mut root_path = match env::var_os("RUST_SAVE_ANALYSIS_FOLDER") {
-        Some(val) => PathBuf::from(val),
-        None => match odir {
-            Some(val) => val.join("save-analysis"),
-            None => PathBuf::from("save-analysis-temp"),
-        },
-    };
+    fn output_file(&self, sess: &Session) -> File {
+        let mut root_path = match env::var_os("RUST_SAVE_ANALYSIS_FOLDER") {
+            Some(val) => PathBuf::from(val),
+            None => match self.odir {
+                Some(val) => val.join("save-analysis"),
+                None => PathBuf::from("save-analysis-temp"),
+            },
+        };
 
-    if let Err(e) = std::fs::create_dir_all(&root_path) {
-        tcx.sess.err(&format!("Could not create directory {}: {}",
-                              root_path.display(),
-                              e));
+        if let Err(e) = std::fs::create_dir_all(&root_path) {
+            error!("Could not create directory {}: {}", root_path.display(), e);
+        }
+
+        {
+            let disp = root_path.display();
+            info!("Writing output to {}", disp);
+        }
+
+        let executable = sess.crate_types.borrow().iter().any(|ct| *ct == CrateTypeExecutable);
+        let mut out_name = if executable {
+            "".to_owned()
+        } else {
+            "lib".to_owned()
+        };
+        out_name.push_str(&self.cratename);
+        out_name.push_str(&sess.opts.cg.extra_filename);
+        out_name.push_str(self.format.extension());
+        root_path.push(&out_name);
+        let output_file = File::create(&root_path).unwrap_or_else(|e| {
+            let disp = root_path.display();
+            sess.fatal(&format!("Could not open {}: {}", disp, e));
+        });
+        root_path.pop();
+        output_file
     }
+}
+
+impl<'a> SaveHandler for DumpHandler<'a> {
+    fn save<'l, 'tcx>(&mut self,
+                      save_ctxt: SaveContext<'l, 'tcx>,
+                      krate: &ast::Crate,
+                      cratename: &str) {
+        macro_rules! dump {
+            ($new_dumper: expr) => {{
+                let mut dumper = $new_dumper;
+                let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
+
+                visitor.dump_crate_info(cratename, krate);
+                visit::walk_crate(&mut visitor, krate);
+            }}
+        }
+
+        let output = &mut self.output_file(&save_ctxt.tcx.sess);
 
-    {
-        let disp = root_path.display();
-        info!("Writing output to {}", disp);
+        match self.format {
+            Format::Csv => dump!(CsvDumper::new(output)),
+            Format::Json => dump!(JsonDumper::new(output)),
+            Format::JsonApi => dump!(JsonApiDumper::new(output)),
+        }
     }
+}
 
-    // Create output file.
-    let executable = tcx.sess.crate_types.borrow().iter().any(|ct| *ct == CrateTypeExecutable);
-    let mut out_name = if executable {
-        "".to_owned()
-    } else {
-        "lib".to_owned()
-    };
-    out_name.push_str(&cratename);
-    out_name.push_str(&tcx.sess.opts.cg.extra_filename);
-    out_name.push_str(format.extension());
-    root_path.push(&out_name);
-    let mut output_file = File::create(&root_path).unwrap_or_else(|e| {
-        let disp = root_path.display();
-        tcx.sess.fatal(&format!("Could not open {}: {}", disp, e));
-    });
-    root_path.pop();
-    let output = &mut output_file;
+/// Call a callback with the results of save-analysis.
+pub struct CallbackHandler<'b> {
+    pub callback: &'b mut FnMut(&rls_data::Analysis),
+}
+
+impl<'b> SaveHandler for CallbackHandler<'b> {
+    fn save<'l, 'tcx>(&mut self,
+                      save_ctxt: SaveContext<'l, 'tcx>,
+                      krate: &ast::Crate,
+                      cratename: &str) {
+        macro_rules! dump {
+            ($new_dumper: expr) => {{
+                let mut dumper = $new_dumper;
+                let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
+
+                visitor.dump_crate_info(cratename, krate);
+                visit::walk_crate(&mut visitor, krate);
+            }}
+        }
+
+        // We're using the JsonDumper here because it has the format of the
+        // save-analysis results that we will pass to the callback. IOW, we are
+        // using the JsonDumper to collect the save-analysis results, but not
+        // actually to dump them to a file. This is all a bit convoluted and
+        // there is certainly a simpler design here trying to get out (FIXME).
+        dump!(JsonDumper::with_callback(self.callback))
+    }
+}
+
+pub fn process_crate<'l, 'tcx, H: SaveHandler>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
+                                               krate: &ast::Crate,
+                                               analysis: &'l ty::CrateAnalysis,
+                                               cratename: &str,
+                                               mut handler: H) {
+    let _ignore = tcx.dep_graph.in_ignore();
+
+    assert!(analysis.glob_map.is_some());
+
+    info!("Dumping crate {}", cratename);
 
     let save_ctxt = SaveContext {
         tcx: tcx,
@@ -923,21 +1000,7 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
         span_utils: SpanUtils::new(&tcx.sess),
     };
 
-    macro_rules! dump {
-        ($new_dumper: expr) => {{
-            let mut dumper = $new_dumper;
-            let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
-
-            visitor.dump_crate_info(cratename, krate);
-            visit::walk_crate(&mut visitor, krate);
-        }}
-    }
-
-    match format {
-        Format::Csv => dump!(CsvDumper::new(output)),
-        Format::Json => dump!(JsonDumper::new(output)),
-        Format::JsonApi => dump!(JsonApiDumper::new(output)),
-    }
+    handler.save(save_ctxt, krate, cratename)
 }
 
 // Utility functions for the module.
index b5c67ad998b69e4ea448eebe5cca0e99078b42f8..07dcb2fc29dc66d4f7db46140fdefd859a2238d6 100644 (file)
@@ -11,7 +11,7 @@ test = false
 
 [dependencies]
 flate = { path = "../libflate" }
-log = { path = "../liblog" }
+log = "0.3"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_bitflags = { path = "../librustc_bitflags" }
index 27a19d211c2908ef4f5910aa1f4915859d28cede..1530708b4b8882c6361608a1936496ae90769e93 100644 (file)
@@ -369,7 +369,7 @@ fn unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             match sig.inputs().last().unwrap().sty {
                 ty::TyTuple(ref tupled_arguments, _) => {
                     inputs = &sig.inputs()[0..sig.inputs().len() - 1];
-                    &tupled_arguments[..]
+                    &tupled_arguments
                 }
                 _ => {
                     bug!("argument to function with \"rust-call\" ABI \
index 058f37f62dd82b70f87814f6ce567b2236d05c99..5c1ced573402e07d8314d0654ee458b6bbde3a18 100644 (file)
@@ -229,11 +229,11 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                  variant_fill].iter().cloned().collect();
             match name {
                 None => {
-                    Type::struct_(cx, &fields[..], false)
+                    Type::struct_(cx, &fields, false)
                 }
                 Some(name) => {
                     let mut llty = Type::named_struct(cx, name);
-                    llty.set_struct_body(&fields[..], false);
+                    llty.set_struct_body(&fields, false);
                     llty
                 }
             }
@@ -330,7 +330,7 @@ fn struct_wrapped_nullable_bitdiscr(
     alignment: Alignment,
 ) -> ValueRef {
     let llptrptr = bcx.gepi(scrutinee,
-        &discrfield.iter().map(|f| *f as usize).collect::<Vec<_>>()[..]);
+        &discrfield.iter().map(|f| *f as usize).collect::<Vec<_>>());
     let llptr = bcx.load(llptrptr, alignment.to_align());
     let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
     bcx.icmp(cmp, llptr, C_null(val_ty(llptr)))
@@ -402,7 +402,7 @@ pub fn trans_set_discr<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, val: Valu
                     base::call_memset(bcx, llptr, fill_byte, size, align, false);
                 } else {
                     let path = discrfield.iter().map(|&i| i as usize).collect::<Vec<_>>();
-                    let llptrptr = bcx.gepi(val, &path[..]);
+                    let llptrptr = bcx.gepi(val, &path);
                     let llptrty = val_ty(llptrptr).element_type();
                     bcx.store(C_null(llptrty), llptrptr, None);
                 }
index 12e4e57964f985e47c9ba31226693965c73b4dd7..b6195765b27c29711856314d9afc1524b0e012e2 100644 (file)
@@ -77,14 +77,14 @@ pub fn trans_inline_asm<'a, 'tcx>(
           .chain(arch_clobbers.iter().map(|s| s.to_string()))
           .collect::<Vec<String>>().join(",");
 
-    debug!("Asm Constraints: {}", &all_constraints[..]);
+    debug!("Asm Constraints: {}", &all_constraints);
 
     // Depending on how many outputs we have, the return type is different
     let num_outputs = output_types.len();
     let output_type = match num_outputs {
         0 => Type::void(bcx.ccx),
         1 => output_types[0],
-        _ => Type::struct_(bcx.ccx, &output_types[..], false)
+        _ => Type::struct_(bcx.ccx, &output_types, false)
     };
 
     let dialect = match ia.dialect {
index 11ab6dcaa87f99fa02a99fac8d9068d8c462d2c1..0f908b7d0698bc48e7bd1fd529d46212c5433a0f 100644 (file)
@@ -65,10 +65,10 @@ pub fn find_library(name: &str, search_paths: &[PathBuf], sess: &Session)
 
     for path in search_paths {
         debug!("looking for {} inside {:?}", name, path);
-        let test = path.join(&oslibname[..]);
+        let test = path.join(&oslibname);
         if test.exists() { return test }
         if oslibname != unixlibname {
-            let test = path.join(&unixlibname[..]);
+            let test = path.join(&unixlibname);
             if test.exists() { return test }
         }
     }
index cf1e10b317b1ed030a4acbdf60bc28131d477d61..6d17b2f0eeda3514c3b6079c2c0d92cc7ce315ff 100644 (file)
@@ -91,7 +91,7 @@ pub fn find_crate_name(sess: Option<&Session>,
                        attrs: &[ast::Attribute],
                        input: &Input) -> String {
     let validate = |s: String, span: Option<Span>| {
-        cstore::validate_crate_name(sess, &s[..], span);
+        cstore::validate_crate_name(sess, &s, span);
         s
     };
 
@@ -109,7 +109,7 @@ pub fn find_crate_name(sess: Option<&Session>,
                     let msg = format!("--crate-name and #[crate_name] are \
                                        required to match, but `{}` != `{}`",
                                       s, name);
-                    sess.span_err(attr.span, &msg[..]);
+                    sess.span_err(attr.span, &msg);
                 }
             }
             return validate(s.clone(), None);
@@ -417,7 +417,7 @@ fn object_filenames(trans: &CrateTranslation,
                     outputs: &OutputFilenames)
                     -> Vec<PathBuf> {
     trans.modules.iter().map(|module| {
-        outputs.temp_path(OutputType::Object, Some(&module.name[..]))
+        outputs.temp_path(OutputType::Object, Some(&module.name))
     }).collect()
 }
 
@@ -551,7 +551,7 @@ fn link_rlib<'a>(sess: &'a Session,
                                                  e))
                 }
 
-                let bc_data_deflated = flate::deflate_bytes(&bc_data[..]);
+                let bc_data_deflated = flate::deflate_bytes(&bc_data);
 
                 let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) {
                     Ok(file) => file,
@@ -819,12 +819,12 @@ fn escape_string(s: &[u8]) -> String {
                                          pname,
                                          prog.status))
                     .note(&format!("{:?}", &cmd))
-                    .note(&escape_string(&output[..]))
+                    .note(&escape_string(&output))
                     .emit();
                 sess.abort_if_errors();
             }
-            info!("linker stderr:\n{}", escape_string(&prog.stderr[..]));
-            info!("linker stdout:\n{}", escape_string(&prog.stdout[..]));
+            info!("linker stderr:\n{}", escape_string(&prog.stderr));
+            info!("linker stdout:\n{}", escape_string(&prog.stdout));
         },
         Err(e) => {
             sess.struct_err(&format!("could not exec the linker `{}`: {}", pname, e))
index 0ef3f351a2a4bffdb58292beb058e482a73416cc..e23ddd2542a808f8ae0b765c2c86a95ecafa3f45 100644 (file)
@@ -61,7 +61,7 @@ pub fn run(sess: &session::Session,
     }
 
     let export_threshold =
-        symbol_export::crates_export_threshold(&sess.crate_types.borrow()[..]);
+        symbol_export::crates_export_threshold(&sess.crate_types.borrow());
 
     let symbol_filter = &|&(ref name, level): &(String, _)| {
         if symbol_export::is_below_threshold(level, export_threshold) {
@@ -147,7 +147,7 @@ pub fn run(sess: &session::Session,
                                                         bc_decoded.len() as libc::size_t) {
                     write::llvm_err(sess.diagnostic(),
                                     format!("failed to load bc of `{}`",
-                                            &name[..]));
+                                            name));
                 }
             });
         }
index 9c982be3fa03ef7215009152e8ebd779bfe0c9dd..104e7bc6a52bde0cf04a013fe4ef0f4d47169a62 100644 (file)
@@ -37,8 +37,8 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
 
     let libs = config.used_crates.clone();
     let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
-    let rpaths = get_rpaths(config, &libs[..]);
-    flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));
+    let rpaths = get_rpaths(config, &libs);
+    flags.extend_from_slice(&rpaths_to_flags(&rpaths));
 
     // Use DT_RUNPATH instead of DT_RPATH if available
     if config.linker_is_gnu {
@@ -84,14 +84,14 @@ fn log_rpaths(desc: &str, rpaths: &[String]) {
         }
     }
 
-    log_rpaths("relative", &rel_rpaths[..]);
-    log_rpaths("fallback", &fallback_rpaths[..]);
+    log_rpaths("relative", &rel_rpaths);
+    log_rpaths("fallback", &fallback_rpaths);
 
     let mut rpaths = rel_rpaths;
-    rpaths.extend_from_slice(&fallback_rpaths[..]);
+    rpaths.extend_from_slice(&fallback_rpaths);
 
     // Remove duplicates
-    let rpaths = minimize_rpaths(&rpaths[..]);
+    let rpaths = minimize_rpaths(&rpaths);
     return rpaths;
 }
 
@@ -177,7 +177,7 @@ fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
     let mut set = HashSet::new();
     let mut minimized = Vec::new();
     for rpath in rpaths {
-        if set.insert(&rpath[..]) {
+        if set.insert(rpath) {
             minimized.push(rpath.clone());
         }
     }
index 005fb3533ab0b793510bdec9fde95630c2a46744..23a67ef5046eebec0a527e24a0859eff3f359dce 100644 (file)
@@ -154,7 +154,7 @@ pub fn exported_symbols(&self,
                             cnum: CrateNum)
                             -> &[(String, SymbolExportLevel)] {
         match self.exports.get(&cnum) {
-            Some(exports) => &exports[..],
+            Some(exports) => exports,
             None => &[]
         }
     }
@@ -167,7 +167,7 @@ pub fn for_each_exported_symbol<F>(&self,
     {
         for &(ref name, export_level) in self.exported_symbols(cnum) {
             if is_below_threshold(export_level, export_threshold) {
-                f(&name[..], export_level)
+                f(&name, export_level)
             }
         }
     }
index 518995dfedcc282fac84b41ada9f0ebb288837be..3ad04e10cb027d20f4a555929eb43eff1a11dd62 100644 (file)
@@ -341,7 +341,7 @@ pub fn sanitize(s: &str) -> String {
     if !result.is_empty() &&
         result.as_bytes()[0] != '_' as u8 &&
         ! (result.as_bytes()[0] as char).is_xid_start() {
-        return format!("_{}", &result[..]);
+        return format!("_{}", result);
     }
 
     return result;
index 377ff34cb7e0db7a745dfc4e802b95137a302586..5a017e4fb8a9aa07e163887f28c443960278b1da 100644 (file)
@@ -105,7 +105,7 @@ fn dump(&mut self, handler: &Handler) {
                 Some(ref code) => {
                     handler.emit_with_code(&MultiSpan::new(),
                                            &diag.msg,
-                                           &code[..],
+                                           &code,
                                            diag.lvl);
                 },
                 None => {
@@ -189,8 +189,8 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
     let fdata_sections = ffunction_sections;
 
     let code_model_arg = match sess.opts.cg.code_model {
-        Some(ref s) => &s[..],
-        None => &sess.target.target.options.code_model[..],
+        Some(ref s) => &s,
+        None => &sess.target.target.options.code_model,
     };
 
     let code_model = match CODE_GEN_MODEL_ARGS.iter().find(
@@ -397,7 +397,7 @@ struct HandlerFreeVars<'a> {
     let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
         .expect("non-UTF8 SMDiagnostic");
 
-    report_inline_asm(cgcx, &msg[..], cookie);
+    report_inline_asm(cgcx, &msg, cookie);
 }
 
 unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
@@ -823,7 +823,7 @@ pub fn run_passes(sess: &Session,
         if trans.modules.len() == 1 {
             // 1) Only one codegen unit.  In this case it's no difficulty
             //    to copy `foo.0.x` to `foo.x`.
-            let module_name = Some(&(trans.modules[0].name)[..]);
+            let module_name = Some(&trans.modules[0].name[..]);
             let path = crate_output.temp_path(output_type, module_name);
             copy_gracefully(&path,
                             &crate_output.path(output_type));
@@ -939,7 +939,7 @@ pub fn run_passes(sess: &Session,
 
         if metadata_config.emit_bc && !user_wants_bitcode {
             let path = crate_output.temp_path(OutputType::Bitcode,
-                                              Some(&trans.metadata_module.name[..]));
+                                              Some(&trans.metadata_module.name));
             remove(sess, &path);
         }
     }
index 80b563729f5ce3678a641d900e8559834d15037f..ec45c5593632ed3fddbc5bf18924ffdec73fc740 100644 (file)
@@ -514,7 +514,7 @@ pub fn call_memcpy<'a, 'tcx>(b: &Builder<'a, 'tcx>,
                                n_bytes: ValueRef,
                                align: u32) {
     let ccx = b.ccx;
-    let ptr_width = &ccx.sess().target.target.target_pointer_width[..];
+    let ptr_width = &ccx.sess().target.target.target_pointer_width;
     let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
     let memcpy = ccx.get_intrinsic(&key);
     let src_ptr = b.pointercast(src, Type::i8p(ccx));
@@ -550,7 +550,7 @@ pub fn call_memset<'a, 'tcx>(b: &Builder<'a, 'tcx>,
                              size: ValueRef,
                              align: ValueRef,
                              volatile: bool) -> ValueRef {
-    let ptr_width = &b.ccx.sess().target.target.target_pointer_width[..];
+    let ptr_width = &b.ccx.sess().target.target.target_pointer_width;
     let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
     let llintrinsicfn = b.ccx.get_intrinsic(&intrinsic_key);
     let volatile = C_bool(b.ccx, volatile);
@@ -755,7 +755,6 @@ enum MetadataKind {
 
     let cstore = &cx.tcx().sess.cstore;
     let metadata = cstore.encode_metadata(cx.tcx(),
-                                          cx.export_map(),
                                           cx.link_meta(),
                                           exported_symbols);
     if kind == MetadataKind::Uncompressed {
@@ -766,7 +765,7 @@ enum MetadataKind {
     let mut compressed = cstore.metadata_encoding_version().to_vec();
     compressed.extend_from_slice(&flate::deflate_bytes(&metadata));
 
-    let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
+    let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed);
     let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
     let name = cx.metadata_symbol_name();
     let buf = CString::new(name).unwrap();
@@ -797,7 +796,7 @@ fn internalize_symbols<'a, 'tcx>(sess: &Session,
                                  symbol_map: &SymbolMap<'tcx>,
                                  exported_symbols: &ExportedSymbols) {
     let export_threshold =
-        symbol_export::crates_export_threshold(&sess.crate_types.borrow()[..]);
+        symbol_export::crates_export_threshold(&sess.crate_types.borrow());
 
     let exported_symbols = exported_symbols
         .exported_symbols(LOCAL_CRATE)
@@ -1036,7 +1035,7 @@ pub fn find_exported_symbols(tcx: TyCtxt, reachable: NodeSet) -> NodeSet {
                 (generics.parent_types == 0 && generics.types.is_empty()) &&
                 // Functions marked with #[inline] are only ever translated
                 // with "internal" linkage and are never exported.
-                !attr::requests_inline(&attributes[..])
+                !attr::requests_inline(&attributes)
             }
 
             _ => false
@@ -1056,7 +1055,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // particular items that will be processed.
     let krate = tcx.hir.krate();
 
-    let ty::CrateAnalysis { export_map, reachable, name, .. } = analysis;
+    let ty::CrateAnalysis { reachable, name, .. } = analysis;
     let exported_symbols = find_exported_symbols(tcx, reachable);
 
     let check_overflow = tcx.sess.overflow_checks();
@@ -1064,7 +1063,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let link_meta = link::build_link_meta(incremental_hashes_map, &name);
 
     let shared_ccx = SharedCrateContext::new(tcx,
-                                             export_map,
                                              link_meta.clone(),
                                              exported_symbols,
                                              check_overflow);
@@ -1576,7 +1574,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
                 cgus.dedup();
                 for &(ref cgu_name, linkage) in cgus.iter() {
                     output.push_str(" ");
-                    output.push_str(&cgu_name[..]);
+                    output.push_str(&cgu_name);
 
                     let linkage_abbrev = match linkage {
                         llvm::Linkage::ExternalLinkage => "External",
index a62f07042a7035749ba970c1d685e2ca6957fed1..8b1010d89fd9fd1c03c5f0e657de371ae090529c 100644 (file)
@@ -627,7 +627,7 @@ pub fn gepi(&self, base: ValueRef, ixs: &[usize]) -> ValueRef {
         } else {
             let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
             self.count_insn("gepi");
-            self.inbounds_gep(base, &v[..])
+            self.inbounds_gep(base, &v)
         }
     }
 
@@ -835,8 +835,8 @@ pub fn add_span_comment(&self, sp: Span, text: &str) {
             let s = format!("{} ({})",
                             text,
                             self.ccx.sess().codemap().span_to_string(sp));
-            debug!("{}", &s[..]);
-            self.add_comment(&s[..]);
+            debug!("{}", s);
+            self.add_comment(&s);
         }
     }
 
index 1c1395f1b7762604309616c59b07979824036bf8..73602dc420b3f9999be6534e41e5df674004cc91 100644 (file)
@@ -14,7 +14,6 @@
                        DepTrackingMapConfig, WorkProduct};
 use middle::cstore::LinkMeta;
 use rustc::hir;
-use rustc::hir::def::ExportMap;
 use rustc::hir::def_id::DefId;
 use rustc::traits;
 use debuginfo;
@@ -68,7 +67,6 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     metadata_llmod: ModuleRef,
     metadata_llcx: ContextRef,
 
-    export_map: ExportMap,
     exported_symbols: NodeSet,
     link_meta: LinkMeta,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -402,7 +400,6 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
 
 impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
     pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
-               export_map: ExportMap,
                link_meta: LinkMeta,
                exported_symbols: NodeSet,
                check_overflow: bool)
@@ -459,7 +456,6 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
         SharedCrateContext {
             metadata_llmod: metadata_llmod,
             metadata_llcx: metadata_llcx,
-            export_map: export_map,
             exported_symbols: exported_symbols,
             link_meta: link_meta,
             empty_param_env: tcx.empty_parameter_environment(),
@@ -499,10 +495,6 @@ pub fn metadata_llcx(&self) -> ContextRef {
         self.metadata_llcx
     }
 
-    pub fn export_map<'a>(&'a self) -> &'a ExportMap {
-        &self.export_map
-    }
-
     pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
         &self.exported_symbols
     }
@@ -702,10 +694,6 @@ pub fn td(&self) -> llvm::TargetDataRef {
         unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
     }
 
-    pub fn export_map<'a>(&'a self) -> &'a ExportMap {
-        &self.shared.export_map
-    }
-
     pub fn exported_symbols<'a>(&'a self) -> &'a NodeSet {
         &self.shared.exported_symbols
     }
index 2c3b479c7dd0f6fb218b873bf05788eb1553c67f..a3968650043ba41a5b29accdf68f238e4c7dc209 100644 (file)
@@ -13,7 +13,8 @@
 
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
-use rustc::mir::{self, Location, TerminatorKind};
+use rustc::middle::const_val::ConstVal;
+use rustc::mir::{self, Location, TerminatorKind, Literal};
 use rustc::mir::visit::{Visitor, LvalueContext};
 use rustc::mir::traversal;
 use common;
@@ -109,7 +110,9 @@ fn visit_terminator_kind(&mut self,
         match *kind {
             mir::TerminatorKind::Call {
                 func: mir::Operand::Constant(mir::Constant {
-                    literal: mir::Literal::Item { def_id, .. }, ..
+                    literal: Literal::Value {
+                        value: ConstVal::Function(def_id, _), ..
+                    }, ..
                 }),
                 ref args, ..
             } if Some(def_id) == self.cx.ccx.tcx().lang_items.box_free_fn() => {
index 107b0982af982b9d606927696c18677d568db207..dbd928194c0329834a14f47eb0a45ed12ae98d1d 100644 (file)
@@ -101,9 +101,12 @@ pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
             ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
             ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
             ConstVal::Struct(_) | ConstVal::Tuple(_) |
-            ConstVal::Array(..) | ConstVal::Repeat(..) |
+            ConstVal::Array(..) | ConstVal::Repeat(..) => {
+                bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
+            }
             ConstVal::Function(..) => {
-                bug!("MIR must not use `{:?}` (which refers to a local ID)", cv)
+                let llty = type_of::type_of(ccx, ty);
+                return Const::new(C_null(llty), ty);
             }
             ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
         };
@@ -476,13 +479,6 @@ fn const_operand(&self, operand: &mir::Operand<'tcx>, span: Span)
                 let ty = self.monomorphize(&constant.ty);
                 match constant.literal.clone() {
                     mir::Literal::Item { def_id, substs } => {
-                        // Shortcut for zero-sized types, including function item
-                        // types, which would not work with MirConstContext.
-                        if common::type_is_zero_size(self.ccx, ty) {
-                            let llty = type_of::type_of(self.ccx, ty);
-                            return Ok(Const::new(C_null(llty), ty));
-                        }
-
                         let substs = self.monomorphize(&substs);
                         MirConstContext::trans_def(self.ccx, def_id, substs, IndexVec::new())
                     }
@@ -924,13 +920,6 @@ pub fn trans_constant(&mut self,
         let ty = self.monomorphize(&constant.ty);
         let result = match constant.literal.clone() {
             mir::Literal::Item { def_id, substs } => {
-                // Shortcut for zero-sized types, including function item
-                // types, which would not work with MirConstContext.
-                if common::type_is_zero_size(bcx.ccx, ty) {
-                    let llty = type_of::type_of(bcx.ccx, ty);
-                    return Const::new(C_null(llty), ty);
-                }
-
                 let substs = self.monomorphize(&substs);
                 MirConstContext::trans_def(bcx.ccx, def_id, substs, IndexVec::new())
             }
index fcf6937d4b6d58670681f042e9bc6deedc71076b..382ca8ef01001ecfd31d922b869d143d5e3a04a0 100644 (file)
@@ -287,7 +287,7 @@ pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx
 
     match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
         traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
-            scx.tcx().custom_coerce_unsized_kind(impl_def_id)
+            scx.tcx().coerce_unsized_info(impl_def_id).custom_kind.unwrap()
         }
         vtable => {
             bug!("invalid CoerceUnsized vtable: {:?}", vtable);
index f08d26373e50e979ef977f2c2346a77275eda918..07998aa4a30ea0aee8b6a633cd8ea96c529d2843 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-log = { path = "../liblog" }
+log = "0.3"
 syntax = { path = "../libsyntax" }
 arena = { path = "../libarena" }
 fmt_macros = { path = "../libfmt_macros" }
index dfa7ababca0bbd8b97f143cbc9efcdca24d44ec6..5b0418921563a2dea56b4fa4bbf47897b57f3fc8 100644 (file)
@@ -479,14 +479,9 @@ fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<DefId>) {
     }
 
     fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
-        // Read the inherent implementation candidates for this type from the
-        // metadata if necessary.
-        self.tcx.populate_inherent_implementations_for_type_if_necessary(self.span, def_id);
-
-        if let Some(impl_infos) = self.tcx.maps.inherent_impls.borrow().get(&def_id) {
-            for &impl_def_id in impl_infos.iter() {
-                self.assemble_inherent_impl_probe(impl_def_id);
-            }
+        let impl_def_ids = ty::queries::inherent_impls::get(self.tcx, self.span, def_id);
+        for &impl_def_id in impl_def_ids.iter() {
+            self.assemble_inherent_impl_probe(impl_def_id);
         }
     }
 
index c857388106d5ad6c2fe89e628c3f3b657b158e3e..416147fd8d4cb4dd659df3ff333396968e156c95 100644 (file)
@@ -84,7 +84,7 @@
 use dep_graph::DepNode;
 use fmt_macros::{Parser, Piece, Position};
 use hir::def::{Def, CtorKind};
-use hir::def_id::{DefId, LOCAL_CRATE};
+use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin, TypeTrace};
 use rustc::infer::type_variable::{self, TypeVariableOrigin};
 use rustc::ty::subst::{Kind, Subst, Substs};
@@ -541,19 +541,21 @@ pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult
 }
 
 pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
-    return tcx.sess.track_errors(|| {
-        tcx.dep_graph.with_task(DepNode::TypeckBodiesKrate, tcx, (), check_item_bodies_task);
-    });
+    ty::queries::typeck_item_bodies::get(tcx, DUMMY_SP, LOCAL_CRATE)
+}
 
-    fn check_item_bodies_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
+fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> CompileResult {
+    debug_assert!(crate_num == LOCAL_CRATE);
+    tcx.sess.track_errors(|| {
         tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
             tcx.item_tables(body_owner_def_id);
         });
-    }
+    })
 }
 
 pub fn provide(providers: &mut Providers) {
     *providers = Providers {
+        typeck_item_bodies,
         typeck_tables,
         closure_type,
         closure_kind,
@@ -4099,6 +4101,17 @@ fn check_block_with_expected(&self,
             };
 
             if self.diverges.get().always() {
+                if let ExpectHasType(ety) = expected {
+                    // Avoid forcing a type (only `!` for now) in unreachable code.
+                    // FIXME(aburka) do we need this special case? and should it be is_uninhabited?
+                    if !ety.is_never() {
+                        if let Some(ref e) = blk.expr {
+                            // Coerce the tail expression to the right type.
+                            self.demand_coerce(e, ty, ety);
+                        }
+                    }
+                }
+
                 ty = self.next_diverging_ty_var(TypeVariableOrigin::DivergingBlockExpr(blk.span));
             } else if let ExpectHasType(ety) = expected {
                 if let Some(ref e) = blk.expr {
index 3cdf9fc93ae600617a4c84aa935dfdb1adcaec07..47b41a75cf5316a9f041d1200ce362f260a45aea 100644 (file)
@@ -18,6 +18,7 @@
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::ParameterEnvironment;
 use rustc::ty::TypeFoldable;
+use rustc::ty::adjustment::CoerceUnsizedInfo;
 use rustc::ty::subst::Subst;
 use rustc::ty::util::CopyImplementationError;
 use rustc::infer;
@@ -159,11 +160,26 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                                    coerce_unsized_trait: DefId,
+                                                    _: DefId,
                                                     impl_did: DefId) {
     debug!("visit_implementation_of_coerce_unsized: impl_did={:?}",
            impl_did);
 
+    // Just compute this for the side-effects, in particular reporting
+    // errors; other parts of the code may demand it for the info of
+    // course.
+    if impl_did.is_local() {
+        let span = tcx.def_span(impl_did);
+        ty::queries::coerce_unsized_info::get(tcx, span, impl_did);
+    }
+}
+
+pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     impl_did: DefId)
+                                     -> CoerceUnsizedInfo {
+    debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did);
+    let coerce_unsized_trait = tcx.lang_items.coerce_unsized_trait().unwrap();
+
     let unsize_trait = match tcx.lang_items.require(UnsizeTraitLangItem) {
         Ok(id) => id,
         Err(err) => {
@@ -171,16 +187,14 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     };
 
-    let impl_node_id = if let Some(n) = tcx.hir.as_local_node_id(impl_did) {
-        n
-    } else {
-        debug!("visit_implementation_of_coerce_unsized(): impl not \
-                in this crate");
-        return;
-    };
+    // this provider should only get invoked for local def-ids
+    let impl_node_id = tcx.hir.as_local_node_id(impl_did).unwrap_or_else(|| {
+        bug!("coerce_unsized_info: invoked for non-local def-id {:?}", impl_did)
+    });
 
     let source = tcx.item_type(impl_did);
     let trait_ref = tcx.impl_trait_ref(impl_did).unwrap();
+    assert_eq!(trait_ref.def_id, coerce_unsized_trait);
     let target = trait_ref.substs.type_at(1);
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)",
            source,
@@ -192,6 +206,8 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let target = target.subst(tcx, &param_env.free_substs);
     assert!(!source.has_escaping_regions());
 
+    let err_info = CoerceUnsizedInfo { custom_kind: None };
+
     debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (free)",
            source,
            target);
@@ -234,7 +250,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                definition; expected {}, found {}",
                               source_path,
                               target_path);
-                    return;
+                    return err_info;
                 }
 
                 let fields = &def_a.struct_variant().fields;
@@ -268,7 +284,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               "the trait `CoerceUnsized` may only be implemented \
                                for a coercion between structures with one field \
                                being coerced, none found");
-                    return;
+                    return err_info;
                 } else if diff_fields.len() > 1 {
                     let item = tcx.hir.expect_item(impl_node_id);
                     let span = if let ItemImpl(.., Some(ref t), _, _) = item.node {
@@ -295,7 +311,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                           .join(", ")));
                     err.span_label(span, &format!("requires multiple coercions"));
                     err.emit();
-                    return;
+                    return err_info;
                 }
 
                 let (i, a, b) = diff_fields[0];
@@ -309,7 +325,7 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           E0376,
                           "the trait `CoerceUnsized` may only be implemented \
                            for a coercion between structures");
-                return;
+                return err_info;
             }
         };
 
@@ -331,8 +347,8 @@ fn visit_implementation_of_coerce_unsized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             .caller_bounds);
         infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
 
-        if let Some(kind) = kind {
-            tcx.maps.custom_coerce_unsized_kind.borrow_mut().insert(impl_did, kind);
+        CoerceUnsizedInfo {
+            custom_kind: kind
         }
-    });
+    })
 }
diff --git a/src/librustc_typeck/coherence/inherent.rs b/src/librustc_typeck/coherence/inherent.rs
deleted file mode 100644 (file)
index e3b4ba9..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright 2017 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 rustc::dep_graph::DepNode;
-use rustc::hir::def_id::DefId;
-use rustc::hir;
-use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::lint;
-use rustc::traits::{self, Reveal};
-use rustc::ty::{self, TyCtxt};
-
-use syntax::ast;
-use syntax_pos::Span;
-
-struct InherentCollect<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>
-}
-
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        let (unsafety, ty) = match item.node {
-            hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
-            _ => return
-        };
-
-        match unsafety {
-            hir::Unsafety::Normal => {
-                // OK
-            }
-            hir::Unsafety::Unsafe => {
-                span_err!(self.tcx.sess,
-                          item.span,
-                          E0197,
-                          "inherent impls cannot be declared as unsafe");
-            }
-        }
-
-        let def_id = self.tcx.hir.local_def_id(item.id);
-        let self_ty = self.tcx.item_type(def_id);
-        match self_ty.sty {
-            ty::TyAdt(def, _) => {
-                self.check_def_id(item, def.did);
-            }
-            ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
-                self.check_def_id(item, data.principal().unwrap().def_id());
-            }
-            ty::TyChar => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.char_impl(),
-                                          "char",
-                                          "char",
-                                          item.span);
-            }
-            ty::TyStr => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.str_impl(),
-                                          "str",
-                                          "str",
-                                          item.span);
-            }
-            ty::TySlice(_) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.slice_impl(),
-                                          "slice",
-                                          "[T]",
-                                          item.span);
-            }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.const_ptr_impl(),
-                                          "const_ptr",
-                                          "*const T",
-                                          item.span);
-            }
-            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.mut_ptr_impl(),
-                                          "mut_ptr",
-                                          "*mut T",
-                                          item.span);
-            }
-            ty::TyInt(ast::IntTy::I8) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i8_impl(),
-                                          "i8",
-                                          "i8",
-                                          item.span);
-            }
-            ty::TyInt(ast::IntTy::I16) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i16_impl(),
-                                          "i16",
-                                          "i16",
-                                          item.span);
-            }
-            ty::TyInt(ast::IntTy::I32) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i32_impl(),
-                                          "i32",
-                                          "i32",
-                                          item.span);
-            }
-            ty::TyInt(ast::IntTy::I64) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i64_impl(),
-                                          "i64",
-                                          "i64",
-                                          item.span);
-            }
-            ty::TyInt(ast::IntTy::I128) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.i128_impl(),
-                                          "i128",
-                                          "i128",
-                                          item.span);
-            }
-            ty::TyInt(ast::IntTy::Is) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.isize_impl(),
-                                          "isize",
-                                          "isize",
-                                          item.span);
-            }
-            ty::TyUint(ast::UintTy::U8) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u8_impl(),
-                                          "u8",
-                                          "u8",
-                                          item.span);
-            }
-            ty::TyUint(ast::UintTy::U16) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u16_impl(),
-                                          "u16",
-                                          "u16",
-                                          item.span);
-            }
-            ty::TyUint(ast::UintTy::U32) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u32_impl(),
-                                          "u32",
-                                          "u32",
-                                          item.span);
-            }
-            ty::TyUint(ast::UintTy::U64) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u64_impl(),
-                                          "u64",
-                                          "u64",
-                                          item.span);
-            }
-            ty::TyUint(ast::UintTy::U128) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.u128_impl(),
-                                          "u128",
-                                          "u128",
-                                          item.span);
-            }
-            ty::TyUint(ast::UintTy::Us) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.usize_impl(),
-                                          "usize",
-                                          "usize",
-                                          item.span);
-            }
-            ty::TyFloat(ast::FloatTy::F32) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.f32_impl(),
-                                          "f32",
-                                          "f32",
-                                          item.span);
-            }
-            ty::TyFloat(ast::FloatTy::F64) => {
-                self.check_primitive_impl(def_id,
-                                          self.tcx.lang_items.f64_impl(),
-                                          "f64",
-                                          "f64",
-                                          item.span);
-            }
-            ty::TyError => {
-                return;
-            }
-            _ => {
-                struct_span_err!(self.tcx.sess,
-                                 ty.span,
-                                 E0118,
-                                 "no base type found for inherent implementation")
-                    .span_label(ty.span, &format!("impl requires a base type"))
-                    .note(&format!("either implement a trait on it or create a newtype \
-                                    to wrap it instead"))
-                    .emit();
-                return;
-            }
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
-
-impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
-    fn check_def_id(&self, item: &hir::Item, def_id: DefId) {
-        if def_id.is_local() {
-            // Add the implementation to the mapping from implementation to base
-            // type def ID, if there is a base type for this implementation and
-            // the implementation does not have any associated traits.
-            let impl_def_id = self.tcx.hir.local_def_id(item.id);
-
-            // Subtle: it'd be better to collect these into a local map
-            // and then write the vector only once all items are known,
-            // but that leads to degenerate dep-graphs. The problem is
-            // that the write of that big vector winds up having reads
-            // from *all* impls in the krate, since we've lost the
-            // precision basically.  This would be ok in the firewall
-            // model so once we've made progess towards that we can modify
-            // the strategy here. In the meantime, using `push` is ok
-            // because we are doing this as a pre-pass before anyone
-            // actually reads from `inherent_impls` -- and we know this is
-            // true beacuse we hold the refcell lock.
-            self.tcx.maps.inherent_impls.borrow_mut().push(def_id, impl_def_id);
-        } else {
-            struct_span_err!(self.tcx.sess,
-                             item.span,
-                             E0116,
-                             "cannot define inherent `impl` for a type outside of the crate \
-                              where the type is defined")
-                .span_label(item.span,
-                            &format!("impl for type defined outside of crate."))
-                .note("define and implement a trait or new type instead")
-                .emit();
-        }
-    }
-
-    fn check_primitive_impl(&self,
-                            impl_def_id: DefId,
-                            lang_def_id: Option<DefId>,
-                            lang: &str,
-                            ty: &str,
-                            span: Span) {
-        match lang_def_id {
-            Some(lang_def_id) if lang_def_id == impl_def_id => {
-                // OK
-            }
-            _ => {
-                struct_span_err!(self.tcx.sess,
-                                 span,
-                                 E0390,
-                                 "only a single inherent implementation marked with `#[lang = \
-                                  \"{}\"]` is allowed for the `{}` primitive",
-                                 lang,
-                                 ty)
-                    .span_help(span, "consider using a trait to implement these methods")
-                    .emit();
-            }
-        }
-    }
-}
-
-struct InherentOverlapChecker<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>
-}
-
-impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
-    fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
-        #[derive(Copy, Clone, PartialEq)]
-        enum Namespace {
-            Type,
-            Value,
-        }
-
-        let name_and_namespace = |def_id| {
-            let item = self.tcx.associated_item(def_id);
-            (item.name, match item.kind {
-                ty::AssociatedKind::Type => Namespace::Type,
-                ty::AssociatedKind::Const |
-                ty::AssociatedKind::Method => Namespace::Value,
-            })
-        };
-
-        let impl_items1 = self.tcx.associated_item_def_ids(impl1);
-        let impl_items2 = self.tcx.associated_item_def_ids(impl2);
-
-        for &item1 in &impl_items1[..] {
-            let (name, namespace) = name_and_namespace(item1);
-
-            for &item2 in &impl_items2[..] {
-                if (name, namespace) == name_and_namespace(item2) {
-                    let msg = format!("duplicate definitions with name `{}`", name);
-                    let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
-                    self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
-                                           node_id,
-                                           self.tcx.span_of_impl(item1).unwrap(),
-                                           msg);
-                }
-            }
-        }
-    }
-
-    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
-        let _task = self.tcx.dep_graph.in_task(DepNode::CoherenceOverlapInherentCheck(ty_def_id));
-
-        let inherent_impls = self.tcx.maps.inherent_impls.borrow();
-        let impls = match inherent_impls.get(&ty_def_id) {
-            Some(impls) => impls,
-            None => return,
-        };
-
-        for (i, &impl1_def_id) in impls.iter().enumerate() {
-            for &impl2_def_id in &impls[(i + 1)..] {
-                self.tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
-                    if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
-                        self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
-                    }
-                });
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
-    fn visit_item(&mut self, item: &'v hir::Item) {
-        match item.node {
-            hir::ItemEnum(..) |
-            hir::ItemStruct(..) |
-            hir::ItemTrait(..) |
-            hir::ItemUnion(..) => {
-                let type_def_id = self.tcx.hir.local_def_id(item.id);
-                self.check_for_overlapping_inherent_impls(type_def_id);
-            }
-            _ => {}
-        }
-    }
-
-    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
-    }
-
-    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
-    }
-}
-
-pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.visit_all_item_likes_in_krate(DepNode::CoherenceCheckImpl,
-                                      &mut InherentCollect { tcx });
-    tcx.visit_all_item_likes_in_krate(DepNode::CoherenceOverlapCheckSpecial,
-                                      &mut InherentOverlapChecker { tcx });
-}
diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs
new file mode 100644 (file)
index 0000000..3a39df5
--- /dev/null
@@ -0,0 +1,325 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The code in this module gathers up all of the inherent impls in
+//! the current crate and organizes them in a map. It winds up
+//! touching the whole crate and thus must be recomputed completely
+//! for any change, but it is very cheap to compute. In practice, most
+//! code in the compiler never *directly* requests this map. Instead,
+//! it requests the inherent impls specific to some type (via
+//! `ty::queries::inherent_impls::get(def_id)`). That value, however,
+//! is computed by selecting an idea from this table.
+
+use rustc::dep_graph::DepNode;
+use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::ty::{self, CrateInherentImpls, TyCtxt};
+use rustc::util::nodemap::DefIdMap;
+
+use std::rc::Rc;
+use syntax::ast;
+use syntax_pos::{DUMMY_SP, Span};
+
+/// On-demand query: yields a map containing all types mapped to their inherent impls.
+pub fn crate_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      crate_num: CrateNum)
+                                      -> CrateInherentImpls {
+    assert_eq!(crate_num, LOCAL_CRATE);
+
+    let krate = tcx.hir.krate();
+    let mut collect = InherentCollect {
+        tcx,
+        impls_map: CrateInherentImpls {
+            inherent_impls: DefIdMap()
+        }
+    };
+    krate.visit_all_item_likes(&mut collect);
+    collect.impls_map
+}
+
+/// On-demand query: yields a vector of the inherent impls for a specific type.
+pub fn inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                ty_def_id: DefId)
+                                -> Rc<Vec<DefId>> {
+    assert!(ty_def_id.is_local());
+
+    // NB. Until we adopt the red-green dep-tracking algorithm (see
+    // [the plan] for details on that), we do some hackery here to get
+    // the dependencies correct.  Basically, we use a `with_ignore` to
+    // read the result we want. If we didn't have the `with_ignore`,
+    // we would wind up with a dependency on the entire crate, which
+    // we don't want. Then we go and add dependencies on all the impls
+    // in the result (which is what we wanted).
+    //
+    // The result is a graph with an edge from `Hir(I)` for every impl
+    // `I` defined on some type `T` to `CoherentInherentImpls(T)`,
+    // thus ensuring that if any of those impls change, the set of
+    // inherent impls is considered dirty.
+    //
+    // [the plan]: https://github.com/rust-lang/rust-roadmap/issues/4
+
+    let result = tcx.dep_graph.with_ignore(|| {
+        let crate_map = ty::queries::crate_inherent_impls::get(tcx, DUMMY_SP, ty_def_id.krate);
+        match crate_map.inherent_impls.get(&ty_def_id) {
+            Some(v) => v.clone(),
+            None => Rc::new(vec![]),
+        }
+    });
+
+    for &impl_def_id in &result[..] {
+        tcx.dep_graph.read(DepNode::Hir(impl_def_id));
+    }
+
+    result
+}
+
+struct InherentCollect<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    impls_map: CrateInherentImpls,
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentCollect<'a, 'tcx> {
+    fn visit_item(&mut self, item: &hir::Item) {
+        let (unsafety, ty) = match item.node {
+            hir::ItemImpl(unsafety, .., None, ref ty, _) => (unsafety, ty),
+            _ => return
+        };
+
+        match unsafety {
+            hir::Unsafety::Normal => {
+                // OK
+            }
+            hir::Unsafety::Unsafe => {
+                span_err!(self.tcx.sess,
+                          item.span,
+                          E0197,
+                          "inherent impls cannot be declared as unsafe");
+            }
+        }
+
+        let def_id = self.tcx.hir.local_def_id(item.id);
+        let self_ty = self.tcx.item_type(def_id);
+        match self_ty.sty {
+            ty::TyAdt(def, _) => {
+                self.check_def_id(item, def.did);
+            }
+            ty::TyDynamic(ref data, ..) if data.principal().is_some() => {
+                self.check_def_id(item, data.principal().unwrap().def_id());
+            }
+            ty::TyChar => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.char_impl(),
+                                          "char",
+                                          "char",
+                                          item.span);
+            }
+            ty::TyStr => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.str_impl(),
+                                          "str",
+                                          "str",
+                                          item.span);
+            }
+            ty::TySlice(_) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.slice_impl(),
+                                          "slice",
+                                          "[T]",
+                                          item.span);
+            }
+            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.const_ptr_impl(),
+                                          "const_ptr",
+                                          "*const T",
+                                          item.span);
+            }
+            ty::TyRawPtr(ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.mut_ptr_impl(),
+                                          "mut_ptr",
+                                          "*mut T",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I8) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i8_impl(),
+                                          "i8",
+                                          "i8",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I16) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i16_impl(),
+                                          "i16",
+                                          "i16",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I32) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i32_impl(),
+                                          "i32",
+                                          "i32",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I64) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i64_impl(),
+                                          "i64",
+                                          "i64",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::I128) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.i128_impl(),
+                                          "i128",
+                                          "i128",
+                                          item.span);
+            }
+            ty::TyInt(ast::IntTy::Is) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.isize_impl(),
+                                          "isize",
+                                          "isize",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U8) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u8_impl(),
+                                          "u8",
+                                          "u8",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U16) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u16_impl(),
+                                          "u16",
+                                          "u16",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U32) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u32_impl(),
+                                          "u32",
+                                          "u32",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U64) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u64_impl(),
+                                          "u64",
+                                          "u64",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::U128) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.u128_impl(),
+                                          "u128",
+                                          "u128",
+                                          item.span);
+            }
+            ty::TyUint(ast::UintTy::Us) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.usize_impl(),
+                                          "usize",
+                                          "usize",
+                                          item.span);
+            }
+            ty::TyFloat(ast::FloatTy::F32) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.f32_impl(),
+                                          "f32",
+                                          "f32",
+                                          item.span);
+            }
+            ty::TyFloat(ast::FloatTy::F64) => {
+                self.check_primitive_impl(def_id,
+                                          self.tcx.lang_items.f64_impl(),
+                                          "f64",
+                                          "f64",
+                                          item.span);
+            }
+            ty::TyError => {
+                return;
+            }
+            _ => {
+                struct_span_err!(self.tcx.sess,
+                                 ty.span,
+                                 E0118,
+                                 "no base type found for inherent implementation")
+                    .span_label(ty.span, &format!("impl requires a base type"))
+                    .note(&format!("either implement a trait on it or create a newtype \
+                                    to wrap it instead"))
+                    .emit();
+                return;
+            }
+        }
+    }
+
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    }
+}
+
+impl<'a, 'tcx> InherentCollect<'a, 'tcx> {
+    fn check_def_id(&mut self, item: &hir::Item, def_id: DefId) {
+        if def_id.is_local() {
+            // Add the implementation to the mapping from implementation to base
+            // type def ID, if there is a base type for this implementation and
+            // the implementation does not have any associated traits.
+            let impl_def_id = self.tcx.hir.local_def_id(item.id);
+            let mut rc_vec = self.impls_map.inherent_impls
+                                           .entry(def_id)
+                                           .or_insert_with(|| Rc::new(vec![]));
+
+            // At this point, there should not be any clones of the
+            // `Rc`, so we can still safely push into it in place:
+            Rc::get_mut(&mut rc_vec).unwrap().push(impl_def_id);
+        } else {
+            struct_span_err!(self.tcx.sess,
+                             item.span,
+                             E0116,
+                             "cannot define inherent `impl` for a type outside of the crate \
+                              where the type is defined")
+                .span_label(item.span,
+                            &format!("impl for type defined outside of crate."))
+                .note("define and implement a trait or new type instead")
+                .emit();
+        }
+    }
+
+    fn check_primitive_impl(&self,
+                            impl_def_id: DefId,
+                            lang_def_id: Option<DefId>,
+                            lang: &str,
+                            ty: &str,
+                            span: Span) {
+        match lang_def_id {
+            Some(lang_def_id) if lang_def_id == impl_def_id => {
+                // OK
+            }
+            _ => {
+                struct_span_err!(self.tcx.sess,
+                                 span,
+                                 E0390,
+                                 "only a single inherent implementation marked with `#[lang = \
+                                  \"{}\"]` is allowed for the `{}` primitive",
+                                 lang,
+                                 ty)
+                    .span_help(span, "consider using a trait to implement these methods")
+                    .emit();
+            }
+        }
+    }
+}
+
diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs
new file mode 100644 (file)
index 0000000..4b36072
--- /dev/null
@@ -0,0 +1,102 @@
+// Copyright 2017 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 rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc::hir;
+use rustc::hir::itemlikevisit::ItemLikeVisitor;
+use rustc::lint;
+use rustc::traits::{self, Reveal};
+use rustc::ty::{self, TyCtxt};
+
+use syntax_pos::DUMMY_SP;
+
+pub fn crate_inherent_impls_overlap_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                    crate_num: CrateNum) {
+    assert_eq!(crate_num, LOCAL_CRATE);
+    let krate = tcx.hir.krate();
+    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
+}
+
+struct InherentOverlapChecker<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
+}
+
+impl<'a, 'tcx> InherentOverlapChecker<'a, 'tcx> {
+    fn check_for_common_items_in_impls(&self, impl1: DefId, impl2: DefId) {
+        #[derive(Copy, Clone, PartialEq)]
+        enum Namespace {
+            Type,
+            Value,
+        }
+
+        let name_and_namespace = |def_id| {
+            let item = self.tcx.associated_item(def_id);
+            (item.name, match item.kind {
+                ty::AssociatedKind::Type => Namespace::Type,
+                ty::AssociatedKind::Const |
+                ty::AssociatedKind::Method => Namespace::Value,
+            })
+        };
+
+        let impl_items1 = self.tcx.associated_item_def_ids(impl1);
+        let impl_items2 = self.tcx.associated_item_def_ids(impl2);
+
+        for &item1 in &impl_items1[..] {
+            let (name, namespace) = name_and_namespace(item1);
+
+            for &item2 in &impl_items2[..] {
+                if (name, namespace) == name_and_namespace(item2) {
+                    let msg = format!("duplicate definitions with name `{}`", name);
+                    let node_id = self.tcx.hir.as_local_node_id(item1).unwrap();
+                    self.tcx.sess.add_lint(lint::builtin::OVERLAPPING_INHERENT_IMPLS,
+                                           node_id,
+                                           self.tcx.span_of_impl(item1).unwrap(),
+                                           msg);
+                }
+            }
+        }
+    }
+
+    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
+        let impls = ty::queries::inherent_impls::get(self.tcx, DUMMY_SP, ty_def_id);
+
+        for (i, &impl1_def_id) in impls.iter().enumerate() {
+            for &impl2_def_id in &impls[(i + 1)..] {
+                self.tcx.infer_ctxt((), Reveal::UserFacing).enter(|infcx| {
+                    if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id).is_some() {
+                        self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id)
+                    }
+                });
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for InherentOverlapChecker<'a, 'tcx> {
+    fn visit_item(&mut self, item: &'v hir::Item) {
+        match item.node {
+            hir::ItemEnum(..) |
+            hir::ItemStruct(..) |
+            hir::ItemTrait(..) |
+            hir::ItemUnion(..) => {
+                let type_def_id = self.tcx.hir.local_def_id(item.id);
+                self.check_for_overlapping_inherent_impls(type_def_id);
+            }
+            _ => {}
+        }
+    }
+
+    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem) {
+    }
+
+    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
+    }
+}
+
index 9ecf42daeaae52021fd7f60f0a4dfd91de90f3d7..b3a7b612dd5b8532af75ac7aee58742cbfb29953 100644 (file)
@@ -24,7 +24,8 @@
 use syntax_pos::DUMMY_SP;
 
 mod builtin;
-mod inherent;
+mod inherent_impls;
+mod inherent_impls_overlap;
 mod orphan;
 mod overlap;
 mod unsafety;
@@ -102,9 +103,16 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d
 }
 
 pub fn provide(providers: &mut Providers) {
+    use self::builtin::coerce_unsized_info;
+    use self::inherent_impls::{crate_inherent_impls, inherent_impls};
+    use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
+
     *providers = Providers {
         coherent_trait,
-        coherent_inherent_impls,
+        crate_inherent_impls,
+        inherent_impls,
+        crate_inherent_impls_overlap_check,
+        coerce_unsized_info,
         ..*providers
     };
 }
@@ -123,10 +131,6 @@ fn coherent_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     builtin::check_trait(tcx, def_id);
 }
 
-fn coherent_inherent_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _: CrateNum) {
-    inherent::check(tcx);
-}
-
 pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::Coherence);
     for &trait_def_id in tcx.hir.krate().trait_impls.keys() {
@@ -137,5 +141,7 @@ pub fn check_coherence<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     orphan::check(tcx);
     overlap::check_default_impls(tcx);
 
-    ty::queries::coherent_inherent_impls::get(tcx, DUMMY_SP, LOCAL_CRATE);
+    // these queries are executed for side-effects (error reporting):
+    ty::queries::crate_inherent_impls::get(tcx, DUMMY_SP, LOCAL_CRATE);
+    ty::queries::crate_inherent_impls_overlap_check::get(tcx, DUMMY_SP, LOCAL_CRATE);
 }
index 0136faef28d8cc1413517a7243b146ba7e45d4d7..bd6129eb5bee3c80befdfa76500988837d72f91e 100644 (file)
@@ -790,7 +790,7 @@ fn main() {
 and [RFC 809] for more details.
 
 [RFC 470]: https://github.com/rust-lang/rfcs/pull/470
-[RFC 809]: https://github.com/rust-lang/rfcs/pull/809
+[RFC 809]: https://github.com/rust-lang/rfcs/blob/master/text/0809-box-and-in-for-stdlib.md
 "##,
 
 E0067: r##"
@@ -1428,7 +1428,7 @@ struct Baz<'a> {
 ```
 
 Note that type parameters for enum-variant constructors go after the variant,
-not after the enum (Option::None::<u32>, not Option::<u32>::None).
+not after the enum (`Option::None::<u32>`, not `Option::<u32>::None`).
 "##,
 
 E0110: r##"
@@ -1521,7 +1521,7 @@ fn get(&self) -> usize { 0 }
 
 For information on the design of the orphan rules, see [RFC 1023].
 
-[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
+[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
 "##,
 
 E0118: r##"
@@ -1911,8 +1911,9 @@ trait Trait {
 
 E0192: r##"
 Negative impls are only allowed for traits with default impls. For more
-information see the [opt-in builtin traits RFC](https://github.com/rust-lang/
-rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
 "##,
 
 E0193: r##"
@@ -2147,7 +2148,7 @@ fn bar(&self) -> bool { self.0 }
 Inherent associated types were part of [RFC 195] but are not yet implemented.
 See [the tracking issue][iss8995] for the status of this implementation.
 
-[RFC 195]: https://github.com/rust-lang/rfcs/pull/195
+[RFC 195]: https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md
 [iss8995]: https://github.com/rust-lang/rust/issues/8995
 "##,
 
@@ -2424,7 +2425,7 @@ impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
 
 For information on the design of the orphan rules, see [RFC 1023].
 
-[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
+[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
 "##,
 
 /*
@@ -2799,8 +2800,9 @@ fn drop(&mut self) { }
 
 E0318: r##"
 Default impls for a trait must be located in the same crate where the trait was
-defined. For more information see the [opt-in builtin traits RFC](https://github
-.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+defined. For more information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
 "##,
 
 E0321: r##"
@@ -3018,10 +3020,8 @@ impl<T> Unsize<T> for MyType {}
 ```
 
 If you are defining your own smart pointer type and would like to enable
-conversion from a sized to an unsized type with the [DST coercion system]
-(https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md), use
-[`CoerceUnsized`](https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html)
-instead.
+conversion from a sized to an unsized type with the
+[DST coercion system][RFC 982], use [`CoerceUnsized`] instead.
 
 ```
 #![feature(coerce_unsized)]
@@ -3035,6 +3035,9 @@ pub struct MyType<T: ?Sized> {
 impl<T, U> CoerceUnsized<MyType<U>> for MyType<T>
     where T: CoerceUnsized<U> {}
 ```
+
+[RFC 982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
+[`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html
 "##,
 
 E0329: r##"
@@ -3438,8 +3441,9 @@ impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
 
 E0380: r##"
 Default impls are only allowed for traits with no methods or associated items.
-For more information see the [opt-in builtin traits RFC](https://github.com/rust
--lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md).
+For more information see the [opt-in builtin traits RFC][RFC 19].
+
+[RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md
 "##,
 
 E0390: r##"
index 93c0bd6d6d836fb646f64c781d02d05949126e29..52f5d99838dc7c342047ed4bd0e19e74844e2b2f 100644 (file)
@@ -2,7 +2,6 @@
 authors = ["The Rust Project Developers"]
 name = "rustdoc"
 version = "0.0.0"
-build = "build.rs"
 
 [lib]
 name = "rustdoc"
@@ -11,11 +10,13 @@ crate-type = ["dylib"]
 
 [dependencies]
 arena = { path = "../libarena" }
+env_logger = { version = "0.4", default-features = false }
+log = "0.3"
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_eval = { path = "../librustc_const_eval" }
-rustc_driver = { path = "../librustc_driver" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_driver = { path = "../librustc_driver" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_lint = { path = "../librustc_lint" }
 rustc_metadata = { path = "../librustc_metadata" }
@@ -24,7 +25,7 @@ rustc_trans = { path = "../librustc_trans" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-log = { path = "../liblog" }
+pulldown-cmark = { version = "0.0.14", default-features = false }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
diff --git a/src/librustdoc/build.rs b/src/librustdoc/build.rs
deleted file mode 100644 (file)
index 9fa6406..0000000
+++ /dev/null
@@ -1,29 +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.
-
-extern crate build_helper;
-extern crate gcc;
-
-fn main() {
-    let src_dir = std::path::Path::new("../rt/hoedown/src");
-    build_helper::rerun_if_changed_anything_in_dir(src_dir);
-    let mut cfg = gcc::Config::new();
-    cfg.file("../rt/hoedown/src/autolink.c")
-       .file("../rt/hoedown/src/buffer.c")
-       .file("../rt/hoedown/src/document.c")
-       .file("../rt/hoedown/src/escape.c")
-       .file("../rt/hoedown/src/html.c")
-       .file("../rt/hoedown/src/html_blocks.c")
-       .file("../rt/hoedown/src/html_smartypants.c")
-       .file("../rt/hoedown/src/stack.c")
-       .file("../rt/hoedown/src/version.c")
-       .include(src_dir)
-       .compile("libhoedown.a");
-}
index c4476483186c7a35ed1de6bb20e9de0e52ff179f..cc30fdf56fc346c08b411d8b027a6400cfbb33f1 100644 (file)
@@ -232,14 +232,12 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
 
 pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
     let tcx = cx.tcx;
-    tcx.populate_inherent_implementations_for_type_if_necessary(DUMMY_SP, did);
     let mut impls = Vec::new();
 
-    if let Some(i) = tcx.maps.inherent_impls.borrow().get(&did) {
-        for &did in i.iter() {
-            build_impl(cx, did, &mut impls);
-        }
+    for &did in ty::queries::inherent_impls::get(tcx, DUMMY_SP, did).iter() {
+        build_impl(cx, did, &mut impls);
     }
+
     // If this is the first time we've inlined something from another crate, then
     // we inline *all* impls from all the crates into this crate. Note that there's
     // currently no way for us to filter this based on type, and we likely need
index 0a9db2c26464ce6370b4c4c573742e469bf55959..a47d5f9937a02c337745038043e5d09735b9c2b2 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config};
 use rustc::hir::def_id::DefId;
-use rustc::hir::def::{Def, ExportMap};
+use rustc::hir::def::Def;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, TyCtxt, GlobalArenas};
 use rustc::hir::map as hir_map;
@@ -64,7 +64,6 @@ pub struct DocContext<'a, 'tcx: 'a> {
     pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
     /// Table node id of lifetime parameter definition -> substituted lifetime
     pub lt_substs: RefCell<FxHashMap<ast::NodeId, clean::Lifetime>>,
-    pub export_map: ExportMap,
 }
 
 impl<'a, 'tcx> DocContext<'a, 'tcx> {
@@ -180,13 +179,13 @@ pub fn run_core(search_paths: SearchPaths,
             sess.fatal("Compilation failed, aborting rustdoc");
         }
 
-        let ty::CrateAnalysis { access_levels, export_map, .. } = analysis;
+        let ty::CrateAnalysis { access_levels, .. } = analysis;
 
         // Convert from a NodeId set to a DefId set since we don't always have easy access
         // to the map from defid -> nodeid
         let access_levels = AccessLevels {
-            map: access_levels.map.into_iter()
-                                  .map(|(k, v)| (tcx.hir.local_def_id(k), v))
+            map: access_levels.map.iter()
+                                  .map(|(&k, &v)| (tcx.hir.local_def_id(k), v))
                                   .collect()
         };
 
@@ -198,7 +197,6 @@ pub fn run_core(search_paths: SearchPaths,
             renderinfo: Default::default(),
             ty_substs: Default::default(),
             lt_substs: Default::default(),
-            export_map: export_map,
         };
         debug!("crate: {:?}", tcx.hir.krate());
 
index c7c5aabab97ae8002ce57b674d6623068c5090dd..117cfbabb52f7211379bdfa040aa9258967802a9 100644 (file)
 
 //! Markdown formatting for rustdoc
 //!
-//! This module implements markdown formatting through the hoedown C-library
-//! (bundled into the rust runtime). This module self-contains the C bindings
-//! and necessary legwork to render markdown, and exposes all of the
+//! This module implements markdown formatting through the pulldown-cmark
+//! rust-library. This module exposes all of the
 //! functionality through a unit-struct, `Markdown`, which has an implementation
 //! of `fmt::Display`. Example usage:
 //!
 //! ```rust,ignore
-//! use rustdoc::html::markdown::Markdown;
+//! use rustdoc::html::markdown::{Markdown, MarkdownOutputStyle};
 //!
 //! let s = "My *markdown* _text_";
-//! let html = format!("{}", Markdown(s));
+//! let html = format!("{}", Markdown(s, MarkdownOutputStyle::Fancy));
 //! // ... something using html
 //! ```
 
 #![allow(non_camel_case_types)]
 
-use libc;
 use std::ascii::AsciiExt;
 use std::cell::RefCell;
 use std::default::Default;
-use std::ffi::CString;
 use std::fmt::{self, Write};
-use std::slice;
 use std::str;
 use syntax::feature_gate::UnstableFeatures;
 use syntax::codemap::Span;
 use html::escape::Escape;
 use test;
 
+use pulldown_cmark::{self, Event, Parser, Tag};
+
+#[derive(Copy, Clone)]
+pub enum MarkdownOutputStyle {
+    Compact,
+    Fancy,
+}
+
+impl MarkdownOutputStyle {
+    pub fn is_compact(&self) -> bool {
+        match *self {
+            MarkdownOutputStyle::Compact => true,
+            _ => false,
+        }
+    }
+
+    pub fn is_fancy(&self) -> bool {
+        match *self {
+            MarkdownOutputStyle::Fancy => true,
+            _ => false,
+        }
+    }
+}
+
 /// A unit struct which has the `fmt::Display` trait implemented. When
 /// formatted, this struct will emit the HTML corresponding to the rendered
 /// version of the contained markdown string.
-pub struct Markdown<'a>(pub &'a str);
+// The second parameter is whether we need a shorter version or not.
+pub struct Markdown<'a>(pub &'a str, pub MarkdownOutputStyle);
 /// A unit struct like `Markdown`, that renders the markdown with a
 /// table of contents.
 pub struct MarkdownWithToc<'a>(pub &'a str);
 /// A unit struct like `Markdown`, that renders the markdown escaping HTML tags.
 pub struct MarkdownHtml<'a>(pub &'a str);
 
-const DEF_OUNIT: libc::size_t = 64;
-const HOEDOWN_EXT_NO_INTRA_EMPHASIS: libc::c_uint = 1 << 11;
-const HOEDOWN_EXT_TABLES: libc::c_uint = 1 << 0;
-const HOEDOWN_EXT_FENCED_CODE: libc::c_uint = 1 << 1;
-const HOEDOWN_EXT_AUTOLINK: libc::c_uint = 1 << 3;
-const HOEDOWN_EXT_STRIKETHROUGH: libc::c_uint = 1 << 4;
-const HOEDOWN_EXT_SUPERSCRIPT: libc::c_uint = 1 << 8;
-const HOEDOWN_EXT_FOOTNOTES: libc::c_uint = 1 << 2;
-const HOEDOWN_HTML_ESCAPE: libc::c_uint = 1 << 1;
-
-const HOEDOWN_EXTENSIONS: libc::c_uint =
-    HOEDOWN_EXT_NO_INTRA_EMPHASIS | HOEDOWN_EXT_TABLES |
-    HOEDOWN_EXT_FENCED_CODE | HOEDOWN_EXT_AUTOLINK |
-    HOEDOWN_EXT_STRIKETHROUGH | HOEDOWN_EXT_SUPERSCRIPT |
-    HOEDOWN_EXT_FOOTNOTES;
-
-enum hoedown_document {}
-
-type blockcodefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                                 *const hoedown_buffer, *const hoedown_renderer_data,
-                                 libc::size_t);
-
-type blockquotefn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                                  *const hoedown_renderer_data, libc::size_t);
-
-type headerfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                              libc::c_int, *const hoedown_renderer_data,
-                              libc::size_t);
-
-type blockhtmlfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                                 *const hoedown_renderer_data, libc::size_t);
-
-type codespanfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                                *const hoedown_renderer_data, libc::size_t) -> libc::c_int;
-
-type linkfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer,
-                             *const hoedown_buffer, *const hoedown_buffer,
-                             *const hoedown_renderer_data, libc::size_t) -> libc::c_int;
-
-type entityfn = extern "C" fn (*mut hoedown_buffer, *const hoedown_buffer,
-                               *const hoedown_renderer_data, libc::size_t);
-
-type normaltextfn = extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                                  *const hoedown_renderer_data, libc::size_t);
-
-#[repr(C)]
-struct hoedown_renderer_data {
-    opaque: *mut libc::c_void,
-}
-
-#[repr(C)]
-struct hoedown_renderer {
-    opaque: *mut libc::c_void,
-
-    blockcode: Option<blockcodefn>,
-    blockquote: Option<blockquotefn>,
-    header: Option<headerfn>,
-
-    other_block_level_callbacks: [libc::size_t; 11],
-
-    blockhtml: Option<blockhtmlfn>,
-
-    /* span level callbacks - NULL or return 0 prints the span verbatim */
-    autolink: libc::size_t, // unused
-    codespan: Option<codespanfn>,
-    other_span_level_callbacks_1: [libc::size_t; 7],
-    link: Option<linkfn>,
-    other_span_level_callbacks_2: [libc::size_t; 6],
-
-    /* low level callbacks - NULL copies input directly into the output */
-    entity: Option<entityfn>,
-    normal_text: Option<normaltextfn>,
-
-    /* header and footer */
-    other_callbacks: [libc::size_t; 2],
-}
-
-#[repr(C)]
-struct hoedown_html_renderer_state {
-    opaque: *mut libc::c_void,
-    toc_data: html_toc_data,
-    flags: libc::c_uint,
-    link_attributes: Option<extern "C" fn(*mut hoedown_buffer,
-                                          *const hoedown_buffer,
-                                          *const hoedown_renderer_data)>,
-}
-
-#[repr(C)]
-struct html_toc_data {
-    header_count: libc::c_int,
-    current_level: libc::c_int,
-    level_offset: libc::c_int,
-    nesting_level: libc::c_int,
-}
-
-struct MyOpaque {
-    dfltblk: extern "C" fn(*mut hoedown_buffer, *const hoedown_buffer,
-                           *const hoedown_buffer, *const hoedown_renderer_data,
-                           libc::size_t),
-    toc_builder: Option<TocBuilder>,
-}
-
-#[repr(C)]
-struct hoedown_buffer {
-    data: *const u8,
-    size: libc::size_t,
-    asize: libc::size_t,
-    unit: libc::size_t,
-}
-
-extern {
-    fn hoedown_html_renderer_new(render_flags: libc::c_uint,
-                                 nesting_level: libc::c_int)
-        -> *mut hoedown_renderer;
-    fn hoedown_html_renderer_free(renderer: *mut hoedown_renderer);
-
-    fn hoedown_document_new(rndr: *const hoedown_renderer,
-                            extensions: libc::c_uint,
-                            max_nesting: libc::size_t) -> *mut hoedown_document;
-    fn hoedown_document_render(doc: *mut hoedown_document,
-                               ob: *mut hoedown_buffer,
-                               document: *const u8,
-                               doc_size: libc::size_t);
-    fn hoedown_document_free(md: *mut hoedown_document);
-
-    fn hoedown_buffer_new(unit: libc::size_t) -> *mut hoedown_buffer;
-    fn hoedown_buffer_put(b: *mut hoedown_buffer, c: *const libc::c_char,
-                          n: libc::size_t);
-    fn hoedown_buffer_puts(b: *mut hoedown_buffer, c: *const libc::c_char);
-    fn hoedown_buffer_free(b: *mut hoedown_buffer);
-
-}
-
-// hoedown_buffer helpers
-impl hoedown_buffer {
-    fn as_bytes(&self) -> &[u8] {
-        unsafe { slice::from_raw_parts(self.data, self.size as usize) }
-    }
-}
-
 /// Returns Some(code) if `s` is a line that should be stripped from
 /// documentation but used in example code. `code` is the portion of
 /// `s` that should be used in tests. (None for lines that should be
@@ -222,123 +103,126 @@ fn collapse_whitespace(s: &str) -> String {
     RefCell::new(None)
 });
 
+macro_rules! event_loop_break {
+    ($parser:expr, $toc_builder:expr, $shorter:expr, $buf:expr, $escape:expr, $id:expr,
+     $($end_event:pat)|*) => {{
+        fn inner(id: &mut Option<&mut String>, s: &str) {
+            if let Some(ref mut id) = *id {
+                id.push_str(s);
+            }
+        }
+        while let Some(event) = $parser.next() {
+            match event {
+                $($end_event)|* => break,
+                Event::Text(ref s) => {
+                    inner($id, s);
+                    if $escape {
+                        $buf.push_str(&format!("{}", Escape(s)));
+                    } else {
+                        $buf.push_str(s);
+                    }
+                }
+                Event::SoftBreak | Event::HardBreak if !$buf.is_empty() => {
+                    $buf.push(' ');
+                }
+                x => {
+                    looper($parser, &mut $buf, Some(x), $toc_builder, $shorter, $id);
+                }
+            }
+        }
+    }}
+}
 
 pub fn render(w: &mut fmt::Formatter,
               s: &str,
               print_toc: bool,
-              html_flags: libc::c_uint) -> fmt::Result {
-    extern fn block(ob: *mut hoedown_buffer, orig_text: *const hoedown_buffer,
-                    lang: *const hoedown_buffer, data: *const hoedown_renderer_data,
-                    line: libc::size_t) {
-        unsafe {
-            if orig_text.is_null() { return }
-
-            let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
-            let my_opaque: &MyOpaque = &*((*opaque).opaque as *const MyOpaque);
-            let text = (*orig_text).as_bytes();
-            let origtext = str::from_utf8(text).unwrap();
-            let origtext = origtext.trim_left();
-            debug!("docblock: ==============\n{:?}\n=======", text);
-            let rendered = if lang.is_null() || origtext.is_empty() {
-                false
-            } else {
-                let rlang = (*lang).as_bytes();
-                let rlang = str::from_utf8(rlang).unwrap();
-                if !LangString::parse(rlang).rust {
-                    (my_opaque.dfltblk)(ob, orig_text, lang,
-                                        opaque as *const hoedown_renderer_data,
-                                        line);
-                    true
-                } else {
-                    false
+              shorter: MarkdownOutputStyle) -> fmt::Result {
+    fn code_block(parser: &mut Parser, buffer: &mut String, lang: &str) {
+        let mut origtext = String::new();
+        while let Some(event) = parser.next() {
+            match event {
+                Event::End(Tag::CodeBlock(_)) => break,
+                Event::Text(ref s) => {
+                    origtext.push_str(s);
                 }
-            };
+                _ => {}
+            }
+        }
+        let origtext = origtext.trim_left();
+        debug!("docblock: ==============\n{:?}\n=======", origtext);
 
-            let lines = origtext.lines().filter(|l| {
-                stripped_filtered_line(*l).is_none()
-            });
-            let text = lines.collect::<Vec<&str>>().join("\n");
-            if rendered { return }
-            PLAYGROUND.with(|play| {
-                // insert newline to clearly separate it from the
-                // previous block so we can shorten the html output
-                let mut s = String::from("\n");
-                let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
-                    if url.is_empty() {
-                        return None;
-                    }
-                    let test = origtext.lines().map(|l| {
-                        stripped_filtered_line(l).unwrap_or(l)
-                    }).collect::<Vec<&str>>().join("\n");
-                    let krate = krate.as_ref().map(|s| &**s);
-                    let test = test::maketest(&test, krate, false,
-                                              &Default::default());
-                    let channel = if test.contains("#![feature(") {
-                        "&amp;version=nightly"
+        let lines = origtext.lines().filter(|l| {
+            stripped_filtered_line(*l).is_none()
+        });
+        let text = lines.collect::<Vec<&str>>().join("\n");
+        let block_info = if lang.is_empty() {
+            LangString::all_false()
+        } else {
+            LangString::parse(lang)
+        };
+        if !block_info.rust {
+            buffer.push_str(&format!("<pre><code class=\"language-{}\">{}</code></pre>",
+                            lang, text));
+            return
+        }
+        PLAYGROUND.with(|play| {
+            // insert newline to clearly separate it from the
+            // previous block so we can shorten the html output
+            buffer.push('\n');
+            let playground_button = play.borrow().as_ref().and_then(|&(ref krate, ref url)| {
+                if url.is_empty() {
+                    return None;
+                }
+                let test = origtext.lines().map(|l| {
+                    stripped_filtered_line(l).unwrap_or(l)
+                }).collect::<Vec<&str>>().join("\n");
+                let krate = krate.as_ref().map(|s| &**s);
+                let test = test::maketest(&test, krate, false,
+                                          &Default::default());
+                let channel = if test.contains("#![feature(") {
+                    "&amp;version=nightly"
+                } else {
+                    ""
+                };
+                // These characters don't need to be escaped in a URI.
+                // FIXME: use a library function for percent encoding.
+                fn dont_escape(c: u8) -> bool {
+                    (b'a' <= c && c <= b'z') ||
+                    (b'A' <= c && c <= b'Z') ||
+                    (b'0' <= c && c <= b'9') ||
+                    c == b'-' || c == b'_' || c == b'.' ||
+                    c == b'~' || c == b'!' || c == b'\'' ||
+                    c == b'(' || c == b')' || c == b'*'
+                }
+                let mut test_escaped = String::new();
+                for b in test.bytes() {
+                    if dont_escape(b) {
+                        test_escaped.push(char::from(b));
                     } else {
-                        ""
-                    };
-                    // These characters don't need to be escaped in a URI.
-                    // FIXME: use a library function for percent encoding.
-                    fn dont_escape(c: u8) -> bool {
-                        (b'a' <= c && c <= b'z') ||
-                        (b'A' <= c && c <= b'Z') ||
-                        (b'0' <= c && c <= b'9') ||
-                        c == b'-' || c == b'_' || c == b'.' ||
-                        c == b'~' || c == b'!' || c == b'\'' ||
-                        c == b'(' || c == b')' || c == b'*'
+                        write!(test_escaped, "%{:02X}", b).unwrap();
                     }
-                    let mut test_escaped = String::new();
-                    for b in test.bytes() {
-                        if dont_escape(b) {
-                            test_escaped.push(char::from(b));
-                        } else {
-                            write!(test_escaped, "%{:02X}", b).unwrap();
-                        }
-                    }
-                    Some(format!(
-                        r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
-                        url, test_escaped, channel
-                    ))
-                });
-                s.push_str(&highlight::render_with_highlighting(
-                               &text,
-                               Some("rust-example-rendered"),
-                               None,
-                               playground_button.as_ref().map(String::as_str)));
-                let output = CString::new(s).unwrap();
-                hoedown_buffer_puts(ob, output.as_ptr());
-            })
-        }
+                }
+                Some(format!(
+                    r#"<a class="test-arrow" target="_blank" href="{}?code={}{}">Run</a>"#,
+                    url, test_escaped, channel
+                ))
+            });
+            buffer.push_str(&highlight::render_with_highlighting(
+                            &text,
+                            Some("rust-example-rendered"),
+                            None,
+                            playground_button.as_ref().map(String::as_str)));
+        });
     }
 
-    extern fn header(ob: *mut hoedown_buffer, text: *const hoedown_buffer,
-                     level: libc::c_int, data: *const hoedown_renderer_data,
-                     _: libc::size_t) {
-        // hoedown does this, we may as well too
-        unsafe { hoedown_buffer_puts(ob, "\n\0".as_ptr() as *const _); }
+    fn heading(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+               shorter: MarkdownOutputStyle, level: i32) {
+        let mut ret = String::new();
+        let mut id = String::new();
+        event_loop_break!(parser, toc_builder, shorter, ret, true, &mut Some(&mut id),
+                          Event::End(Tag::Header(_)));
+        ret = ret.trim_right().to_owned();
 
-        // Extract the text provided
-        let s = if text.is_null() {
-            "".to_owned()
-        } else {
-            let s = unsafe { (*text).as_bytes() };
-            str::from_utf8(&s).unwrap().to_owned()
-        };
-
-        // Discard '<em>', '<code>' tags and some escaped characters,
-        // transform the contents of the header into a hyphenated string
-        // without non-alphanumeric characters other than '-' and '_'.
-        //
-        // This is a terrible hack working around how hoedown gives us rendered
-        // html for text rather than the raw text.
-        let mut id = s.clone();
-        let repl_sub = vec!["<em>", "</em>", "<code>", "</code>",
-                            "<strong>", "</strong>",
-                            "&lt;", "&gt;", "&amp;", "&#39;", "&quot;"];
-        for sub in repl_sub {
-            id = id.replace(sub, "");
-        }
         let id = id.chars().filter_map(|c| {
             if c.is_alphanumeric() || c == '-' || c == '_' {
                 if c.is_ascii() {
@@ -353,145 +237,309 @@ fn dont_escape(c: u8) -> bool {
             }
         }).collect::<String>();
 
-        let opaque = unsafe { (*data).opaque as *mut hoedown_html_renderer_state };
-        let opaque = unsafe { &mut *((*opaque).opaque as *mut MyOpaque) };
-
         let id = derive_id(id);
 
-        let sec = opaque.toc_builder.as_mut().map_or("".to_owned(), |builder| {
-            format!("{} ", builder.push(level as u32, s.clone(), id.clone()))
+        let sec = toc_builder.as_mut().map_or("".to_owned(), |builder| {
+            format!("{} ", builder.push(level as u32, ret.clone(), id.clone()))
         });
 
         // Render the HTML
-        let text = format!("<h{lvl} id='{id}' class='section-header'>\
-                           <a href='#{id}'>{sec}{}</a></h{lvl}>",
-                           s, lvl = level, id = id, sec = sec);
-
-        let text = CString::new(text).unwrap();
-        unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
-    }
-
-    extern fn codespan(
-        ob: *mut hoedown_buffer,
-        text: *const hoedown_buffer,
-        _: *const hoedown_renderer_data,
-        _: libc::size_t
-    ) -> libc::c_int {
-        let content = if text.is_null() {
-            "".to_owned()
-        } else {
-            let bytes = unsafe { (*text).as_bytes() };
-            let s = str::from_utf8(bytes).unwrap();
-            collapse_whitespace(s)
-        };
+        buffer.push_str(&format!("<h{lvl} id=\"{id}\" class=\"section-header\">\
+                                  <a href=\"#{id}\">{sec}{}</a></h{lvl}>",
+                                 ret, lvl = level, id = id, sec = sec));
+    }
 
-        let content = format!("<code>{}</code>", Escape(&content));
-        let element = CString::new(content).unwrap();
-        unsafe { hoedown_buffer_puts(ob, element.as_ptr()); }
-        // Return anything except 0, which would mean "also print the code span verbatim".
-        1
+    fn inline_code(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                   shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+        let mut content = String::new();
+        event_loop_break!(parser, toc_builder, shorter, content, false, id, Event::End(Tag::Code));
+        buffer.push_str(&format!("<code>{}</code>",
+                                 Escape(&collapse_whitespace(content.trim_right()))));
     }
 
-    unsafe {
-        let ob = hoedown_buffer_new(DEF_OUNIT);
-        let renderer = hoedown_html_renderer_new(html_flags, 0);
-        let mut opaque = MyOpaque {
-            dfltblk: (*renderer).blockcode.unwrap(),
-            toc_builder: if print_toc {Some(TocBuilder::new())} else {None}
-        };
-        (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
-                = &mut opaque as *mut _ as *mut libc::c_void;
-        (*renderer).blockcode = Some(block);
-        (*renderer).header = Some(header);
-        (*renderer).codespan = Some(codespan);
+    fn link(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+            shorter: MarkdownOutputStyle, url: &str, mut title: String,
+            id: &mut Option<&mut String>) {
+        event_loop_break!(parser, toc_builder, shorter, title, true, id,
+                          Event::End(Tag::Link(_, _)));
+        buffer.push_str(&format!("<a href=\"{}\">{}</a>", url, title));
+    }
 
-        let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
-        hoedown_document_render(document, ob, s.as_ptr(),
-                                s.len() as libc::size_t);
-        hoedown_document_free(document);
+    fn paragraph(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                 shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+        let mut content = String::new();
+        event_loop_break!(parser, toc_builder, shorter, content, true, id,
+                          Event::End(Tag::Paragraph));
+        buffer.push_str(&format!("<p>{}</p>", content.trim_right()));
+    }
 
-        hoedown_html_renderer_free(renderer);
+    fn table_cell(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                  shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        event_loop_break!(parser, toc_builder, shorter, content, true, &mut None,
+                          Event::End(Tag::TableHead) |
+                              Event::End(Tag::Table(_)) |
+                              Event::End(Tag::TableRow) |
+                              Event::End(Tag::TableCell));
+        buffer.push_str(&format!("<td>{}</td>", content.trim()));
+    }
 
-        let mut ret = opaque.toc_builder.map_or(Ok(()), |builder| {
-            write!(w, "<nav id=\"TOC\">{}</nav>", builder.into_toc())
-        });
+    fn table_row(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                 shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        while let Some(event) = parser.next() {
+            match event {
+                Event::End(Tag::TableHead) |
+                    Event::End(Tag::Table(_)) |
+                    Event::End(Tag::TableRow) => break,
+                Event::Start(Tag::TableCell) => {
+                    table_cell(parser, &mut content, toc_builder, shorter);
+                }
+                x => {
+                    looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+                }
+            }
+        }
+        buffer.push_str(&format!("<tr>{}</tr>", content));
+    }
 
-        if ret.is_ok() {
-            let buf = (*ob).as_bytes();
-            ret = w.write_str(str::from_utf8(buf).unwrap());
+    fn table_head(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                  shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        while let Some(event) = parser.next() {
+            match event {
+                Event::End(Tag::TableHead) | Event::End(Tag::Table(_)) => break,
+                Event::Start(Tag::TableCell) => {
+                    table_cell(parser, &mut content, toc_builder, shorter);
+                }
+                x => {
+                    looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+                }
+            }
+        }
+        if !content.is_empty() {
+            buffer.push_str(&format!("<thead><tr>{}</tr></thead>", content.replace("td>", "th>")));
         }
-        hoedown_buffer_free(ob);
-        ret
     }
-}
 
-pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
-    extern fn block(_ob: *mut hoedown_buffer,
-                    text: *const hoedown_buffer,
-                    lang: *const hoedown_buffer,
-                    data: *const hoedown_renderer_data,
-                    line: libc::size_t) {
-        unsafe {
-            if text.is_null() { return }
-            let block_info = if lang.is_null() {
-                LangString::all_false()
-            } else {
-                let lang = (*lang).as_bytes();
-                let s = str::from_utf8(lang).unwrap();
-                LangString::parse(s)
-            };
-            if !block_info.rust { return }
-            let text = (*text).as_bytes();
-            let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
-            let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
-            let text = str::from_utf8(text).unwrap();
-            let lines = text.lines().map(|l| {
-                stripped_filtered_line(l).unwrap_or(l)
-            });
-            let text = lines.collect::<Vec<&str>>().join("\n");
-            let line = tests.get_line() + line;
-            let filename = tests.get_filename();
-            tests.add_test(text.to_owned(),
-                           block_info.should_panic, block_info.no_run,
-                           block_info.ignore, block_info.test_harness,
-                           block_info.compile_fail, block_info.error_codes,
-                           line, filename);
+    fn table(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+             shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        let mut rows = String::new();
+        while let Some(event) = parser.next() {
+            match event {
+                Event::End(Tag::Table(_)) => break,
+                Event::Start(Tag::TableHead) => {
+                    table_head(parser, &mut content, toc_builder, shorter);
+                }
+                Event::Start(Tag::TableRow) => {
+                    table_row(parser, &mut rows, toc_builder, shorter);
+                }
+                _ => {}
+            }
         }
+        buffer.push_str(&format!("<table>{}{}</table>",
+                                 content,
+                                 if shorter.is_compact() || rows.is_empty() {
+                                     String::new()
+                                 } else {
+                                     format!("<tbody>{}</tbody>", rows)
+                                 }));
     }
 
-    extern fn header(_ob: *mut hoedown_buffer,
-                     text: *const hoedown_buffer,
-                     level: libc::c_int, data: *const hoedown_renderer_data,
-                     _: libc::size_t) {
-        unsafe {
-            let opaque = (*data).opaque as *mut hoedown_html_renderer_state;
-            let tests = &mut *((*opaque).opaque as *mut ::test::Collector);
-            if text.is_null() {
-                tests.register_header("", level as u32);
-            } else {
-                let text = (*text).as_bytes();
-                let text = str::from_utf8(text).unwrap();
-                tests.register_header(text, level as u32);
+    fn blockquote(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                  shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        event_loop_break!(parser, toc_builder, shorter, content, true, &mut None,
+                          Event::End(Tag::BlockQuote));
+        buffer.push_str(&format!("<blockquote>{}</blockquote>", content.trim_right()));
+    }
+
+    fn list_item(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                 shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        while let Some(event) = parser.next() {
+            match event {
+                Event::End(Tag::Item) => break,
+                Event::Text(ref s) => {
+                    content.push_str(&format!("{}", Escape(s)));
+                }
+                x => {
+                    looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+                }
+            }
+        }
+        buffer.push_str(&format!("<li>{}</li>", content));
+    }
+
+    fn list(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+            shorter: MarkdownOutputStyle) {
+        let mut content = String::new();
+        while let Some(event) = parser.next() {
+            match event {
+                Event::End(Tag::List(_)) => break,
+                Event::Start(Tag::Item) => {
+                    list_item(parser, &mut content, toc_builder, shorter);
+                }
+                x => {
+                    looper(parser, &mut content, Some(x), toc_builder, shorter, &mut None);
+                }
+            }
+        }
+        buffer.push_str(&format!("<ul>{}</ul>", content));
+    }
+
+    fn emphasis(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+                shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+        let mut content = String::new();
+        event_loop_break!(parser, toc_builder, shorter, content, false, id,
+                          Event::End(Tag::Emphasis));
+        buffer.push_str(&format!("<em>{}</em>", content));
+    }
+
+    fn strong(parser: &mut Parser, buffer: &mut String, toc_builder: &mut Option<TocBuilder>,
+              shorter: MarkdownOutputStyle, id: &mut Option<&mut String>) {
+        let mut content = String::new();
+        event_loop_break!(parser, toc_builder, shorter, content, false, id,
+                          Event::End(Tag::Strong));
+        buffer.push_str(&format!("<strong>{}</strong>", content));
+    }
+
+    fn looper<'a>(parser: &'a mut Parser, buffer: &mut String, next_event: Option<Event<'a>>,
+                  toc_builder: &mut Option<TocBuilder>, shorter: MarkdownOutputStyle,
+                  id: &mut Option<&mut String>) -> bool {
+        if let Some(event) = next_event {
+            match event {
+                Event::Start(Tag::CodeBlock(lang)) => {
+                    code_block(parser, buffer, &*lang);
+                }
+                Event::Start(Tag::Header(level)) => {
+                    heading(parser, buffer, toc_builder, shorter, level);
+                }
+                Event::Start(Tag::Code) => {
+                    inline_code(parser, buffer, toc_builder, shorter, id);
+                }
+                Event::Start(Tag::Paragraph) => {
+                    paragraph(parser, buffer, toc_builder, shorter, id);
+                }
+                Event::Start(Tag::Link(ref url, ref t)) => {
+                    link(parser, buffer, toc_builder, shorter, url, t.as_ref().to_owned(), id);
+                }
+                Event::Start(Tag::Table(_)) => {
+                    table(parser, buffer, toc_builder, shorter);
+                }
+                Event::Start(Tag::BlockQuote) => {
+                    blockquote(parser, buffer, toc_builder, shorter);
+                }
+                Event::Start(Tag::List(_)) => {
+                    list(parser, buffer, toc_builder, shorter);
+                }
+                Event::Start(Tag::Emphasis) => {
+                    emphasis(parser, buffer, toc_builder, shorter, id);
+                }
+                Event::Start(Tag::Strong) => {
+                    strong(parser, buffer, toc_builder, shorter, id);
+                }
+                Event::Html(h) | Event::InlineHtml(h) => {
+                    buffer.push_str(&*h);
+                }
+                _ => {}
             }
+            shorter.is_fancy()
+        } else {
+            false
+        }
+    }
+
+    let mut toc_builder = if print_toc {
+        Some(TocBuilder::new())
+    } else {
+        None
+    };
+    let mut buffer = String::new();
+    let mut parser = Parser::new_ext(s, pulldown_cmark::OPTION_ENABLE_TABLES);
+    loop {
+        let next_event = parser.next();
+        if !looper(&mut parser, &mut buffer, next_event, &mut toc_builder, shorter, &mut None) {
+            break
         }
     }
+    let mut ret = toc_builder.map_or(Ok(()), |builder| {
+        write!(w, "<nav id=\"TOC\">{}</nav>", builder.into_toc())
+    });
+
+    if ret.is_ok() {
+        ret = w.write_str(&buffer);
+    }
+    ret
+}
 
+pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Span) {
     tests.set_position(position);
-    unsafe {
-        let ob = hoedown_buffer_new(DEF_OUNIT);
-        let renderer = hoedown_html_renderer_new(0, 0);
-        (*renderer).blockcode = Some(block);
-        (*renderer).header = Some(header);
-        (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
-                = tests as *mut _ as *mut libc::c_void;
-
-        let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
-        hoedown_document_render(document, ob, doc.as_ptr(),
-                                doc.len() as libc::size_t);
-        hoedown_document_free(document);
-
-        hoedown_html_renderer_free(renderer);
-        hoedown_buffer_free(ob);
+
+    let mut parser = Parser::new(doc);
+    let mut prev_offset = 0;
+    let mut nb_lines = 0;
+    let mut register_header = None;
+    'main: while let Some(event) = parser.next() {
+        match event {
+            Event::Start(Tag::CodeBlock(s)) => {
+                let block_info = if s.is_empty() {
+                    LangString::all_false()
+                } else {
+                    LangString::parse(&*s)
+                };
+                if !block_info.rust {
+                    continue
+                }
+                let mut test_s = String::new();
+                let mut offset = None;
+                loop {
+                    let event = parser.next();
+                    if let Some(event) = event {
+                        match event {
+                            Event::End(Tag::CodeBlock(_)) => break,
+                            Event::Text(ref s) => {
+                                test_s.push_str(s);
+                                if offset.is_none() {
+                                    offset = Some(parser.get_offset());
+                                }
+                            }
+                            _ => {}
+                        }
+                    } else {
+                        break 'main;
+                    }
+                }
+                let offset = offset.unwrap_or(0);
+                let lines = test_s.lines().map(|l| {
+                    stripped_filtered_line(l).unwrap_or(l)
+                });
+                let text = lines.collect::<Vec<&str>>().join("\n");
+                nb_lines += doc[prev_offset..offset].lines().count();
+                let line = tests.get_line() + (nb_lines - 1);
+                let filename = tests.get_filename();
+                tests.add_test(text.to_owned(),
+                               block_info.should_panic, block_info.no_run,
+                               block_info.ignore, block_info.test_harness,
+                               block_info.compile_fail, block_info.error_codes,
+                               line, filename);
+                prev_offset = offset;
+            }
+            Event::Start(Tag::Header(level)) => {
+                register_header = Some(level as u32);
+            }
+            Event::Text(ref s) if register_header.is_some() => {
+                let level = register_header.unwrap();
+                if s.is_empty() {
+                    tests.register_header("", level);
+                } else {
+                    tests.register_header(s, level);
+                }
+                register_header = None;
+            }
+            _ => {}
+        }
     }
 }
 
@@ -570,17 +618,17 @@ fn parse(string: &str) -> LangString {
 
 impl<'a> fmt::Display for Markdown<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        let Markdown(md) = *self;
+        let Markdown(md, shorter) = *self;
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
-        render(fmt, md, false, 0)
+        render(fmt, md, false, shorter)
     }
 }
 
 impl<'a> fmt::Display for MarkdownWithToc<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let MarkdownWithToc(md) = *self;
-        render(fmt, md, true, 0)
+        render(fmt, md, true, MarkdownOutputStyle::Fancy)
     }
 }
 
@@ -589,62 +637,67 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let MarkdownHtml(md) = *self;
         // This is actually common enough to special-case
         if md.is_empty() { return Ok(()) }
-        render(fmt, md, false, HOEDOWN_HTML_ESCAPE)
+        render(fmt, md, false, MarkdownOutputStyle::Fancy)
     }
 }
 
 pub fn plain_summary_line(md: &str) -> String {
-    extern fn link(_ob: *mut hoedown_buffer,
-                       _link: *const hoedown_buffer,
-                       _title: *const hoedown_buffer,
-                       content: *const hoedown_buffer,
-                       data: *const hoedown_renderer_data,
-                       _: libc::size_t) -> libc::c_int
-    {
-        unsafe {
-            if !content.is_null() && (*content).size > 0 {
-                let ob = (*data).opaque as *mut hoedown_buffer;
-                hoedown_buffer_put(ob, (*content).data as *const libc::c_char,
-                                   (*content).size);
-            }
-        }
-        1
-    }
-
-    extern fn normal_text(_ob: *mut hoedown_buffer,
-                          text: *const hoedown_buffer,
-                          data: *const hoedown_renderer_data,
-                          _: libc::size_t)
-    {
-        unsafe {
-            let ob = (*data).opaque as *mut hoedown_buffer;
-            hoedown_buffer_put(ob, (*text).data as *const libc::c_char,
-                               (*text).size);
-        }
+    struct ParserWrapper<'a> {
+        inner: Parser<'a>,
+        is_in: isize,
+        is_first: bool,
     }
 
-    unsafe {
-        let ob = hoedown_buffer_new(DEF_OUNIT);
-        let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed();
-        let renderer: *mut hoedown_renderer = &mut plain_renderer;
-        (*renderer).opaque = ob as *mut libc::c_void;
-        (*renderer).link = Some(link);
-        (*renderer).normal_text = Some(normal_text);
+    impl<'a> Iterator for ParserWrapper<'a> {
+        type Item = String;
 
-        let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
-        hoedown_document_render(document, ob, md.as_ptr(),
-                                md.len() as libc::size_t);
-        hoedown_document_free(document);
-        let plain_slice = (*ob).as_bytes();
-        let plain = str::from_utf8(plain_slice).unwrap_or("").to_owned();
-        hoedown_buffer_free(ob);
-        plain
+        fn next(&mut self) -> Option<String> {
+            let next_event = self.inner.next();
+            if next_event.is_none() {
+                return None
+            }
+            let next_event = next_event.unwrap();
+            let (ret, is_in) = match next_event {
+                Event::Start(Tag::Paragraph) => (None, 1),
+                Event::Start(Tag::Link(_, ref t)) if !self.is_first => {
+                    (Some(t.as_ref().to_owned()), 1)
+                }
+                Event::Start(Tag::Code) => (Some("`".to_owned()), 1),
+                Event::End(Tag::Code) => (Some("`".to_owned()), -1),
+                Event::Start(Tag::Header(_)) => (None, 1),
+                Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0),
+                Event::End(Tag::Link(_, ref t)) => (Some(t.as_ref().to_owned()), -1),
+                Event::End(Tag::Paragraph) | Event::End(Tag::Header(_)) => (None, -1),
+                _ => (None, 0),
+            };
+            if is_in > 0 || (is_in < 0 && self.is_in > 0) {
+                self.is_in += is_in;
+            }
+            if ret.is_some() {
+                self.is_first = false;
+                ret
+            } else {
+                Some(String::new())
+            }
+        }
+    }
+    let mut s = String::with_capacity(md.len() * 3 / 2);
+    let mut p = ParserWrapper {
+        inner: Parser::new(md),
+        is_in: 0,
+        is_first: true,
+    };
+    while let Some(t) = p.next() {
+        if !t.is_empty() {
+            s.push_str(&t);
+        }
     }
+    s
 }
 
 #[cfg(test)]
 mod tests {
-    use super::{LangString, Markdown, MarkdownHtml};
+    use super::{LangString, Markdown, MarkdownHtml, MarkdownOutputStyle};
     use super::plain_summary_line;
     use html::render::reset_ids;
 
@@ -684,52 +737,52 @@ fn t(s: &str,
     #[test]
     fn issue_17736() {
         let markdown = "# title";
-        format!("{}", Markdown(markdown));
+        format!("{}", Markdown(markdown, MarkdownOutputStyle::Fancy));
         reset_ids(true);
     }
 
     #[test]
     fn test_header() {
         fn t(input: &str, expect: &str) {
-            let output = format!("{}", Markdown(input));
-            assert_eq!(output, expect);
+            let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy));
+            assert_eq!(output, expect, "original: {}", input);
             reset_ids(true);
         }
 
-        t("# Foo bar", "\n<h1 id='foo-bar' class='section-header'>\
-          <a href='#foo-bar'>Foo bar</a></h1>");
-        t("## Foo-bar_baz qux", "\n<h2 id='foo-bar_baz-qux' class=\'section-\
-          header'><a href='#foo-bar_baz-qux'>Foo-bar_baz qux</a></h2>");
+        t("# Foo bar", "<h1 id=\"foo-bar\" class=\"section-header\">\
+          <a href=\"#foo-bar\">Foo bar</a></h1>");
+        t("## Foo-bar_baz qux", "<h2 id=\"foo-bar_baz-qux\" class=\"section-\
+          header\"><a href=\"#foo-bar_baz-qux\">Foo-bar_baz qux</a></h2>");
         t("### **Foo** *bar* baz!?!& -_qux_-%",
-          "\n<h3 id='foo-bar-baz--_qux_-' class='section-header'>\
-          <a href='#foo-bar-baz--_qux_-'><strong>Foo</strong> \
-          <em>bar</em> baz!?!&amp; -_qux_-%</a></h3>");
-        t("####**Foo?** & \\*bar?!*  _`baz`_ ❤ #qux",
-          "\n<h4 id='foo--bar--baz--qux' class='section-header'>\
-          <a href='#foo--bar--baz--qux'><strong>Foo?</strong> &amp; *bar?!*  \
+          "<h3 id=\"foo-bar-baz--qux-\" class=\"section-header\">\
+          <a href=\"#foo-bar-baz--qux-\"><strong>Foo</strong> \
+          <em>bar</em> baz!?!&amp; -<em>qux</em>-%</a></h3>");
+        t("#### **Foo?** & \\*bar?!*  _`baz`_ ❤ #qux",
+          "<h4 id=\"foo--bar--baz--qux\" class=\"section-header\">\
+          <a href=\"#foo--bar--baz--qux\"><strong>Foo?</strong> &amp; *bar?!*  \
           <em><code>baz</code></em> ❤ #qux</a></h4>");
     }
 
     #[test]
     fn test_header_ids_multiple_blocks() {
         fn t(input: &str, expect: &str) {
-            let output = format!("{}", Markdown(input));
-            assert_eq!(output, expect);
+            let output = format!("{}", Markdown(input, MarkdownOutputStyle::Fancy));
+            assert_eq!(output, expect, "original: {}", input);
         }
 
         let test = || {
-            t("# Example", "\n<h1 id='example' class='section-header'>\
-              <a href='#example'>Example</a></h1>");
-            t("# Panics", "\n<h1 id='panics' class='section-header'>\
-              <a href='#panics'>Panics</a></h1>");
-            t("# Example", "\n<h1 id='example-1' class='section-header'>\
-              <a href='#example-1'>Example</a></h1>");
-            t("# Main", "\n<h1 id='main-1' class='section-header'>\
-              <a href='#main-1'>Main</a></h1>");
-            t("# Example", "\n<h1 id='example-2' class='section-header'>\
-              <a href='#example-2'>Example</a></h1>");
-            t("# Panics", "\n<h1 id='panics-1' class='section-header'>\
-              <a href='#panics-1'>Panics</a></h1>");
+            t("# Example", "<h1 id=\"example\" class=\"section-header\">\
+              <a href=\"#example\">Example</a></h1>");
+            t("# Panics", "<h1 id=\"panics\" class=\"section-header\">\
+              <a href=\"#panics\">Panics</a></h1>");
+            t("# Example", "<h1 id=\"example-1\" class=\"section-header\">\
+              <a href=\"#example-1\">Example</a></h1>");
+            t("# Main", "<h1 id=\"main-1\" class=\"section-header\">\
+              <a href=\"#main-1\">Main</a></h1>");
+            t("# Example", "<h1 id=\"example-2\" class=\"section-header\">\
+              <a href=\"#example-2\">Example</a></h1>");
+            t("# Panics", "<h1 id=\"panics-1\" class=\"section-header\">\
+              <a href=\"#panics-1\">Panics</a></h1>");
         };
         test();
         reset_ids(true);
@@ -740,7 +793,7 @@ fn t(input: &str, expect: &str) {
     fn test_plain_summary_line() {
         fn t(input: &str, expect: &str) {
             let output = plain_summary_line(input);
-            assert_eq!(output, expect);
+            assert_eq!(output, expect, "original: {}", input);
         }
 
         t("hello [Rust](https://www.rust-lang.org) :)", "hello Rust :)");
@@ -754,10 +807,10 @@ fn t(input: &str, expect: &str) {
     fn test_markdown_html_escape() {
         fn t(input: &str, expect: &str) {
             let output = format!("{}", MarkdownHtml(input));
-            assert_eq!(output, expect);
+            assert_eq!(output, expect, "original: {}", input);
         }
 
-        t("`Struct<'a, T>`", "<p><code>Struct&lt;&#39;a, T&gt;</code></p>\n");
-        t("Struct<'a, T>", "<p>Struct&lt;&#39;a, T&gt;</p>\n");
+        t("`Struct<'a, T>`", "<p><code>Struct&lt;&#39;a, T&gt;</code></p>");
+        t("Struct<'a, T>", "<p>Struct&lt;&#39;a, T&gt;</p>");
     }
 }
index 10fde67a45674b7cf1efd8e258a4e7f2cf981cbd..f0b624105e3475de90a56d967e2a23b1013d8093 100644 (file)
@@ -72,7 +72,7 @@
 use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace};
 use html::format::fmt_impl_for_trait_page;
 use html::item_type::ItemType;
-use html::markdown::{self, Markdown, MarkdownHtml};
+use html::markdown::{self, Markdown, MarkdownHtml, MarkdownOutputStyle};
 use html::{highlight, layout};
 
 /// A pair of name and its optional document.
@@ -1650,7 +1650,8 @@ fn document_short(w: &mut fmt::Formatter, item: &clean::Item, link: AssocItemLin
         } else {
             format!("{}", &plain_summary_line(Some(s)))
         };
-        write!(w, "<div class='docblock'>{}</div>", Markdown(&markdown))?;
+        write!(w, "<div class='docblock'>{}</div>",
+               Markdown(&markdown, MarkdownOutputStyle::Fancy))?;
     }
     Ok(())
 }
@@ -1683,7 +1684,8 @@ fn get_doc_value(item: &clean::Item) -> Option<&str> {
 fn document_full(w: &mut fmt::Formatter, item: &clean::Item) -> fmt::Result {
     if let Some(s) = get_doc_value(item) {
         write!(w, "<div class='docblock'>{}</div>",
-               Markdown(&format!("{}{}", md_render_assoc_item(item), s)))?;
+               Markdown(&format!("{}{}", md_render_assoc_item(item), s),
+                                 MarkdownOutputStyle::Fancy))?;
     }
     Ok(())
 }
@@ -1700,6 +1702,23 @@ fn document_stability(w: &mut fmt::Formatter, cx: &Context, item: &clean::Item)
     Ok(())
 }
 
+fn name_key(name: &str) -> (&str, u64, usize) {
+    // find number at end
+    let split = name.bytes().rposition(|b| b < b'0' || b'9' < b).map_or(0, |s| s + 1);
+
+    // count leading zeroes
+    let after_zeroes =
+        name[split..].bytes().position(|b| b != b'0').map_or(name.len(), |extra| split + extra);
+
+    // sort leading zeroes last
+    let num_zeroes = after_zeroes - split;
+
+    match name[split..].parse() {
+        Ok(n) => (&name[..split], n, num_zeroes),
+        Err(_) => (name, 0, num_zeroes),
+    }
+}
+
 fn item_module(w: &mut fmt::Formatter, cx: &Context,
                item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
     document(w, cx, item)?;
@@ -1744,7 +1763,9 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
             (Some(stability::Stable), Some(stability::Unstable)) => return Ordering::Less,
             _ => {}
         }
-        i1.name.cmp(&i2.name)
+        let lhs = i1.name.as_ref().map_or("", |s| &**s);
+        let rhs = i2.name.as_ref().map_or("", |s| &**s);
+        name_key(lhs).cmp(&name_key(rhs))
     }
 
     indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
@@ -1852,7 +1873,8 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
                        </tr>",
                        name = *myitem.name.as_ref().unwrap(),
                        stab_docs = stab_docs,
-                       docs = shorter(Some(&Markdown(doc_value).to_string())),
+                       docs = shorter(Some(&Markdown(doc_value,
+                                                     MarkdownOutputStyle::Compact).to_string())),
                        class = myitem.type_(),
                        stab = myitem.stability_class().unwrap_or("".to_string()),
                        unsafety_flag = unsafety_flag,
@@ -2592,7 +2614,7 @@ fn render_attribute(attr: &ast::MetaItem) -> Option<String> {
     if attr.is_word() {
         Some(format!("{}", name))
     } else if let Some(v) = attr.value_str() {
-        Some(format!("{} = {:?}", name, &v.as_str()[..]))
+        Some(format!("{} = {:?}", name, v.as_str()))
     } else if let Some(values) = attr.meta_item_list() {
         let display: Vec<_> = values.iter().filter_map(|attr| {
             attr.meta_item().and_then(|mi| render_attribute(mi))
@@ -2623,7 +2645,7 @@ fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result {
 
     for attr in &it.attrs.other_attrs {
         let name = attr.name().unwrap();
-        if !ATTRIBUTE_WHITELIST.contains(&&name.as_str()[..]) {
+        if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) {
             continue;
         }
         if let Some(s) = render_attribute(&attr.meta().unwrap()) {
@@ -2882,7 +2904,7 @@ fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLi
         write!(w, "</span>")?;
         write!(w, "</h3>\n")?;
         if let Some(ref dox) = i.impl_item.doc_value() {
-            write!(w, "<div class='docblock'>{}</div>", Markdown(dox))?;
+            write!(w, "<div class='docblock'>{}</div>", Markdown(dox, MarkdownOutputStyle::Fancy))?;
         }
     }
 
@@ -3198,3 +3220,32 @@ fn test_unique_id() {
     reset_ids(true);
     test();
 }
+
+#[cfg(test)]
+#[test]
+fn test_name_key() {
+    assert_eq!(name_key("0"), ("", 0, 1));
+    assert_eq!(name_key("123"), ("", 123, 0));
+    assert_eq!(name_key("Fruit"), ("Fruit", 0, 0));
+    assert_eq!(name_key("Fruit0"), ("Fruit", 0, 1));
+    assert_eq!(name_key("Fruit0000"), ("Fruit", 0, 4));
+    assert_eq!(name_key("Fruit01"), ("Fruit", 1, 1));
+    assert_eq!(name_key("Fruit10"), ("Fruit", 10, 0));
+    assert_eq!(name_key("Fruit123"), ("Fruit", 123, 0));
+}
+
+#[cfg(test)]
+#[test]
+fn test_name_sorting() {
+    let names = ["Apple",
+                 "Banana",
+                 "Fruit", "Fruit0", "Fruit00",
+                 "Fruit1", "Fruit01",
+                 "Fruit2", "Fruit02",
+                 "Fruit20",
+                 "Fruit100",
+                 "Pear"];
+    let mut sorted = names.to_owned();
+    sorted.sort_by_key(|&s| name_key(s));
+    assert_eq!(names, sorted);
+}
index 84f69cd35045c91fd833f4dce04235ecd14048d6..447d60018d91291f4e5fe469c7f26f253e8dfa44 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![crate_name = "rustdoc"]
-#![unstable(feature = "rustdoc", issue = "27812")]
+#![unstable(feature = "rustc_private", issue = "27812")]
 #![crate_type = "dylib"]
 #![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -30,6 +30,7 @@
 
 extern crate arena;
 extern crate getopts;
+extern crate env_logger;
 extern crate libc;
 extern crate rustc;
 extern crate rustc_const_eval;
@@ -47,6 +48,7 @@
 extern crate std_unicode;
 #[macro_use] extern crate log;
 extern crate rustc_errors as errors;
+extern crate pulldown_cmark;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
@@ -99,6 +101,7 @@ struct Output {
 
 pub fn main() {
     const STACK_SIZE: usize = 32_000_000; // 32MB
+    env_logger::init().unwrap();
     let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
         let s = env::args().collect::<Vec<_>>();
         main_args(&s)
index c67e2fdc2b0276a7ecf45938b19cfb66f94cdef5..5cc0f03e1f629f4ff3021684d766a13640ebe15a 100644 (file)
 use html::render::reset_ids;
 use html::escape::Escape;
 use html::markdown;
-use html::markdown::{Markdown, MarkdownWithToc, find_testable_code};
+use html::markdown::{Markdown, MarkdownWithToc, MarkdownOutputStyle, find_testable_code};
 use test::{TestOptions, Collector};
 
-/// Separate any lines at the start of the file that begin with `%`.
+/// Separate any lines at the start of the file that begin with `# ` or `%`.
 fn extract_leading_metadata<'a>(s: &'a str) -> (Vec<&'a str>, &'a str) {
     let mut metadata = Vec::new();
     let mut count = 0;
+
     for line in s.lines() {
-        if line.starts_with("%") {
-            // remove %<whitespace>
+        if line.starts_with("# ") || line.starts_with("%") {
+            // trim the whitespace after the symbol
             metadata.push(line[1..].trim_left());
             count += line.len() + 1;
         } else {
             return (metadata, &s[count..]);
         }
     }
-    // if we're here, then all lines were metadata % lines.
+
+    // if we're here, then all lines were metadata `# ` or `%` lines.
     (metadata, "")
 }
 
@@ -83,7 +85,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
     if metadata.is_empty() {
         let _ = writeln!(
             &mut io::stderr(),
-            "rustdoc: invalid markdown file: expecting initial line with `% ...TITLE...`"
+            "rustdoc: invalid markdown file: no initial lines starting with `# ` or `%`"
         );
         return 5;
     }
@@ -94,7 +96,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
     let rendered = if include_toc {
         format!("{}", MarkdownWithToc(text))
     } else {
-        format!("{}", Markdown(text))
+        format!("{}", Markdown(text, MarkdownOutputStyle::Fancy))
     };
 
     let err = write!(
index 4a909f8e2a9728c8117919d6cedc84104246e737..2793307697852b8aa1b36a0e971e2bc115f549e4 100644 (file)
@@ -198,7 +198,7 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
             self.visit_item(item, None, &mut om);
         }
         self.inside_public_path = orig_inside_public_path;
-        if let Some(exports) = self.cx.export_map.get(&id) {
+        if let Some(exports) = self.cx.tcx.export_map.get(&id) {
             for export in exports {
                 if let Def::Macro(def_id, ..) = export.def {
                     if def_id.krate == LOCAL_CRATE {
index af21d6d906eb5d2569964202e91f1510f0fc9408..1cac11f668d95ebc90366af15145066816921d16 100644 (file)
@@ -17,7 +17,7 @@
 use ops::Range;
 use iter::FusedIterator;
 
-/// Extension methods for ASCII-subset only operations on string slices.
+/// Extension methods for ASCII-subset only operations.
 ///
 /// Be aware that operations on seemingly non-ASCII characters can sometimes
 /// have unexpected results. Consider this example:
@@ -54,19 +54,21 @@ pub trait AsciiExt {
     ///
     /// let ascii = 'a';
     /// let utf8 = '❤';
+    /// let int_ascii = 97;
     ///
     /// assert!(ascii.is_ascii());
     /// assert!(!utf8.is_ascii());
+    /// assert!(int_ascii.is_ascii());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn is_ascii(&self) -> bool;
 
-    /// Makes a copy of the string in ASCII upper case.
+    /// Makes a copy of the value in its ASCII upper case equivalent.
     ///
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
     /// but non-ASCII letters are unchanged.
     ///
-    /// To uppercase the string in-place, use [`make_ascii_uppercase`].
+    /// To uppercase the value in-place, use [`make_ascii_uppercase`].
     ///
     /// To uppercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_uppercase`].
@@ -78,9 +80,11 @@ pub trait AsciiExt {
     ///
     /// let ascii = 'a';
     /// let utf8 = '❤';
+    /// let int_ascii = 97;
     ///
     /// assert_eq!('A', ascii.to_ascii_uppercase());
     /// assert_eq!('❤', utf8.to_ascii_uppercase());
+    /// assert_eq!(65, int_ascii.to_ascii_uppercase());
     /// ```
     ///
     /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase
@@ -88,12 +92,12 @@ pub trait AsciiExt {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn to_ascii_uppercase(&self) -> Self::Owned;
 
-    /// Makes a copy of the string in ASCII lower case.
+    /// Makes a copy of the value in its ASCII lower case equivalent.
     ///
     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
     /// but non-ASCII letters are unchanged.
     ///
-    /// To lowercase the string in-place, use [`make_ascii_lowercase`].
+    /// To lowercase the value in-place, use [`make_ascii_lowercase`].
     ///
     /// To lowercase ASCII characters in addition to non-ASCII characters, use
     /// [`str::to_lowercase`].
@@ -105,9 +109,11 @@ pub trait AsciiExt {
     ///
     /// let ascii = 'A';
     /// let utf8 = '❤';
+    /// let int_ascii = 65;
     ///
     /// assert_eq!('a', ascii.to_ascii_lowercase());
     /// assert_eq!('❤', utf8.to_ascii_lowercase());
+    /// assert_eq!(97, int_ascii.to_ascii_lowercase());
     /// ```
     ///
     /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase
@@ -115,10 +121,10 @@ pub trait AsciiExt {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn to_ascii_lowercase(&self) -> Self::Owned;
 
-    /// Checks that two strings are an ASCII case-insensitive match.
+    /// Checks that two values are an ASCII case-insensitive match.
     ///
     /// Same as `to_ascii_lowercase(a) == to_ascii_lowercase(b)`,
-    /// but without allocating and copying temporary strings.
+    /// but without allocating and copying temporaries.
     ///
     /// # Examples
     ///
@@ -142,7 +148,7 @@ pub trait AsciiExt {
     /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
     /// but non-ASCII letters are unchanged.
     ///
-    /// To return a new uppercased string without modifying the existing one, use
+    /// To return a new uppercased value without modifying the existing one, use
     /// [`to_ascii_uppercase`].
     ///
     /// # Examples
@@ -166,7 +172,7 @@ pub trait AsciiExt {
     /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
     /// but non-ASCII letters are unchanged.
     ///
-    /// To return a new lowercased string without modifying the existing one, use
+    /// To return a new lowercased value without modifying the existing one, use
     /// [`to_ascii_lowercase`].
     ///
     /// # Examples
index 211605bef1ee092aa8dc9201b78f1dc49fbcffb4..da5fb1a47333ea1757bfa47845fec5baeca9324f 100644 (file)
@@ -896,15 +896,23 @@ pub fn drain(&mut self) -> Drain<K, V> {
         }
     }
 
-    /// Returns an iterator that copies out each entry. Used while the table
-    /// is being dropped.
-    unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets<K, V> {
-        let raw_bucket = self.first_bucket_raw();
-        RevMoveBuckets {
-            raw: raw_bucket.offset(self.capacity as isize),
-            hashes_end: raw_bucket.hash,
-            elems_left: self.size,
-            marker: marker::PhantomData,
+    /// Drops buckets in reverse order. It leaves the table in an inconsistent
+    /// state and should only be used for dropping the table's remaining
+    /// entries. It's used in the implementation of Drop.
+    unsafe fn rev_drop_buckets(&mut self) {
+        let first_raw = self.first_bucket_raw();
+        let mut raw = first_raw.offset(self.capacity as isize);
+        let mut elems_left = self.size;
+
+        while elems_left != 0 {
+            debug_assert!(raw.hash != first_raw.hash);
+
+            raw = raw.offset(-1);
+
+            if *raw.hash != EMPTY_BUCKET {
+                elems_left -= 1;
+                ptr::drop_in_place(raw.pair as *mut (K, V));
+            }
         }
     }
 
@@ -964,43 +972,6 @@ fn next(&mut self) -> Option<RawBucket<K, V>> {
     }
 }
 
-/// An iterator that moves out buckets in reverse order. It leaves the table
-/// in an inconsistent state and should only be used for dropping
-/// the table's remaining entries. It's used in the implementation of Drop.
-struct RevMoveBuckets<'a, K, V> {
-    raw: RawBucket<K, V>,
-    hashes_end: *mut HashUint,
-    elems_left: usize,
-
-    // As above, `&'a (K,V)` would seem better, but we often use
-    // 'static for the lifetime, and this is not a publicly exposed
-    // type.
-    marker: marker::PhantomData<&'a ()>,
-}
-
-impl<'a, K, V> Iterator for RevMoveBuckets<'a, K, V> {
-    type Item = (K, V);
-
-    fn next(&mut self) -> Option<(K, V)> {
-        if self.elems_left == 0 {
-            return None;
-        }
-
-        loop {
-            debug_assert!(self.raw.hash != self.hashes_end);
-
-            unsafe {
-                self.raw = self.raw.offset(-1);
-
-                if *self.raw.hash != EMPTY_BUCKET {
-                    self.elems_left -= 1;
-                    return Some(ptr::read(self.raw.pair));
-                }
-            }
-        }
-    }
-}
-
 /// Iterator over shared references to entries in a table.
 pub struct Iter<'a, K: 'a, V: 'a> {
     iter: RawBuckets<'a, K, V>,
@@ -1227,7 +1198,7 @@ fn drop(&mut self) {
         unsafe {
             if needs_drop::<(K, V)>() {
                 // avoid linear runtime for types that don't need drop
-                for _ in self.rev_move_buckets() {}
+                self.rev_drop_buckets();
             }
         }
 
index 60767ea4786618551f9720c2318db53ef7e3543c..53347eb14db0dec614cc5c9ee3dc2573496c7f06 100644 (file)
@@ -89,6 +89,10 @@ pub struct Cursor<T> {
 impl<T> Cursor<T> {
     /// Creates a new cursor wrapping the provided underlying I/O object.
     ///
+    /// Cursor initial position is `0` even if underlying object (e.
+    /// g. `Vec`) is not empty. So writing to cursor starts with
+    /// overwriting `Vec` content, not with appending to it.
+    ///
     /// # Examples
     ///
     /// ```
index 850885a8c0f3aaf76799ab398ce79bf132f8e00f..5b628d51d1513986eb31cbc17d2ff19756553849 100644 (file)
@@ -1290,28 +1290,42 @@ pub trait BufRead: Read {
     /// If an I/O error is encountered then all bytes read so far will be
     /// present in `buf` and its length will have been adjusted appropriately.
     ///
-    /// # Examples
-    ///
-    /// A locked standard input implements `BufRead`. In this example, we'll
-    /// read from standard input until we see an `a` byte.
-    ///
     /// [`fill_buf`]: #tymethod.fill_buf
     /// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
     ///
-    /// ```
-    /// use std::io;
-    /// use std::io::prelude::*;
+    /// # Examples
     ///
-    /// fn foo() -> io::Result<()> {
-    /// let stdin = io::stdin();
-    /// let mut stdin = stdin.lock();
-    /// let mut buffer = Vec::new();
+    /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+    /// this example, we use [`Cursor`] to read all the bytes in a byte slice
+    /// in hyphen delimited segments:
     ///
-    /// stdin.read_until(b'a', &mut buffer)?;
+    /// [`Cursor`]: struct.Cursor.html
     ///
-    /// println!("{:?}", buffer);
-    /// # Ok(())
-    /// # }
+    /// ```
+    /// use std::io::{self, BufRead};
+    ///
+    /// let mut cursor = io::Cursor::new(b"lorem-ipsum");
+    /// let mut buf = vec![];
+    ///
+    /// // cursor is at 'l'
+    /// let num_bytes = cursor.read_until(b'-', &mut buf)
+    ///     .expect("reading from cursor won't fail");
+    /// assert_eq!(num_bytes, 6);
+    /// assert_eq!(buf, b"lorem-");
+    /// buf.clear();
+    ///
+    /// // cursor is at 'i'
+    /// let num_bytes = cursor.read_until(b'-', &mut buf)
+    ///     .expect("reading from cursor won't fail");
+    /// assert_eq!(num_bytes, 5);
+    /// assert_eq!(buf, b"ipsum");
+    /// buf.clear();
+    ///
+    /// // cursor is at EOF
+    /// let num_bytes = cursor.read_until(b'-', &mut buf)
+    ///     .expect("reading from cursor won't fail");
+    /// assert_eq!(num_bytes, 0);
+    /// assert_eq!(buf, b"");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
@@ -1337,28 +1351,36 @@ fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
     ///
     /// # Examples
     ///
-    /// A locked standard input implements `BufRead`. In this example, we'll
-    /// read all of the lines from standard input. If we were to do this in
-    /// an actual project, the [`lines`] method would be easier, of
-    /// course.
+    /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+    /// this example, we use [`Cursor`] to read all the lines in a byte slice:
     ///
-    /// [`lines`]: #method.lines
-    /// [`read_until`]: #method.read_until
+    /// [`Cursor`]: struct.Cursor.html
     ///
     /// ```
-    /// use std::io;
-    /// use std::io::prelude::*;
-    ///
-    /// let stdin = io::stdin();
-    /// let mut stdin = stdin.lock();
-    /// let mut buffer = String::new();
-    ///
-    /// while stdin.read_line(&mut buffer).unwrap() > 0 {
-    ///     // work with buffer
-    ///     println!("{:?}", buffer);
-    ///
-    ///     buffer.clear();
-    /// }
+    /// use std::io::{self, BufRead};
+    ///
+    /// let mut cursor = io::Cursor::new(b"foo\nbar");
+    /// let mut buf = String::new();
+    ///
+    /// // cursor is at 'f'
+    /// let num_bytes = cursor.read_line(&mut buf)
+    ///     .expect("reading from cursor won't fail");
+    /// assert_eq!(num_bytes, 4);
+    /// assert_eq!(buf, "foo\n");
+    /// buf.clear();
+    ///
+    /// // cursor is at 'b'
+    /// let num_bytes = cursor.read_line(&mut buf)
+    ///     .expect("reading from cursor won't fail");
+    /// assert_eq!(num_bytes, 3);
+    /// assert_eq!(buf, "bar");
+    /// buf.clear();
+    ///
+    /// // cursor is at EOF
+    /// let num_bytes = cursor.read_line(&mut buf)
+    ///     .expect("reading from cursor won't fail");
+    /// assert_eq!(num_bytes, 0);
+    /// assert_eq!(buf, "");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn read_line(&mut self, buf: &mut String) -> Result<usize> {
@@ -1378,24 +1400,28 @@ fn read_line(&mut self, buf: &mut String) -> Result<usize> {
     /// This function will yield errors whenever [`read_until`] would have
     /// also yielded an error.
     ///
-    /// # Examples
-    ///
-    /// A locked standard input implements `BufRead`. In this example, we'll
-    /// read some input from standard input, splitting on commas.
-    ///
     /// [`io::Result`]: type.Result.html
     /// [`Vec<u8>`]: ../vec/struct.Vec.html
     /// [`read_until`]: #method.read_until
     ///
+    /// # Examples
+    ///
+    /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+    /// this example, we use [`Cursor`] to iterate over all hyphen delimited
+    /// segments in a byte slice
+    ///
+    /// [`Cursor`]: struct.Cursor.html
+    ///
     /// ```
-    /// use std::io;
-    /// use std::io::prelude::*;
+    /// use std::io::{self, BufRead};
     ///
-    /// let stdin = io::stdin();
+    /// let cursor = io::Cursor::new(b"lorem-ipsum-dolor");
     ///
-    /// for content in stdin.lock().split(b',') {
-    ///     println!("{:?}", content.unwrap());
-    /// }
+    /// let mut split_iter = cursor.split(b'-').map(|l| l.unwrap());
+    /// assert_eq!(split_iter.next(), Some(b"lorem".to_vec()));
+    /// assert_eq!(split_iter.next(), Some(b"ipsum".to_vec()));
+    /// assert_eq!(split_iter.next(), Some(b"dolor".to_vec()));
+    /// assert_eq!(split_iter.next(), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn split(self, byte: u8) -> Split<Self> where Self: Sized {
@@ -1413,17 +1439,22 @@ fn split(self, byte: u8) -> Split<Self> where Self: Sized {
     ///
     /// # Examples
     ///
-    /// A locked standard input implements `BufRead`:
+    /// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
+    /// this example, we use [`Cursor`] to iterate over all the lines in a byte
+    /// slice.
+    ///
+    /// [`Cursor`]: struct.Cursor.html
     ///
     /// ```
-    /// use std::io;
-    /// use std::io::prelude::*;
+    /// use std::io::{self, BufRead};
     ///
-    /// let stdin = io::stdin();
+    /// let cursor = io::Cursor::new(b"lorem\nipsum\r\ndolor");
     ///
-    /// for line in stdin.lock().lines() {
-    ///     println!("{}", line.unwrap());
-    /// }
+    /// let mut lines_iter = cursor.lines().map(|l| l.unwrap());
+    /// assert_eq!(lines_iter.next(), Some(String::from("lorem")));
+    /// assert_eq!(lines_iter.next(), Some(String::from("ipsum")));
+    /// assert_eq!(lines_iter.next(), Some(String::from("dolor")));
+    /// assert_eq!(lines_iter.next(), None);
     /// ```
     ///
     /// # Errors
index 84c4acb8d9247c4365ca33db13653297f405a914..36c06dc0b58d057d8a0f6df048b48e8837ebfafd 100644 (file)
 use iter;
 use slice;
 
-/// Representation of a socket address for networking applications.
+/// An internet socket address, either IPv4 or IPv6.
 ///
-/// A socket address can either represent the IPv4 or IPv6 protocol and is
-/// paired with at least a port number as well. Each protocol may have more
-/// specific information about the address available to it as well.
+/// Internet socket addresses consist of an [IP address], a 16-bit port number, as well
+/// as possibly some version-dependent additional information. See [`SocketAddrV4`]'s and
+/// [`SocketAddrV6`]'s respective documentation for more details.
+///
+/// [IP address]: ../../std/net/enum.IpAddr.html
+/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{IpAddr, Ipv4Addr, SocketAddr};
+///
+/// let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.port(), 8080);
+/// assert_eq!(socket.is_ipv4(), true);
+/// ```
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum SocketAddr {
-    /// An IPv4 socket address which is a (ip, port) combination.
+    /// An IPv4 socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     V4(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV4),
     /// An IPv6 socket address.
@@ -36,18 +52,63 @@ pub enum SocketAddr {
     V6(#[stable(feature = "rust1", since = "1.0.0")] SocketAddrV6),
 }
 
-/// An IPv4 socket address which is a (ip, port) combination.
+/// An IPv4 socket address.
+///
+/// IPv4 socket addresses consist of an [IPv4 address] and a 16-bit port number, as
+/// stated in [IETF RFC 793].
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv4Addr, SocketAddrV4};
+///
+/// let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
+///
+/// assert_eq!("127.0.0.1:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
 #[derive(Copy)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SocketAddrV4 { inner: c::sockaddr_in }
 
 /// An IPv6 socket address.
+///
+/// IPv6 socket addresses consist of an [Ipv6 address], a 16-bit port number, as well
+/// as fields containing the traffic class, the flow label, and a scope identifier
+/// (see [IETF RFC 2553, Section 3.3] for more details).
+///
+/// See [`SocketAddr`] for a type encompassing both IPv4 and IPv6 socket addresses.
+///
+/// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+/// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::{Ipv6Addr, SocketAddrV6};
+///
+/// let socket = SocketAddrV6::new(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1), 8080, 0, 0);
+///
+/// assert_eq!("[2001:db8::1]:8080".parse(), Ok(socket));
+/// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(socket.port(), 8080);
+/// ```
 #[derive(Copy)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SocketAddrV6 { inner: c::sockaddr_in6 }
 
 impl SocketAddr {
-    /// Creates a new socket address from the (ip, port) pair.
+    /// Creates a new socket address from an [IP address] and a port number.
+    ///
+    /// [IP address]: ../../std/net/enum.IpAddr.html
     ///
     /// # Examples
     ///
@@ -84,7 +145,7 @@ pub fn ip(&self) -> IpAddr {
         }
     }
 
-    /// Change the IP address associated with this socket address.
+    /// Changes the IP address associated with this socket address.
     ///
     /// # Examples
     ///
@@ -123,7 +184,7 @@ pub fn port(&self) -> u16 {
         }
     }
 
-    /// Change the port number associated with this socket address.
+    /// Changes the port number associated with this socket address.
     ///
     /// # Examples
     ///
@@ -142,8 +203,13 @@ pub fn set_port(&mut self, new_port: u16) {
         }
     }
 
-    /// Returns true if the IP in this `SocketAddr` is a valid IPv4 address,
-    /// false if it's a valid IPv6 address.
+    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+    /// [IPv4 address], and [`false`] otherwise.
+    ///
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [`false`]: ../../std/primitive.bool.html
+    /// [IP address]: ../../std/net/enum.IpAddr.html
+    /// [IPv4 address]: ../../std/net/enum.IpAddr.html#variant.V4
     ///
     /// # Examples
     ///
@@ -164,8 +230,13 @@ pub fn is_ipv4(&self) -> bool {
         }
     }
 
-    /// Returns true if the IP in this `SocketAddr` is a valid IPv6 address,
-    /// false if it's a valid IPv4 address.
+    /// Returns [`true`] if the [IP address] in this `SocketAddr` is an
+    /// [IPv6 address], and [`false`] otherwise.
+    ///
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [`false`]: ../../std/primitive.bool.html
+    /// [IP address]: ../../std/net/enum.IpAddr.html
+    /// [IPv6 address]: ../../std/net/enum.IpAddr.html#variant.V6
     ///
     /// # Examples
     ///
@@ -189,7 +260,9 @@ pub fn is_ipv6(&self) -> bool {
 }
 
 impl SocketAddrV4 {
-    /// Creates a new socket address from the (ip, port) pair.
+    /// Creates a new socket address from an [IPv4 address] and a port number.
+    ///
+    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
     ///
     /// # Examples
     ///
@@ -227,7 +300,7 @@ pub fn ip(&self) -> &Ipv4Addr {
         }
     }
 
-    /// Change the IP address associated with this socket address.
+    /// Changes the IP address associated with this socket address.
     ///
     /// # Examples
     ///
@@ -258,7 +331,7 @@ pub fn port(&self) -> u16 {
         ntoh(self.inner.sin_port)
     }
 
-    /// Change the port number associated with this socket address.
+    /// Changes the port number associated with this socket address.
     ///
     /// # Examples
     ///
@@ -276,8 +349,14 @@ pub fn set_port(&mut self, new_port: u16) {
 }
 
 impl SocketAddrV6 {
-    /// Creates a new socket address from the ip/port/flowinfo/scope_id
-    /// components.
+    /// Creates a new socket address from an [IPv6 address], a 16-bit port number,
+    /// and the `flowinfo` and `scope_id` fields.
+    ///
+    /// For more information on the meaning and layout of the `flowinfo` and `scope_id`
+    /// parameters, see [IETF RFC 2553, Section 3.3].
+    ///
+    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+    /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
     ///
     /// # Examples
     ///
@@ -318,7 +397,7 @@ pub fn ip(&self) -> &Ipv6Addr {
         }
     }
 
-    /// Change the IP address associated with this socket address.
+    /// Changes the IP address associated with this socket address.
     ///
     /// # Examples
     ///
@@ -349,7 +428,7 @@ pub fn port(&self) -> u16 {
         ntoh(self.inner.sin6_port)
     }
 
-    /// Change the port number associated with this socket address.
+    /// Changes the port number associated with this socket address.
     ///
     /// # Examples
     ///
@@ -365,8 +444,17 @@ pub fn set_port(&mut self, new_port: u16) {
         self.inner.sin6_port = hton(new_port);
     }
 
-    /// Returns the flow information associated with this address,
-    /// corresponding to the `sin6_flowinfo` field in C.
+    /// Returns the flow information associated with this address.
+    ///
+    /// This information corresponds to the `sin6_flowinfo` field in C's `netinet/in.h`,
+    /// as specified in [IETF RFC 2553, Section 3.3].
+    /// It combines information about the flow label and the traffic class as specified
+    /// in [IETF RFC 2460], respectively [Section 6] and [Section 7].
+    ///
+    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
+    /// [IETF RFC 2460]: https://tools.ietf.org/html/rfc2460
+    /// [Section 6]: https://tools.ietf.org/html/rfc2460#section-6
+    /// [Section 7]: https://tools.ietf.org/html/rfc2460#section-7
     ///
     /// # Examples
     ///
@@ -381,7 +469,11 @@ pub fn flowinfo(&self) -> u32 {
         self.inner.sin6_flowinfo
     }
 
-    /// Change the flow information associated with this socket address.
+    /// Changes the flow information associated with this socket address.
+    ///
+    /// See the [`flowinfo`] method's documentation for more details.
+    ///
+    /// [`flowinfo`]: #method.flowinfo
     ///
     /// # Examples
     ///
@@ -397,8 +489,12 @@ pub fn set_flowinfo(&mut self, new_flowinfo: u32) {
         self.inner.sin6_flowinfo = new_flowinfo;
     }
 
-    /// Returns the scope ID associated with this address,
-    /// corresponding to the `sin6_scope_id` field in C.
+    /// Returns the scope ID associated with this address.
+    ///
+    /// This information corresponds to the `sin6_scope_id` field in C's `netinet/in.h`,
+    /// as specified in [IETF RFC 2553, Section 3.3].
+    ///
+    /// [IETF RFC 2553, Section 3.3]: https://tools.ietf.org/html/rfc2553#section-3.3
     ///
     /// # Examples
     ///
@@ -415,6 +511,10 @@ pub fn scope_id(&self) -> u32 {
 
     /// Change the scope ID associated with this socket address.
     ///
+    /// See the [`scope_id`] method's documentation for more details.
+    ///
+    /// [`scope_id`]: #method.scope_id
+    ///
     /// # Examples
     ///
     /// ```
@@ -559,37 +659,51 @@ fn hash<H: hash::Hasher>(&self, s: &mut H) {
 }
 
 /// A trait for objects which can be converted or resolved to one or more
-/// `SocketAddr` values.
+/// [`SocketAddr`] values.
 ///
 /// This trait is used for generic address resolution when constructing network
 /// objects.  By default it is implemented for the following types:
 ///
-///  * `SocketAddr`, `SocketAddrV4`, `SocketAddrV6` - `to_socket_addrs` is
-///    identity function.
+///  * [`SocketAddr`]: [`to_socket_addrs`] is the identity function.
 ///
-///  * `(IpvNAddr, u16)` - `to_socket_addrs` constructs `SocketAddr` trivially.
+///  * [`SocketAddrV4`], [`SocketAddrV6`], `(`[`IpAddr`]`, `[`u16`]`)`,
+///    `(`[`Ipv4Addr`]`, `[`u16`]`)`, `(`[`Ipv6Addr`]`, `[`u16`]`)`:
+///    [`to_socket_addrs`] constructs a [`SocketAddr`] trivially.
 ///
-///  * `(&str, u16)` - the string should be either a string representation of an
-///    IP address expected by `FromStr` implementation for `IpvNAddr` or a host
+///  * `(`[`&str`]`, `[`u16`]`)`: the string should be either a string representation
+///    of an [`IpAddr`] address as expected by [`FromStr`] implementation or a host
 ///    name.
 ///
-///  * `&str` - the string should be either a string representation of a
-///    `SocketAddr` as expected by its `FromStr` implementation or a string like
-///    `<host_name>:<port>` pair where `<port>` is a `u16` value.
+///  * [`&str`]: the string should be either a string representation of a
+///    [`SocketAddr`] as expected by its [`FromStr`] implementation or a string like
+///    `<host_name>:<port>` pair where `<port>` is a [`u16`] value.
 ///
-/// This trait allows constructing network objects like `TcpStream` or
-/// `UdpSocket` easily with values of various types for the bind/connection
+/// This trait allows constructing network objects like [`TcpStream`] or
+/// [`UdpSocket`] easily with values of various types for the bind/connection
 /// address. It is needed because sometimes one type is more appropriate than
 /// the other: for simple uses a string like `"localhost:12345"` is much nicer
-/// than manual construction of the corresponding `SocketAddr`, but sometimes
-/// `SocketAddr` value is *the* main source of the address, and converting it to
+/// than manual construction of the corresponding [`SocketAddr`], but sometimes
+/// [`SocketAddr`] value is *the* main source of the address, and converting it to
 /// some other type (e.g. a string) just for it to be converted back to
-/// `SocketAddr` in constructor methods is pointless.
+/// [`SocketAddr`] in constructor methods is pointless.
 ///
 /// Addresses returned by the operating system that are not IP addresses are
 /// silently ignored.
 ///
-/// Some examples:
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+/// [`&str`]: ../../std/primitive.str.html
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+/// [`to_socket_addrs`]: #tymethod.to_socket_addrs
+/// [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
+/// [`u16`]: ../../std/primitive.u16.html
+///
+/// # Examples
 ///
 /// ```no_run
 /// use std::net::{SocketAddrV4, TcpStream, UdpSocket, TcpListener, Ipv4Addr};
@@ -629,10 +743,6 @@ pub trait ToSocketAddrs {
     ///
     /// Note that this function may block the current thread while resolution is
     /// performed.
-    ///
-    /// # Errors
-    ///
-    /// Any errors encountered during resolution will be returned as an `Err`.
     #[stable(feature = "rust1", since = "1.0.0")]
     fn to_socket_addrs(&self) -> io::Result<Self::Iter>;
 }
index 24e0e6f3fa659f3ec98204ecdec3ffe60588188e..c46fe4a58c7e246f919c74ec28afb9b679f63948 100644 (file)
 use sys::net::netc as c;
 use sys_common::{AsInner, FromInner};
 
-/// An IP address, either an IPv4 or IPv6 address.
+/// An IP address, either IPv4 or IPv6.
 ///
-/// # Examples
+/// This enum can contain either an [`Ipv4Addr`] or an [`Ipv6Addr`], see their
+/// respective documentation for more details.
 ///
-/// Constructing an IPv4 address:
+/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
 ///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr};
+/// # Examples
 ///
-/// IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
 /// ```
+/// use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
 ///
-/// Constructing an IPv6 address:
+/// let localhost_v4 = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
+/// let localhost_v6 = IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
 ///
-/// ```
-/// use std::net::{IpAddr, Ipv6Addr};
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost_v4));
+/// assert_eq!("::1".parse(), Ok(localhost_v6));
 ///
-/// IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+/// assert_eq!(localhost_v4.is_ipv6(), false);
+/// assert_eq!(localhost_v4.is_ipv4(), true);
 /// ```
 #[stable(feature = "ip_addr", since = "1.7.0")]
 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
 pub enum IpAddr {
-    /// Representation of an IPv4 address.
+    /// An IPv4 address.
     #[stable(feature = "ip_addr", since = "1.7.0")]
     V4(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv4Addr),
-    /// Representation of an IPv6 address.
+    /// An IPv6 address.
     #[stable(feature = "ip_addr", since = "1.7.0")]
     V6(#[stable(feature = "ip_addr", since = "1.7.0")] Ipv6Addr),
 }
 
-/// Representation of an IPv4 address.
+/// An IPv4 address.
+///
+/// IPv4 addresses are defined as 32-bit integers in [IETF RFC 791].
+/// They are usually represented as four octets.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// [IETF RFC 791]: https://tools.ietf.org/html/rfc791
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+///
+/// # Textual representation
+///
+/// `Ipv4Addr` provides a [`FromStr`] implementation. The four octets are in decimal
+/// notation, divided by `.` (this is called "dot-decimal notation").
+///
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv4Addr;
+///
+/// let localhost = Ipv4Addr::new(127, 0, 0, 1);
+/// assert_eq!("127.0.0.1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
 #[derive(Copy)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ipv4Addr {
     inner: c::in_addr,
 }
 
-/// Representation of an IPv6 address.
+/// An IPv6 address.
+///
+/// IPv6 addresses are defined as 128-bit integers in [IETF RFC 4291].
+/// They are usually represented as eight 16-bit segments.
+///
+/// See [`IpAddr`] for a type encompassing both IPv4 and IPv6 addresses.
+///
+/// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+///
+/// # Textual representation
+///
+/// `Ipv6Addr` provides a [`FromStr`] implementation. There are many ways to represent
+/// an IPv6 address in text, but in general, each segments is written in hexadecimal
+/// notation, and segments are separated by `:`. For more information, see
+/// [IETF RFC 5952].
+///
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [IETF RFC 5952]: https://tools.ietf.org/html/rfc5952
+///
+/// # Examples
+///
+/// ```
+/// use std::net::Ipv6Addr;
+///
+/// let localhost = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);
+/// assert_eq!("::1".parse(), Ok(localhost));
+/// assert_eq!(localhost.is_loopback(), true);
+/// ```
 #[derive(Copy)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Ipv6Addr {
@@ -78,10 +134,14 @@ pub enum Ipv6MulticastScope {
 }
 
 impl IpAddr {
-    /// Returns true for the special 'unspecified' address ([IPv4], [IPv6]).
+    /// Returns [`true`] for the special 'unspecified' address.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_unspecified`][IPv4] and
+    /// [`Ipv6Addr::is_unspecified`][IPv6] for more details.
     ///
     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -99,10 +159,14 @@ pub fn is_unspecified(&self) -> bool {
         }
     }
 
-    /// Returns true if this is a loopback address ([IPv4], [IPv6]).
+    /// Returns [`true`] if this is a loopback address.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_loopback`][IPv4] and
+    /// [`Ipv6Addr::is_loopback`][IPv6] for more details.
     ///
     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -120,10 +184,14 @@ pub fn is_loopback(&self) -> bool {
         }
     }
 
-    /// Returns true if the address appears to be globally routable ([IPv4], [IPv6]).
+    /// Returns [`true`] if the address appears to be globally routable.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_global`][IPv4] and
+    /// [`Ipv6Addr::is_global`][IPv6] for more details.
     ///
     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -145,10 +213,14 @@ pub fn is_global(&self) -> bool {
         }
     }
 
-    /// Returns true if this is a multicast address ([IPv4], [IPv6]).
+    /// Returns [`true`] if this is a multicast address.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_multicast`][IPv4] and
+    /// [`Ipv6Addr::is_multicast`][IPv6] for more details.
     ///
     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -166,10 +238,14 @@ pub fn is_multicast(&self) -> bool {
         }
     }
 
-    /// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]).
+    /// Returns [`true`] if this address is in a range designated for documentation.
+    ///
+    /// See the documentation for [`Ipv4Addr::is_documentation`][IPv4] and
+    /// [`Ipv6Addr::is_documentation`][IPv6] for more details.
     ///
     /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
     /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -191,7 +267,11 @@ pub fn is_documentation(&self) -> bool {
         }
     }
 
-    /// Returns true if this address is a valid IPv4 address, false if it's a valid IPv6 address.
+    /// Returns [`true`] if this address is an [IPv4 address], and [`false`] otherwise.
+    ///
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [`false`]: ../../std/primitive.bool.html
+    /// [IPv4 address]: #variant.V4
     ///
     /// # Examples
     ///
@@ -212,7 +292,11 @@ pub fn is_ipv4(&self) -> bool {
         }
     }
 
-    /// Returns true if this address is a valid IPv6 address, false if it's a valid IPv4 address.
+    /// Returns [`true`] if this address is an [IPv6 address], and [`false`] otherwise.
+    ///
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [`false`]: ../../std/primitive.bool.html
+    /// [IPv6 address]: #variant.V6
     ///
     /// # Examples
     ///
@@ -274,12 +358,13 @@ pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
     }
 
-    /// Returns true for the special 'unspecified' address (0.0.0.0).
+    /// Returns [`true`] for the special 'unspecified' address (0.0.0.0).
     ///
     /// This property is defined in _UNIX Network Programming, Second Edition_,
     /// W. Richard Stevens, p. 891; see also [ip7].
     ///
     /// [ip7]: http://man7.org/linux/man-pages/man7/ip.7.html
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -294,11 +379,12 @@ pub fn is_unspecified(&self) -> bool {
         self.inner.s_addr == 0
     }
 
-    /// Returns true if this is a loopback address (127.0.0.0/8).
+    /// Returns [`true`] if this is a loopback address (127.0.0.0/8).
     ///
-    /// This property is defined by [RFC 1122].
+    /// This property is defined by [IETF RFC 1122].
     ///
-    /// [RFC 1122]: https://tools.ietf.org/html/rfc1122
+    /// [IETF RFC 1122]: https://tools.ietf.org/html/rfc1122
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -313,15 +399,16 @@ pub fn is_loopback(&self) -> bool {
         self.octets()[0] == 127
     }
 
-    /// Returns true if this is a private address.
+    /// Returns [`true`] if this is a private address.
     ///
-    /// The private address ranges are defined in [RFC 1918] and include:
+    /// The private address ranges are defined in [IETF RFC 1918] and include:
     ///
     ///  - 10.0.0.0/8
     ///  - 172.16.0.0/12
     ///  - 192.168.0.0/16
     ///
-    /// [RFC 1918]: https://tools.ietf.org/html/rfc1918
+    /// [IETF RFC 1918]: https://tools.ietf.org/html/rfc1918
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -346,11 +433,12 @@ pub fn is_private(&self) -> bool {
         }
     }
 
-    /// Returns true if the address is link-local (169.254.0.0/16).
+    /// Returns [`true`] if the address is link-local (169.254.0.0/16).
     ///
-    /// This property is defined by [RFC 3927].
+    /// This property is defined by [IETF RFC 3927].
     ///
-    /// [RFC 3927]: https://tools.ietf.org/html/rfc3927
+    /// [IETF RFC 3927]: https://tools.ietf.org/html/rfc3927
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -366,7 +454,7 @@ pub fn is_link_local(&self) -> bool {
         self.octets()[0] == 169 && self.octets()[1] == 254
     }
 
-    /// Returns true if the address appears to be globally routable.
+    /// Returns [`true`] if the address appears to be globally routable.
     /// See [iana-ipv4-special-registry][ipv4-sr].
     ///
     /// The following return false:
@@ -379,6 +467,7 @@ pub fn is_link_local(&self) -> bool {
     /// - the unspecified address (0.0.0.0)
     ///
     /// [ipv4-sr]: http://goo.gl/RaZ7lg
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -400,12 +489,13 @@ pub fn is_global(&self) -> bool {
         !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
     }
 
-    /// Returns true if this is a multicast address (224.0.0.0/4).
+    /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
     ///
     /// Multicast addresses have a most significant octet between 224 and 239,
-    /// and is defined by [RFC 5771].
+    /// and is defined by [IETF RFC 5771].
     ///
-    /// [RFC 5771]: https://tools.ietf.org/html/rfc5771
+    /// [IETF RFC 5771]: https://tools.ietf.org/html/rfc5771
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -421,11 +511,12 @@ pub fn is_multicast(&self) -> bool {
         self.octets()[0] >= 224 && self.octets()[0] <= 239
     }
 
-    /// Returns true if this is a broadcast address (255.255.255.255).
+    /// Returns [`true`] if this is a broadcast address (255.255.255.255).
     ///
-    /// A broadcast address has all octets set to 255 as defined in [RFC 919].
+    /// A broadcast address has all octets set to 255 as defined in [IETF RFC 919].
     ///
-    /// [RFC 919]: https://tools.ietf.org/html/rfc919
+    /// [IETF RFC 919]: https://tools.ietf.org/html/rfc919
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -441,15 +532,16 @@ pub fn is_broadcast(&self) -> bool {
         self.octets()[2] == 255 && self.octets()[3] == 255
     }
 
-    /// Returns true if this address is in a range designated for documentation.
+    /// Returns [`true`] if this address is in a range designated for documentation.
     ///
-    /// This is defined in [RFC 5737]:
+    /// This is defined in [IETF RFC 5737]:
     ///
     /// - 192.0.2.0/24 (TEST-NET-1)
     /// - 198.51.100.0/24 (TEST-NET-2)
     /// - 203.0.113.0/24 (TEST-NET-3)
     ///
-    /// [RFC 5737]: https://tools.ietf.org/html/rfc5737
+    /// [IETF RFC 5737]: https://tools.ietf.org/html/rfc5737
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -471,10 +563,12 @@ pub fn is_documentation(&self) -> bool {
         }
     }
 
-    /// Converts this address to an IPv4-compatible IPv6 address.
+    /// Converts this address to an IPv4-compatible [IPv6 address].
     ///
     /// a.b.c.d becomes ::a.b.c.d
     ///
+    /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -490,10 +584,12 @@ pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
                       ((self.octets()[2] as u16) << 8) | self.octets()[3] as u16)
     }
 
-    /// Converts this address to an IPv4-mapped IPv6 address.
+    /// Converts this address to an IPv4-mapped [IPv6 address].
     ///
     /// a.b.c.d becomes ::ffff:a.b.c.d
     ///
+    /// [IPv6 address]: ../../std/net/struct.Ipv6Addr.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -717,11 +813,12 @@ pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
         ]
     }
 
-    /// Returns true for the special 'unspecified' address (::).
+    /// Returns [`true`] for the special 'unspecified' address (::).
     ///
-    /// This property is defined in [RFC 4291].
+    /// This property is defined in [IETF RFC 4291].
     ///
-    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -736,11 +833,12 @@ pub fn is_unspecified(&self) -> bool {
         self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
     }
 
-    /// Returns true if this is a loopback address (::1).
+    /// Returns [`true`] if this is a loopback address (::1).
     ///
-    /// This property is defined in [RFC 4291].
+    /// This property is defined in [IETF RFC 4291].
     ///
-    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -755,14 +853,17 @@ pub fn is_loopback(&self) -> bool {
         self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
     }
 
-    /// Returns true if the address appears to be globally routable.
+    /// Returns [`true`] if the address appears to be globally routable.
     ///
-    /// The following return false:
+    /// The following return [`false`]:
     ///
     /// - the loopback address
     /// - link-local, site-local, and unique local unicast addresses
     /// - interface-, link-, realm-, admin- and site-local multicast addresses
     ///
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [`false`]: ../../std/primitive.bool.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -784,11 +885,12 @@ pub fn is_global(&self) -> bool {
         }
     }
 
-    /// Returns true if this is a unique local address (fc00::/7).
+    /// Returns [`true`] if this is a unique local address (fc00::/7).
     ///
-    /// This property is defined in [RFC 4193].
+    /// This property is defined in [IETF RFC 4193].
     ///
-    /// [RFC 4193]: https://tools.ietf.org/html/rfc4193
+    /// [IETF RFC 4193]: https://tools.ietf.org/html/rfc4193
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -807,11 +909,12 @@ pub fn is_unique_local(&self) -> bool {
         (self.segments()[0] & 0xfe00) == 0xfc00
     }
 
-    /// Returns true if the address is unicast and link-local (fe80::/10).
+    /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
     ///
-    /// This property is defined in [RFC 4291].
+    /// This property is defined in [IETF RFC 4291].
     ///
-    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -830,9 +933,11 @@ pub fn is_unicast_link_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
 
-    /// Returns true if this is a deprecated unicast site-local address
+    /// Returns [`true`] if this is a deprecated unicast site-local address
     /// (fec0::/10).
     ///
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -850,12 +955,13 @@ pub fn is_unicast_site_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfec0
     }
 
-    /// Returns true if this is an address reserved for documentation
+    /// Returns [`true`] if this is an address reserved for documentation
     /// (2001:db8::/32).
     ///
-    /// This property is defined in [RFC 3849].
+    /// This property is defined in [IETF RFC 3849].
     ///
-    /// [RFC 3849]: https://tools.ietf.org/html/rfc3849
+    /// [IETF RFC 3849]: https://tools.ietf.org/html/rfc3849
+    /// [`true`]: ../../std/primitive.bool.html
     ///
     /// # Examples
     ///
@@ -874,7 +980,7 @@ pub fn is_documentation(&self) -> bool {
         (self.segments()[0] == 0x2001) && (self.segments()[1] == 0xdb8)
     }
 
-    /// Returns true if the address is a globally routable unicast address.
+    /// Returns [`true`] if the address is a globally routable unicast address.
     ///
     /// The following return false:
     ///
@@ -885,6 +991,8 @@ pub fn is_documentation(&self) -> bool {
     /// - the unspecified address
     /// - the address range reserved for documentation
     ///
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
     /// # Examples
     ///
     /// ```
@@ -937,11 +1045,13 @@ pub fn multicast_scope(&self) -> Option<Ipv6MulticastScope> {
         }
     }
 
-    /// Returns true if this is a multicast address (ff00::/8).
+    /// Returns [`true`] if this is a multicast address (ff00::/8).
+    ///
+    /// This property is defined by [IETF RFC 4291].
     ///
-    /// This property is defined by [RFC 4291].
+    /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [`true`]: ../../std/primitive.bool.html
     ///
-    /// [RFC 4291]: https://tools.ietf.org/html/rfc4291
     /// # Examples
     ///
     /// ```
@@ -955,11 +1065,16 @@ pub fn is_multicast(&self) -> bool {
         (self.segments()[0] & 0xff00) == 0xff00
     }
 
-    /// Converts this address to an IPv4 address. Returns None if this address is
+    /// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
     /// neither IPv4-compatible or IPv4-mapped.
     ///
     /// ::a.b.c.d and ::ffff:a.b.c.d become a.b.c.d
     ///
+    /// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
     /// ```
     /// use std::net::{Ipv4Addr, Ipv6Addr};
     ///
index b0d2e3e4687b44c24e4fee5cf64a14b9109261c0..9fcb93e2032b3ce40489f2cb6d4be9cd103cdb24 100644 (file)
@@ -9,6 +9,32 @@
 // except according to those terms.
 
 //! Networking primitives for TCP/UDP communication.
+//!
+//! This module provides networking functionality for the Transmission Control and User
+//! Datagram Protocols, as well as types for IP and socket addresses.
+//!
+//! # Organization
+//!
+//! * [`TcpListener`] and [`TcpStream`] provide functionality for communication over TCP
+//! * [`UdpSocket`] provides functionality for communication over UDP
+//! * [`IpAddr`] represents IP addresses of either IPv4 or IPv6; [`Ipv4Addr`] and
+//!   [`Ipv6Addr`] are respectively IPv4 and IPv6 addresses
+//! * [`SocketAddr`] represents socket addresses of either IPv4 or IPv6; [`SocketAddrV4`]
+//!   and [`SocketAddrV6`] are respectively IPv4 and IPv6 socket addresses
+//! * [`ToSocketAddrs`] is a trait that used for generic address resolution when interacting
+//!   with networking objects like [`TcpListener`], [`TcpStream`] or [`UdpSocket`]
+//! * Other types are return or parameter types for various methods in this module
+//!
+//! [`IpAddr`]: ../../std/net/enum.IpAddr.html
+//! [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+//! [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
+//! [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+//! [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+//! [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
+//! [`TcpListener`]: ../../std/net/struct.TcpListener.html
+//! [`TcpStream`]: ../../std/net/struct.TcpStream.html
+//! [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
+//! [`UdpSocket`]: ../../std/net/struct.UdpSocket.html
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Shutdown {
-    /// Indicates that the reading portion of this stream/socket should be shut
-    /// down. All currently blocked and future reads will return `Ok(0)`.
+    /// The reading portion of the [`TcpStream`] should be shut down.
+    ///
+    /// All currently blocked and future [reads] will return [`Ok(0)`].
+    ///
+    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+    /// [reads]: ../../std/io/trait.Read.html
+    /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok
     #[stable(feature = "rust1", since = "1.0.0")]
     Read,
-    /// Indicates that the writing portion of this stream/socket should be shut
-    /// down. All currently blocked and future writes will return an error.
+    /// The writing portion of the [`TcpStream`] should be shut down.
+    ///
+    /// All currently blocked and future [writes] will return an error.
+    ///
+    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+    /// [writes]: ../../std/io/trait.Write.html
     #[stable(feature = "rust1", since = "1.0.0")]
     Write,
-    /// Shut down both the reading and writing portions of this stream.
+    /// Both the reading and the writing portions of the [`TcpStream`] should be shut down.
+    ///
+    /// See [`Shutdown::Read`] and [`Shutdown::Write`] for more information.
     ///
-    /// See `Shutdown::Read` and `Shutdown::Write` for more information.
+    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+    /// [`Shutdown::Read`]: #variant.Read
+    /// [`Shutdown::Write`]: #variant.Write
     #[stable(feature = "rust1", since = "1.0.0")]
     Both,
 }
index d86711c10ac7965c9dfcb17ab474ce8e771c3875..7d7c67ff3f9f767fcc80801af177543767797851 100644 (file)
@@ -368,7 +368,19 @@ fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
     }
 }
 
-/// An error returned when parsing an IP address or a socket address.
+/// An error which can be returned when parsing an IP address or a socket address.
+///
+/// This error is used as the error type for the [`FromStr`] implementation for
+/// [`IpAddr`], [`Ipv4Addr`], [`Ipv6Addr`], [`SocketAddr`], [`SocketAddrV4`], and
+/// [`SocketAddrV6`].
+///
+/// [`FromStr`]: ../../std/str/trait.FromStr.html
+/// [`IpAddr`]: ../../std/net/enum.IpAddr.html
+/// [`Ipv4Addr`]: ../../std/net/struct.Ipv4Addr.html
+/// [`Ipv6Addr`]: ../../std/net/struct.Ipv6Addr.html
+/// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+/// [`SocketAddrV4`]: ../../std/net/struct.SocketAddrV4.html
+/// [`SocketAddrV6`]: ../../std/net/struct.SocketAddrV6.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct AddrParseError(());
index a07972468e68a3afdfeff1d871d15ea413791fbb..cf119720e5a17cc1d3f9ae62cfb772d5c6d49287 100644 (file)
 use sys_common::{AsInner, FromInner, IntoInner};
 use time::Duration;
 
-/// A structure which represents a TCP stream between a local socket and a
-/// remote socket.
+/// A TCP stream between a local and a remote socket.
 ///
-/// The socket will be closed when the value is dropped.
+/// After creating a `TcpStream` by either [`connect`]ing to a remote host or
+/// [`accept`]ing a connection on a [`TcpListener`], data can be transmitted
+/// by [reading] and [writing] to it.
+///
+/// The connection will be closed when the value is dropped. The reading and writing
+/// portions of the connection can also be shut down individually with the [`shutdown`]
+/// method.
+///
+/// The Transmission Control Protocol is specified in [IETF RFC 793].
+///
+/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
+/// [`connect`]: #method.connect
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [reading]: ../../std/io/trait.Read.html
+/// [`shutdown`]: #method.shutdown
+/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+/// [writing]: ../../std/io/trait.Write.html
 ///
 /// # Examples
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct TcpStream(net_imp::TcpStream);
 
-/// A structure representing a socket server.
+/// A TCP socket server, listening for connections.
+///
+/// After creating a `TcpListener` by [`bind`]ing it to a socket address, it listens
+/// for incoming TCP connections. These can be accepted by calling [`accept`] or by
+/// iterating over the [`Incoming`] iterator returned by [`incoming`].
+///
+/// The socket will be closed when the value is dropped.
+///
+/// The Transmission Control Protocol is specified in [IETF RFC 793].
+///
+/// [`accept`]: #method.accept
+/// [`bind`]: #method.bind
+/// [IETF RFC 793]: https://tools.ietf.org/html/rfc793
+/// [`Incoming`]: ../../std/net/struct.Incoming.html
+/// [`incoming`]: #method.incoming
 ///
 /// # Examples
 ///
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct TcpListener(net_imp::TcpListener);
 
-/// An infinite iterator over the connections from a `TcpListener`.
-///
-/// This iterator will infinitely yield [`Some`] of the accepted connections. It
-/// is equivalent to calling `accept` in a loop.
+/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
 ///
 /// This `struct` is created by the [`incoming`] method on [`TcpListener`].
+/// See its documentation for more.
 ///
-/// [`Some`]: ../../std/option/enum.Option.html#variant.Some
-/// [`incoming`]: struct.TcpListener.html#method.incoming
-/// [`TcpListener`]: struct.TcpListener.html
+/// [`accept`]: ../../std/net/struct.TcpListener.html#method.accept
+/// [`incoming`]: ../../std/net/struct.TcpListener.html#method.incoming
+/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Incoming<'a> { listener: &'a TcpListener }
@@ -83,11 +110,15 @@ impl TcpStream {
     /// Opens a TCP connection to a remote host.
     ///
     /// `addr` is an address of the remote host. Anything which implements
-    /// `ToSocketAddrs` trait can be supplied for the address; see this trait
+    /// [`ToSocketAddrs`] trait can be supplied for the address; see this trait
     /// documentation for concrete examples.
-    /// In case `ToSocketAddrs::to_socket_addrs()` returns more than one entry,
+    /// In case [`ToSocketAddrs::to_socket_addrs()`] returns more than one entry,
     /// then the first valid and reachable address is used.
     ///
+    /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
+    /// [`ToSocketAddrs::to_socket_addrs()`]:
+    /// ../../std/net/trait.ToSocketAddrs.html#tymethod.to_socket_addrs
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -494,11 +525,14 @@ impl TcpListener {
     ///
     /// Binding with a port number of 0 will request that the OS assigns a port
     /// to this listener. The port allocated can be queried via the
-    /// `local_addr` method.
+    /// [`local_addr`] method.
     ///
-    /// The address type can be any implementor of `ToSocketAddrs` trait. See
+    /// The address type can be any implementor of [`ToSocketAddrs`] trait. See
     /// its documentation for concrete examples.
     ///
+    /// [`local_addr`]: #method.local_addr
+    /// [`ToSocketAddrs`]: ../../std/net/trait.ToSocketAddrs.html
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -529,10 +563,12 @@ pub fn local_addr(&self) -> io::Result<SocketAddr> {
 
     /// Creates a new independently owned handle to the underlying socket.
     ///
-    /// The returned `TcpListener` is a reference to the same socket that this
+    /// The returned [`TcpListener`] is a reference to the same socket that this
     /// object references. Both handles can be used to accept incoming
     /// connections and options set on one listener will affect the other.
     ///
+    /// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -549,9 +585,11 @@ pub fn try_clone(&self) -> io::Result<TcpListener> {
     /// Accept a new incoming connection from this listener.
     ///
     /// This function will block the calling thread until a new TCP connection
-    /// is established. When established, the corresponding `TcpStream` and the
+    /// is established. When established, the corresponding [`TcpStream`] and the
     /// remote peer's address will be returned.
     ///
+    /// [`TcpStream`]: ../../std/net/struct.TcpStream.html
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -572,10 +610,12 @@ pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
     /// listener.
     ///
     /// The returned iterator will never return [`None`] and will also not yield
-    /// the peer's [`SocketAddr`] structure.
+    /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
+    /// calling [`accept`] in a loop.
     ///
     /// [`None`]: ../../std/option/enum.Option.html#variant.None
     /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
+    /// [`accept`]: #method.accept
     ///
     /// # Examples
     ///
index 1ebce939348401d5087250e7cd365a092b717614..cdf04f7f1a484bb02f5f257000060fe82d98b7b8 100644 (file)
 use sys_common::{AsInner, FromInner, IntoInner};
 use time::Duration;
 
-/// A User Datagram Protocol socket.
+/// A UDP socket.
 ///
-/// This is an implementation of a bound UDP socket. This supports both IPv4 and
-/// IPv6 addresses, and there is no corresponding notion of a server because UDP
-/// is a datagram protocol.
+/// After creating a `UdpSocket` by [`bind`]ing it to a socket address, data can be
+/// [sent to] and [received from] any other socket address.
+///
+/// Although UDP is a connectionless protocol, this implementation provides an interface
+/// to set an address where data should be sent and received from. After setting a remote
+/// address with [`connect`], data can be sent to and received from that address with
+/// [`send`] and [`recv`].
+///
+/// As stated in the User Datagram Protocol's specification in [IETF RFC 768], UDP is
+/// an unordered, unreliable protocol; refer to [`TcpListener`] and [`TcpStream`] for TCP
+/// primitives.
+///
+/// [`bind`]: #method.bind
+/// [`connect`]: #method.connect
+/// [IETF RFC 768]: https://tools.ietf.org/html/rfc768
+/// [`recv`]: #method.recv
+/// [received from]: #method.recv_from
+/// [`send`]: #method.send
+/// [sent to]: #method.send_to
+/// [`TcpListener`]: ../../std/net/struct.TcpListener.html
+/// [`TcpStream`]: ../../std/net/struct.TcpStream.html
 ///
 /// # Examples
 ///
@@ -582,9 +600,11 @@ pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
     /// Receives data on the socket from the remote address to which it is
     /// connected.
     ///
-    /// The `connect` method will connect this socket to a remote address. This
+    /// The [`connect`] method will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
     ///
+    /// [`connect`]: #method.connect
+    ///
     /// # Examples
     ///
     /// ```no_run
index 68d4ca900195c5ed8c3161eaa5d9853942fb5500..c34491941d69010a25f60a5ec6aa3ac947c36f98 100644 (file)
 
 use fmt;
 
-#[cfg(any(target_os = "android",
-          target_os = "emscripten",
+#[cfg(any(target_os = "emscripten",
           all(target_os = "linux", any(target_arch = "aarch64",
                                        target_arch = "arm",
                                        target_arch = "powerpc",
                                        target_arch = "powerpc64",
                                        target_arch = "s390x")),
+          all(target_os = "android", any(target_arch = "aarch64",
+                                         target_arch = "arm")),
           all(target_os = "fuchsia", target_arch = "aarch64")))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
-#[cfg(not(any(target_os = "android",
-              target_os = "emscripten",
+#[cfg(not(any(target_os = "emscripten",
               all(target_os = "linux", any(target_arch = "aarch64",
                                            target_arch = "arm",
                                            target_arch = "powerpc",
                                            target_arch = "powerpc64",
                                            target_arch = "s390x")),
+              all(target_os = "android", any(target_arch = "aarch64",
+                                             target_arch = "arm")),
               all(target_os = "fuchsia", target_arch = "aarch64"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
index 7a85e58866236ad5d10d28bf7ba75ccb90f4320b..d46cf7a26daf06aa5a17b0ebe5d3a724f4d88d00 100644 (file)
@@ -437,7 +437,10 @@ pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Command
     /// # Examples
     ///
     /// Basic usage:
+    ///
     /// ```no_run
+    /// #![feature(command_envs)]
+    ///
     /// use std::process::{Command, Stdio};
     /// use std::env;
     /// use std::collections::HashMap;
index 1e7394c0b09e7e88f9b52fb9e2f0f57efe702b9c..d9edf5d1254896c492fb5f9cc2009a77d528e76f 100644 (file)
 
 /// A synchronization primitive which can be used to run a one-time global
 /// initialization. Useful for one-time initialization for FFI or related
-/// functionality. This type can only be constructed with the `ONCE_INIT`
+/// functionality. This type can only be constructed with the [`ONCE_INIT`]
 /// value.
 ///
+/// [`ONCE_INIT`]: constant.ONCE_INIT.html
+///
 /// # Examples
 ///
 /// ```
@@ -101,15 +103,28 @@ unsafe impl Sync for Once {}
 #[stable(feature = "rust1", since = "1.0.0")]
 unsafe impl Send for Once {}
 
-/// State yielded to the `call_once_force` method which can be used to query
-/// whether the `Once` was previously poisoned or not.
+/// State yielded to the [`call_once_force`] method which can be used to query
+/// whether the [`Once`] was previously poisoned or not.
+///
+/// [`call_once_force`]: struct.Once.html#method.call_once_force
+/// [`Once`]: struct.Once.html
 #[unstable(feature = "once_poison", issue = "33577")]
 #[derive(Debug)]
 pub struct OnceState {
     poisoned: bool,
 }
 
-/// Initialization value for static `Once` values.
+/// Initialization value for static [`Once`] values.
+///
+/// [`Once`]: struct.Once.html
+///
+/// # Examples
+///
+/// ```
+/// use std::sync::{Once, ONCE_INIT};
+///
+/// static START: Once = ONCE_INIT;
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const ONCE_INIT: Once = Once::new();
 
@@ -212,15 +227,19 @@ pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
         self.call_inner(false, &mut |_| f.take().unwrap()());
     }
 
-    /// Performs the same function as `call_once` except ignores poisoning.
+    /// Performs the same function as [`call_once`] except ignores poisoning.
+    ///
+    /// [`call_once`]: struct.Once.html#method.call_once
     ///
     /// If this `Once` has been poisoned (some initialization panicked) then
     /// this function will continue to attempt to call initialization functions
     /// until one of them doesn't panic.
     ///
-    /// The closure `f` is yielded a structure which can be used to query the
+    /// The closure `f` is yielded a [`OnceState`] structure which can be used to query the
     /// state of this `Once` (whether initialization has previously panicked or
     /// not).
+    ///
+    /// [`OnceState`]: struct.OnceState.html
     #[unstable(feature = "once_poison", issue = "33577")]
     pub fn call_once_force<F>(&'static self, f: F) where F: FnOnce(&OnceState) {
         // same as above, just with a different parameter to `call_inner`.
@@ -366,10 +385,12 @@ fn drop(&mut self) {
 }
 
 impl OnceState {
-    /// Returns whether the associated `Once` has been poisoned.
+    /// Returns whether the associated [`Once`] has been poisoned.
     ///
-    /// Once an initalization routine for a `Once` has panicked it will forever
+    /// Once an initalization routine for a [`Once`] has panicked it will forever
     /// indicate to future forced initialization routines that it is poisoned.
+    ///
+    /// [`Once`]: struct.Once.html
     #[unstable(feature = "once_poison", issue = "33577")]
     pub fn poisoned(&self) -> bool {
         self.poisoned
index 55118829eee9f950ef900cb1a5ca62c068c63eb9..d688f2fa504517cb3fe450b15f68cc8ea7005f6e 100644 (file)
@@ -641,7 +641,7 @@ fn inner(path: &Path) -> io::Result<UnixListener> {
                 let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
                 let (addr, len) = sockaddr_un(path)?;
 
-                cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len))?;
+                cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
                 cvt(libc::listen(*inner.as_inner(), 128))?;
 
                 Ok(UnixListener(inner))
@@ -920,7 +920,7 @@ fn inner(path: &Path) -> io::Result<UnixDatagram> {
                 let socket = UnixDatagram::unbound()?;
                 let (addr, len) = sockaddr_un(path)?;
 
-                cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len))?;
+                cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
 
                 Ok(socket)
             }
index 5f1a6c2f7465150a9132072807c3f9259d617651..e9f41009064ca43ea267861b2bfe76cc8fd64718 100644 (file)
@@ -417,12 +417,26 @@ macro_rules! t {
         }
     }
 
+    // Android with api less than 21 define sig* functions inline, so it is not
+    // available for dynamic link. Implementing sigemptyset and sigaddset allow us
+    // to support older Android version (independent of libc version).
+    // The following implementations are based on https://git.io/vSkNf
+
     #[cfg(not(target_os = "android"))]
     extern {
+        #[cfg_attr(target_os = "netbsd", link_name = "__sigemptyset14")]
+        fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int;
+
         #[cfg_attr(target_os = "netbsd", link_name = "__sigaddset14")]
         fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int;
     }
 
+    #[cfg(target_os = "android")]
+    unsafe fn sigemptyset(set: *mut libc::sigset_t) -> libc::c_int {
+        libc::memset(set as *mut _, 0, mem::size_of::<libc::sigset_t>());
+        return 0;
+    }
+
     #[cfg(target_os = "android")]
     unsafe fn sigaddset(set: *mut libc::sigset_t, signum: libc::c_int) -> libc::c_int {
         use slice;
@@ -450,7 +464,7 @@ fn test_process_mask() {
 
             let mut set: libc::sigset_t = mem::uninitialized();
             let mut old_set: libc::sigset_t = mem::uninitialized();
-            t!(cvt(libc::sigemptyset(&mut set)));
+            t!(cvt(sigemptyset(&mut set)));
             t!(cvt(sigaddset(&mut set, libc::SIGINT)));
             t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set, &mut old_set)));
 
index a213273aac8fd55f174a91b145b2e27b139546ee..edd322ca6fa0708b1e4a928f7ecdb3ff66e5480c 100644 (file)
@@ -193,7 +193,16 @@ macro_rules! t {
             // need to clean things up now to avoid confusing the program
             // we're about to run.
             let mut set: libc::sigset_t = mem::uninitialized();
-            t!(cvt(libc::sigemptyset(&mut set)));
+            if cfg!(target_os = "android") {
+                // Implementing sigemptyset allow us to support older Android
+                // versions. See the comment about Android and sig* functions in
+                // process_common.rs
+                libc::memset(&mut set as *mut _ as *mut _,
+                             0,
+                             mem::size_of::<libc::sigset_t>());
+            } else {
+                t!(cvt(libc::sigemptyset(&mut set)));
+            }
             t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
                                          ptr::null_mut())));
             let ret = sys::signal(libc::SIGPIPE, libc::SIG_DFL);
index 1afb3728c9d72e7d00d20a153631a312b72302e6..dfbc1b581ee55f39b4bb22366beb1240e3c4c79a 100644 (file)
@@ -257,8 +257,13 @@ fn to_handle(&self, stdio_id: c::DWORD, pipe: &mut Option<AnonPipe>)
             // INVALID_HANDLE_VALUE.
             Stdio::Inherit => {
                 match stdio::get(stdio_id) {
-                    Ok(io) => io.handle().duplicate(0, true,
-                                                    c::DUPLICATE_SAME_ACCESS),
+                    Ok(io) => {
+                        let io = Handle::new(io.handle());
+                        let ret = io.duplicate(0, true,
+                                               c::DUPLICATE_SAME_ACCESS);
+                        io.into_raw();
+                        return ret
+                    }
                     Err(..) => Ok(Handle::new(c::INVALID_HANDLE_VALUE)),
                 }
             }
index b1a57c349fbb909e942fc854571ed57967e708ee..d72e4b4438b7bc8d367638bcb55ec96a6bf77474 100644 (file)
 use sys::handle::Handle;
 use sys_common::io::read_to_end_uninitialized;
 
-pub struct NoClose(Option<Handle>);
-
 pub enum Output {
-    Console(NoClose),
-    Pipe(NoClose),
+    Console(c::HANDLE),
+    Pipe(c::HANDLE),
 }
 
 pub struct Stdin {
-    handle: Output,
     utf8: Mutex<io::Cursor<Vec<u8>>>,
 }
-pub struct Stdout(Output);
-pub struct Stderr(Output);
+pub struct Stdout;
+pub struct Stderr;
 
 pub fn get(handle: c::DWORD) -> io::Result<Output> {
     let handle = unsafe { c::GetStdHandle(handle) };
     if handle == c::INVALID_HANDLE_VALUE {
         Err(io::Error::last_os_error())
     } else if handle.is_null() {
-        Err(io::Error::new(io::ErrorKind::Other,
-                           "no stdio handle available for this process"))
+        Err(io::Error::from_raw_os_error(c::ERROR_INVALID_HANDLE as i32))
     } else {
-        let ret = NoClose::new(handle);
         let mut out = 0;
         match unsafe { c::GetConsoleMode(handle, &mut out) } {
-            0 => Ok(Output::Pipe(ret)),
-            _ => Ok(Output::Console(ret)),
+            0 => Ok(Output::Pipe(handle)),
+            _ => Ok(Output::Console(handle)),
         }
     }
 }
 
-fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
-    let handle = match *out {
-        Output::Console(ref c) => c.get().raw(),
-        Output::Pipe(ref p) => return p.get().write(data),
+fn write(handle: c::DWORD, data: &[u8]) -> io::Result<usize> {
+    let handle = match try!(get(handle)) {
+        Output::Console(c) => c,
+        Output::Pipe(p) => {
+            let handle = Handle::new(p);
+            let ret = handle.write(data);
+            handle.into_raw();
+            return ret
+        }
     };
+
     // As with stdin on windows, stdout often can't handle writes of large
     // sizes. For an example, see #14940. For this reason, don't try to
     // write the entire output buffer on windows.
@@ -93,18 +94,20 @@ fn write(out: &Output, data: &[u8]) -> io::Result<usize> {
 
 impl Stdin {
     pub fn new() -> io::Result<Stdin> {
-        get(c::STD_INPUT_HANDLE).map(|handle| {
-            Stdin {
-                handle: handle,
-                utf8: Mutex::new(Cursor::new(Vec::new())),
-            }
+        Ok(Stdin {
+            utf8: Mutex::new(Cursor::new(Vec::new())),
         })
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        let handle = match self.handle {
-            Output::Console(ref c) => c.get().raw(),
-            Output::Pipe(ref p) => return p.get().read(buf),
+        let handle = match try!(get(c::STD_INPUT_HANDLE)) {
+            Output::Console(c) => c,
+            Output::Pipe(p) => {
+                let handle = Handle::new(p);
+                let ret = handle.read(buf);
+                handle.into_raw();
+                return ret
+            }
         };
         let mut utf8 = self.utf8.lock().unwrap();
         // Read more if the buffer is empty
@@ -125,11 +128,9 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
                 Ok(utf8) => utf8.into_bytes(),
                 Err(..) => return Err(invalid_encoding()),
             };
-            if let Output::Console(_) = self.handle {
-                if let Some(&last_byte) = data.last() {
-                    if last_byte == CTRL_Z {
-                        data.pop();
-                    }
+            if let Some(&last_byte) = data.last() {
+                if last_byte == CTRL_Z {
+                    data.pop();
                 }
             }
             *utf8 = Cursor::new(data);
@@ -158,11 +159,11 @@ fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
 
 impl Stdout {
     pub fn new() -> io::Result<Stdout> {
-        get(c::STD_OUTPUT_HANDLE).map(Stdout)
+        Ok(Stdout)
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
-        write(&self.0, data)
+        write(c::STD_OUTPUT_HANDLE, data)
     }
 
     pub fn flush(&self) -> io::Result<()> {
@@ -172,11 +173,11 @@ pub fn flush(&self) -> io::Result<()> {
 
 impl Stderr {
     pub fn new() -> io::Result<Stderr> {
-        get(c::STD_ERROR_HANDLE).map(Stderr)
+        Ok(Stderr)
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
-        write(&self.0, data)
+        write(c::STD_ERROR_HANDLE, data)
     }
 
     pub fn flush(&self) -> io::Result<()> {
@@ -197,27 +198,12 @@ fn flush(&mut self) -> io::Result<()> {
     }
 }
 
-impl NoClose {
-    fn new(handle: c::HANDLE) -> NoClose {
-        NoClose(Some(Handle::new(handle)))
-    }
-
-    fn get(&self) -> &Handle { self.0.as_ref().unwrap() }
-}
-
-impl Drop for NoClose {
-    fn drop(&mut self) {
-        self.0.take().unwrap().into_raw();
-    }
-}
-
 impl Output {
-    pub fn handle(&self) -> &Handle {
-        let nc = match *self {
-            Output::Console(ref c) => c,
-            Output::Pipe(ref c) => c,
-        };
-        nc.0.as_ref().unwrap()
+    pub fn handle(&self) -> c::HANDLE {
+        match *self {
+            Output::Console(c) => c,
+            Output::Pipe(c) => c,
+        }
     }
 }
 
index 3cdeb511945756d7d8c451ad4ff89ff6aac8f164..9239c18e59717a2bf088859ff05a8dbbccfbe81a 100644 (file)
@@ -339,7 +339,7 @@ pub fn bind(addr: &SocketAddr) -> io::Result<TcpListener> {
 
         // Bind our new socket
         let (addrp, len) = addr.into_inner();
-        cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })?;
+        cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
 
         // Start listening
         cvt(unsafe { c::listen(*sock.as_inner(), 128) })?;
@@ -430,7 +430,7 @@ pub fn bind(addr: &SocketAddr) -> io::Result<UdpSocket> {
 
         let sock = Socket::new(addr, c::SOCK_DGRAM)?;
         let (addrp, len) = addr.into_inner();
-        cvt(unsafe { c::bind(*sock.as_inner(), addrp, len) })?;
+        cvt(unsafe { c::bind(*sock.as_inner(), addrp, len as _) })?;
         Ok(UdpSocket { inner: sock })
     }
 
index b980300126e4b8a2b8b05d9323ecdf3b6dfc063e..92e5369758b4e5914dff87ebfedbf2862ae02a42 100644 (file)
@@ -842,11 +842,11 @@ pub fn to_lowercase(self) -> ToLowercase {
     /// Returns an iterator that yields the uppercase equivalent of a `char`
     /// as one or more `char`s.
     ///
-    /// If a character does not have a uppercase equivalent, the same character
+    /// If a character does not have an uppercase equivalent, the same character
     /// will be returned back by the iterator.
     ///
     /// This performs complex unconditional mappings with no tailoring: it maps
-    /// one Unicode character to its lowercase equivalent according to the
+    /// one Unicode character to its uppercase equivalent according to the
     /// [Unicode database] and the additional complex mappings
     /// [`SpecialCasing.txt`]. Conditional mappings (based on context or
     /// language) are not considered here.
index 0b38f5450b63faf09251971ad20926318130c2ff..97d37266130af750a304561f1eb0ec33ae06f5e7 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 serialize = { path = "../libserialize" }
-log = { path = "../liblog" }
+log = "0.3"
 rustc_bitflags = { path = "../librustc_bitflags" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_errors = { path = "../librustc_errors" }
index f0e328a551d5f37003d53bf6f93a40617708ea83..2d0994a7b78fb1b798f00cd04366b20fab589d7c 100644 (file)
@@ -106,8 +106,8 @@ fn remove(&mut self, id: ast::NodeId) -> Expansion {
 impl<'a, 'b> Folder for PlaceholderExpander<'a, 'b> {
     fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         match item.node {
-            ast::ItemKind::Mac(ref mac) if !mac.node.path.segments.is_empty() => {}
             ast::ItemKind::Mac(_) => return self.remove(item.id).make_items(),
+            ast::ItemKind::MacroDef(_) => return SmallVector::one(item),
             _ => {}
         }
 
index 021c5398a4200459218a8f94d78df25ed77b6502..66f5520b8826371991822087a551cfc35277a80e 100644 (file)
@@ -119,7 +119,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 };
                 let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), false);
                 p.root_module_name = cx.current_expansion.module.mod_path.last()
-                    .map(|id| (*id.name.as_str()).to_owned());
+                    .map(|id| id.name.as_str().to_string());
 
                 p.check_unknown_macro_variable();
                 // Let the context choose how to interpret the result.
index 7af432176cf6ea44d0160cb0387ee577f3ea9013..9d280a413e666c5403015bcbdc9ccec310febd68 100644 (file)
@@ -818,7 +818,7 @@ pub struct GatedCfg {
 
 impl GatedCfg {
     pub fn gate(cfg: &ast::MetaItem) -> Option<GatedCfg> {
-        let name = &*cfg.name().as_str();
+        let name = cfg.name().as_str();
         GATED_CFGS.iter()
                   .position(|info| info.0 == name)
                   .map(|idx| {
@@ -865,8 +865,7 @@ macro_rules! gate_feature {
 impl<'a> Context<'a> {
     fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
-        let name = unwrap_or!(attr.name(), return);
-
+        let name = unwrap_or!(attr.name(), return).as_str();
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if name == n {
                 if let &Gated(_, ref name, ref desc, ref has_feature) = gateage {
@@ -885,12 +884,12 @@ fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
                 return;
             }
         }
-        if name.as_str().starts_with("rustc_") {
+        if name.starts_with("rustc_") {
             gate_feature!(self, rustc_attrs, attr.span,
                           "unless otherwise specified, attributes \
                            with the prefix `rustc_` \
                            are reserved for internal compiler diagnostics");
-        } else if name.as_str().starts_with("derive_") {
+        } else if name.starts_with("derive_") {
             gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
         } else if !attr::is_known(attr) {
             // Only run the custom attribute lint during regular
index df4ccc94c0421cbb9397a459079f405fac7f5a29..43a9d8c5f787c77bcc993e6f5a701c668e97b95f 100644 (file)
@@ -4626,7 +4626,7 @@ pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> {
 
         let mut attrs = self.parse_outer_attributes()?;
         let lo = self.span.lo;
-        let vis = self.parse_visibility()?;
+        let vis = self.parse_visibility(false)?;
         let defaultness = self.parse_defaultness()?;
         let (name, node) = if self.eat_keyword(keywords::Type) {
             let name = self.parse_ident()?;
@@ -4939,25 +4939,8 @@ pub fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
             |p| {
                 let attrs = p.parse_outer_attributes()?;
                 let lo = p.span.lo;
-                let mut vis = p.parse_visibility()?;
-                let ty_is_interpolated =
-                    p.token.is_interpolated() || p.look_ahead(1, |t| t.is_interpolated());
-                let mut ty = p.parse_ty()?;
-
-                // Handle `pub(path) type`, in which `vis` will be `pub` and `ty` will be `(path)`.
-                if vis == Visibility::Public && !ty_is_interpolated &&
-                   p.token != token::Comma && p.token != token::CloseDelim(token::Paren) {
-                    ty = if let TyKind::Paren(ref path_ty) = ty.node {
-                        if let TyKind::Path(None, ref path) = path_ty.node {
-                            vis = Visibility::Restricted { path: P(path.clone()), id: path_ty.id };
-                            Some(p.parse_ty()?)
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    }.unwrap_or(ty);
-                }
+                let vis = p.parse_visibility(true)?;
+                let ty = p.parse_ty()?;
                 Ok(StructField {
                     span: mk_sp(lo, p.span.hi),
                     vis: vis,
@@ -4996,18 +4979,25 @@ pub fn parse_single_struct_field(&mut self,
     fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span.lo;
-        let vis = self.parse_visibility()?;
+        let vis = self.parse_visibility(false)?;
         self.parse_single_struct_field(lo, vis, attrs)
     }
 
-    // Parse `pub`, `pub(crate)` and `pub(in path)` plus shortcuts
-    // `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`.
-    fn parse_visibility(&mut self) -> PResult<'a, Visibility> {
+    /// Parse `pub`, `pub(crate)` and `pub(in path)` plus shortcuts `pub(self)` for `pub(in self)`
+    /// and `pub(super)` for `pub(in super)`.  If the following element can't be a tuple (i.e. it's
+    /// a function definition, it's not a tuple struct field) and the contents within the parens
+    /// isn't valid, emit a proper diagnostic.
+    fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> {
         if !self.eat_keyword(keywords::Pub) {
             return Ok(Visibility::Inherited)
         }
 
         if self.check(&token::OpenDelim(token::Paren)) {
+            let start_span = self.span;
+            // We don't `self.bump()` the `(` yet because this might be a struct definition where
+            // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
+            // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
+            // by the following tokens.
             if self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) {
                 // `pub(crate)`
                 self.bump(); // `(`
@@ -5032,6 +5022,28 @@ fn parse_visibility(&mut self) -> PResult<'a, Visibility> {
                 let vis = Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID };
                 self.expect(&token::CloseDelim(token::Paren))?; // `)`
                 return Ok(vis)
+            } else if !can_take_tuple {  // Provide this diagnostic if this is not a tuple struct
+                // `pub(something) fn ...` or `struct X { pub(something) y: Z }`
+                self.bump(); // `(`
+                let msg = "incorrect visibility restriction";
+                let suggestion = r##"some possible visibility restrictions are:
+`pub(crate)`: visible only on the current crate
+`pub(super)`: visible only in the current module's parent
+`pub(in path::to::module)`: visible only on the specified path"##;
+                let path = self.parse_path(PathStyle::Mod)?;
+                let path_span = self.prev_span;
+                let help_msg = format!("to make this visible only to module `{}`, add `in` before \
+                                       the path:",
+                                       path);
+                self.expect(&token::CloseDelim(token::Paren))?;  // `)`
+                let sp = Span {
+                    lo: start_span.lo,
+                    hi: self.prev_span.hi,
+                    expn_id: start_span.expn_id,
+                };
+                let mut err = self.span_fatal_help(sp, &msg, &suggestion);
+                err.span_suggestion(path_span, &help_msg, format!("in {}", path));
+                err.emit();  // emit diagnostic, but continue with public visibility
             }
         }
 
@@ -5139,15 +5151,15 @@ fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo>
 
     fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
         if let Some(path) = attr::first_attr_value_str_by_name(attrs, "path") {
-            self.directory.path.push(&*path.as_str());
+            self.directory.path.push(&path.as_str());
             self.directory.ownership = DirectoryOwnership::Owned;
         } else {
-            self.directory.path.push(&*id.name.as_str());
+            self.directory.path.push(&id.name.as_str());
         }
     }
 
     pub fn submod_path_from_attr(attrs: &[ast::Attribute], dir_path: &Path) -> Option<PathBuf> {
-        attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&*d.as_str()))
+        attr::first_attr_value_str_by_name(attrs, "path").map(|d| dir_path.join(&d.as_str()))
     }
 
     /// Returns either a path to a module, or .
@@ -5508,7 +5520,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
 
         let lo = self.span.lo;
 
-        let visibility = self.parse_visibility()?;
+        let visibility = self.parse_visibility(false)?;
 
         if self.eat_keyword(keywords::Use) {
             // USE ITEM
@@ -5787,7 +5799,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
     fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span.lo;
-        let visibility = self.parse_visibility()?;
+        let visibility = self.parse_visibility(false)?;
 
         if self.check_keyword(keywords::Static) {
             // FOREIGN STATIC ITEM
index 6642c60d256b3c4e40e0cc437ddb60993544e1f6..2acbeee426beead4b72b286e16bfffacf89957ad 100644 (file)
@@ -72,9 +72,9 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
     }
 }
 
-impl<'a> PartialEq<&'a str> for Symbol {
-    fn eq(&self, other: &&str) -> bool {
-        *self.as_str() == **other
+impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
+    fn eq(&self, other: &T) -> bool {
+        self.as_str() == other.deref()
     }
 }
 
@@ -244,11 +244,47 @@ fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
 /// destroyed. In particular, they must not access string contents. This can
 /// be fixed in the future by just leaking all strings until thread death
 /// somehow.
-#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
+#[derive(Clone, Hash, PartialOrd, Eq, Ord)]
 pub struct InternedString {
     string: &'static str,
 }
 
+impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
+    fn as_ref(&self) -> &U {
+        self.string.as_ref()
+    }
+}
+
+impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
+    fn eq(&self, other: &T) -> bool {
+        self.string == other.deref()
+    }
+}
+
+impl ::std::cmp::PartialEq<InternedString> for str {
+    fn eq(&self, other: &InternedString) -> bool {
+        self == other.string
+    }
+}
+
+impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
+    fn eq(&self, other: &InternedString) -> bool {
+        *self == other.string
+    }
+}
+
+impl ::std::cmp::PartialEq<InternedString> for String {
+    fn eq(&self, other: &InternedString) -> bool {
+        self == other.string
+    }
+}
+
+impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
+    fn eq(&self, other: &InternedString) -> bool {
+        *self == other.string
+    }
+}
+
 impl !Send for InternedString { }
 
 impl ::std::ops::Deref for InternedString {
index e052d2cda3a42469b000be576f82b416a08bb20c..6fb6db9ca0282fd09cac855a9f6f3838714694ea 100644 (file)
@@ -616,7 +616,7 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
 
 fn is_test_crate(krate: &ast::Crate) -> bool {
     match attr::find_crate_name(&krate.attrs) {
-        Some(s) if "test" == &*s.as_str() => true,
+        Some(s) if "test" == s.as_str() => true,
         _ => false
     }
 }
index 960db792a623e4c2a1ab38cb60b12ba37481ff41..bdcec26cb838b211ba5980542da2ca62bb386b99 100644 (file)
@@ -10,7 +10,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 fmt_macros = { path = "../libfmt_macros" }
-log = { path = "../liblog" }
+log = "0.3"
 proc_macro = { path = "../libproc_macro" }
 rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
index d5ef27a79661d4f0d57d7b7d2cdbe9204f790a4a..2e951c3ae354bcbd2e50b30798e232949a926b75 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit d5ef27a79661d4f0d57d7b7d2cdbe9204f790a4a
+Subproject commit 2e951c3ae354bcbd2e50b30798e232949a926b75
diff --git a/src/rt/hoedown b/src/rt/hoedown
deleted file mode 160000 (submodule)
index da282f1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit da282f1bb7277b4d30fa1599ee29ad8eb4dd2a92
index 6fecd3a27a8a459f2d3237fe67d3bc4be2ca5502..a4f43c42623d33be11e547c4b6f9f1694f841e6b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustdoc)]
+#![feature(rustc_private)]
 
 extern crate rustdoc;
 
index be6d535dc732b63c606312aeb14fddaeefd5bed7..c8732e27b82528e9e988d4ebfe21385aa5d41c72 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be (optionally) 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.
-2017-03-19
+2017-03-23
index 92a8b10669ceeb1ab6c9785aede66dfa810a33a7..736aa465aa7327a2db646b2f502c98c2db1d8983 100644 (file)
@@ -27,7 +27,7 @@ fn main() {
     x;  //~ value moved here
 
     let y = Int(2);
-    //~^use `mut y` here to make mutable
+    //~^ consider changing this to `mut y`
     y   //~ error: cannot borrow immutable local variable `y` as mutable
         //~| cannot borrow
     +=
index 64033623fe2d13e86ca3349dd9d520de47346564..8b7ccedd6974fe1be00649de25d8220e7ba7c581 100644 (file)
@@ -23,7 +23,7 @@ fn indirect_write_to_imm_box() {
     let mut x: isize = 1;
     let y: Box<_> = box &mut x;
     let p = &y;
-    ***p = 2; //~ ERROR cannot assign to data in an immutable container
+    ***p = 2; //~ ERROR cannot assign to data in a `&` reference
     drop(p);
 }
 
@@ -43,7 +43,6 @@ fn borrow_in_var_from_var_via_imm_box() {
     let p = &y;
     let q = &***p;
     **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed
-    //~^         ERROR cannot assign to data in an immutable container
     drop(p);
     drop(q);
 }
@@ -64,7 +63,6 @@ fn borrow_in_var_from_field_via_imm_box() {
     let p = &y;
     let q = &***p;
     **y = 2; //~ ERROR cannot assign to `**y` because it is borrowed
-    //~^         ERROR cannot assign to data in an immutable container
     drop(p);
     drop(q);
 }
@@ -85,7 +83,6 @@ fn borrow_in_field_from_var_via_imm_box() {
     let p = &y.a;
     let q = &***p;
     **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed
-    //~^           ERROR cannot assign to data in an immutable container
     drop(p);
     drop(q);
 }
@@ -106,7 +103,6 @@ fn borrow_in_field_from_field_via_imm_box() {
     let p = &y.a;
     let q = &***p;
     **y.a = 2; //~ ERROR cannot assign to `**y.a` because it is borrowed
-    //~^           ERROR cannot assign to data in an immutable container
     drop(p);
     drop(q);
 }
diff --git a/src/test/compile-fail/imports/shadow_builtin_macros.rs b/src/test/compile-fail/imports/shadow_builtin_macros.rs
new file mode 100644 (file)
index 0000000..2b3ba1b
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright 2017 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:two_macros.rs
+
+#![feature(use_extern_macros)]
+
+mod foo {
+    extern crate two_macros;
+    pub use self::two_macros::m as panic;
+}
+
+mod m1 {
+    use foo::panic; // ok
+    fn f() { panic!(); }
+}
+
+mod m2 {
+    use foo::*; //~ NOTE `panic` could refer to the name imported here
+    fn f() { panic!(); } //~ ERROR ambiguous
+    //~| NOTE `panic` is also a builtin macro
+    //~| NOTE consider adding an explicit import of `panic` to disambiguate
+}
+
+mod m3 {
+    ::two_macros::m!(use foo::panic;); //~ NOTE `panic` could refer to the name imported here
+    //~| NOTE in this expansion
+    fn f() { panic!(); } //~ ERROR ambiguous
+    //~| NOTE `panic` is also a builtin macro
+    //~| NOTE macro-expanded macro imports do not shadow
+}
+
+mod m4 {
+    macro_rules! panic { () => {} } // ok
+    panic!();
+}
+
+mod m5 {
+    macro_rules! m { () => {
+        macro_rules! panic { () => {} } //~ ERROR `panic` is already in scope
+        //~| NOTE macro-expanded `macro_rules!`s may not shadow existing macros
+    } }
+    m!(); //~ NOTE in this expansion
+    //~| NOTE in this expansion
+    panic!();
+}
+
+#[macro_use(n)] //~ NOTE `n` could also refer to the name imported here
+extern crate two_macros;
+mod bar {
+    pub use two_macros::m as n;
+}
+
+mod m6 {
+    use bar::n; // ok
+    n!();
+}
+
+mod m7 {
+    use bar::*; //~ NOTE `n` could refer to the name imported here
+    n!(); //~ ERROR ambiguous
+    //~| NOTE consider adding an explicit import of `n` to disambiguate
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-10176.rs b/src/test/compile-fail/issue-10176.rs
new file mode 100644 (file)
index 0000000..434b795
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn f() -> isize {
+    (return 1, return 2)
+//~^ ERROR mismatched types
+//~| expected type `isize`
+//~| found type `(_, _)`
+//~| expected isize, found tuple
+}
+
+fn main() {}
index 9c9677c1e98638d996bf7fc4ee3e9eda1538725e..499e7e54947b70ed50962dd104ba66b71d6458a6 100644 (file)
@@ -12,7 +12,7 @@ fn main() {
     match op {
         Some(ref v) => { let a = &mut v; },
         //~^ ERROR:cannot borrow immutable
-        //~| use `ref mut v` here to make mutable
+        //~| cannot borrow mutably
         None => {},
     }
 }
diff --git a/src/test/compile-fail/issue-40000.rs b/src/test/compile-fail/issue-40000.rs
new file mode 100644 (file)
index 0000000..9be114e
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2017 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(closure_to_fn_coercion)]
+
+fn main() {
+    let bar: fn(&mut u32) = |_| {}; //~ ERROR mismatched types
+    //~| expected concrete lifetime, found bound lifetime parameter
+
+    fn foo(x: Box<Fn(&i32)>) {}
+    let bar = Box::new(|x: &i32| {}) as Box<Fn(_)>;
+    foo(bar); //~ ERROR mismatched types
+    //~| expected concrete lifetime, found bound lifetime parameter
+}
diff --git a/src/test/compile-fail/issue-40749.rs b/src/test/compile-fail/issue-40749.rs
new file mode 100644 (file)
index 0000000..261ed49
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 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() {
+    [0; ..10];
+    //~^ ERROR mismatched types
+    //~| expected type `usize`
+    //~| found type `std::ops::RangeTo<{integer}>`
+}
diff --git a/src/test/compile-fail/issue-40845.rs b/src/test/compile-fail/issue-40845.rs
new file mode 100644 (file)
index 0000000..c5604a0
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait T { m!(); } //~ ERROR cannot find macro `m!` in this scope
+
+struct S;
+impl S { m!(); } //~ ERROR cannot find macro `m!` in this scope
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-5500.rs b/src/test/compile-fail/issue-5500.rs
new file mode 100644 (file)
index 0000000..1cbb758
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    &panic!()
+    //~^ ERROR mismatched types
+    //~| expected type `()`
+    //~| found type `&_`
+    //~| expected (), found reference
+}
index 242ad7aee8d1229c48622c0d9ad4e24bbc02ac16..0015c8e5c00a1212731754a71b73af892d25d0e2 100644 (file)
@@ -17,7 +17,7 @@ fn mutate(&mut self) {
 }
 
 fn func(arg: S) {
-    //~^ here to make mutable
+    //~^ consider changing this to `mut arg`
     arg.mutate();
     //~^ ERROR cannot borrow immutable argument
     //~| cannot borrow mutably
@@ -25,7 +25,7 @@ fn func(arg: S) {
 
 fn main() {
     let local = S;
-    //~^ here to make mutable
+    //~^ consider changing this to `mut local`
     local.mutate();
     //~^ ERROR cannot borrow immutable local variable
     //~| cannot borrow mutably
index 74d1ad62f14c3be3fb4d8c0d0c21bb4a77c652e7..a93c056c410c6d5e48f108905ea6e62e07b0d2bb 100644 (file)
@@ -24,7 +24,7 @@ fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
 
 fn make_baz<T:Baz>(t: &T) -> &Baz {
     //~^ ERROR E0038
-    //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
+    //~| NOTE the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
     //~| NOTE the trait `Baz` cannot be made into an object
     t
 }
index 208f1a0e2ee259403fd7c75142f2d07eacc82013..d17b604717e70bc7de0b38862fdd30b0cc8311b9 100644 (file)
@@ -10,7 +10,8 @@
 
 mod foo {
     type T = ();
-    struct S1(pub(foo) (), pub(T), pub(crate) (), pub(((), T)));
-    struct S2(pub((foo)) ()); //~ ERROR expected `,`, found `(`
-                              //~| ERROR expected one of `;` or `where`, found `(`
+    struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
+    struct S2(pub((foo)) ());
+    //~^ ERROR expected `,`, found `(`
+    //~| ERROR expected one of `;` or `where`, found `(`
 }
index 57769646e3b8f2de2118f7357fc13f9278df75e0..166d5e27e8d96ce8d75a26ce0dc70cb0f53c6f9b 100644 (file)
 macro_rules! define_struct {
     ($t:ty) => {
         struct S1(pub $t);
-        struct S2(pub (foo) ());
-        struct S3(pub $t ()); //~ ERROR expected `,`, found `(`
-                              //~| ERROR expected one of `;` or `where`, found `(`
+        struct S2(pub (in foo) ());
+        struct S3(pub $t ());
+        //~^ ERROR expected `,`, found `(`
+        //~| ERROR expected one of `;` or `where`, found `(`
     }
 }
 
index db3358f7d50aec95f39d29f4ff2733c4544cea6c..edab175f4cd91d3c2e7a5d9a63631eb93e57f508 100644 (file)
 macro_rules! define_struct {
     ($t:ty) => {
         struct S1(pub($t));
-        struct S2(pub (foo) ());
-        struct S3(pub($t) ()); //~ ERROR expected `,`, found `(`
-                               //~| ERROR expected one of `;` or `where`, found `(`
+        struct S2(pub (in foo) ());
+        struct S3(pub($t) ());
+        //~^ ERROR expected `,`, found `(`
+        //~| ERROR expected one of `;` or `where`, found `(`
     }
 }
 
diff --git a/src/test/compile-fail/static-lifetime-bound.rs b/src/test/compile-fail/static-lifetime-bound.rs
new file mode 100644 (file)
index 0000000..38534ab
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 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 f<'a: 'static>(_: &'a i32) {} //~WARN unnecessary lifetime parameter `'a`
+
+fn main() {
+    let x = 0;
+    f(&x); //~ERROR does not live long enough
+}
diff --git a/src/test/run-pass-fulldeps/auxiliary/logging_right_crate.rs b/src/test/run-pass-fulldeps/auxiliary/logging_right_crate.rs
deleted file mode 100644 (file)
index db26b10..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(rustc_private)]
-
-#[macro_use] extern crate log;
-
-pub fn foo<T>() {
-    fn death() -> isize { panic!() }
-    debug!("{}", (||{ death() })());
-}
diff --git a/src/test/run-pass-fulldeps/conditional-debug-macro-off.rs b/src/test/run-pass-fulldeps/conditional-debug-macro-off.rs
deleted file mode 100644 (file)
index c6beb5b..0000000
+++ /dev/null
@@ -1,23 +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.
-
-// compile-flags: -C debug-assertions=no
-// exec-env:RUST_LOG=conditional-debug-macro-off=4
-
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-pub fn main() {
-    // only panics if println! evaluates its argument.
-    debug!("{:?}", { if true { panic!() } });
-}
diff --git a/src/test/run-pass-fulldeps/logging-enabled-debug.rs b/src/test/run-pass-fulldeps/logging-enabled-debug.rs
deleted file mode 100644 (file)
index 3ae4884..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags:-C debug-assertions=no
-// exec-env:RUST_LOG=logging-enabled-debug=debug
-
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-pub fn main() {
-    if log_enabled!(log::DEBUG) {
-        panic!("what?! debugging?");
-    }
-}
diff --git a/src/test/run-pass-fulldeps/logging-enabled.rs b/src/test/run-pass-fulldeps/logging-enabled.rs
deleted file mode 100644 (file)
index 2626134..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// exec-env:RUST_LOG=logging_enabled=info
-// ignore-emscripten: FIXME(#31622)
-
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-pub fn main() {
-    if log_enabled!(log::DEBUG) {
-        panic!("what?! debugging?");
-    }
-    if !log_enabled!(log::INFO) {
-        panic!("what?! no info?");
-    }
-}
diff --git a/src/test/run-pass-fulldeps/logging-right-crate.rs b/src/test/run-pass-fulldeps/logging-right-crate.rs
deleted file mode 100644 (file)
index 7caeeb4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:logging_right_crate.rs
-// exec-env:RUST_LOG=logging-right-crate=debug
-
-// This is a test for issue #3046 to make sure that when we monomorphize a
-// function from one crate to another the right top-level logging name is
-// preserved.
-//
-// It used to be the case that if logging were turned on for this crate, all
-// monomorphized functions from other crates had logging turned on (their
-// logging module names were all incorrect). This test ensures that this no
-// longer happens by enabling logging for *this* crate and then invoking a
-// function in an external crate which will panic when logging is enabled.
-
-// pretty-expanded FIXME #23616
-
-extern crate logging_right_crate;
-
-pub fn main() {
-    // this function panicks if logging is turned on
-    logging_right_crate::foo::<isize>();
-}
diff --git a/src/test/run-pass-fulldeps/logging-separate-lines.rs b/src/test/run-pass-fulldeps/logging-separate-lines.rs
deleted file mode 100644 (file)
index 183a522..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-windows
-// exec-env:RUST_LOG=debug
-// compile-flags:-C debug-assertions=y
-// ignore-emscripten: FIXME(#31622)
-
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-use std::process::Command;
-use std::env;
-use std::str;
-
-fn main() {
-    let args: Vec<String> = env::args().collect();
-    if args.len() > 1 && args[1] == "child" {
-        debug!("foo");
-        debug!("bar");
-        return
-    }
-
-    let p = Command::new(&args[0])
-                    .arg("child")
-                    .output().unwrap();
-    assert!(p.status.success());
-    let mut lines = str::from_utf8(&p.stderr).unwrap().lines();
-    assert!(lines.next().unwrap().contains("foo"));
-    assert!(lines.next().unwrap().contains("bar"));
-}
diff --git a/src/test/run-pass-fulldeps/rust-log-filter.rs b/src/test/run-pass-fulldeps/rust-log-filter.rs
deleted file mode 100644 (file)
index 306d24e..0000000
+++ /dev/null
@@ -1,58 +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.
-
-// exec-env:RUST_LOG=rust_log_filter/foo
-// ignore-emscripten no threads support
-
-#![allow(unknown_features)]
-#![feature(box_syntax, std_misc, rustc_private)]
-
-#[macro_use]
-extern crate log;
-
-use std::sync::mpsc::{channel, Sender, Receiver};
-use std::thread;
-
-pub struct ChannelLogger {
-    tx: Sender<String>
-}
-
-impl ChannelLogger {
-    pub fn new() -> (Box<ChannelLogger>, Receiver<String>) {
-        let (tx, rx) = channel();
-        (box ChannelLogger { tx: tx }, rx)
-    }
-}
-
-impl log::Logger for ChannelLogger {
-    fn log(&mut self, record: &log::LogRecord) {
-        self.tx.send(format!("{}", record.args)).unwrap();
-    }
-}
-
-pub fn main() {
-    let (logger, rx) = ChannelLogger::new();
-
-    let t = thread::spawn(move|| {
-        log::set_logger(logger);
-
-        info!("foo");
-        info!("bar");
-        info!("foo bar");
-        info!("bar foo");
-    });
-
-    assert_eq!(rx.recv().unwrap(), "foo");
-    assert_eq!(rx.recv().unwrap(), "foo bar");
-    assert_eq!(rx.recv().unwrap(), "bar foo");
-    assert!(rx.recv().is_err());
-
-    t.join();
-}
diff --git a/src/test/run-pass-fulldeps/switch-stdout.rs b/src/test/run-pass-fulldeps/switch-stdout.rs
new file mode 100644 (file)
index 0000000..4542e27
--- /dev/null
@@ -0,0 +1,64 @@
+// 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.
+
+#![feature(rustc_private)]
+
+extern crate rustc_back;
+
+use std::fs::File;
+use std::io::{Read, Write};
+
+use rustc_back::tempdir::TempDir;
+
+#[cfg(unix)]
+fn switch_stdout_to(file: File) {
+    use std::os::unix::prelude::*;
+
+    extern {
+        fn dup2(old: i32, new: i32) -> i32;
+    }
+
+    unsafe {
+        assert_eq!(dup2(file.as_raw_fd(), 1), 1);
+    }
+}
+
+#[cfg(windows)]
+fn switch_stdout_to(file: File) {
+    use std::os::windows::prelude::*;
+
+    extern "system" {
+        fn SetStdHandle(nStdHandle: u32, handle: *mut u8) -> i32;
+    }
+
+    const STD_OUTPUT_HANDLE: u32 = (-11i32) as u32;
+
+    unsafe {
+        let rc = SetStdHandle(STD_OUTPUT_HANDLE,
+                              file.into_raw_handle() as *mut _);
+        assert!(rc != 0);
+    }
+}
+
+fn main() {
+    let td = TempDir::new("foo").unwrap();
+    let path = td.path().join("bar");
+    let f = File::create(&path).unwrap();
+
+    println!("foo");
+    std::io::stdout().flush().unwrap();
+    switch_stdout_to(f);
+    println!("bar");
+    std::io::stdout().flush().unwrap();
+
+    let mut contents = String::new();
+    File::open(&path).unwrap().read_to_string(&mut contents).unwrap();
+    assert_eq!(contents, "bar\n");
+}
diff --git a/src/test/run-pass/auxiliary/llvm_pr32379.rs b/src/test/run-pass/auxiliary/llvm_pr32379.rs
new file mode 100644 (file)
index 0000000..a7b15bd
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 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 fn pr32379(mut data: u64, f1: bool, f2: bool) -> u64 {
+    if f1 { data &= !2; }
+    if f2 { data |= 2; }
+    data
+}
index b335e20f91d932df7a127b37a6eca2e56c4b73f8..7da33be7a57daf19faa1a47bcad1fc9f4be345a4 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// exec-env:RUST_LOG=conditional-debug-macro-on=4
-
 pub fn main() {
     // exits early if println! evaluates its arguments, otherwise it
     // will hit the panic.
diff --git a/src/test/run-pass/inference-changes-39485.rs b/src/test/run-pass/inference-changes-39485.rs
deleted file mode 100644 (file)
index 193c66b..0000000
+++ /dev/null
@@ -1,19 +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.
-
-fn g() {
-    &panic!()
-}
-
-fn f() -> isize {
-    (return 1, return 2)
-}
-
-fn main() {}
index f77888c29554db81c6ab7ba84eb6d245d9712403..0baaaac26768571ca91c8d118794d0bb2a4d5c50 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![allow(unused_features)]
-#![allow(unreachable_code)]
+#![allow(unknown_features)]
 #![feature(box_syntax)]
 
 #[derive(PartialEq, Debug)]
@@ -29,14 +28,14 @@ struct Foo {
 }
 
 fn foo() -> Result<Foo, isize> {
-    return Ok::<Foo, isize>(Foo {
+    return Ok(Foo {
         x: Bar { x: 22 },
         a: return Err(32)
     });
 }
 
 fn baz() -> Result<Foo, isize> {
-    Ok::<Foo, isize>(Foo {
+    Ok(Foo {
         x: Bar { x: 22 },
         a: return Err(32)
     })
index 2be04551cb92f82244a8fe1c16f2d730d6e65ab7..71a19d98190548f8ba068b968eeff75895b25d92 100644 (file)
@@ -8,26 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// DON'T REENABLE THIS UNLESS YOU'VE ACTUALLY FIXED THE UNDERLYING ISSUE
-// ignore-android seems to block forever
+#![deny(warnings)]
 
-// ignore-emscripten no threads support
+fn foo<F: FnOnce()>(_f: F) { }
 
-#![forbid(warnings)]
-
-// Pretty printing tests complain about `use std::predule::*`
-#![allow(unused_imports)]
-
-// A var moved into a proc, that has a mutable loan path should
-// not trigger a misleading unused_mut warning.
-
-use std::io::prelude::*;
-use std::thread;
-
-pub fn main() {
-    let mut stdin = std::io::stdin();
-    thread::spawn(move|| {
-        let mut v = Vec::new();
-        let _ = stdin.read_to_end(&mut v);
-    }).join().ok().unwrap();
+fn main() {
+    let mut var = Vec::new();;
+    foo(move|| {
+        var.push(1);
+    });
 }
diff --git a/src/test/run-pass/issue-39984.rs b/src/test/run-pass/issue-39984.rs
new file mode 100644 (file)
index 0000000..a0019e7
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2016 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 issue #39984.
+//
+// The key here is that the error type of the `Ok` call ought to be
+// constrained to `String`, even though it is dead-code.
+
+fn main() {}
+
+fn t() -> Result<(), String> {
+    return Err("".into());
+    Ok(())
+}
diff --git a/src/test/run-pass/issue-40770.rs b/src/test/run-pass/issue-40770.rs
new file mode 100644 (file)
index 0000000..599d0b2
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 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.
+
+macro_rules! m {
+    ($e:expr) => {
+        macro_rules! n { () => { $e } }
+    }
+}
+
+fn main() {
+    m!(foo!());
+}
diff --git a/src/test/run-pass/llvm-pr32379.rs b/src/test/run-pass/llvm-pr32379.rs
new file mode 100644 (file)
index 0000000..5625e81
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2017 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:llvm_pr32379.rs
+
+// LLVM PR #32379 (https://bugs.llvm.org/show_bug.cgi?id=32379), which
+// applies to upstream LLVM 3.9.1, is known to cause rustc itself to be
+// miscompiled on ARM (Rust issue #40593). Because cross builds don't test
+// our *compiler* on ARM, have a test for the miscompilation directly.
+
+extern crate llvm_pr32379;
+
+pub fn main() {
+    let val = llvm_pr32379::pr32379(2, false, false);
+    assert_eq!(val, 2);
+}
index 8e008c639b30eb6cc00d1977f5ce1f2a6fa156be..9a6ea2272fea7c5ca453595a1c0f3343eed99212 100644 (file)
@@ -11,8 +11,6 @@
 // A regression test extracted from image-0.3.11. The point of
 // failure was in `index_colors` below.
 
-#![allow(unused)]
-
 use std::ops::{Deref, DerefMut};
 
 #[derive(Copy, Clone)]
@@ -94,7 +92,7 @@ pub fn index_colors<Pix>(image: &ImageBuffer<Pix, Vec<u8>>)
                          -> ImageBuffer<Luma<u8>, Vec<u8>>
 where Pix: Pixel<Subpixel=u8> + 'static,
 {
-    let mut indices: ImageBuffer<Luma<u8>, Vec<u8>> = loop { };
+    let mut indices: ImageBuffer<_,Vec<_>> = loop { };
     for (pixel, idx) in image.pixels().zip(indices.pixels_mut()) {
         // failured occurred here ^^ because we were requiring that we
         // could project Pixel or Subpixel from `T_indices` (type of
index edbfd72df615fd49723fa6fd6715f38a3a64419c..7bb69caa1024af4c060687c83e5bc9ba41a59a5e 100644 (file)
@@ -2,7 +2,7 @@ error: cannot borrow immutable local variable `x` as mutable
    --> $DIR/huge_multispan_highlight.rs:100:18
     |
 12  |     let x = "foo";
-    |         - use `mut x` here to make mutable
+    |         - consider changing this to `mut x`
 ...
 100 |     let y = &mut x;
     |                  ^ cannot borrow mutably
index 4873acf551ebc0c1c7f31c0117eb9e3c66269e61..60fa06d314ff7bcf7da74a8c2f8a7fa53f1750d7 100644 (file)
@@ -10,6 +10,8 @@ error: cannot borrow immutable argument `self` as mutable
 error: cannot borrow immutable argument `self` as mutable
   --> $DIR/issue-31424.rs:23:15
    |
+22 |     fn bar(self: &mut Self) {
+   |            ---- consider changing this to `mut self`
 23 |         (&mut self).bar();
    |               ^^^^ cannot borrow mutably
 
diff --git a/src/test/ui/did_you_mean/issue-35937.rs b/src/test/ui/did_you_mean/issue-35937.rs
new file mode 100644 (file)
index 0000000..9ec8728
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2017 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 {
+    pub v: Vec<String>
+}
+
+fn main() {
+    let f = Foo { v: Vec::new() };
+    f.v.push("cat".to_string());
+}
+
+
+struct S {
+    x: i32,
+}
+fn foo() {
+    let s = S { x: 42 };
+    s.x += 1;
+}
+
+fn bar(s: S) {
+    s.x += 1;
+}
diff --git a/src/test/ui/did_you_mean/issue-35937.stderr b/src/test/ui/did_you_mean/issue-35937.stderr
new file mode 100644 (file)
index 0000000..bea3d12
--- /dev/null
@@ -0,0 +1,26 @@
+error: cannot borrow immutable field `f.v` as mutable
+  --> $DIR/issue-35937.rs:17:5
+   |
+16 |     let f = Foo { v: Vec::new() };
+   |         - consider changing this to `mut f`
+17 |     f.v.push("cat".to_string());
+   |     ^^^ cannot mutably borrow immutable field
+
+error: cannot assign to immutable field `s.x`
+  --> $DIR/issue-35937.rs:26:5
+   |
+25 |     let s = S { x: 42 };
+   |         - consider changing this to `mut s`
+26 |     s.x += 1;
+   |     ^^^^^^^^ cannot mutably borrow immutable field
+
+error: cannot assign to immutable field `s.x`
+  --> $DIR/issue-35937.rs:30:5
+   |
+29 | fn bar(s: S) {
+   |        - consider changing this to `mut s`
+30 |     s.x += 1;
+   |     ^^^^^^^^ cannot mutably borrow immutable field
+
+error: aborting due to 3 previous errors
+
index fdaf0cd44d9d4626900657bba701823726b49b76..855feaf7d2d5e6931e58b0081234dfb866e4a70a 100644 (file)
@@ -2,7 +2,7 @@ error: cannot borrow immutable borrowed content `*self.s` as mutable
   --> $DIR/issue-38147-2.rs:17:9
    |
 12 |     s: &'a String
-   |     ------------- use `&'a mut String` here to make mutable
+   |        ---------- use `&'a mut String` here to make mutable
 ...
 17 |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
index d2280fa561bdeb12cf049731f2c2f7c83104692d..d970d078df8d96c395d088d5a32b442df964ee88 100644 (file)
@@ -2,10 +2,8 @@ error: cannot borrow immutable borrowed content `*self.s` as mutable
   --> $DIR/issue-38147-3.rs:17:9
    |
 12 |     s: &'a String
-   |     ------------- use `&'a mut String` here to make mutable
+   |        ---------- use `&'a mut String` here to make mutable
 ...
-16 |     fn f(&self) {
-   |          ----- use `&mut self` here to make mutable
 17 |         self.s.push('x');
    |         ^^^^^^ cannot borrow as mutable
 
index bcdafefa2472b370ef466afa6e8f70490ef1d297..6331fc5771fcbb218694944e4034efe72e3cdad3 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-enum X {
+pub enum X {
     Y
 }
 
-struct Z {
+pub struct Z {
     x: X
 }
 
@@ -20,3 +20,34 @@ fn main() {
     let z = Z { x: X::Y };
     let _ = &mut z.x;
 }
+
+impl Z {
+    fn foo<'z>(&'z self) {
+        let _ = &mut self.x;
+    }
+
+    fn foo1(&self, other: &Z) {
+        let _ = &mut self.x;
+        let _ = &mut other.x;
+    }
+
+    fn foo2<'a>(&'a self, other: &Z) {
+        let _ = &mut self.x;
+        let _ = &mut other.x;
+    }
+
+    fn foo3<'a>(self: &'a Self, other: &Z) {
+        let _ = &mut self.x;
+        let _ = &mut other.x;
+    }
+
+    fn foo4(other: &Z) {
+        let _ = &mut other.x;
+    }
+
+}
+
+pub fn with_arg(z: Z, w: &Z) {
+    let _ = &mut z.x;
+    let _ = &mut w.x;
+}
index 7f124e6d34d354e0161ec23143d3b28050524409..e1e229a8b05725acb48415d4dc01a566cc60fab4 100644 (file)
@@ -6,5 +6,89 @@ error: cannot borrow immutable field `z.x` as mutable
 21 |     let _ = &mut z.x;
    |                  ^^^ cannot mutably borrow immutable field
 
-error: aborting due to previous error
+error: cannot borrow immutable field `self.x` as mutable
+  --> $DIR/issue-39544.rs:26:22
+   |
+25 |     fn foo<'z>(&'z self) {
+   |                -------- use `&'z mut self` here to make mutable
+26 |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `self.x` as mutable
+  --> $DIR/issue-39544.rs:30:22
+   |
+29 |     fn foo1(&self, other: &Z) {
+   |             ----- use `&mut self` here to make mutable
+30 |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `other.x` as mutable
+  --> $DIR/issue-39544.rs:31:22
+   |
+29 |     fn foo1(&self, other: &Z) {
+   |                           -- use `&mut Z` here to make mutable
+30 |         let _ = &mut self.x;
+31 |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `self.x` as mutable
+  --> $DIR/issue-39544.rs:35:22
+   |
+34 |     fn foo2<'a>(&'a self, other: &Z) {
+   |                 -------- use `&'a mut self` here to make mutable
+35 |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `other.x` as mutable
+  --> $DIR/issue-39544.rs:36:22
+   |
+34 |     fn foo2<'a>(&'a self, other: &Z) {
+   |                                  -- use `&mut Z` here to make mutable
+35 |         let _ = &mut self.x;
+36 |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `self.x` as mutable
+  --> $DIR/issue-39544.rs:40:22
+   |
+39 |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                       -------- use `&'a mut Self` here to make mutable
+40 |         let _ = &mut self.x;
+   |                      ^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `other.x` as mutable
+  --> $DIR/issue-39544.rs:41:22
+   |
+39 |     fn foo3<'a>(self: &'a Self, other: &Z) {
+   |                                        -- use `&mut Z` here to make mutable
+40 |         let _ = &mut self.x;
+41 |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `other.x` as mutable
+  --> $DIR/issue-39544.rs:45:22
+   |
+44 |     fn foo4(other: &Z) {
+   |                    -- use `&mut Z` here to make mutable
+45 |         let _ = &mut other.x;
+   |                      ^^^^^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `z.x` as mutable
+  --> $DIR/issue-39544.rs:51:18
+   |
+50 | pub fn with_arg(z: Z, w: &Z) {
+   |                 - consider changing this to `mut z`
+51 |     let _ = &mut z.x;
+   |                  ^^^ cannot mutably borrow immutable field
+
+error: cannot borrow immutable field `w.x` as mutable
+  --> $DIR/issue-39544.rs:52:18
+   |
+50 | pub fn with_arg(z: Z, w: &Z) {
+   |                          -- use `&mut Z` here to make mutable
+51 |     let _ = &mut z.x;
+52 |     let _ = &mut w.x;
+   |                  ^^^ cannot mutably borrow immutable field
+
+error: aborting due to 11 previous errors
 
diff --git a/src/test/ui/did_you_mean/issue-40823.rs b/src/test/ui/did_you_mean/issue-40823.rs
new file mode 100644 (file)
index 0000000..f4ae325
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2017 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 mut buf = &[1, 2, 3, 4];
+    buf.iter_mut();
+}
diff --git a/src/test/ui/did_you_mean/issue-40823.stderr b/src/test/ui/did_you_mean/issue-40823.stderr
new file mode 100644 (file)
index 0000000..8e77ebd
--- /dev/null
@@ -0,0 +1,8 @@
+error: cannot borrow immutable borrowed content `*buf` as mutable
+  --> $DIR/issue-40823.rs:13:5
+   |
+13 |     buf.iter_mut();
+   |     ^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs
new file mode 100644 (file)
index 0000000..1351431
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 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(pub_restricted)]
+
+pub(crate) () fn foo() {}
diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr
new file mode 100644 (file)
index 0000000..470e833
--- /dev/null
@@ -0,0 +1,8 @@
+error: unmatched visibility `pub`
+  --> $DIR/pub-restricted-error-fn.rs:13:10
+   |
+13 | pub(crate) () fn foo() {}
+   |          ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted-error.rs b/src/test/ui/pub/pub-restricted-error.rs
new file mode 100644 (file)
index 0000000..99af031
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 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(pub_restricted)]
+
+struct Bar(pub(()));
+
+struct Foo {
+    pub(crate) () foo: usize,
+}
+
+
diff --git a/src/test/ui/pub/pub-restricted-error.stderr b/src/test/ui/pub/pub-restricted-error.stderr
new file mode 100644 (file)
index 0000000..b8b4c80
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected identifier, found `(`
+  --> $DIR/pub-restricted-error.rs:16:16
+   |
+16 |     pub(crate) () foo: usize,
+   |                ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted-non-path.rs b/src/test/ui/pub/pub-restricted-non-path.rs
new file mode 100644 (file)
index 0000000..3f74285
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 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(pub_restricted)]
+
+pub (.) fn afn() {}
+
+fn main() {}
diff --git a/src/test/ui/pub/pub-restricted-non-path.stderr b/src/test/ui/pub/pub-restricted-non-path.stderr
new file mode 100644 (file)
index 0000000..ebfccc4
--- /dev/null
@@ -0,0 +1,8 @@
+error: expected identifier, found `.`
+  --> $DIR/pub-restricted-non-path.rs:13:6
+   |
+13 | pub (.) fn afn() {}
+   |      ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/pub/pub-restricted.rs b/src/test/ui/pub/pub-restricted.rs
new file mode 100644 (file)
index 0000000..48e487f
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2017 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(pub_restricted)]
+
+mod a {}
+
+pub (a) fn afn() {}
+pub (b) fn bfn() {}
+pub fn privfn() {}
+mod x {
+    mod y {
+        pub (in x) fn foo() {}
+        pub (super) fn bar() {}
+        pub (crate) fn qux() {}
+    }
+}
+
+mod y {
+    struct Foo {
+        pub (crate) c: usize,
+        pub (super) s: usize,
+        valid_private: usize,
+        pub (in y) valid_in_x: usize,
+        pub (a) invalid: usize,
+        pub (in x) non_parent_invalid: usize,
+    }
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/ui/pub/pub-restricted.stderr b/src/test/ui/pub/pub-restricted.stderr
new file mode 100644 (file)
index 0000000..5bc230e
--- /dev/null
@@ -0,0 +1,47 @@
+error: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:15:5
+   |
+15 | pub (a) fn afn() {}
+   |     ^^^
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+help: to make this visible only to module `a`, add `in` before the path:
+   | pub (in a) fn afn() {}
+
+error: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:16:5
+   |
+16 | pub (b) fn bfn() {}
+   |     ^^^
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+help: to make this visible only to module `b`, add `in` before the path:
+   | pub (in b) fn bfn() {}
+
+error: incorrect visibility restriction
+  --> $DIR/pub-restricted.rs:32:13
+   |
+32 |         pub (a) invalid: usize,
+   |             ^^^
+   |
+   = help: some possible visibility restrictions are:
+           `pub(crate)`: visible only on the current crate
+           `pub(super)`: visible only in the current module's parent
+           `pub(in path::to::module)`: visible only on the specified path
+help: to make this visible only to module `a`, add `in` before the path:
+   |         pub (in a) invalid: usize,
+
+error: visibilities can only be restricted to ancestor modules
+  --> $DIR/pub-restricted.rs:33:17
+   |
+33 |         pub (in x) non_parent_invalid: usize,
+   |                 ^
+
+error: aborting due to 4 previous errors
+
index b83a6aaebf3232026db99be66a7af5d9ebccf1e6..edf1635a6b84fe7f1b0f187bf865cc4fccc9e787 100644 (file)
@@ -2,7 +2,7 @@ error: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:63:24
    |
 62 | fn deref_mut_field1(x: Own<Point>) {
-   |                     - use `mut x` here to make mutable
+   |                     - consider changing this to `mut x`
 63 |     let __isize = &mut x.y; //~ ERROR cannot borrow
    |                        ^ cannot borrow mutably
 
@@ -28,7 +28,7 @@ error: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:98:5
    |
 97 | fn assign_field1<'a>(x: Own<Point>) {
-   |                      - use `mut x` here to make mutable
+   |                      - consider changing this to `mut x`
 98 |     x.y = 3; //~ ERROR cannot borrow
    |     ^ cannot borrow mutably
 
@@ -54,7 +54,7 @@ error: cannot borrow immutable argument `x` as mutable
    --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:119:5
     |
 118 | fn deref_mut_method1(x: Own<Point>) {
-    |                      - use `mut x` here to make mutable
+    |                      - consider changing this to `mut x`
 119 |     x.set(0, 0); //~ ERROR cannot borrow
     |     ^ cannot borrow mutably
 
@@ -70,7 +70,7 @@ error: cannot borrow immutable argument `x` as mutable
    --> $DIR/borrowck-borrow-overloaded-auto-deref-mut.rs:139:6
     |
 138 | fn assign_method1<'a>(x: Own<Point>) {
-    |                       - use `mut x` here to make mutable
+    |                       - consider changing this to `mut x`
 139 |     *x.y_mut() = 3; //~ ERROR cannot borrow
     |      ^ cannot borrow mutably
 
index af954a4d7924f1bada77d8e0be10738ad34af0dc..2ec01168721798684e360cd3a54fca6aa53868dc 100644 (file)
@@ -2,7 +2,7 @@ error: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:39:25
    |
 38 | fn deref_mut1(x: Own<isize>) {
-   |               - use `mut x` here to make mutable
+   |               - consider changing this to `mut x`
 39 |     let __isize = &mut *x; //~ ERROR cannot borrow
    |                         ^ cannot borrow mutably
 
@@ -18,7 +18,7 @@ error: cannot borrow immutable argument `x` as mutable
   --> $DIR/borrowck-borrow-overloaded-deref-mut.rs:59:6
    |
 58 | fn assign1<'a>(x: Own<isize>) {
-   |                - use `mut x` here to make mutable
+   |                - consider changing this to `mut x`
 59 |     *x = 3; //~ ERROR cannot borrow
    |      ^ cannot borrow mutably
 
index 4ef1cb9c239e4ba3fe0ee5ce5a944714c8689ed4..0abdbdc3a21b58f1560763529439ac66aeb5ca35 100644 (file)
@@ -10,6 +10,9 @@ error: cannot borrow immutable borrowed content `*x` as mutable
 error: cannot borrow immutable `Box` content `*x` as mutable
   --> $DIR/borrowck-object-mutability.rs:29:5
    |
+27 | fn owned_receiver(x: Box<Foo>) {
+   |                   - consider changing this to `mut x`
+28 |     x.borrowed();
 29 |     x.borrowed_mut(); //~ ERROR cannot borrow
    |     ^ cannot borrow as mutable
 
index 1fc98a78a7c473c73148174942d0e62f82bb9fda..7530b65a9b7c4fc383dc24fe94a6426e81593d66 100644 (file)
@@ -5,6 +5,6 @@ version = "0.0.0"
 
 [dependencies]
 log = "0.3"
-env_logger = { version = "0.3.5", default-features = false }
+env_logger = { version = "0.4", default-features = false }
 rustc-serialize = "0.3"
 filetime = "0.1"
index 7e4f40af9cea6c37bee97afe8f09d587e05df734..3d8f2296236a2014c6c60df5657c7ab5fd522b26 100644 (file)
@@ -57,9 +57,10 @@ pub fn run(lib_path: &str,
 
     let mut cmd = Command::new(prog);
     cmd.args(args)
-        .stdin(Stdio::piped())
         .stdout(Stdio::piped())
-        .stderr(Stdio::piped());
+        .stderr(Stdio::piped())
+        .stdin(Stdio::piped());
+
     add_target_env(&mut cmd, lib_path, aux_path);
     for (key, val) in env {
         cmd.env(&key, &val);
index e33df0dfbc8dec5cf344341d76546138dc15e39a..1d4f2c60d544f6ea05366167e93ba0aed74bc959 100644 (file)
@@ -24,7 +24,7 @@
 
 use syntax::diagnostics::metadata::{get_metadata_dir, ErrorMetadataMap, ErrorMetadata};
 
-use rustdoc::html::markdown::{Markdown, PLAYGROUND};
+use rustdoc::html::markdown::{Markdown, MarkdownOutputStyle, PLAYGROUND};
 use rustc_serialize::json;
 
 enum OutputFormat {
@@ -100,7 +100,7 @@ fn error_code_block(&self, output: &mut Write, info: &ErrorMetadata,
 
         // Description rendered as markdown.
         match info.description {
-            Some(ref desc) => write!(output, "{}", Markdown(desc))?,
+            Some(ref desc) => write!(output, "{}", Markdown(desc, MarkdownOutputStyle::Fancy))?,
             None => write!(output, "<p>No description.</p>\n")?,
         }