]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #40814 - abonander:issue_39436, r=jseyfried
authorCorey Farwell <coreyf@rwell.org>
Wed, 29 Mar 2017 20:53:30 +0000 (16:53 -0400)
committerGitHub <noreply@github.com>
Wed, 29 Mar 2017 20:53:30 +0000 (16:53 -0400)
Rustdoc: memoize `pub use`-reexported macros so they don't appear twice in docs

Closes #39436

Preserves existing behavior for `#[macro_reexport]`. `pub use`'d macros are shown as reexports unless inlined, and also correctly obey `#[doc(hidden)]`.

r? @jseyfried

cc @SergioBenitez

274 files changed:
.gitmodules
.travis.yml
appveyor.yml
cargo
src/Cargo.lock
src/bootstrap/bin/rustdoc.rs
src/bootstrap/check.rs
src/ci/docker/run.sh
src/ci/init_repo.sh [new file with mode: 0755]
src/ci/shared.sh
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.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/linked_list.rs
src/libcollections/str.rs
src/libcollections/vec.rs
src/libcollectionstest/vec.rs
src/libcore/char.rs
src/libcore/cmp.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/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/dep_tracking_map.rs
src/librustc/diagnostics.rs
src/librustc/hir/lowering.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/mem_categorization.rs
src/librustc/middle/stability.rs
src/librustc/ty/adjustment.rs
src/librustc/ty/error.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/structural_impls.rs
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/_match.rs
src/librustc_const_eval/check_match.rs
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/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_incremental/persist/file_format.rs
src/librustc_lint/bad_style.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_llvm/build.rs
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_plugin/load.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_save_analysis/csv_dumper.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
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/monomorphize.rs
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/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/libstd/ascii.rs
src/libstd/io/cursor.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/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/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/rt/hoedown [deleted submodule]
src/rustc/rustdoc.rs
src/test/compile-fail/augmented-assignments.rs
src/test/compile-fail/borrowck/borrowck-issue-14498.rs
src/test/compile-fail/issue-33819.rs
src/test/compile-fail/issue-40000.rs [new file with mode: 0644]
src/test/compile-fail/issue-40845.rs [new file with mode: 0644]
src/test/compile-fail/mut-suggestion.rs
src/test/run-pass-fulldeps/switch-stdout.rs [new file with mode: 0644]
src/test/run-pass/issue-40770.rs [new file with mode: 0644]
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/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/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 148b59e8c64ebc5209ab68710d6f331001ca416a..83e837e2d7690afd4e6458442b4d1545a6b937d4 100644 (file)
@@ -133,13 +133,14 @@ before_script:
 script:
   - >
       if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
-          echo skipping, not a full build;
-      elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
-          travis_retry stamp sh -c 'git submodule deinit -f . && git submodule update --init' &&
-          stamp src/ci/run.sh;
+          echo skipping, not a full build
       else
-          travis_retry stamp sh -c 'git submodule deinit -f . && git submodule update --init' &&
-          stamp src/ci/docker/run.sh $IMAGE;
+          stamp src/ci/init_repo.sh . "$HOME/rustsrc" &&
+          if [ "$TRAVIS_OS_NAME" = "osx" ]; then
+              stamp src/ci/run.sh;
+          else
+              stamp src/ci/docker/run.sh $IMAGE;
+          fi
       fi
 
 after_success:
@@ -169,13 +170,21 @@ after_failure:
   - 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)
+# https://github.com/travis-ci/travis-ci/issues/4472
 before_cache:
   - docker history -q rust-ci |
     grep -v missing |
     xargs docker save |
     gzip > $HOME/docker/rust-ci.tar.gz
+  - if [ ! -f $HOME/rustsrc/cache_valid1 ]; then
+        echo "WARNING rustsrc cache was invalid when saving";
+        rm -rf $HOME/rustsrc && mkdir $HOME/rustsrc;
+    fi
 before_install:
   - zcat $HOME/docker/rust-ci.tar.gz | docker load || true
+  - mkdir -p $HOME/rustsrc
 
 notifications:
   email: false
@@ -183,6 +192,7 @@ notifications:
 cache:
   directories:
     - $HOME/docker
+    - $HOME/rustsrc
 
 before_deploy:
   - mkdir -p deploy/$TRAVIS_COMMIT
index 0f4d053b6cfeb30260ef50096fc5a8d647c1a13a..fa599a00c4de349144f9acb15252afd477fdb533 100644 (file)
@@ -46,13 +46,13 @@ environment:
     RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-ninja
     SCRIPT: python x.py test
     MINGW_URL: https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror
-    MINGW_ARCHIVE: i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z
+    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/rust-ci-mirror
-    MINGW_ARCHIVE: x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z
+    MINGW_ARCHIVE: x86_64-6.2.0-release-win32-seh-rt_v5-rev1.7z
     MINGW_DIR: mingw64
 
   # 32/64 bit MSVC and GNU deployment
@@ -71,14 +71,14 @@ environment:
     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/rust-ci-mirror
-    MINGW_ARCHIVE: i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z
+    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/rust-ci-mirror
-    MINGW_ARCHIVE: x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z
+    MINGW_ARCHIVE: x86_64-6.2.0-release-win32-seh-rt_v5-rev1.7z
     MINGW_DIR: mingw64
     DEPLOY: 1
 
@@ -141,7 +141,8 @@ install:
   - set SCCACHE_ERROR_LOG=%CD%/sccache.log
 
 test_script:
-  - appveyor-retry sh -c 'git submodule deinit -f . && git submodule update --init'
+  - mkdir C:\cache\rustsrc
+  - sh src/ci/init_repo.sh . /c/cache/rustsrc
   - set SRC=.
   - set NO_CCACHE=1
   - sh src/ci/run.sh
@@ -150,6 +151,7 @@ on_failure:
   - cat %CD%/sccache.log
 
 cache:
+  - C:\cache\rustsrc
   - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
   - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
   - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
diff --git a/cargo b/cargo
index c995e9eb5acf3976ae8674a0dc6d9e958053d9fd..4e95c6b41eca3388f54dd5f7787366ad2df637b5 160000 (submodule)
--- a/cargo
+++ b/cargo
@@ -1 +1 @@
-Subproject commit c995e9eb5acf3976ae8674a0dc6d9e958053d9fd
+Subproject commit 4e95c6b41eca3388f54dd5f7787366ad2df637b5
index a0b47f4f0b2bb575be40d6eefd1801047a5969eb..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,7 +140,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)",
 ]
 
 [[package]]
@@ -188,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]]
@@ -197,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]]
@@ -215,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)",
@@ -243,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]]
@@ -272,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)",
@@ -358,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"
@@ -383,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)",
@@ -416,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)",
 ]
 
@@ -593,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",
 ]
 
@@ -770,8 +778,9 @@ dependencies = [
  "arena 0.0.0",
  "build_helper 0.1.0",
  "env_logger 0.4.2 (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)",
  "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",
@@ -818,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",
@@ -978,22 +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.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"
@@ -1002,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 c418d427b15b3ae6a2c294caad4957b27dd2a779..71a4bfae3caf9424b930bf81aeba9a26b15e1a7e 100755 (executable)
@@ -57,6 +57,7 @@ exec docker \
   --env DEPLOY_ALT=$DEPLOY_ALT \
   --env LOCAL_USER_ID=`id -u` \
   --volume "$HOME/.cargo:/cargo" \
+  --volume "$HOME/rustsrc:$HOME/rustsrc" \
   --privileged \
   --rm \
   rust-ci \
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
new file mode 100755 (executable)
index 0000000..4e22907
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+# 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.
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+set -o xtrace
+
+ci_dir=$(cd $(dirname $0) && pwd)
+. "$ci_dir/shared.sh"
+
+REPO_DIR="$1"
+CACHE_DIR="$2"
+
+cache_src_dir="$CACHE_DIR/src"
+# If the layout of the cache directory changes, bump the number here
+# (and anywhere else this file is referenced) so the cache is wiped
+cache_valid_file="$CACHE_DIR/cache_valid1"
+
+if [ ! -d "$REPO_DIR" -o ! -d "$REPO_DIR/.git" ]; then
+    echo "Error: $REPO_DIR does not exist or is not a git repo"
+    exit 1
+fi
+cd $REPO_DIR
+if [ ! -d "$CACHE_DIR" ]; then
+    echo "Error: $CACHE_DIR does not exist or is not an absolute path"
+    exit 1
+fi
+
+# Wipe the cache if it's not valid, or mark it as invalid while we update it
+if [ ! -f "$cache_valid_file" ]; then
+    rm -rf "$CACHE_DIR" && mkdir "$CACHE_DIR"
+else
+    rm "$cache_valid_file"
+fi
+
+# Update the cache (a pristine copy of the rust source master)
+if [ ! -d "$cache_src_dir/.git" ]; then
+    retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
+        git clone https://github.com/rust-lang/rust.git $cache_src_dir"
+fi
+retry sh -c "cd $cache_src_dir && git reset --hard && git pull"
+retry sh -c "cd $cache_src_dir && \
+    git submodule deinit -f . && git submodule sync && git submodule update --init"
+
+# Cache was updated without errors, mark it as valid
+touch "$cache_valid_file"
+
+# Update the submodules of the repo we're in, using the pristine repo as
+# a cache for any object files
+# No, `git submodule foreach` won't work:
+# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
+modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
+for module in $modules; do
+    if [ ! -d "$cache_src_dir/$module" ]; then
+        echo "WARNING: $module not found in pristine repo"
+        retry sh -c "git submodule deinit -f $module && git submodule update --init $module"
+        continue
+    fi
+    retry sh -c "git submodule deinit -f $module && \
+        git submodule update --init --reference $cache_src_dir/$module $module"
+done
index ecd9b7e98a4823b0e13a9da3b1de6e2acf49b726..f2e13fc73ae4778930fcd635a8c85f21a9e91d7a 100644 (file)
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/false
 # 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.
@@ -9,13 +9,16 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+# This file is intended to be sourced with `. shared.sh` or
+# `source shared.sh`, hence the invalid shebang and not being
+# marked as an executable file in git.
+
 # See http://unix.stackexchange.com/questions/82598
 function retry {
+  echo "Attempting with retry:" "$@"
   local n=1
   local max=5
-  local delay=15
   while true; do
-    echo "Attempting:" "$@"
     "$@" && break || {
       if [[ $n -lt $max ]]; then
         ((n++))
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
+
+------------------------
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 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 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 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 307e4974d9769f6a1762c6c32951b6e88866674d..3612ee65bca0dba78c5ad3fd35e51bbba3b3340e 100644 (file)
@@ -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
index 5ee9258852b0b8bb75892e79ff02403afa68ec33..5aea2bcaa4f5c5fd5f4979df6ddb5183f4a9dcc5 100644 (file)
@@ -75,7 +75,6 @@ pub enum DepNode<D: Clone + Debug> {
     CoherenceCheckImpl(D),
     CoherenceOverlapCheck(D),
     CoherenceOverlapCheckSpecial(D),
-    CoherenceOverlapInherentCheck(D),
     CoherenceOrphanCheck(D),
     Variance,
     WfCheck(D),
@@ -252,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 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 6ca0c971ea4979951919b7e1e6e388e443acb8b9..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
+                }
+            })
         })
     }
 
index f4f2f4cf9211b532aa19a18001802a763a17225b..27fa7487270885968948620ca571e64f7d849762 100644 (file)
@@ -1383,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 d35f965e2ffd767332f88977af762b6db35d14de..20bf241a99906e3afe1a5196fb29718bc88f9cc1 100644 (file)
@@ -40,7 +40,6 @@
 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;
@@ -485,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 {
@@ -496,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));
index 56bbc0480c30afb44237f67ad276edb96ce76630..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>;
@@ -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![] }
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 4115b4669f4b20874938c929313f10030c394bb8..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,
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 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 da4e58addd71b08b9d3d5da76f664b80550ac863..4a183191cef29c70c82920b26f1873cf04e37c73 100644 (file)
@@ -13,7 +13,8 @@
 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};
@@ -177,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")
     }
 }
 
@@ -196,6 +203,13 @@ fn describe(_: TyCtxt, _: CrateNum) -> String {
     }
 }
 
+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])*
@@ -375,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
@@ -400,14 +414,24 @@ 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.
@@ -423,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 4283b10ec624fb01bf47458b9a53fb0e8f905c6d..6a4e7db21dd127d2d20bf57cb32a2517e4b1d0d1 100644 (file)
@@ -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;
@@ -2057,8 +2057,8 @@ 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 {
@@ -2348,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) {
@@ -2640,3 +2612,16 @@ pub fn provide(providers: &mut ty::maps::Providers) {
         ..*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 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 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 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 53adc9d95972a00a72e23d531f8d43902d02b3da..4873b21c548740f98480346794ea5abc76309c64 100644 (file)
@@ -258,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
index 68b9f85721ad5de950274ff21fb401610eeb242d..c90dde3a5f6e0232694ae37dec7e11e70c91b446 100644 (file)
@@ -67,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;
@@ -233,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();
@@ -507,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;
@@ -800,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);
         }
@@ -838,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");
     };
@@ -945,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()),
     };
@@ -1084,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") {
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 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 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 42717ec289c34d019bf2b6f1a462b214f39fab59..2b945e0a3afaff2f8e7d8ffe10335be2e719bbea 100644 (file)
@@ -140,7 +140,7 @@ fn main() {
         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);
@@ -173,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") {
index e1255110a83d1e8a80f7743b94fad92df4bcf984..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();
index 17484138ad3a0d26a847df11d15e809742bba62e..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 {
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 a324c166e738d4cea6a2d53aafabeb0bd34f318d..38d774992a55111b8d901b75a5d192730f76ba38 100644 (file)
@@ -693,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)),
                 };
 
@@ -713,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)),
                 };
 
@@ -918,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);
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 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 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 879d8816488b20e8a1e8fc420b4215ee59e986a2..0466e76475da3d1f05069ec0b24edccf45500de3 100644 (file)
@@ -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> {
index 3d6c6896549a4bb8f5996bc7615526b73218f41e..05f30f039c8f0649dd3eaf3bab6fc28c909219ee 100644 (file)
@@ -172,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);
     }
 
@@ -390,7 +389,7 @@ 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;
         }
@@ -410,7 +409,7 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
             }
         };
 
-        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
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 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 f7ca468fddaef037cedac253beac73e9d8841145..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);
@@ -765,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();
@@ -796,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)
@@ -1035,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
@@ -1574,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 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 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 9c62fd486d45a6f7574133a2e5fa387767e27a50..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,
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 1c479ce1d0157beaee792e163f9caff0f8832316..52f5d99838dc7c342047ed4bd0e19e74844e2b2f 100644 (file)
@@ -2,7 +2,6 @@
 authors = ["The Rust Project Developers"]
 name = "rustdoc"
 version = "0.0.0"
-build = "build.rs"
 
 [lib]
 name = "rustdoc"
@@ -26,6 +25,7 @@ rustc_trans = { path = "../librustc_trans" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+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 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 5c94032c6b9cf74df6fd754e13e4bd4b4079892a..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(())
 }
@@ -1871,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,
@@ -2611,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))
@@ -2642,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()) {
@@ -2901,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))?;
         }
     }
 
index 8dd03f6edc4d57cde00ef209a2a30d2ad73b77f5..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",
@@ -48,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
 
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 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 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 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 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 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 649e90599345bf93aa5ee6bc0f7e4e8e3dad75ec..43a9d8c5f787c77bcc993e6f5a701c668e97b95f 100644 (file)
@@ -5151,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 .
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
     }
 }
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 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);
 }
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-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() {}
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
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/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!());
+}
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
+
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 f55667f93c031939c534cd8d79ced66704d71e91..3d8f2296236a2014c6c60df5657c7ab5fd522b26 100644 (file)
@@ -58,24 +58,8 @@ pub fn run(lib_path: &str,
     let mut cmd = Command::new(prog);
     cmd.args(args)
         .stdout(Stdio::piped())
-        .stderr(Stdio::piped());
-
-    // Why oh why do we sometimes make a pipe and sometimes inherit the stdin
-    // stream, well that's an excellent question! In theory it should suffice to
-    // always create a pipe here and be done with it. Unfortunately though
-    // there's apparently something odd with the gdb that comes with gcc 6.3.0
-    // on MinGW. Tracked at rust-lang/rust#40184 when stdin is piped here
-    // (unconditionally) then all gdb tests will fail on MinGW when using gcc
-    // 6.3.0. WHen using an inherited stdin though they happen to all work!
-    //
-    // As to why this fixes the issue, well, I have no idea. If you can remove
-    // this branch and unconditionally use `piped` and it gets past @bors please
-    // feel free to send a PR!
-    if input.is_some() || !cfg!(windows) {
-        cmd.stdin(Stdio::piped());
-    } else {
-        cmd.stdin(Stdio::inherit());
-    }
+        .stderr(Stdio::piped())
+        .stdin(Stdio::piped());
 
     add_target_env(&mut cmd, lib_path, aux_path);
     for (key, val) in env {
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")?,
         }