]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #44562 - eddyb:ugh-rustdoc, r=nikomatsakis
authorTim Neumann <mail@timnn.me>
Sun, 17 Sep 2017 11:19:07 +0000 (13:19 +0200)
committerGitHub <noreply@github.com>
Sun, 17 Sep 2017 11:19:07 +0000 (13:19 +0200)
rustdoc: pretty-print Unevaluated expressions in types.

Fixes #44555.

r? @nikomatsakis

196 files changed:
.gitmodules
.travis.yml
CONTRIBUTING.md
appveyor.yml
fn.rs [deleted file]
src/Cargo.lock
src/Cargo.toml
src/bootstrap/Cargo.toml
src/bootstrap/builder.rs
src/bootstrap/check.rs
src/bootstrap/dist.rs
src/bootstrap/mk/Makefile.in
src/bootstrap/native.rs
src/bootstrap/tool.rs
src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile [new file with mode: 0644]
src/ci/docker/disabled/dist-x86_64-haiku/build-toolchain.sh [new file with mode: 0755]
src/ci/docker/disabled/dist-x86_64-haiku/fetch-packages.sh [new file with mode: 0755]
src/ci/docker/disabled/dist-x86_64-haiku/llvm-config.sh [new file with mode: 0755]
src/ci/docker/run.sh
src/ci/run.sh
src/doc/rustdoc/src/documentation-tests.md
src/liballoc/arc.rs
src/liballoc/btree/set.rs
src/liballoc/macros.rs
src/liballoc/rc.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/liballoc/vec.rs
src/libcompiler_builtins
src/libcore/benches/iter.rs
src/libcore/cell.rs
src/libcore/cmp.rs
src/libcore/intrinsics.rs
src/libcore/iter/mod.rs
src/libcore/lib.rs
src/libcore/mem.rs
src/libcore/nonzero.rs
src/libcore/num/mod.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/sync/atomic.rs
src/libcore/tests/iter.rs
src/libcore/tests/lib.rs
src/librustc/dep_graph/query.rs
src/librustc/hir/lowering.rs
src/librustc/ich/hcx.rs
src/librustc/ich/impls_syntax.rs
src/librustc/infer/error_reporting/different_lifetimes.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/util.rs
src/librustc/infer/mod.rs
src/librustc/lib.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/liveness.rs
src/librustc/middle/stability.rs
src/librustc/mir/mod.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/ty/instance.rs
src/librustc/ty/layout.rs
src/librustc_apfloat/lib.rs
src/librustc_back/target/armv7_linux_androideabi.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_const_eval/lib.rs
src/librustc_const_math/lib.rs
src/librustc_data_structures/bitslice.rs
src/librustc_data_structures/graph/mod.rs
src/librustc_data_structures/indexed_set.rs
src/librustc_data_structures/snapshot_vec.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/fs.rs
src/librustc_incremental/persist/load.rs
src/librustc_incremental/persist/mod.rs
src/librustc_incremental/persist/save.rs
src/librustc_incremental/persist/work_product.rs
src/librustc_lint/unused.rs
src/librustc_metadata/astencode.rs
src/librustc_mir/build/cfg.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/impls/storage_liveness.rs [new file with mode: 0644]
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/diagnostics.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/write.rs
src/librustc_trans/collector.rs
src/librustc_trans/context.rs
src/librustc_trans/declare.rs
src/librustc_trans/glue.rs
src/librustc_trans/lib.rs
src/librustc_trans/meth.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/monomorphize.rs
src/librustc_trans_utils/lib.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/constrained_type_params.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/librustdoc/test.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/fs.rs
src/libstd/lib.rs
src/libstd/net/ip.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/sync/once.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/thread.rs
src/libsyntax/attr.rs
src/libsyntax/diagnostic_list.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax_pos/lib.rs
src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs
src/test/compile-fail/const-call.rs
src/test/compile-fail/const-fn-feature-flags.rs [new file with mode: 0644]
src/test/compile-fail/const-fn-stability-calls.rs [deleted file]
src/test/compile-fail/dropck_trait_cycle_checked.rs
src/test/compile-fail/feature-gate-rustc_const_unstable.rs [new file with mode: 0644]
src/test/compile-fail/functional-struct-update-respects-privacy.rs
src/test/compile-fail/issue-17718-const-borrow.rs
src/test/compile-fail/issue-43733-2.rs
src/test/compile-fail/issue-7364.rs
src/test/compile-fail/lint-unused-mut-variables.rs
src/test/compile-fail/stability-attribute-sanity.rs
src/test/debuginfo/constant-debug-locs.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-pass-valgrind/cast-enum-with-dtor.rs
src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
src/test/run-pass/auxiliary/const_fn_lib.rs
src/test/run-pass/auxiliary/issue-17718-aux.rs
src/test/run-pass/auxiliary/thread-local-extern-static.rs
src/test/run-pass/box-of-array-of-drop-1.rs
src/test/run-pass/box-of-array-of-drop-2.rs
src/test/run-pass/const-fn-cross-crate.rs [deleted file]
src/test/run-pass/const-fn-feature-flags.rs [new file with mode: 0644]
src/test/run-pass/const-fn-stability-calls.rs [new file with mode: 0644]
src/test/run-pass/const-size_of-align_of.rs
src/test/run-pass/generator/match-bindings.rs [new file with mode: 0644]
src/test/run-pass/issue-17718-static-unsafe-interior.rs
src/test/run-pass/issue-17718.rs
src/test/run-pass/issue-21486.rs
src/test/run-pass/issue-26655.rs
src/test/run-pass/issue-27997.rs
src/test/run-pass/nested-vec-3.rs
src/test/run-pass/panic-handler-chain.rs
src/test/run-pass/panic-handler-set-twice.rs
src/test/run-pass/struct-order-of-eval-3.rs
src/test/run-pass/struct-order-of-eval-4.rs
src/test/run-pass/vector-sort-panic-safe.rs
src/test/rustdoc/codeblock-title.rs [new file with mode: 0644]
src/test/rustdoc/const-fn.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr [new file with mode: 0644]
src/test/ui/macros/assert_eq_trailing_comma.stderr
src/test/ui/macros/assert_ne_trailing_comma.stderr
src/test/ui/macros/trace_faulty_macros.rs [new file with mode: 0644]
src/test/ui/macros/trace_faulty_macros.stderr [new file with mode: 0644]
src/test/ui/span/dropck_arr_cycle_checked.rs
src/test/ui/span/dropck_vec_cycle_checked.rs
src/test/ui/span/issue-24690.stderr
src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
src/tools/rls
src/tools/rust-installer
src/tools/rustbook/Cargo.toml
src/tools/rustbook/src/main.rs
src/tools/rustfmt [new submodule]
src/tools/tidy/src/lib.rs

index fbebccf408fb6634104d8a63a74c660cd0a42b96..d5ae25646547f8be4ec143c30e2ba3ba305c043d 100644 (file)
@@ -36,3 +36,6 @@
 [submodule "src/tools/clippy"]
        path = src/tools/clippy
        url = https://github.com/rust-lang-nursery/rust-clippy.git
+[submodule "src/tools/rustfmt"]
+       path = src/tools/rustfmt
+       url = https://github.com/rust-lang-nursery/rustfmt.git
index 23bae6d9f1721eba30a74acc68beb90e1ce5dbd7..889d1d4ef76bae0ce478d7ffa03ed37d62e28b43 100644 (file)
@@ -12,14 +12,19 @@ matrix:
   fast_finish: true
   include:
     # Images used in testing PR and try-build should be run first.
-    - env: IMAGE=x86_64-gnu-llvm-3.7 ALLOW_PR=1 RUST_BACKTRACE=1
-    - env: IMAGE=dist-x86_64-linux DEPLOY=1 ALLOW_TRY=1
+    - env: IMAGE=x86_64-gnu-llvm-3.7 RUST_BACKTRACE=1
+      if: type = pull_request OR branch = auto
+
+    - env: IMAGE=dist-x86_64-linux DEPLOY=1
+      if: branch = try OR branch = auto
 
     # "alternate" deployments, these are "nightlies" but don't have assertions
     # turned on, they're deployed to a different location primarily for projects
     # which are stuck on nightly and don't want llvm assertions in the artifacts
     # that they use.
     - env: IMAGE=dist-x86_64-linux DEPLOY_ALT=1
+      if: branch = auto
+
     - env: >
         RUST_CHECK_TARGET=dist
         RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler"
@@ -28,8 +33,11 @@ matrix:
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
         SCCACHE_ERROR_LOG=/tmp/sccache.log
         MACOSX_DEPLOYMENT_TARGET=10.7
+        NO_LLVM_ASSERTIONS=1
+        NO_DEBUG_ASSERTIONS=1
       os: osx
       osx_image: xcode7
+      if: branch = auto
 
     # macOS builders. These are placed near the beginning because they are very
     # slow to run.
@@ -46,8 +54,12 @@ matrix:
         SCCACHE_ERROR_LOG=/tmp/sccache.log
         MACOSX_DEPLOYMENT_TARGET=10.8
         MACOSX_STD_DEPLOYMENT_TARGET=10.7
+        NO_LLVM_ASSERTIONS=1
+        NO_DEBUG_ASSERTIONS=1
       os: osx
       osx_image: xcode8.2
+      if: branch = auto
+
     - env: >
         RUST_CHECK_TARGET=check
         RUST_CONFIGURE_ARGS=--build=i686-apple-darwin
@@ -56,8 +68,11 @@ matrix:
         SCCACHE_ERROR_LOG=/tmp/sccache.log
         MACOSX_DEPLOYMENT_TARGET=10.8
         MACOSX_STD_DEPLOYMENT_TARGET=10.7
+        NO_LLVM_ASSERTIONS=1
+        NO_DEBUG_ASSERTIONS=1
       os: osx
       osx_image: xcode8.2
+      if: branch = auto
 
     # OSX builders producing releases. These do not run the full test suite and
     # just produce a bunch of artifacts.
@@ -73,8 +88,12 @@ matrix:
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
         SCCACHE_ERROR_LOG=/tmp/sccache.log
         MACOSX_DEPLOYMENT_TARGET=10.7
+        NO_LLVM_ASSERTIONS=1
+        NO_DEBUG_ASSERTIONS=1
       os: osx
       osx_image: xcode7
+      if: branch = auto
+
     - env: >
         RUST_CHECK_TARGET=dist
         RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers --enable-profiler"
@@ -83,81 +102,96 @@ matrix:
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
         SCCACHE_ERROR_LOG=/tmp/sccache.log
         MACOSX_DEPLOYMENT_TARGET=10.7
+        NO_LLVM_ASSERTIONS=1
+        NO_DEBUG_ASSERTIONS=1
       os: osx
       osx_image: xcode7
+      if: branch = auto
 
     # Linux builders, remaining docker images
     - env: IMAGE=arm-android
+      if: branch = auto
     - env: IMAGE=armhf-gnu
+      if: branch = auto
     - env: IMAGE=cross DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-aarch64-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-android DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-arm-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-armhf-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-armv7-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-fuchsia DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-i686-freebsd DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-i686-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-mips-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-mips64-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-mips64el-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-mipsel-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-powerpc-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-powerpc64-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-powerpc64le-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-s390x-linux DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-x86_64-freebsd DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-x86_64-musl DEPLOY=1
+      if: branch = auto
     - env: IMAGE=dist-x86_64-netbsd DEPLOY=1
+      if: branch = auto
     - env: IMAGE=asmjs
+      if: branch = auto
     - env: IMAGE=i686-gnu
+      if: branch = auto
     - env: IMAGE=i686-gnu-nopt
+      if: branch = auto
     # - env: IMAGE=wasm32 issue 42646
+    #   if: branch = auto
     - env: IMAGE=x86_64-gnu
+      if: branch = auto
     - env: IMAGE=x86_64-gnu-full-bootstrap
+      if: branch = auto
     - env: IMAGE=x86_64-gnu-aux
+      if: branch = auto
     - env: IMAGE=x86_64-gnu-debug
+      if: branch = auto
     - env: IMAGE=x86_64-gnu-nopt
+      if: branch = auto
     - env: IMAGE=x86_64-gnu-distcheck
+      if: branch = auto
     - env: IMAGE=x86_64-gnu-incremental
+      if: branch = auto
 
 env:
   global:
-    - SCCACHE_BUCKET=rust-lang-ci-sccache
+    - SCCACHE_BUCKET=rust-lang-ci-sccache2
+    - SCCACHE_REGION=us-west-1
     - AWS_ACCESS_KEY_ID=AKIAJAMV3QAMMA6AXHFQ
     # AWS_SECRET_ACCESS_KEY=...
     - secure: "j96XxTVOSUf4s4r4htIxn/fvIa5DWbMgLqWl7r8z2QfgUwscmkMXAwXuFNc7s7bGTpV/+CgDiMFFM6BAFLGKutytIF6oA02s9b+usQYnM0th7YQ2AIgm9GtMTJCJp4AoyfFmh8F2faUICBZlfVLUJ34udHEe35vOklix+0k4WDo="
 
 before_install:
-  # If we are building a pull request, do the build if $ALLOW_PR == 1
-  # Otherwise, do the build if we are on the auto branch, or the try branch and $ALLOW_TRY == 1
-  - >
-    if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then
-        if [[ "$ALLOW_PR" == "1" ]]; then
-            export SKIP_BUILD=false;
-        else
-            export SKIP_BUILD=true;
-        fi;
-    elif [[ "$TRAVIS_BRANCH" == "auto" || ( "$ALLOW_TRY" == "1" && "$TRAVIS_BRANCH" == "try" ) ]]; then
-        export SKIP_BUILD=false;
-    else
-        export SKIP_BUILD=true;
-    fi
-  - >
-    if [[ "$SKIP_BUILD" == false ]]; then
-      zcat $HOME/docker/rust-ci.tar.gz | docker load || true
-    fi
+  - zcat $HOME/docker/rust-ci.tar.gz | docker load || true
   - mkdir -p $HOME/rustsrc
 
 install:
-  - >
-    if [[ "$SKIP_BUILD" == true ]]; then
-      echo echo skipping, not a full build > $HOME/stamp &&
-        chmod +x $HOME/stamp &&
-        export PATH=$PATH:$HOME;
-    else
-      case "$TRAVIS_OS_NAME" in
+  - case "$TRAVIS_OS_NAME" in
         linux)
           travis_retry curl -fo $HOME/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-unknown-linux-musl &&
             chmod +x $HOME/stamp &&
@@ -173,8 +207,7 @@ install:
           travis_retry curl -fo /usr/local/bin/stamp https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-03-17-stamp-x86_64-apple-darwin &&
             chmod +x /usr/local/bin/stamp
           ;;
-      esac
-    fi
+    esac
 
 before_script:
   - >
@@ -279,7 +312,7 @@ deploy:
       secure: "kUGd3t7JcVWFESgIlzvsM8viZgCA9Encs3creW0xLJaLSeI1iVjlJK4h/2/nO6y224AFrh/GUfsNr4/4AlxPuYb8OU5oC5Lv+Ff2JiRDYtuNpyQSKAQp+bRYytWMtrmhja91h118Mbm90cUfcLPwkdiINgJNTXhPKg5Cqu3VYn0="
     on:
       branch: try
-      condition: $DEPLOY = 1 && $ALLOW_TRY = 1
+      condition: $DEPLOY = 1
 
   # this is the same as the above deployment provider except that it uploads to
   # a slightly different directory and has a different trigger
index 7441d51055ffb2bb83098675d380d102ff9a7fec..741ced8f0912d21157b9919522f9b767a30ba164 100644 (file)
@@ -400,30 +400,53 @@ labels to triage issues:
 
 * Magenta, **B**-prefixed labels identify bugs which are **blockers**.
 
+* Dark blue, **beta-** labels track changes which need to be backported into
+  the beta branches.
+
+* Light purple, **C**-prefixed labels represent the **category** of an issue.
+
 * Green, **E**-prefixed labels explain the level of **experience** necessary
   to fix the issue.
 
+* The dark blue **final-comment-period** label marks bugs that are using the
+  RFC signoff functionality of [rfcbot][rfcbot] and are currenty in the final
+  comment period.
+
 * Red, **I**-prefixed labels indicate the **importance** of the issue. The
   [I-nominated][inom] label indicates that an issue has been nominated for
   prioritizing at the next triage meeting.
 
+* The purple **metabug** label marks lists of bugs collected by other
+  categories.
+
+* Purple gray, **O**-prefixed labels are the **operating system** or platform
+  that this issue is specific to.
+
 * Orange, **P**-prefixed labels indicate a bug's **priority**. These labels
   are only assigned during triage meetings, and replace the [I-nominated][inom]
   label.
 
-* Blue, **T**-prefixed bugs denote which **team** the issue belongs to.
+* The gray **proposed-final-comment-period** label marks bugs that are using
+  the RFC signoff functionality of [rfcbot][rfcbot] and are currently awaiting
+  signoff of all team members in order to enter the final comment period.
 
-* Dark blue, **beta-** labels track changes which need to be backported into
-  the beta branches.
+* Pink, **regression**-prefixed labels track regressions from stable to the
+  release channels.
 
-* The purple **metabug** label marks lists of bugs collected by other
-  categories.
+* The light orange **relnotes** label marks issues that should be documented in
+  the release notes of the next release.
+
+* Gray, **S**-prefixed labels are used for tracking the **status** of pull
+  requests.
+
+* Blue, **T**-prefixed bugs denote which **team** the issue belongs to.
 
 If you're looking for somewhere to start, check out the [E-easy][eeasy] tag.
 
 [inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated
 [eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy
 [lru]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-asc
+[rfcbot]: https://github.com/dikaiosune/rust-dashboard/blob/master/RFCBOT.md
 
 ## Out-of-tree Contributions
 
index 62b62ae7c42e9da0343d4c0365ae29e519072e21..e922b930675ebfd620681cbbf4b5ca7376aa257a 100644 (file)
@@ -1,5 +1,6 @@
 environment:
-  SCCACHE_BUCKET: rust-lang-ci-sccache
+  SCCACHE_BUCKET: rust-lang-ci-sccache2
+  SCCACHE_REGION: us-west-1
   AWS_ACCESS_KEY_ID: AKIAJAMV3QAMMA6AXHFQ
   AWS_SECRET_ACCESS_KEY:
     secure: 7Y+JiquYedOAgnUU26uL0DPzrxmTtR+qIwG6rNKSuWDffqU3vVZxbGXim9QpTO80
diff --git a/fn.rs b/fn.rs
deleted file mode 100644 (file)
index 186eda9..0000000
--- a/fn.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-
-fn foo(x:  fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
-// Debruijn   1    1            1        1
-// Anon-Index 0    1            0        1
-//            ------
-//            debruijn indices are shifted by 1 in here
-  y.push(z); // index will be zero or one
-}
index 1bbe8ca7575f11b6b9110ec415b1dd504296cfda..44faf4b445de16ff71ee242b391172d454b0ee84 100644 (file)
@@ -47,7 +47,7 @@ dependencies = [
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -103,7 +103,7 @@ name = "backtrace-sys"
 version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -135,9 +135,9 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (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.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -267,10 +267,10 @@ dependencies = [
 
 [[package]]
 name = "cmake"
-version = "0.1.24"
+version = "0.1.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -286,7 +286,7 @@ name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
  "core 0.0.0",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -402,7 +402,7 @@ name = "curl-sys"
 version = "0.3.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -490,6 +490,14 @@ dependencies = [
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "error-chain"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "error-chain"
 version = "0.11.0"
@@ -574,7 +582,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "gcc"
-version = "0.3.53"
+version = "0.3.54"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -642,7 +650,7 @@ dependencies = [
 
 [[package]]
 name = "handlebars"
-version = "0.26.2"
+version = "0.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -832,9 +840,9 @@ name = "libgit2-sys"
 version = "0.6.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -847,7 +855,7 @@ name = "libssh2-sys"
 version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -859,7 +867,7 @@ name = "libz-sys"
 version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -880,7 +888,7 @@ version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -926,18 +934,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.0.22"
+version = "0.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "handlebars 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (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.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -962,7 +974,7 @@ name = "miniz-sys"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1098,7 +1110,7 @@ name = "openssl-sys"
 version = "0.9.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1203,7 +1215,7 @@ name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
  "core 0.0.0",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1334,12 +1346,12 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.2.5",
  "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1348,7 +1360,7 @@ dependencies = [
 
 [[package]]
 name = "rls-analysis"
-version = "0.6.5"
+version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1398,7 +1410,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1464,7 +1476,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1599,7 +1611,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
 ]
 
@@ -1610,7 +1622,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1655,7 +1667,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1729,7 +1741,7 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1767,7 +1779,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1794,7 +1806,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1810,7 +1822,6 @@ dependencies = [
 [[package]]
 name = "rustfmt-nightly"
 version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1967,7 +1978,7 @@ dependencies = [
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -2443,7 +2454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0"
-"checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
+"checksum cmake 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "0c8a6541a55bcd72d3de4faee2d101a5a66df29790282c7f797082a7228a9b3d"
 "checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
 "checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7"
 "checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
@@ -2463,6 +2474,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
 "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
+"checksum error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
 "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
@@ -2471,14 +2483,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum fs2 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ab76cfd2aaa59b7bf6688ad9ba15bbae64bff97f04ea02144cfd3443e5c2866"
 "checksum futf 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "51f93f3de6ba1794dcd5810b3546d004600a59a98266487c8407bc4b24e398f3"
 "checksum futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a82bdc62350ca9d7974c760e9665102fc9d740992a528c2254aa930e53b783c4"
-"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a"
+"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
 "checksum git2 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1c0203d653f4140241da0c1375a404f0a397249ec818cd2076c6280c50f6fa"
 "checksum git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "68676bc784bf0bef83278898929bf64a251e87c0340723d0b93fa096c9c5bf8e"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum globset 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "feeb1b6840809ef5efcf7a4a990bc4e1b7ee3df8cf9e2379a75aeb2ba42ac9c3"
 "checksum hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4"
-"checksum handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fbba80e74e9591a5f6a4ffff6b7f9d645759a896e431cfbdc853e9184370294a"
+"checksum handlebars 0.27.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef7567daf271a32e60301e4821fcb5b51a5b535167115d1ce04f46c3f0a15f0b"
 "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
 "checksum home 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f25ae61099d8f3fee8b483df0bd4ecccf4b2731897aad40d50eca1b641fe6db"
 "checksum html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5298d63081a642508fce965740ddb03a386c5d81bf1fef0579a815cf49cb8c68"
@@ -2503,7 +2515,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699"
 "checksum markup5ever 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff834ac7123c6a37826747e5ca09db41fd7a83126792021c2e636ad174bb77d3"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
-"checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700"
+"checksum mdbook 0.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "146eadfc6d141452a364c351f07bb19208d1401e931f40b8532f87bba3ecc40f"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
 "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
@@ -2542,14 +2554,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d2cb40c0371765897ae428b5706bb17135705ad4f6d1b8b6afbaabcf8c9b5cff"
+"checksum rls-analysis 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4302cc8291570d7f817945845d8c01756e833dbc93c0a87d4f6c9a0b0b7992f1"
 "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
 "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7d6dbb39239e54df780a850721fba87b3fdb2e645b39041742ec111369cec6af"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
index 35ba022c4899a5e528f260b3181aa4360ae0c1f1..8142213b20421b7dfba670268ead87ea88638ef9 100644 (file)
@@ -18,6 +18,7 @@ members = [
   "tools/cargo",
   "tools/rustdoc",
   "tools/rls",
+  "tools/rustfmt",
   # FIXME(https://github.com/rust-lang/cargo/issues/4089): move these to exclude
   "tools/rls/test_data/borrow_error",
   "tools/rls/test_data/completion",
@@ -56,5 +57,13 @@ debug-assertions = false
 debug = false
 debug-assertions = false
 
-[patch.'https://github.com/rust-lang/cargo']
+[patch."https://github.com/rust-lang/cargo"]
 cargo = { path = "tools/cargo" }
+
+# Override rustfmt dependencies both on the repo and the crate (the RLS
+# sometimes uses either).
+# FIXME should only need the crates.io patch, long term.
+[patch.'https://github.com/rust-lang-nursery/rustfmt']
+rustfmt-nightly = { path = "tools/rustfmt" }
+[patch.crates-io]
+rustfmt-nightly = { path = "tools/rustfmt" }
index daa2a3d0a0ff485c1927fe3626be3ece37e70410..85e3b65c1953cf080d0e35afdbff226514f6d18a 100644 (file)
@@ -34,7 +34,7 @@ cmake = "0.1.23"
 filetime = "0.1"
 num_cpus = "1.0"
 getopts = "0.2"
-gcc = "0.3.50"
+gcc = "0.3.54"
 libc = "0.2"
 serde = "1.0.8"
 serde_derive = "1.0.8"
index 4765546b184d39bffa0c1375f8af83da2e9e9b2f..7ff0154bf8bb30532bfbedc8710421e4b87b1134 100644 (file)
@@ -249,11 +249,11 @@ macro_rules! describe {
                 tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest,
                 tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient,
                 tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
-                native::Llvm),
+                native::Llvm, tool::Rustfmt),
             Kind::Test => describe!(check::Tidy, check::Bootstrap, check::DefaultCompiletest,
                 check::HostCompiletest, check::Crate, check::CrateLibrustc, check::Rustdoc,
                 check::Linkcheck, check::Cargotest, check::Cargo, check::Rls, check::Docs,
-                check::ErrorIndex, check::Distcheck),
+                check::ErrorIndex, check::Distcheck, check::Rustfmt),
             Kind::Bench => describe!(check::Crate, check::CrateLibrustc),
             Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook,
                 doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon,
index 0d5c3addd9e7447df135a5ac11610f57af94dc1d..94bb89145fbf3d1068342316b85b583d26c3e957 100644 (file)
@@ -253,6 +253,47 @@ fn run(self, builder: &Builder) {
     }
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub struct Rustfmt {
+    stage: u32,
+    host: Interned<String>,
+}
+
+impl Step for Rustfmt {
+    type Output = ();
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/tools/rustfmt")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(Rustfmt {
+            stage: run.builder.top_stage,
+            host: run.target,
+        });
+    }
+
+    /// Runs `cargo test` for rustfmt.
+    fn run(self, builder: &Builder) {
+        let build = builder.build;
+        let stage = self.stage;
+        let host = self.host;
+        let compiler = builder.compiler(stage, host);
+
+        builder.ensure(tool::Rustfmt { compiler, target: self.host });
+        let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
+        cargo.arg("--manifest-path").arg(build.src.join("src/tools/rustfmt/Cargo.toml"));
+
+        // Don't build tests dynamically, just a pain to work with
+        cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
+
+        builder.add_rustc_lib_path(compiler, &mut cargo);
+
+        try_run(build, &mut cargo);
+    }
+}
+
 fn path_for_cargo(builder: &Builder, compiler: Compiler) -> OsString {
     // Configure PATH to find the right rustc. NB. we have to use PATH
     // and not RUSTC because the Cargo test suite has tests that will
@@ -1118,10 +1159,11 @@ fn run(self, builder: &Builder) {
         let compiler = builder.compiler(builder.top_stage, self.host);
         let target = compiler.host;
 
-        builder.ensure(RemoteCopyLibs { compiler, target });
-
-        let mut cargo = builder.cargo(compiler, Mode::Librustc, target, test_kind.subcommand());
-        compile::rustc_cargo(build, &compiler, target, &mut cargo);
+        let mut cargo = tool::prepare_tool_cargo(builder,
+                                                 compiler,
+                                                 target,
+                                                 test_kind.subcommand(),
+                                                 "src/tools/rustdoc");
         let _folder = build.fold_output(|| {
             format!("{}_stage{}-rustdoc", test_kind.subcommand(), compiler.stage)
         });
index 9180c7d165a37a300379280f68f725bb93e36adb..7bca088dbd5a8f8529738b5fce536ca66a030576 100644 (file)
@@ -1098,8 +1098,14 @@ fn run(self, builder: &Builder) -> PathBuf {
            .arg("--output-dir").arg(&distdir(build))
            .arg("--non-installed-overlay").arg(&overlay)
            .arg(format!("--package-name={}-{}", name, target))
-           .arg("--component-name=rls")
            .arg("--legacy-manifest-dirs=rustlib,cargo");
+
+        if build.config.channel == "nightly" {
+            cmd.arg("--component-name=rls");
+        } else {
+            cmd.arg("--component-name=rls-preview");
+        }
+
         build.run(&mut cmd);
         distdir(build).join(format!("{}-{}.tar.gz", name, target))
     }
@@ -1302,9 +1308,12 @@ fn run(self, builder: &Builder) {
             cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-std"), target))
                         .join(format!("rust-std-{}", target)),
                     &exe.join("rust-std"));
-            cp_r(&work.join(&format!("{}-{}", pkgname(build, "rls"), target))
-                        .join("rls"),
-                    &exe.join("rls"));
+            let rls_path = if build.config.channel == "nightly" {
+                work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls")
+            } else {
+                work.join(&format!("{}-{}", pkgname(build, "rls"), target)).join("rls-preview")
+            };
+            cp_r(&rls_path, &exe.join("rls"));
             cp_r(&work.join(&format!("{}-{}", pkgname(build, "rust-analysis"), target))
                         .join(format!("rust-analysis-{}", target)),
                     &exe.join("rust-analysis"));
index 67495b891f80d9bdf31c4332cc3e9bd3746014f7..72be9c12e84e6b0952db05e09b487c76427f405e 100644 (file)
@@ -55,6 +55,7 @@ check-aux:
                src/tools/cargotest \
                src/tools/cargo \
                src/tools/rls \
+               src/tools/rustfmt \
                src/test/pretty \
                src/test/run-pass/pretty \
                src/test/run-fail/pretty \
index 2cbae083fc464bd7610d825fcb72e3e5e41e8c95..a2c436627f6da0c360618ec4dc997d2dac04ad15 100644 (file)
@@ -389,7 +389,8 @@ fn run(self, builder: &Builder) {
         drop(fs::remove_dir_all(&dst));
         build.run(Command::new("tar").arg("xf").arg(&tarball).current_dir(&out));
 
-        let mut configure = Command::new(obj.join("Configure"));
+        let mut configure = Command::new("perl");
+        configure.arg(obj.join("Configure"));
         configure.arg(format!("--prefix={}", dst.display()));
         configure.arg("no-dso");
         configure.arg("no-ssl2");
index eaa2b1244236fa59f74c9836229305fd0a704e59..d082012acc191beef353cde52f16de6d0db2bb01 100644 (file)
@@ -94,20 +94,21 @@ fn run(self, builder: &Builder) -> PathBuf {
         let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
         println!("Building stage{} tool {} ({})", compiler.stage, tool, target);
 
-        let mut cargo = prepare_tool_cargo(builder, compiler, target, path);
+        let mut cargo = prepare_tool_cargo(builder, compiler, target, "build", path);
         build.run(&mut cargo);
         build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
     }
 }
 
-fn prepare_tool_cargo(
+pub fn prepare_tool_cargo(
     builder: &Builder,
     compiler: Compiler,
     target: Interned<String>,
+    command: &'static str,
     path: &'static str,
 ) -> Command {
     let build = builder.build;
-    let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
+    let mut cargo = builder.cargo(compiler, Mode::Tool, target, command);
     let dir = build.src.join(path);
     cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
 
@@ -148,15 +149,27 @@ pub enum Tool {
 
         impl<'a> Builder<'a> {
             pub fn tool_exe(&self, tool: Tool) -> PathBuf {
+                let stage = self.tool_default_stage(tool);
                 match tool {
                     $(Tool::$name =>
                         self.ensure($name {
-                            compiler: self.compiler(0, self.build.build),
+                            compiler: self.compiler(stage, self.build.build),
                             target: self.build.build,
                         }),
                     )+
                 }
             }
+
+            pub fn tool_default_stage(&self, tool: Tool) -> u32 {
+                // Compile the error-index in the top stage as it depends on
+                // rustdoc, so we want to avoid recompiling rustdoc twice if we
+                // can. Otherwise compile everything else in stage0 as there's
+                // no need to rebootstrap everything
+                match tool {
+                    Tool::ErrorIndex => self.top_stage,
+                    _ => 0,
+                }
+            }
         }
 
         $(
@@ -283,6 +296,7 @@ fn run(self, builder: &Builder) -> PathBuf {
         let mut cargo = prepare_tool_cargo(builder,
                                            build_compiler,
                                            target,
+                                           "build",
                                            "src/tools/rustdoc");
         build.run(&mut cargo);
         // Cargo adds a number of paths to the dylib search path on windows, which results in
@@ -431,12 +445,46 @@ fn run(self, builder: &Builder) -> PathBuf {
     }
 }
 
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Rustfmt {
+    pub compiler: Compiler,
+    pub target: Interned<String>,
+}
+
+impl Step for Rustfmt {
+    type Output = PathBuf;
+    const DEFAULT: bool = true;
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        let builder = run.builder;
+        run.path("src/tools/rustfmt").default_condition(builder.build.config.extended)
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(Rustfmt {
+            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
+            target: run.target,
+        });
+    }
+
+    fn run(self, builder: &Builder) -> PathBuf {
+        builder.ensure(ToolBuild {
+            compiler: self.compiler,
+            target: self.target,
+            tool: "rustfmt",
+            mode: Mode::Librustc,
+            path: "src/tools/rustfmt",
+        })
+    }
+}
+
 impl<'a> Builder<'a> {
     /// Get a `Command` which is ready to run `tool` in `stage` built for
     /// `host`.
     pub fn tool_cmd(&self, tool: Tool) -> Command {
         let mut cmd = Command::new(self.tool_exe(tool));
-        let compiler = self.compiler(0, self.build.build);
+        let compiler = self.compiler(self.tool_default_stage(tool), self.build.build);
         self.prepare_tool_cmd(compiler, &mut cmd);
         cmd
     }
diff --git a/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile b/src/ci/docker/disabled/dist-x86_64-haiku/Dockerfile
new file mode 100644 (file)
index 0000000..621976b
--- /dev/null
@@ -0,0 +1,49 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  autoconf \
+  automake \
+  bison \
+  bzip2 \
+  ca-certificates \
+  cmake \
+  curl \
+  file \
+  flex \
+  g++ \
+  gawk \
+  git \
+  libcurl4-openssl-dev \
+  libssl-dev \
+  make \
+  nasm \
+  pkg-config \
+  python2.7 \
+  sudo \
+  texinfo \
+  wget \
+  xz-utils \
+  zlib1g-dev
+
+COPY dist-x86_64-haiku/llvm-config.sh /bin/llvm-config-haiku
+
+ENV ARCH=x86_64
+
+WORKDIR /tmp
+COPY dist-x86_64-haiku/build-toolchain.sh /tmp/
+RUN /tmp/build-toolchain.sh $ARCH
+
+COPY dist-x86_64-haiku/fetch-packages.sh /tmp/
+RUN /tmp/fetch-packages.sh
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV HOST=x86_64-unknown-haiku
+ENV TARGET=target.$HOST
+
+ENV RUST_CONFIGURE_ARGS --host=$HOST --target=$HOST --disable-jemalloc \
+  --set=$TARGET.cc=x86_64-unknown-haiku-gcc \
+  --set=$TARGET.cxx=x86_64-unknown-haiku-g++ \
+  --set=$TARGET.llvm-config=/bin/llvm-config-haiku
+ENV SCRIPT python2.7 ../x.py dist
diff --git a/src/ci/docker/disabled/dist-x86_64-haiku/build-toolchain.sh b/src/ci/docker/disabled/dist-x86_64-haiku/build-toolchain.sh
new file mode 100755 (executable)
index 0000000..0776d44
--- /dev/null
@@ -0,0 +1,74 @@
+#!/bin/bash
+# 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.
+
+set -ex
+
+ARCH=$1
+
+TOP=$(pwd)
+
+BUILDTOOLS=$TOP/buildtools
+HAIKU=$TOP/haiku
+OUTPUT=/tools
+SYSROOT=$OUTPUT/cross-tools-$ARCH/sysroot
+PACKAGE_ROOT=/system
+
+hide_output() {
+  set +x
+  on_err="
+echo ERROR: An error was encountered with the build.
+cat /tmp/build.log
+exit 1
+"
+  trap "$on_err" ERR
+  bash -c "while true; do sleep 30; echo \$(date) - building ...; done" &
+  PING_LOOP_PID=$!
+  $@ &> /tmp/build.log
+  trap - ERR
+  kill $PING_LOOP_PID
+  set -x
+}
+
+# First up, build a cross-compiler
+git clone --depth=1 https://git.haiku-os.org/haiku
+git clone --depth=1 https://git.haiku-os.org/buildtools
+cd $BUILDTOOLS/jam
+hide_output make
+hide_output ./jam0 install
+mkdir -p $OUTPUT
+cd $OUTPUT
+hide_output $HAIKU/configure --build-cross-tools $ARCH $TOP/buildtools
+
+# Set up sysroot to redirect to /system
+mkdir -p $SYSROOT/boot
+mkdir -p $PACKAGE_ROOT
+ln -s $PACKAGE_ROOT $SYSROOT/boot/system
+
+# Build needed packages and tools for the cross-compiler
+hide_output jam -q haiku.hpkg haiku_devel.hpkg '<build>package'
+
+# Set up our sysroot
+cp $OUTPUT/objects/linux/lib/*.so /lib/x86_64-linux-gnu
+cp $OUTPUT/objects/linux/x86_64/release/tools/package/package /bin/
+find $SYSROOT/../bin/ -type f -exec ln -s {} /bin/ \;
+
+# Extract packages
+package extract -C $PACKAGE_ROOT $OUTPUT/objects/haiku/$ARCH/packaging/packages/haiku.hpkg
+package extract -C $PACKAGE_ROOT $OUTPUT/objects/haiku/$ARCH/packaging/packages/haiku_devel.hpkg
+find $OUTPUT/download/ -name '*.hpkg' -exec package extract -C $PACKAGE_ROOT {} \;
+
+# Fix libgcc_s so we can link to it
+cd $PACKAGE_ROOT/develop/lib
+ln -s ../../lib/libgcc_s.so libgcc_s.so
+
+# Clean up
+rm -rf $BUILDTOOLS $HAIKU $OUTPUT/Jamfile $OUTPUT/attributes $OUTPUT/build \
+  $OUTPUT/build_packages $OUTPUT/download $OUTPUT/objects
diff --git a/src/ci/docker/disabled/dist-x86_64-haiku/fetch-packages.sh b/src/ci/docker/disabled/dist-x86_64-haiku/fetch-packages.sh
new file mode 100755 (executable)
index 0000000..0f6034c
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+# 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.
+
+wget http://packages.haiku-os.org/haikuports/master/hpkg/llvm-4.0.1-2-x86_64.hpkg
+wget http://packages.haiku-os.org/haikuports/master/hpkg/llvm_libs-4.0.1-2-x86_64.hpkg
+
+package extract -C /system llvm-4.0.1-2-x86_64.hpkg
+package extract -C /system llvm_libs-4.0.1-2-x86_64.hpkg
+
+rm -f *.hpkg
diff --git a/src/ci/docker/disabled/dist-x86_64-haiku/llvm-config.sh b/src/ci/docker/disabled/dist-x86_64-haiku/llvm-config.sh
new file mode 100755 (executable)
index 0000000..fb5206b
--- /dev/null
@@ -0,0 +1,67 @@
+#!/bin/sh
+# 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.
+
+case $1 in
+--version) echo  4.0.1;;
+--prefix) echo  $SCRATCH/haiku-cross/sysroot/boot/system;;
+--bindir) echo  $SCRATCH/haiku-cross/sysroot/boot/system/bin;;
+--includedir) echo  $SCRATCH/haiku-cross/sysroot/boot/system/develop/headers;;
+--libdir) echo  $SCRATCH/haiku-/cross/sysroot/boot/system/develop/lib;;
+--cmakedir) echo  $SCRATCH/haiku-/cross/sysroot/boot/system/develop/lib/cmake/llvm;;
+--cppflags) echo  -I$SCRATCH/haiku-/cross/sysroot/boot/system/develop/headers \
+                  -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS;;
+--cflags) echo  -I$SCRATCH/haiku-cross/sysroot/boot/system/develop/headers \
+                -fPIC -Wall -W -Wno-unused-parameter -Wwrite-strings \
+                -Wno-missing-field-initializers -pedantic -Wno-long-long -Wno-comment \
+                -Werror=date-time -ffunction-sections -fdata-sections -O3 -DNDEBUG \
+                -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS;;
+--cxxflags) echo  -I/$SCRATCH/haiku-cross/sysroot/boot/system/develop/headers \
+                  -fPIC -fvisibility-inlines-hidden -Wall -W -Wno-unused-parameter \
+                  -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic \
+                  -Wno-long-long -Wno-maybe-uninitialized -Wdelete-non-virtual-dtor \
+                  -Wno-comment -Werror=date-time -std=c++11 -ffunction-sections \
+                  -fdata-sections -O3 -DNDEBUG  -fno-exceptions \
+                  -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS;;
+--ldflags) echo  -L$SCRATCH/haiku-cross/sysroot/boot/system/develop/lib ;;
+--system-libs) echo ;;
+--libs) echo  -lLLVM-4.0;;
+--libfiles) echo  $SCRATCH/haiku-cross/sysroot/boot/system/develop/lib/libLLVM-4.0.so;;
+--components) echo  aarch64 aarch64asmparser aarch64asmprinter aarch64codegen \
+                    aarch64desc aarch64disassembler aarch64info aarch64utils all \
+                    all-targets amdgpu amdgpuasmparser amdgpuasmprinter amdgpucodegen \
+                    amdgpudesc amdgpudisassembler amdgpuinfo amdgpuutils analysis arm \
+                    armasmparser armasmprinter armcodegen armdesc armdisassembler \
+                    arminfo asmparser asmprinter bitreader bitwriter bpf bpfasmprinter \
+                    bpfcodegen bpfdesc bpfdisassembler bpfinfo codegen core coroutines \
+                    coverage debuginfocodeview debuginfodwarf debuginfomsf debuginfopdb \
+                    demangle engine executionengine globalisel hexagon hexagonasmparser \
+                    hexagoncodegen hexagondesc hexagondisassembler hexagoninfo \
+                    instcombine instrumentation interpreter ipo irreader lanai \
+                    lanaiasmparser lanaicodegen lanaidesc lanaidisassembler lanaiinfo \
+                    lanaiinstprinter libdriver lineeditor linker lto mc mcdisassembler \
+                    mcjit mcparser mips mipsasmparser mipsasmprinter mipscodegen \
+                    mipsdesc mipsdisassembler mipsinfo mirparser msp430 msp430asmprinter \
+                    msp430codegen msp430desc msp430info native nativecodegen nvptx \
+                    nvptxasmprinter nvptxcodegen nvptxdesc nvptxinfo objcarcopts object \
+                    objectyaml option orcjit passes powerpc powerpcasmparser \
+                    powerpcasmprinter powerpccodegen powerpcdesc powerpcdisassembler \
+                    powerpcinfo profiledata riscv riscvcodegen riscvdesc riscvinfo \
+                    runtimedyld scalaropts selectiondag sparc sparcasmparser \
+                    sparcasmprinter sparccodegen sparcdesc sparcdisassembler sparcinfo \
+                    support symbolize systemz systemzasmparser systemzasmprinter \
+                    systemzcodegen systemzdesc systemzdisassembler systemzinfo tablegen \
+                    target transformutils vectorize x86 x86asmparser x86asmprinter \
+                    x86codegen x86desc x86disassembler x86info x86utils xcore \
+                    xcoreasmprinter xcorecodegen xcoredesc xcoredisassembler xcoreinfo;;
+--host-target) echo  x86_64-unknown-haiku;;
+--has-rtti) echo  YES;;
+--shared-mode) echo  shared;;
+esac
index 5eba81ff60a22a935777712d32d43305a69d6454..7087033e117a23b5d277450361ae48f7eb25668b 100755 (executable)
@@ -57,9 +57,10 @@ mkdir -p $objdir/tmp
 
 args=
 if [ "$SCCACHE_BUCKET" != "" ]; then
-    args="$args --env SCCACHE_BUCKET=$SCCACHE_BUCKET"
-    args="$args --env AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID"
-    args="$args --env AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY"
+    args="$args --env SCCACHE_BUCKET"
+    args="$args --env SCCACHE_REGION"
+    args="$args --env AWS_ACCESS_KEY_ID"
+    args="$args --env AWS_SECRET_ACCESS_KEY"
     args="$args --env SCCACHE_ERROR_LOG=/tmp/sccache/sccache.log"
     args="$args --volume $objdir/tmp:/tmp/sccache"
 else
@@ -82,10 +83,10 @@ exec docker \
   --env SRC=/checkout \
   $args \
   --env CARGO_HOME=/cargo \
-  --env DEPLOY=$DEPLOY \
-  --env DEPLOY_ALT=$DEPLOY_ALT \
+  --env DEPLOY \
+  --env DEPLOY_ALT \
   --env LOCAL_USER_ID=`id -u` \
-  --env TRAVIS=${TRAVIS-false} \
+  --env TRAVIS \
   --env TRAVIS_BRANCH \
   --volume "$HOME/.cargo:/cargo" \
   --volume "$HOME/rustsrc:$HOME/rustsrc" \
index 39fb4e44078124f118794ca89d37d5e6da1ebd6b..b4fa033c4a668aeb465fb49a4db628ce1a3e9287 100755 (executable)
@@ -52,7 +52,11 @@ if [ "$DEPLOY$DEPLOY_ALT" != "" ]; then
     RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-llvm-assertions"
   fi
 else
-  RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-debug-assertions"
+  # We almost always want debug assertions enabled, but sometimes this takes too
+  # long for too little benefit, so we just turn them off.
+  if [ "$NO_DEBUG_ASSERTIONS" = "" ]; then
+    RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-debug-assertions"
+  fi
 
   # In general we always want to run tests with LLVM assertions enabled, but not
   # all platforms currently support that, so we have an option to disable.
index 4f7736d8df6bb6cd79fc8448c0b7de1a5a7e0152..eb3e6a9dd5067ee9c96acec3527499f795491f00 100644 (file)
@@ -5,7 +5,7 @@ that your tests are up to date and working.
 
 The basic idea is this:
 
-```rust,ignore
+```ignore
 /// # Examples
 ///
 /// ```
@@ -16,6 +16,19 @@ The basic idea is this:
 The triple backticks start and end code blocks. If this were in a file named `foo.rs`,
 running `rustdoc --test foo.rs` will extract this example, and then run it as a test.
 
+Please note that by default, if no language is set for the block code, `rustdoc`
+assumes it is `Rust` code. So the following:
+
+```rust
+let x = 5;
+```
+
+is strictly equivalent to:
+
+```
+let x = 5;
+```
+
 There's some subtlety though! Read on for more details.
 
 ## Pre-processing examples
@@ -106,7 +119,7 @@ our source code:
 ```text
     First, we set `x` to five:
 
-    ```rust
+    ```
     let x = 5;
     # let y = 6;
     # println!("{}", x + y);
@@ -114,7 +127,7 @@ our source code:
 
     Next, we set `y` to six:
 
-    ```rust
+    ```
     # let x = 5;
     let y = 6;
     # println!("{}", x + y);
@@ -122,7 +135,7 @@ our source code:
 
     Finally, we print the sum of `x` and `y`:
 
-    ```rust
+    ```
     # let x = 5;
     # let y = 6;
     println!("{}", x + y);
@@ -136,7 +149,7 @@ explanation.
 Another case where the use of `#` is handy is when you want to ignore
 error handling. Lets say you want the following,
 
-```rust,ignore
+```ignore
 /// use std::io;
 /// let mut input = String::new();
 /// io::stdin().read_line(&mut input)?;
@@ -145,7 +158,7 @@ error handling. Lets say you want the following,
 The problem is that `?` returns a `Result<T, E>` and test functions
 don't return anything so this will give a mismatched types error.
 
-```rust,ignore
+```ignore
 /// A doc test using ?
 ///
 /// ```
@@ -179,7 +192,7 @@ Here’s an example of documenting a macro:
 /// # }
 /// ```
 ///
-/// ```rust,should_panic
+/// ```should_panic
 /// # #[macro_use] extern crate foo;
 /// # fn main() {
 /// panic_unless!(true == false, “I’m broken.”);
@@ -224,7 +237,7 @@ only shows the part you care about.
 `should_panic` tells `rustdoc` that the code should compile correctly, but
 not actually pass as a test.
 
-```rust
+```text
 /// ```no_run
 /// loop {
 ///     println!("Hello, world");
@@ -233,6 +246,18 @@ not actually pass as a test.
 # fn foo() {}
 ```
 
+`compile_fail` tells `rustdoc` that the compilation should fail. If it
+compiles, then the test will fail. However please note that code failing
+with the current Rust release may work in a future release, as new features
+are added.
+
+```text
+/// ```compile_fail
+/// let x = 5;
+/// x += 2; // shouldn't compile!
+/// ```
+```
+
 The `no_run` attribute will compile your code, but not run it. This is
 important for examples such as "Here's how to retrieve a web page,"
 which you would want to ensure compiles, but might be run in a test
index d734ae6a2cf61b2184bba55d315bff8024a7ea3a..4b695ad7c7933ae11dcf066daf4c30955063c440 100644 (file)
@@ -22,7 +22,7 @@
 use core::fmt;
 use core::cmp::Ordering;
 use core::intrinsics::abort;
-use core::mem::{self, size_of_val, uninitialized};
+use core::mem::{self, align_of_val, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
@@ -324,7 +324,9 @@ pub fn try_unwrap(this: Self) -> Result<T, Self> {
             Ok(elem)
         }
     }
+}
 
+impl<T: ?Sized> Arc<T> {
     /// Consumes the `Arc`, returning the wrapped pointer.
     ///
     /// To avoid a memory leak the pointer must be converted back to an `Arc` using
@@ -378,16 +380,21 @@ pub fn into_raw(this: Self) -> *const T {
     /// ```
     #[stable(feature = "rc_raw", since = "1.17.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
-        // To find the corresponding pointer to the `ArcInner` we need to subtract the offset of the
-        // `data` field from the pointer.
-        let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner<T>, data));
+        // Align the unsized value to the end of the ArcInner.
+        // Because it is ?Sized, it will always be the last field in memory.
+        let align = align_of_val(&*ptr);
+        let layout = Layout::new::<ArcInner<()>>();
+        let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
+
+        // Reverse the offset to find the original ArcInner.
+        let fake_ptr = ptr as *mut ArcInner<T>;
+        let arc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
+
         Arc {
-            ptr: Shared::new_unchecked(ptr as *mut u8 as *mut _),
+            ptr: Shared::new_unchecked(arc_ptr),
         }
     }
-}
 
-impl<T: ?Sized> Arc<T> {
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///
     /// [weak]: struct.Weak.html
@@ -1491,6 +1498,28 @@ fn into_from_raw() {
         }
     }
 
+    #[test]
+    fn test_into_from_raw_unsized() {
+        use std::fmt::Display;
+        use std::string::ToString;
+
+        let arc: Arc<str> = Arc::from("foo");
+
+        let ptr = Arc::into_raw(arc.clone());
+        let arc2 = unsafe { Arc::from_raw(ptr) };
+
+        assert_eq!(unsafe { &*ptr }, "foo");
+        assert_eq!(arc, arc2);
+
+        let arc: Arc<Display> = Arc::new(123);
+
+        let ptr = Arc::into_raw(arc.clone());
+        let arc2 = unsafe { Arc::from_raw(ptr) };
+
+        assert_eq!(unsafe { &*ptr }.to_string(), "123");
+        assert_eq!(arc2.to_string(), "123");
+    }
+
     #[test]
     fn test_cowarc_clone_make_mut() {
         let mut cow0 = Arc::new(75);
index d32460da9392342e12834e28d1e5684956297b0a..7da6371cc19072dd94e001a317ebe107c6d4a46c 100644 (file)
@@ -1110,15 +1110,13 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> {
-        loop {
-            match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
-                Less => return self.a.next(),
-                Equal => {
-                    self.b.next();
-                    return self.a.next();
-                }
-                Greater => return self.b.next(),
+        match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) {
+            Less => self.a.next(),
+            Equal => {
+                self.b.next();
+                self.a.next()
             }
+            Greater => self.b.next(),
         }
     }
 
index 43ebaa4fbdb3f17a0024a61c81abdf2b1bc4ae6b..c2a3019515f106cb9ce53d1eecaa83821024d16d 100644 (file)
@@ -105,22 +105,3 @@ macro_rules! vec {
 macro_rules! format {
     ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
 }
-
-// Private macro to get the offset of a struct field in bytes from the address of the struct.
-macro_rules! offset_of {
-    ($container:path, $field:ident) => {{
-        // Make sure the field actually exists. This line ensures that a compile-time error is
-        // generated if $field is accessed through a Deref impl.
-        let $container { $field : _, .. };
-
-        // Create an (invalid) instance of the container and calculate the offset to its
-        // field. Using a null pointer might be UB if `&(*(0 as *const T)).field` is interpreted to
-        // be nullptr deref.
-        let invalid: $container = ::core::mem::uninitialized();
-        let offset = &invalid.$field as *const _ as usize - &invalid as *const _ as usize;
-
-        // Do not run destructors on the made up invalid instance.
-        ::core::mem::forget(invalid);
-        offset as isize
-    }};
-}
index 47f537caf31c45bddb197416b706b5c177cdd8dc..553980d463fc5e8799870fbc004d61fa52d35835 100644 (file)
 #[cfg(test)]
 use std::boxed::Box;
 
+use core::any::Any;
 use core::borrow;
 use core::cell::Cell;
 use core::cmp::Ordering;
 use core::intrinsics::abort;
 use core::marker;
 use core::marker::Unsize;
-use core::mem::{self, forget, size_of_val, uninitialized};
+use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
@@ -358,7 +359,9 @@ pub fn try_unwrap(this: Self) -> Result<T, Self> {
             Err(this)
         }
     }
+}
 
+impl<T: ?Sized> Rc<T> {
     /// Consumes the `Rc`, returning the wrapped pointer.
     ///
     /// To avoid a memory leak the pointer must be converted back to an `Rc` using
@@ -412,17 +415,21 @@ pub fn into_raw(this: Self) -> *const T {
     /// ```
     #[stable(feature = "rc_raw", since = "1.17.0")]
     pub unsafe fn from_raw(ptr: *const T) -> Self {
-        // To find the corresponding pointer to the `RcBox` we need to subtract the offset of the
-        // `value` field from the pointer.
+        // Align the unsized value to the end of the RcBox.
+        // Because it is ?Sized, it will always be the last field in memory.
+        let align = align_of_val(&*ptr);
+        let layout = Layout::new::<RcBox<()>>();
+        let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
+
+        // Reverse the offset to find the original RcBox.
+        let fake_ptr = ptr as *mut RcBox<T>;
+        let rc_ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
 
-        let ptr = (ptr as *const u8).offset(-offset_of!(RcBox<T>, value));
         Rc {
-            ptr: Shared::new_unchecked(ptr as *mut u8 as *mut _)
+            ptr: Shared::new_unchecked(rc_ptr),
         }
     }
-}
 
-impl<T: ?Sized> Rc<T> {
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///
     /// [weak]: struct.Weak.html
@@ -608,6 +615,46 @@ pub fn make_mut(this: &mut Self) -> &mut T {
     }
 }
 
+impl Rc<Any> {
+    #[inline]
+    #[unstable(feature = "rc_downcast", issue = "44608")]
+    /// Attempt to downcast the `Rc<Any>` to a concrete type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(rc_downcast)]
+    /// use std::any::Any;
+    /// use std::rc::Rc;
+    ///
+    /// fn print_if_string(value: Rc<Any>) {
+    ///     if let Ok(string) = value.downcast::<String>() {
+    ///         println!("String ({}): {}", string.len(), string);
+    ///     }
+    /// }
+    ///
+    /// fn main() {
+    ///     let my_string = "Hello World".to_string();
+    ///     print_if_string(Rc::new(my_string));
+    ///     print_if_string(Rc::new(0i8));
+    /// }
+    /// ```
+    pub fn downcast<T: Any>(self) -> Result<Rc<T>, Rc<Any>> {
+        if (*self).is::<T>() {
+            // avoid the pointer arithmetic in from_raw
+            unsafe {
+                let raw: *const RcBox<Any> = self.ptr.as_ptr();
+                forget(self);
+                Ok(Rc {
+                    ptr: Shared::new_unchecked(raw as *const RcBox<T> as *mut _),
+                })
+            }
+        } else {
+            Err(self)
+        }
+    }
+}
+
 impl<T: ?Sized> Rc<T> {
     // Allocates an `RcBox<T>` with sufficient space for an unsized value
     unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
@@ -1481,6 +1528,28 @@ fn into_from_raw() {
         }
     }
 
+    #[test]
+    fn test_into_from_raw_unsized() {
+        use std::fmt::Display;
+        use std::string::ToString;
+
+        let rc: Rc<str> = Rc::from("foo");
+
+        let ptr = Rc::into_raw(rc.clone());
+        let rc2 = unsafe { Rc::from_raw(ptr) };
+
+        assert_eq!(unsafe { &*ptr }, "foo");
+        assert_eq!(rc, rc2);
+
+        let rc: Rc<Display> = Rc::new(123);
+
+        let ptr = Rc::into_raw(rc.clone());
+        let rc2 = unsafe { Rc::from_raw(ptr) };
+
+        assert_eq!(unsafe { &*ptr }.to_string(), "123");
+        assert_eq!(rc2.to_string(), "123");
+    }
+
     #[test]
     fn get_mut() {
         let mut x = Rc::new(3);
@@ -1696,6 +1765,26 @@ fn test_from_vec() {
 
         assert_eq!(&r[..], [1, 2, 3]);
     }
+
+    #[test]
+    fn test_downcast() {
+        use std::any::Any;
+
+        let r1: Rc<Any> = Rc::new(i32::max_value());
+        let r2: Rc<Any> = Rc::new("abc");
+
+        assert!(r1.clone().downcast::<u32>().is_err());
+
+        let r1i32 = r1.downcast::<i32>();
+        assert!(r1i32.is_ok());
+        assert_eq!(r1i32.unwrap(), Rc::new(i32::max_value()));
+
+        assert!(r2.clone().downcast::<i32>().is_err());
+
+        let r2str = r2.downcast::<&'static str>();
+        assert!(r2str.is_ok());
+        assert_eq!(r2str.unwrap(), Rc::new("abc"));
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index f0c63a2eb55d5cb99f58c2861f8e3e7b2f428a4f..62b5f13675c231c31012fa755749683a94255c59 100644 (file)
@@ -855,6 +855,19 @@ pub fn lines_any(&self) -> LinesAny {
     }
 
     /// Returns an iterator of `u16` over the string encoded as UTF-16.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let text = "Zażółć gęślą jaźń";
+    ///
+    /// let utf8_len = text.len();
+    /// let utf16_len = text.encode_utf16().count();
+    ///
+    /// assert!(utf16_len <= utf8_len);
+    /// ```
     #[stable(feature = "encode_utf16", since = "1.8.0")]
     pub fn encode_utf16(&self) -> EncodeUtf16 {
         EncodeUtf16 { encoder: Utf16Encoder::new(self[..].chars()) }
@@ -1783,6 +1796,17 @@ pub fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
     }
 
     /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// let s = "this is a string";
+    /// let boxed_str = s.to_owned().into_boxed_str();
+    /// let boxed_bytes = boxed_str.into_boxed_bytes();
+    /// assert_eq!(*boxed_bytes, *s.as_bytes());
+    /// ```
     #[stable(feature = "str_box_extras", since = "1.20.0")]
     pub fn into_boxed_bytes(self: Box<str>) -> Box<[u8]> {
         self.into()
@@ -2050,6 +2074,17 @@ pub fn repeat(&self, n: usize) -> String {
 
 /// Converts a boxed slice of bytes to a boxed string slice without checking
 /// that the string contains valid UTF-8.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// let smile_utf8 = Box::new([226, 152, 186]);
+/// let smile = unsafe { std::str::from_boxed_utf8_unchecked(smile_utf8) };
+///
+/// assert_eq!("☺", &*smile);
+/// ```
 #[stable(feature = "str_box_extras", since = "1.20.0")]
 pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
     mem::transmute(v)
index 1708f3e398756d493b22d8ec6c8810363c6ede06..46b96df1eabd7405720f29346e58484b800f1866 100644 (file)
@@ -622,6 +622,13 @@ pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
     /// Decode a UTF-16 encoded slice `v` into a `String`, replacing
     /// invalid data with the replacement character (U+FFFD).
     ///
+    /// Unlike [`from_utf8_lossy`] which returns a [`Cow<'a, str>`],
+    /// `from_utf16_lossy` returns a `String` since the UTF-16 to UTF-8
+    /// conversion requires a memory allocation.
+    ///
+    /// [`from_utf8_lossy`]: #method.from_utf8_lossy
+    /// [`Cow<'a, str>`]: ../borrow/enum.Cow.html
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -759,7 +766,22 @@ pub fn as_str(&self) -> &str {
         self
     }
 
-    /// Extracts a string slice containing the entire string.
+    /// Converts a `String` into a mutable string slice.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// use std::ascii::AsciiExt;
+    ///
+    /// let mut s = String::from("foobar");
+    /// let s_mut_str = s.as_mut_str();
+    ///
+    /// s_mut_str.make_ascii_uppercase();
+    ///
+    /// assert_eq!("FOOBAR", s_mut_str);
+    /// ```
     #[inline]
     #[stable(feature = "string_as_str", since = "1.7.0")]
     pub fn as_mut_str(&mut self) -> &mut str {
index 8141851b8c9af9cbd22567a94cc40309a55bccfd..45574bad9ac07eb93b2abeb5629e73445fd6bbac 100644 (file)
@@ -370,6 +370,7 @@ pub fn with_capacity(capacity: usize) -> Vec<T> {
     ///
     /// * `ptr` needs to have been previously allocated via [`String`]/`Vec<T>`
     ///   (at least, it's highly likely to be incorrect if it wasn't).
+    /// * `ptr`'s `T` needs to have the same size and alignment as it was allocated with.
     /// * `length` needs to be less than or equal to `capacity`.
     /// * `capacity` needs to be the capacity that the pointer was allocated with.
     ///
@@ -1969,16 +1970,19 @@ pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<I::IntoIter>
     /// Using this method is equivalent to the following code:
     ///
     /// ```
-    /// # let some_predicate = |x: &mut i32| { *x == 2 };
-    /// # let mut vec = vec![1, 2, 3, 4, 5];
+    /// # let some_predicate = |x: &mut i32| { *x == 2 || *x == 3 || *x == 6 };
+    /// # let mut vec = vec![1, 2, 3, 4, 5, 6];
     /// let mut i = 0;
     /// while i != vec.len() {
     ///     if some_predicate(&mut vec[i]) {
     ///         let val = vec.remove(i);
     ///         // your code here
+    ///     } else {
+    ///         i += 1;
     ///     }
-    ///     i += 1;
     /// }
+    ///
+    /// # assert_eq!(vec, vec![1, 4, 5]);
     /// ```
     ///
     /// But `drain_filter` is easier to use. `drain_filter` is also more efficient,
index 38ffaf97aa418cc369ca0197a72a0b927cc0f622..ef4951582f620c589cd9e18ec182538bf116bce3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 38ffaf97aa418cc369ca0197a72a0b927cc0f622
+Subproject commit ef4951582f620c589cd9e18ec182538bf116bce3
index 5b06229c21f23367f0682273c1926884659afe12..827c6354c60baccab3033212df5ec052c0a14df7 100644 (file)
@@ -146,3 +146,41 @@ fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
         acc
     });
 }
+
+#[bench]
+fn bench_flat_map_sum(b: &mut Bencher) {
+    b.iter(|| -> i64 {
+        (0i64..1000).flat_map(|x| x..x+1000)
+            .map(black_box)
+            .sum()
+    });
+}
+
+#[bench]
+fn bench_flat_map_ref_sum(b: &mut Bencher) {
+    b.iter(|| -> i64 {
+        (0i64..1000).flat_map(|x| x..x+1000)
+            .map(black_box)
+            .by_ref()
+            .sum()
+    });
+}
+
+#[bench]
+fn bench_flat_map_chain_sum(b: &mut Bencher) {
+    b.iter(|| -> i64 {
+        (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
+            .map(black_box)
+            .sum()
+    });
+}
+
+#[bench]
+fn bench_flat_map_chain_ref_sum(b: &mut Bencher) {
+    b.iter(|| -> i64 {
+        (0i64..1000000).flat_map(|x| once(x).chain(once(x)))
+            .map(black_box)
+            .by_ref()
+            .sum()
+    });
+}
index e0a3b8d52f40efb5df9180a1b741928196675fed..b9c5ff10f87b976670101468f2ed7fac070b6482 100644 (file)
@@ -329,6 +329,7 @@ impl<T> Cell<T> {
     /// let c = Cell::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_cell_new"))]
     #[inline]
     pub const fn new(value: T) -> Cell<T> {
         Cell {
@@ -543,6 +544,7 @@ impl<T> RefCell<T> {
     /// let c = RefCell::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_refcell_new"))]
     #[inline]
     pub const fn new(value: T) -> RefCell<T> {
         RefCell {
@@ -1188,6 +1190,7 @@ impl<T> UnsafeCell<T> {
     /// let uc = UnsafeCell::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_unsafe_cell_new"))]
     #[inline]
     pub const fn new(value: T) -> UnsafeCell<T> {
         UnsafeCell { value: value }
index ec6525485f7a1d2a5107d4490f90ae8370936d51..6f86f8caad07343cc87f94310fc75040a00a2856 100644 (file)
@@ -453,12 +453,10 @@ pub trait Ord: Eq + PartialOrd<Self> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(ord_max_min)]
-    ///
     /// assert_eq!(2, 1.max(2));
     /// assert_eq!(2, 2.max(2));
     /// ```
-    #[unstable(feature = "ord_max_min", issue = "25663")]
+    #[stable(feature = "ord_max_min", since = "1.22.0")]
     fn max(self, other: Self) -> Self
     where Self: Sized {
         if other >= self { other } else { self }
@@ -471,12 +469,10 @@ fn max(self, other: Self) -> Self
     /// # Examples
     ///
     /// ```
-    /// #![feature(ord_max_min)]
-    ///
     /// assert_eq!(1, 1.min(2));
     /// assert_eq!(2, 2.min(2));
     /// ```
-    #[unstable(feature = "ord_max_min", issue = "25663")]
+    #[stable(feature = "ord_max_min", since = "1.22.0")]
     fn min(self, other: Self) -> Self
     where Self: Sized {
         if self <= other { self } else { other }
index 607f6f3701799c3337f0bad75fe5878f17c34fd9..f7f1dd12d28b150be07d9bd7b58a45ef5bc6e078 100644 (file)
     /// // The no-copy, unsafe way, still using transmute, but not UB.
     /// // This is equivalent to the original, but safer, and reuses the
     /// // same Vec internals. Therefore the new inner type must have the
-    /// // exact same size, and the same or lesser alignment, as the old
-    /// // type. The same caveats exist for this method as transmute, for
+    /// // exact same size, and the same alignment, as the old type.
+    /// // The same caveats exist for this method as transmute, for
     /// // the original inner type (`&i32`) to the converted inner type
     /// // (`Option<&i32>`), so read the nomicon pages linked above.
     /// let v_from_raw = unsafe {
-    ///     Vec::from_raw_parts(v_orig.as_mut_ptr(),
+    ///     Vec::from_raw_parts(v_orig.as_mut_ptr() as *mut Option<&i32>,
     ///                         v_orig.len(),
     ///                         v_orig.capacity())
     /// };
index ebedfe1d743bb37583c7ac4ccd70f670a19dc5ac..a596ffd6ae8fc9caf840b117cc7857ff0bf4e4c3 100644 (file)
@@ -1902,6 +1902,16 @@ fn size_hint(&self) -> (usize, Option<usize>) {
             _ => (lo, None)
         }
     }
+
+    #[inline]
+    fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
+        where Fold: FnMut(Acc, Self::Item) -> Acc,
+    {
+        self.frontiter.into_iter()
+            .chain(self.iter.map(self.f).map(U::into_iter))
+            .chain(self.backiter)
+            .fold(init, |acc, iter| iter.fold(acc, &mut fold))
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index c270c6ae0dbad23944db36f3d19ff8ecc2b885e2..69612bd2a32a4e838d103ff829bc65c05c6b7ff2 100644 (file)
 #![feature(prelude_import)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
+#![cfg_attr(not(stage0), feature(rustc_const_unstable))]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 
+#![cfg_attr(not(stage0), feature(const_min_value))]
+#![cfg_attr(not(stage0), feature(const_max_value))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_isize_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_usize_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i8_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u8_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i16_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u16_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i32_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u32_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i64_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u64_new))]
+#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))]
+#![cfg_attr(not(stage0), feature(const_cell_new))]
+#![cfg_attr(not(stage0), feature(const_nonzero_new))]
+
 #[prelude_import]
 #[allow(unused)]
 use prelude::v1::*;
index af2f876a2f35906010bad6e63e94c1d8c4ceeca6..3e24623dad89533f57975c00abc6c427d399cf9b 100644 (file)
@@ -189,6 +189,7 @@ pub fn forget<T>(t: T) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_size_of"))]
 pub const fn size_of<T>() -> usize {
     unsafe { intrinsics::size_of::<T>() }
 }
@@ -280,6 +281,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_align_of"))]
 pub const fn align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
@@ -712,39 +714,39 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
 /// Opaque type representing the discriminant of an enum.
 ///
 /// See the `discriminant` function in this module for more information.
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 pub struct Discriminant<T>(u64, PhantomData<*const T>);
 
 // N.B. These trait implementations cannot be derived because we don't want any bounds on T.
 
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 impl<T> Copy for Discriminant<T> {}
 
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 impl<T> clone::Clone for Discriminant<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 impl<T> cmp::PartialEq for Discriminant<T> {
     fn eq(&self, rhs: &Self) -> bool {
         self.0 == rhs.0
     }
 }
 
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 impl<T> cmp::Eq for Discriminant<T> {}
 
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 impl<T> hash::Hash for Discriminant<T> {
     fn hash<H: hash::Hasher>(&self, state: &mut H) {
         self.0.hash(state);
     }
 }
 
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 impl<T> fmt::Debug for Discriminant<T> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt.debug_tuple("Discriminant")
@@ -777,7 +779,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 /// assert!(mem::discriminant(&Foo::B(1))     == mem::discriminant(&Foo::B(2)));
 /// assert!(mem::discriminant(&Foo::B(3))     != mem::discriminant(&Foo::C(3)));
 /// ```
-#[stable(feature = "discriminant_value", since = "1.22.0")]
+#[stable(feature = "discriminant_value", since = "1.21.0")]
 pub fn discriminant<T>(v: &T) -> Discriminant<T> {
     unsafe {
         Discriminant(intrinsics::discriminant_value(v), PhantomData)
index 3ff1068b93763581de7f71133b75bd8194eb1ea6..f075d825f5d53f81f5f03bf8bf277c5596004fac 100644 (file)
@@ -68,6 +68,10 @@ fn is_zero(&self) -> bool {
 impl<T: Zeroable> NonZero<T> {
     /// Creates an instance of NonZero with the provided value.
     /// You must indeed ensure that the value is actually "non-zero".
+    #[unstable(feature = "nonzero",
+               reason = "needs an RFC to flesh out the design",
+               issue = "27730")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_nonzero_new"))]
     #[inline]
     pub const unsafe fn new_unchecked(inner: T) -> Self {
         NonZero(inner)
index c5175287ccfa63cf5ff654583bb4ee454b7391c4..bf31deae7a62576330f198c04ee8f62cb973a4a7 100644 (file)
@@ -109,6 +109,7 @@ macro_rules! int_impl {
         /// assert_eq!(i8::min_value(), -128);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_min_value"))]
         #[inline]
         pub const fn min_value() -> Self {
             !0 ^ ((!0 as $UnsignedT) >> 1) as Self
@@ -122,6 +123,7 @@ pub const fn min_value() -> Self {
         /// assert_eq!(i8::max_value(), 127);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_max_value"))]
         #[inline]
         pub const fn max_value() -> Self {
             !Self::min_value()
@@ -1280,6 +1282,7 @@ macro_rules! uint_impl {
         /// assert_eq!(u8::min_value(), 0);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_min_value"))]
         #[inline]
         pub const fn min_value() -> Self { 0 }
 
@@ -1291,6 +1294,7 @@ pub const fn min_value() -> Self { 0 }
         /// assert_eq!(u8::max_value(), 255);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_max_value"))]
         #[inline]
         pub const fn max_value() -> Self { !0 }
 
index 2e42e0dfd550d3b04d5a67907f2807054e100c02..dd01534ec02d98a593b8eee3e070e0347edfdd72 100644 (file)
@@ -51,7 +51,7 @@
 ///   as the compiler doesn't need to prove that it's sound to elide the
 ///   copy.
 ///
-/// # Undefined Behavior
+/// # Safety
 ///
 /// This has all the same safety problems as `ptr::read` with respect to
 /// invalid pointers, types, and double drops.
@@ -76,6 +76,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_null"))]
 pub const fn null<T>() -> *const T { 0 as *const T }
 
 /// Creates a null mutable raw pointer.
@@ -90,6 +91,7 @@ pub const fn null<T>() -> *const T { 0 as *const T }
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_null_mut"))]
 pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
 
 /// Swaps the values at two mutable locations of the same type, without
@@ -525,15 +527,41 @@ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
         }
     }
 
-    /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
-    /// `count` of 3 represents a pointer offset of `3 * size_of::<T>()` bytes.
+    /// Calculates the offset from a pointer.
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// Both the starting and resulting pointer must be either in bounds or one
-    /// byte past the end of an allocated object. If either pointer is out of
-    /// bounds or arithmetic overflow occurs then
-    /// any further use of the returned value will result in undefined behavior.
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of an allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow or underflow an
+    ///   `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().offset(vec.len() as isize)` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2^63 bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using `wrapping_offset` instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
     ///
     /// # Examples
     ///
@@ -555,6 +583,7 @@ pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {
     }
 
     /// Calculates the offset from a pointer using wrapping arithmetic.
+    ///
     /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
     /// offset of `3 * size_of::<T>()` bytes.
     ///
@@ -630,6 +659,412 @@ pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
             Some(diff / size as isize)
         }
     }
+
+    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of an allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow or underflow an
+    ///   `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a `usize`.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2^63 bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using `wrapping_offset` instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let s: &str = "123";
+    /// let ptr: *const u8 = s.as_ptr();
+    ///
+    /// unsafe {
+    ///     println!("{}", *ptr.add(1) as char);
+    ///     println!("{}", *ptr.add(2) as char);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn add(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer (convenience for
+    /// `.offset((count as isize).wrapping_neg())`).
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of an allocated object.
+    ///
+    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2^63 bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using `wrapping_offset` instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let s: &str = "123";
+    ///
+    /// unsafe {
+    ///     let end: *const u8 = s.as_ptr().add(3);
+    ///     println!("{}", *end.sub(1) as char);
+    ///     println!("{}", *end.sub(2) as char);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn sub(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.offset((count as isize).wrapping_neg())
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset(count as isize)`)
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// Always use `.add(count)` instead when possible, because `add`
+    /// allows the compiler to optimize better.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// // Iterate using a raw pointer in increments of two elements
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let step = 2;
+    /// let end_rounded_up = ptr.wrapping_add(6);
+    ///
+    /// // This loop prints "1, 3, 5, "
+    /// while ptr != end_rounded_up {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_add(step);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub fn wrapping_add(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.wrapping_offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// Always use `.sub(count)` instead when possible, because `sub`
+    /// allows the compiler to optimize better.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// // Iterate using a raw pointer in increments of two elements (backwards)
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let start_rounded_down = ptr.wrapping_sub(2);
+    /// ptr = ptr.wrapping_add(4);
+    /// let step = 2;
+    /// // This loop prints "5, 3, 1, "
+    /// while ptr != start_rounded_down {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_sub(step);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub fn wrapping_sub(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.wrapping_offset((count as isize).wrapping_neg())
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// # Safety
+    ///
+    /// Beyond accepting a raw pointer, this is unsafe because it semantically
+    /// moves the value out of `self` without preventing further usage of `self`.
+    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
+    /// `self` is not used before the data is overwritten again (e.g. with `write`,
+    /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use
+    /// because it will attempt to drop the value previously at `*self`.
+    ///
+    /// The pointer must be aligned; use `read_unaligned` if that is not the case.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let x = 12;
+    /// let y = &x as *const i32;
+    ///
+    /// unsafe {
+    ///     assert_eq!(y.read(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn read(self) -> T
+        where T: Sized,
+    {
+        read(self)
+    }
+
+    /// Performs a volatile read of the value from `self` without moving it. This
+    /// leaves the memory in `self` unchanged.
+    ///
+    /// Volatile operations are intended to act on I/O memory, and are guaranteed
+    /// to not be elided or reordered by the compiler across other volatile
+    /// operations.
+    ///
+    /// # Notes
+    ///
+    /// Rust does not currently have a rigorously and formally defined memory model,
+    /// so the precise semantics of what "volatile" means here is subject to change
+    /// over time. That being said, the semantics will almost always end up pretty
+    /// similar to [C11's definition of volatile][c11].
+    ///
+    /// The compiler shouldn't change the relative order or number of volatile
+    /// memory operations. However, volatile memory operations on zero-sized types
+    /// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops
+    /// and may be ignored.
+    ///
+    /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+    ///
+    /// # Safety
+    ///
+    /// Beyond accepting a raw pointer, this is unsafe because it semantically
+    /// moves the value out of `self` without preventing further usage of `self`.
+    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
+    /// `self` is not used before the data is overwritten again (e.g. with `write`,
+    /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use
+    /// because it will attempt to drop the value previously at `*self`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let x = 12;
+    /// let y = &x as *const i32;
+    ///
+    /// unsafe {
+    ///     assert_eq!(y.read_volatile(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn read_volatile(self) -> T
+        where T: Sized,
+    {
+        read_volatile(self)
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// Unlike `read`, the pointer may be unaligned.
+    ///
+    /// # Safety
+    ///
+    /// Beyond accepting a raw pointer, this is unsafe because it semantically
+    /// moves the value out of `self` without preventing further usage of `self`.
+    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
+    /// `self` is not used before the data is overwritten again (e.g. with `write`,
+    /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use
+    /// because it will attempt to drop the value previously at `*self`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let x = 12;
+    /// let y = &x as *const i32;
+    ///
+    /// unsafe {
+    ///     assert_eq!(y.read_unaligned(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn read_unaligned(self) -> T
+        where T: Sized,
+    {
+        read_unaligned(self)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may overlap.
+    ///
+    /// NOTE: this has the *same* argument order as `ptr::copy`.
+    ///
+    /// This is semantically equivalent to C's `memmove`.
+    ///
+    /// # Safety
+    ///
+    /// Care must be taken with the ownership of `self` and `dest`.
+    /// This method semantically moves the values of `self` into `dest`.
+    /// However it does not drop the contents of `self`, or prevent the contents
+    /// of `dest` from being dropped or used.
+    ///
+    /// # Examples
+    ///
+    /// Efficiently create a Rust vector from an unsafe buffer:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// # #[allow(dead_code)]
+    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
+    ///     let mut dst = Vec::with_capacity(elts);
+    ///     dst.set_len(elts);
+    ///     ptr.copy_to(dst.as_mut_ptr(), elts);
+    ///     dst
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+        where T: Sized,
+    {
+        copy(self, dest, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may *not* overlap.
+    ///
+    /// NOTE: this has the *same* argument order as `ptr::copy_nonoverlapping`.
+    ///
+    /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`.
+    ///
+    /// # Safety
+    ///
+    /// Beyond requiring that the program must be allowed to access both regions
+    /// of memory, it is Undefined Behavior for source and destination to
+    /// overlap. Care must also be taken with the ownership of `self` and
+    /// `self`. This method semantically moves the values of `self` into `dest`.
+    /// However it does not drop the contents of `dest`, or prevent the contents
+    /// of `self` from being dropped or used.
+    ///
+    /// # Examples
+    ///
+    /// Efficiently create a Rust vector from an unsafe buffer:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// # #[allow(dead_code)]
+    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
+    ///     let mut dst = Vec::with_capacity(elts);
+    ///     dst.set_len(elts);
+    ///     ptr.copy_to_nonoverlapping(dst.as_mut_ptr(), elts);
+    ///     dst
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+        where T: Sized,
+    {
+        copy_nonoverlapping(self, dest, count)
+    }
+
+
 }
 
 #[lang = "mut_ptr"]
@@ -687,14 +1122,41 @@ pub unsafe fn as_ref<'a>(self) -> Option<&'a T> where T: Sized {
         }
     }
 
-    /// Calculates the offset from a pointer. `count` is in units of T; e.g. a
-    /// `count` of 3 represents a pointer offset of `3 * size_of::<T>()` bytes.
+    /// Calculates the offset from a pointer.
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
     ///
     /// # Safety
     ///
-    /// The offset must be in-bounds of the object, or one-byte-past-the-end.
-    /// Otherwise `offset` invokes Undefined Behavior, regardless of whether
-    /// the pointer is used.
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of an allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow or underflow an
+    ///   `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum, **in bytes** must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().offset(vec.len() as isize)` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2^63 bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using `wrapping_offset` instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
     ///
     /// # Examples
     ///
@@ -821,37 +1283,739 @@ pub fn offset_to(self, other: *const T) -> Option<isize> where T: Sized {
             Some(diff / size as isize)
         }
     }
-}
-
-// Equality for pointers
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialEq for *const T {
-    #[inline]
-    fn eq(&self, other: &*const T) -> bool { *self == *other }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Eq for *const T {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> PartialEq for *mut T {
-    #[inline]
-    fn eq(&self, other: &*mut T) -> bool { *self == *other }
-}
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: ?Sized> Eq for *mut T {}
 
-/// Compare raw pointers for equality.
-///
-/// This is the same as using the `==` operator, but less generic:
-/// the arguments have to be `*const T` raw pointers,
-/// not anything that implements `PartialEq`.
-///
-/// This can be used to compare `&T` references (which coerce to `*const T` implicitly)
-/// by their address rather than comparing the values they point to
-/// (which is what the `PartialEq for &T` implementation does).
-///
+    /// Calculates the offset from a pointer (convenience for `.offset(count as isize)`).
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of an allocated object.
+    ///
+    /// * The computed offset, **in bytes**, cannot overflow or underflow an
+    ///   `isize`.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a `usize`.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2^63 bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using `wrapping_offset` instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let s: &str = "123";
+    /// let ptr: *const u8 = s.as_ptr();
+    ///
+    /// unsafe {
+    ///     println!("{}", *ptr.add(1) as char);
+    ///     println!("{}", *ptr.add(2) as char);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn add(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer (convenience for
+    /// `.offset((count as isize).wrapping_neg())`).
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// If any of the following conditions are violated, the result is Undefined
+    /// Behavior:
+    ///
+    /// * Both the starting and resulting pointer must be either in bounds or one
+    ///   byte past the end of an allocated object.
+    ///
+    /// * The computed offset cannot exceed `isize::MAX` **bytes**.
+    ///
+    /// * The offset being in bounds cannot rely on "wrapping around" the address
+    ///   space. That is, the infinite-precision sum must fit in a usize.
+    ///
+    /// The compiler and standard library generally tries to ensure allocations
+    /// never reach a size where an offset is a concern. For instance, `Vec`
+    /// and `Box` ensure they never allocate more than `isize::MAX` bytes, so
+    /// `vec.as_ptr().add(vec.len()).sub(vec.len())` is always safe.
+    ///
+    /// Most platforms fundamentally can't even construct such an allocation.
+    /// For instance, no known 64-bit platform can ever serve a request
+    /// for 2^63 bytes due to page-table limitations or splitting the address space.
+    /// However, some 32-bit and 16-bit platforms may successfully serve a request for
+    /// more than `isize::MAX` bytes with things like Physical Address
+    /// Extension. As such, memory acquired directly from allocators or memory
+    /// mapped files *may* be too large to handle with this function.
+    ///
+    /// Consider using `wrapping_offset` instead if these constraints are
+    /// difficult to satisfy. The only advantage of this method is that it
+    /// enables more aggressive compiler optimizations.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let s: &str = "123";
+    ///
+    /// unsafe {
+    ///     let end: *const u8 = s.as_ptr().add(3);
+    ///     println!("{}", *end.sub(1) as char);
+    ///     println!("{}", *end.sub(2) as char);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn sub(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.offset((count as isize).wrapping_neg())
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset(count as isize)`)
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// Always use `.add(count)` instead when possible, because `add`
+    /// allows the compiler to optimize better.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// // Iterate using a raw pointer in increments of two elements
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let step = 2;
+    /// let end_rounded_up = ptr.wrapping_add(6);
+    ///
+    /// // This loop prints "1, 3, 5, "
+    /// while ptr != end_rounded_up {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_add(step);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub fn wrapping_add(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.wrapping_offset(count as isize)
+    }
+
+    /// Calculates the offset from a pointer using wrapping arithmetic.
+    /// (convenience for `.wrapping_offset((count as isize).wrapping_sub())`)
+    ///
+    /// `count` is in units of T; e.g. a `count` of 3 represents a pointer
+    /// offset of `3 * size_of::<T>()` bytes.
+    ///
+    /// # Safety
+    ///
+    /// The resulting pointer does not need to be in bounds, but it is
+    /// potentially hazardous to dereference (which requires `unsafe`).
+    ///
+    /// Always use `.sub(count)` instead when possible, because `sub`
+    /// allows the compiler to optimize better.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// // Iterate using a raw pointer in increments of two elements (backwards)
+    /// let data = [1u8, 2, 3, 4, 5];
+    /// let mut ptr: *const u8 = data.as_ptr();
+    /// let start_rounded_down = ptr.wrapping_sub(2);
+    /// ptr = ptr.wrapping_add(4);
+    /// let step = 2;
+    /// // This loop prints "5, 3, 1, "
+    /// while ptr != start_rounded_down {
+    ///     unsafe {
+    ///         print!("{}, ", *ptr);
+    ///     }
+    ///     ptr = ptr.wrapping_sub(step);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub fn wrapping_sub(self, count: usize) -> Self
+        where T: Sized,
+    {
+        self.wrapping_offset((count as isize).wrapping_neg())
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// # Safety
+    ///
+    /// Beyond accepting a raw pointer, this is unsafe because it semantically
+    /// moves the value out of `self` without preventing further usage of `self`.
+    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
+    /// `self` is not used before the data is overwritten again (e.g. with `write`,
+    /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use
+    /// because it will attempt to drop the value previously at `*self`.
+    ///
+    /// The pointer must be aligned; use `read_unaligned` if that is not the case.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let x = 12;
+    /// let y = &x as *const i32;
+    ///
+    /// unsafe {
+    ///     assert_eq!(y.read(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn read(self) -> T
+        where T: Sized,
+    {
+        read(self)
+    }
+
+    /// Performs a volatile read of the value from `self` without moving it. This
+    /// leaves the memory in `self` unchanged.
+    ///
+    /// Volatile operations are intended to act on I/O memory, and are guaranteed
+    /// to not be elided or reordered by the compiler across other volatile
+    /// operations.
+    ///
+    /// # Notes
+    ///
+    /// Rust does not currently have a rigorously and formally defined memory model,
+    /// so the precise semantics of what "volatile" means here is subject to change
+    /// over time. That being said, the semantics will almost always end up pretty
+    /// similar to [C11's definition of volatile][c11].
+    ///
+    /// The compiler shouldn't change the relative order or number of volatile
+    /// memory operations. However, volatile memory operations on zero-sized types
+    /// (e.g. if a zero-sized type is passed to `read_volatile`) are no-ops
+    /// and may be ignored.
+    ///
+    /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+    ///
+    /// # Safety
+    ///
+    /// Beyond accepting a raw pointer, this is unsafe because it semantically
+    /// moves the value out of `self` without preventing further usage of `self`.
+    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
+    /// `src` is not used before the data is overwritten again (e.g. with `write`,
+    /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use
+    /// because it will attempt to drop the value previously at `*self`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let x = 12;
+    /// let y = &x as *const i32;
+    ///
+    /// unsafe {
+    ///     assert_eq!(y.read_volatile(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn read_volatile(self) -> T
+        where T: Sized,
+    {
+        read_volatile(self)
+    }
+
+    /// Reads the value from `self` without moving it. This leaves the
+    /// memory in `self` unchanged.
+    ///
+    /// Unlike `read`, the pointer may be unaligned.
+    ///
+    /// # Safety
+    ///
+    /// Beyond accepting a raw pointer, this is unsafe because it semantically
+    /// moves the value out of `self` without preventing further usage of `self`.
+    /// If `T` is not `Copy`, then care must be taken to ensure that the value at
+    /// `self` is not used before the data is overwritten again (e.g. with `write`,
+    /// `zero_memory`, or `copy_memory`). Note that `*self = foo` counts as a use
+    /// because it will attempt to drop the value previously at `*self`.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let x = 12;
+    /// let y = &x as *const i32;
+    ///
+    /// unsafe {
+    ///     assert_eq!(y.read_unaligned(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn read_unaligned(self) -> T
+        where T: Sized,
+    {
+        read_unaligned(self)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may overlap.
+    ///
+    /// NOTE: this has the *same* argument order as `ptr::copy`.
+    ///
+    /// This is semantically equivalent to C's `memmove`.
+    ///
+    /// # Safety
+    ///
+    /// Care must be taken with the ownership of `self` and `dest`.
+    /// This method semantically moves the values of `self` into `dest`.
+    /// However it does not drop the contents of `self`, or prevent the contents
+    /// of `dest` from being dropped or used.
+    ///
+    /// # Examples
+    ///
+    /// Efficiently create a Rust vector from an unsafe buffer:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// # #[allow(dead_code)]
+    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
+    ///     let mut dst = Vec::with_capacity(elts);
+    ///     dst.set_len(elts);
+    ///     ptr.copy_to(dst.as_mut_ptr(), elts);
+    ///     dst
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn copy_to(self, dest: *mut T, count: usize)
+        where T: Sized,
+    {
+        copy(self, dest, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `self` to `dest`. The source
+    /// and destination may *not* overlap.
+    ///
+    /// NOTE: this has the *same* argument order as `ptr::copy_nonoverlapping`.
+    ///
+    /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`.
+    ///
+    /// # Safety
+    ///
+    /// Beyond requiring that the program must be allowed to access both regions
+    /// of memory, it is Undefined Behavior for source and destination to
+    /// overlap. Care must also be taken with the ownership of `self` and
+    /// `self`. This method semantically moves the values of `self` into `dest`.
+    /// However it does not drop the contents of `dest`, or prevent the contents
+    /// of `self` from being dropped or used.
+    ///
+    /// # Examples
+    ///
+    /// Efficiently create a Rust vector from an unsafe buffer:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// # #[allow(dead_code)]
+    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
+    ///     let mut dst = Vec::with_capacity(elts);
+    ///     dst.set_len(elts);
+    ///     ptr.copy_to_nonoverlapping(dst.as_mut_ptr(), elts);
+    ///     dst
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn copy_to_nonoverlapping(self, dest: *mut T, count: usize)
+        where T: Sized,
+    {
+        copy_nonoverlapping(self, dest, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
+    /// and destination may overlap.
+    ///
+    /// NOTE: this has the *opposite* argument order of `ptr::copy`.
+    ///
+    /// This is semantically equivalent to C's `memmove`.
+    ///
+    /// # Safety
+    ///
+    /// Care must be taken with the ownership of `src` and `self`.
+    /// This method semantically moves the values of `src` into `self`.
+    /// However it does not drop the contents of `self`, or prevent the contents
+    /// of `src` from being dropped or used.
+    ///
+    /// # Examples
+    ///
+    /// Efficiently create a Rust vector from an unsafe buffer:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// # #[allow(dead_code)]
+    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
+    ///     let mut dst = Vec::with_capacity(elts);
+    ///     dst.set_len(elts);
+    ///     dst.as_mut_ptr().copy_from(ptr, elts);
+    ///     dst
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn copy_from(self, src: *const T, count: usize)
+        where T: Sized,
+    {
+        copy(src, self, count)
+    }
+
+    /// Copies `count * size_of<T>` bytes from `src` to `self`. The source
+    /// and destination may *not* overlap.
+    ///
+    /// NOTE: this has the *opposite* argument order of `ptr::copy_nonoverlapping`.
+    ///
+    /// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`.
+    ///
+    /// # Safety
+    ///
+    /// Beyond requiring that the program must be allowed to access both regions
+    /// of memory, it is Undefined Behavior for source and destination to
+    /// overlap. Care must also be taken with the ownership of `src` and
+    /// `self`. This method semantically moves the values of `src` into `self`.
+    /// However it does not drop the contents of `self`, or prevent the contents
+    /// of `src` from being dropped or used.
+    ///
+    /// # Examples
+    ///
+    /// Efficiently create a Rust vector from an unsafe buffer:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// # #[allow(dead_code)]
+    /// unsafe fn from_buf_raw<T: Copy>(ptr: *const T, elts: usize) -> Vec<T> {
+    ///     let mut dst = Vec::with_capacity(elts);
+    ///     dst.set_len(elts);
+    ///     dst.as_mut_ptr().copy_from_nonoverlapping(ptr, elts);
+    ///     dst
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn copy_from_nonoverlapping(self, src: *const T, count: usize)
+        where T: Sized,
+    {
+        copy_nonoverlapping(src, self, count)
+    }
+
+    /// Executes the destructor (if any) of the pointed-to value.
+    ///
+    /// This has two use cases:
+    ///
+    /// * It is *required* to use `drop_in_place` to drop unsized types like
+    ///   trait objects, because they can't be read out onto the stack and
+    ///   dropped normally.
+    ///
+    /// * It is friendlier to the optimizer to do this over `ptr::read` when
+    ///   dropping manually allocated memory (e.g. when writing Box/Rc/Vec),
+    ///   as the compiler doesn't need to prove that it's sound to elide the
+    ///   copy.
+    ///
+    /// # Safety
+    ///
+    /// This has all the same safety problems as `ptr::read` with respect to
+    /// invalid pointers, types, and double drops.
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn drop_in_place(self) {
+        drop_in_place(self)
+    }
+
+    /// Overwrites a memory location with the given value without reading or
+    /// dropping the old value.
+    ///
+    /// # Safety
+    ///
+    /// This operation is marked unsafe because it writes through a raw pointer.
+    ///
+    /// It does not drop the contents of `self`. This is safe, but it could leak
+    /// allocations or resources, so care must be taken not to overwrite an object
+    /// that should be dropped.
+    ///
+    /// Additionally, it does not drop `val`. Semantically, `val` is moved into the
+    /// location pointed to by `self`.
+    ///
+    /// This is appropriate for initializing uninitialized memory, or overwriting
+    /// memory that has previously been `read` from.
+    ///
+    /// The pointer must be aligned; use `write_unaligned` if that is not the case.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let mut x = 0;
+    /// let y = &mut x as *mut i32;
+    /// let z = 12;
+    ///
+    /// unsafe {
+    ///     y.write(z);
+    ///     assert_eq!(y.read(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn write(self, val: T)
+        where T: Sized,
+    {
+        write(self, val)
+    }
+
+    /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
+    /// bytes of memory starting at `self` to `val`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let mut vec = vec![0; 4];
+    /// unsafe {
+    ///     let vec_ptr = vec.as_mut_ptr();
+    ///     vec_ptr.write_bytes(b'a', 2);
+    /// }
+    /// assert_eq!(vec, [b'a', b'a', 0, 0]);
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn write_bytes(self, val: u8, count: usize)
+        where T: Sized,
+    {
+        write_bytes(self, val, count)
+    }
+
+    /// Performs a volatile write of a memory location with the given value without
+    /// reading or dropping the old value.
+    ///
+    /// Volatile operations are intended to act on I/O memory, and are guaranteed
+    /// to not be elided or reordered by the compiler across other volatile
+    /// operations.
+    ///
+    /// # Notes
+    ///
+    /// Rust does not currently have a rigorously and formally defined memory model,
+    /// so the precise semantics of what "volatile" means here is subject to change
+    /// over time. That being said, the semantics will almost always end up pretty
+    /// similar to [C11's definition of volatile][c11].
+    ///
+    /// The compiler shouldn't change the relative order or number of volatile
+    /// memory operations. However, volatile memory operations on zero-sized types
+    /// (e.g. if a zero-sized type is passed to `write_volatile`) are no-ops
+    /// and may be ignored.
+    ///
+    /// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+    ///
+    /// # Safety
+    ///
+    /// This operation is marked unsafe because it accepts a raw pointer.
+    ///
+    /// It does not drop the contents of `self`. This is safe, but it could leak
+    /// allocations or resources, so care must be taken not to overwrite an object
+    /// that should be dropped.
+    ///
+    /// This is appropriate for initializing uninitialized memory, or overwriting
+    /// memory that has previously been `read` from.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let mut x = 0;
+    /// let y = &mut x as *mut i32;
+    /// let z = 12;
+    ///
+    /// unsafe {
+    ///     y.write_volatile(z);
+    ///     assert_eq!(y.read_volatile(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn write_volatile(self, val: T)
+        where T: Sized,
+    {
+        write_volatile(self, val)
+    }
+
+    /// Overwrites a memory location with the given value without reading or
+    /// dropping the old value.
+    ///
+    /// Unlike `write`, the pointer may be unaligned.
+    ///
+    /// # Safety
+    ///
+    /// This operation is marked unsafe because it writes through a raw pointer.
+    ///
+    /// It does not drop the contents of `self`. This is safe, but it could leak
+    /// allocations or resources, so care must be taken not to overwrite an object
+    /// that should be dropped.
+    ///
+    /// Additionally, it does not drop `src`. Semantically, `src` is moved into the
+    /// location pointed to by `dst`.
+    ///
+    /// This is appropriate for initializing uninitialized memory, or overwriting
+    /// memory that has previously been `read` from.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(pointer_methods)]
+    ///
+    /// let mut x = 0;
+    /// let y = &mut x as *mut i32;
+    /// let z = 12;
+    ///
+    /// unsafe {
+    ///     y.write_unaligned(z);
+    ///     assert_eq!(y.read_unaligned(), 12);
+    /// }
+    /// ```
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn write_unaligned(self, val: T)
+        where T: Sized,
+    {
+        write_unaligned(self, val)
+    }
+
+    /// Replaces the value at `self` with `src`, returning the old
+    /// value, without dropping either.
+    ///
+    /// # Safety
+    ///
+    /// This is only unsafe because it accepts a raw pointer.
+    /// Otherwise, this operation is identical to `mem::replace`.
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn replace(self, src: T) -> T
+        where T: Sized,
+    {
+        replace(self, src)
+    }
+
+    /// Swaps the values at two mutable locations of the same type, without
+    /// deinitializing either. They may overlap, unlike `mem::swap` which is
+    /// otherwise equivalent.
+    ///
+    /// # Safety
+    ///
+    /// This function copies the memory through the raw pointers passed to it
+    /// as arguments.
+    ///
+    /// Ensure that these pointers are valid before calling `swap`.
+    #[unstable(feature = "pointer_methods", issue = "43941")]
+    #[inline]
+    pub unsafe fn swap(self, with: *mut T)
+        where T: Sized,
+    {
+        swap(self, with)
+    }
+}
+
+// Equality for pointers
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialEq for *const T {
+    #[inline]
+    fn eq(&self, other: &*const T) -> bool { *self == *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Eq for *const T {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> PartialEq for *mut T {
+    #[inline]
+    fn eq(&self, other: &*mut T) -> bool { *self == *other }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: ?Sized> Eq for *mut T {}
+
+/// Compare raw pointers for equality.
+///
+/// This is the same as using the `==` operator, but less generic:
+/// the arguments have to be `*const T` raw pointers,
+/// not anything that implements `PartialEq`.
+///
+/// This can be used to compare `&T` references (which coerce to `*const T` implicitly)
+/// by their address rather than comparing the values they point to
+/// (which is what the `PartialEq for &T` implementation does).
+///
 /// # Examples
 ///
 /// ```
@@ -1097,6 +2261,8 @@ impl<T: ?Sized> Unique<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
+    #[unstable(feature = "unique", issue = "27730")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_unique_new"))]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
     }
@@ -1230,6 +2396,8 @@ impl<T: ?Sized> Shared<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
+    #[unstable(feature = "shared", issue = "27730")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_shared_new"))]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Shared { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
     }
index 31d8266510a1ea652cb400e407829307f90938b5..dacc014955a902f3d79a32f63c71f9ee57a7cb94 100644 (file)
@@ -35,7 +35,6 @@
 // * The `raw` and `bytes` submodules.
 // * Boilerplate trait implementations.
 
-use borrow::Borrow;
 use cmp::Ordering::{self, Less, Equal, Greater};
 use cmp;
 use fmt;
@@ -122,19 +121,17 @@ unsafe fn get_unchecked<I>(&self, index: I) -> &I::Output
     fn as_ptr(&self) -> *const Self::Item;
 
     #[stable(feature = "core", since = "1.6.0")]
-    fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
-        where Self::Item: Borrow<Q>,
-              Q: Ord;
+    fn binary_search(&self, x: &Self::Item) -> Result<usize, usize>
+        where Self::Item: Ord;
 
     #[stable(feature = "core", since = "1.6.0")]
     fn binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> Ordering;
 
     #[stable(feature = "slice_binary_search_by_key", since = "1.10.0")]
-    fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, f: F) -> Result<usize, usize>
+    fn binary_search_by_key<'a, B, F>(&'a self, b: &B, f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> B,
-              B: Borrow<Q>,
-              Q: Ord;
+              B: Ord;
 
     #[stable(feature = "core", since = "1.6.0")]
     fn len(&self) -> usize;
@@ -635,11 +632,10 @@ fn ends_with(&self, needle: &[T]) -> bool where T: PartialEq {
         m >= n && needle == &self[m-n..]
     }
 
-    fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
-        where T: Borrow<Q>,
-              Q: Ord
+    fn binary_search(&self, x: &T) -> Result<usize, usize>
+        where T: Ord
     {
-        self.binary_search_by(|p| p.borrow().cmp(x))
+        self.binary_search_by(|p| p.cmp(x))
     }
 
     fn rotate(&mut self, mid: usize) {
@@ -687,12 +683,11 @@ fn swap_with_slice(&mut self, src: &mut [T]) {
     }
 
     #[inline]
-    fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
+    fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> B,
-              B: Borrow<Q>,
-              Q: Ord
+              B: Ord
     {
-        self.binary_search_by(|k| f(k).borrow().cmp(b))
+        self.binary_search_by(|k| f(k).cmp(b))
     }
 
     #[inline]
index 62e84c9ebd0175f5278e644411e5950493fcfd72..d4fef45ae4e8f1f94cba2c903d4165b1b2076cb0 100644 (file)
@@ -302,6 +302,37 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> {
 }
 
 /// Converts a mutable slice of bytes to a mutable string slice.
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::str;
+///
+/// // "Hello, Rust!" as a mutable vector
+/// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33];
+///
+/// // As we know these bytes are valid, we can use `unwrap()`
+/// let outstr = str::from_utf8_mut(&mut hellorust).unwrap();
+///
+/// assert_eq!("Hello, Rust!", outstr);
+/// ```
+///
+/// Incorrect bytes:
+///
+/// ```
+/// use std::str;
+///
+/// // Some invalid bytes in a mutable vector
+/// let mut invalid = vec![128, 223];
+///
+/// assert!(str::from_utf8_mut(&mut invalid).is_err());
+/// ```
+/// See the docs for [`Utf8Error`][error] for more details on the kinds of
+/// errors that can be returned.
+///
+/// [error]: struct.Utf8Error.html
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
     run_utf8_validation(v)?;
@@ -382,6 +413,19 @@ pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
 /// See the immutable version, [`from_utf8_unchecked()`][fromutf8], for more information.
 ///
 /// [fromutf8]: fn.from_utf8_unchecked.html
+///
+/// # Examples
+///
+/// Basic usage:
+///
+/// ```
+/// use std::str;
+///
+/// let mut heart = vec![240, 159, 146, 150];
+/// let heart = unsafe { str::from_utf8_unchecked_mut(&mut heart) };
+///
+/// assert_eq!("💖", heart);
+/// ```
 #[inline]
 #[stable(feature = "str_mut_extras", since = "1.20.0")]
 pub unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut str {
index 510e01db0e965ed190343d11552ce3343ad52b0f..09f3586a8c99fa96d37881a8540c5304f92eec65 100644 (file)
@@ -241,6 +241,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_atomic_bool_new"))]
     pub const fn new(v: bool) -> AtomicBool {
         AtomicBool { v: UnsafeCell::new(v as u8) }
     }
@@ -649,6 +650,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_atomic_ptr_new"))]
     pub const fn new(p: *mut T) -> AtomicPtr<T> {
         AtomicPtr { p: UnsafeCell::new(p) }
     }
@@ -920,7 +922,7 @@ pub fn compare_exchange_weak(&self,
 
 #[cfg(target_has_atomic = "ptr")]
 macro_rules! atomic_int {
-    ($stable:meta,
+    ($stable:meta, $const_unstable:meta,
      $stable_cxchg:meta,
      $stable_debug:meta,
      $stable_access:meta,
@@ -969,6 +971,7 @@ impl $atomic_type {
             /// ```
             #[inline]
             #[$stable]
+            #[cfg_attr(not(stage0), $const_unstable)]
             pub const fn new(v: $int_type) -> Self {
                 $atomic_type {v: UnsafeCell::new(v)}
             }
@@ -1332,6 +1335,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "8")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i8_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1340,6 +1344,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "8")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u8_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1348,6 +1353,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "16")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i16_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1356,6 +1362,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "16")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u16_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1364,6 +1371,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "32")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i32_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1372,6 +1380,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "32")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u32_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1380,6 +1389,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "64")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i64_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1388,6 +1398,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "64")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u64_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1396,6 +1407,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "ptr")]
 atomic_int!{
     stable(feature = "rust1", since = "1.0.0"),
+    rustc_const_unstable(feature = "const_atomic_isize_new"),
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
@@ -1404,6 +1416,7 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type {
 #[cfg(target_has_atomic = "ptr")]
 atomic_int!{
     stable(feature = "rust1", since = "1.0.0"),
+    rustc_const_unstable(feature = "const_atomic_usize_new"),
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
index ed6923929d6b0b15d0ac294c67fd159c5105af98..59ae30de452c96f9f41ff28cbfbf56779f875502 100644 (file)
@@ -654,6 +654,22 @@ fn test_iterator_flat_map() {
     assert_eq!(i, ys.len());
 }
 
+/// Test `FlatMap::fold` with items already picked off the front and back,
+/// to make sure all parts of the `FlatMap` are folded correctly.
+#[test]
+fn test_iterator_flat_map_fold() {
+    let xs = [0, 3, 6];
+    let ys = [1, 2, 3, 4, 5, 6, 7];
+    let mut it = xs.iter().flat_map(|&x| x..x+3);
+    it.next();
+    it.next_back();
+    let i = it.fold(0, |i, x| {
+        assert_eq!(x, ys[i]);
+        i + 1
+    });
+    assert_eq!(i, ys.len());
+}
+
 #[test]
 fn test_inspect() {
     let xs = [1, 2, 3, 4];
index ab2022b1824ca3a2e5f5b682731d53c52abb5a14..47995597a0a91d16e039dacb7a02a895c2da2290 100644 (file)
@@ -11,7 +11,6 @@
 #![deny(warnings)]
 
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(core_float)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
@@ -27,7 +26,6 @@
 #![feature(inclusive_range_syntax)]
 #![feature(iter_rfind)]
 #![feature(nonzero)]
-#![feature(ord_max_min)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(refcell_replace_swap)]
 #![feature(try_from)]
 #![feature(unique)]
 
+#![feature(const_atomic_bool_new)]
+#![feature(const_atomic_usize_new)]
+#![feature(const_atomic_isize_new)]
+
 extern crate core;
 extern crate test;
 extern crate rand;
index 283da1050aedc8393c1d6ca7057ba5d39f846d3a..ea83a4f8b3104dd2de1113fa6eba381d1d043444 100644 (file)
@@ -22,11 +22,10 @@ impl DepGraphQuery {
     pub fn new(nodes: &[DepNode],
                edges: &[(DepNode, DepNode)])
                -> DepGraphQuery {
-        let mut graph = Graph::new();
+        let mut graph = Graph::with_capacity(nodes.len(), edges.len());
         let mut indices = FxHashMap();
         for node in nodes {
-            indices.insert(node.clone(), graph.next_node_index());
-            graph.add_node(node.clone());
+            indices.insert(node.clone(), graph.add_node(node.clone()));
         }
 
         for &(ref source, ref target) in edges {
index bae419da26c58839e44bf087cf222ba563806c6f..113a5d0e5e96e28d72f7ffefcb3b6224c132126b 100644 (file)
@@ -40,6 +40,7 @@
 //! get confused if the spans from leaf AST nodes occur in multiple places
 //! in the HIR, especially for multiple identifiers.
 
+use dep_graph::DepGraph;
 use hir;
 use hir::map::{Definitions, DefKey};
 use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
@@ -122,13 +123,14 @@ pub trait Resolver {
 
 pub fn lower_crate(sess: &Session,
                    cstore: &CrateStore,
+                   dep_graph: &DepGraph,
                    krate: &Crate,
                    resolver: &mut Resolver)
                    -> hir::Crate {
     // We're constructing the HIR here; we don't care what we will
     // read, since we haven't even constructed the *input* to
     // incr. comp. yet.
-    let _ignore = sess.dep_graph.in_ignore();
+    let _ignore = dep_graph.in_ignore();
 
     LoweringContext {
         crate_root: std_inject::injected_crate_name(krate),
index 81cf20cfc77f0f4a7b4104096d1af2334072facd..5c011042deeee26ebcd8c420c480ce28c852351b 100644 (file)
@@ -13,7 +13,7 @@
 use hir::map::DefPathHash;
 use ich::{self, CachingCodemapView};
 use session::config::DebugInfoLevel::NoDebugInfo;
-use ty;
+use ty::TyCtxt;
 use util::nodemap::{NodeMap, ItemLocalMap};
 
 use std::hash as std_hash;
@@ -34,7 +34,7 @@
 /// a reference to the TyCtxt) and it holds a few caches for speeding up various
 /// things (e.g. each DefId/DefPath is only hashed once).
 pub struct StableHashingContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
-    tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     codemap: CachingCodemapView<'gcx>,
     hash_spans: bool,
     hash_bodies: bool,
@@ -53,7 +53,7 @@ pub enum NodeIdHashingMode {
 
 impl<'a, 'gcx, 'tcx> StableHashingContext<'a, 'gcx, 'tcx> {
 
-    pub fn new(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>) -> Self {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self {
         let hash_spans_initial = tcx.sess.opts.debuginfo != NoDebugInfo;
         let check_overflow_initial = tcx.sess.overflow_checks();
 
@@ -111,7 +111,7 @@ pub fn with_node_id_hashing_mode<F: FnOnce(&mut Self)>(&mut self,
     }
 
     #[inline]
-    pub fn tcx(&self) -> ty::TyCtxt<'a, 'gcx, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
         self.tcx
     }
 
index b827284271ed2235925313eadd31a1b662332fd8..e52be70190c81b043ab02334efd8eed0aaee8edf 100644 (file)
@@ -81,7 +81,12 @@ fn hash_stable<W: StableHasherResult>(&self,
 });
 
 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
-impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
+impl_stable_hash_for!(struct ::syntax::attr::Stability {
+    level,
+    feature,
+    rustc_depr,
+    rustc_const_unstable
+});
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 for ::syntax::attr::StabilityLevel {
@@ -102,6 +107,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
+impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
 
 
 impl_stable_hash_for!(enum ::syntax::attr::IntType {
index 051263dfb53ef30f5e8f5283c7550d25049b3f70..536715ffadb15b7f7501ac78af5cd39c6791e413 100644 (file)
@@ -287,6 +287,7 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
                                           found_it: false,
                                           bound_region: self.bound_region,
                                           hir_map: self.hir_map,
+                                          depth: self.depth,
                                       };
                 intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
                 // this will visit only outermost type
@@ -313,6 +314,7 @@ struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     hir_map: &'a hir::map::Map<'gcx>,
     found_it: bool,
     bound_region: ty::BoundRegion,
+    depth: u32,
 }
 
 impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
@@ -321,24 +323,47 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
     }
 
     fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
-        let br_index = match self.bound_region {
-            ty::BrAnon(index) => index,
-            _ => return,
-        };
 
         let hir_id = self.infcx.tcx.hir.node_to_hir_id(lifetime.id);
-        match self.infcx.tcx.named_region(hir_id) {
+        match (self.infcx.tcx.named_region(hir_id), self.bound_region) {
             // the lifetime of the TyPath!
-            Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
-                if debruijn_index.depth == 1 && anon_index == br_index {
+            (Some(rl::Region::LateBoundAnon(debruijn_index, anon_index)), ty::BrAnon(br_index)) => {
+                if debruijn_index.depth == self.depth && anon_index == br_index {
+                    self.found_it = true;
+                    return;
+                }
+            }
+
+            (Some(rl::Region::EarlyBound(_, id)), ty::BrNamed(def_id, _)) => {
+                debug!("EarlyBound self.infcx.tcx.hir.local_def_id(id)={:?} \
+                                        def_id={:?}",
+                       self.infcx.tcx.hir.local_def_id(id),
+                       def_id);
+                if self.infcx.tcx.hir.local_def_id(id) == def_id {
+                    self.found_it = true;
+                    return; // we can stop visiting now
+                }
+            }
+
+            (Some(rl::Region::LateBound(debruijn_index, id)), ty::BrNamed(def_id, _)) => {
+                debug!("FindNestedTypeVisitor::visit_ty: LateBound depth = {:?}",
+                       debruijn_index.depth);
+                debug!("self.infcx.tcx.hir.local_def_id(id)={:?}",
+                       self.infcx.tcx.hir.local_def_id(id));
+                debug!("def_id={:?}", def_id);
+                if debruijn_index.depth == self.depth &&
+                   self.infcx.tcx.hir.local_def_id(id) == def_id {
                     self.found_it = true;
+                    return; // we can stop visiting now
                 }
             }
-            Some(rl::Region::Static) |
-            Some(rl::Region::EarlyBound(_, _)) |
-            Some(rl::Region::LateBound(_, _)) |
-            Some(rl::Region::Free(_, _)) |
-            None => {
+
+            (Some(rl::Region::Static), _) |
+            (Some(rl::Region::EarlyBound(_, _)), _) |
+            (Some(rl::Region::LateBound(_, _)), _) |
+            (Some(rl::Region::LateBoundAnon(_, _)), _) |
+            (Some(rl::Region::Free(_, _)), _) |
+            (None, _) => {
                 debug!("no arg found");
             }
         }
index 6fc76a1d09037740ec003bb723dead46eb348828..a88e90caee3076608b93427b332259000ead0b91 100644 (file)
@@ -66,7 +66,7 @@
 use hir::def_id::DefId;
 use middle::region;
 use traits::{ObligationCause, ObligationCauseCode};
-use ty::{self, Region, TyCtxt, TypeFoldable};
+use ty::{self, Region, Ty, TyCtxt, TypeFoldable};
 use ty::error::TypeError;
 use syntax::ast::DUMMY_NODE_ID;
 use syntax_pos::{Pos, Span};
@@ -418,7 +418,7 @@ fn highlight_outer(&self,
                        name: String,
                        sub: &ty::subst::Substs<'tcx>,
                        pos: usize,
-                       other_ty: &ty::Ty<'tcx>) {
+                       other_ty: &Ty<'tcx>) {
         // `value` and `other_value` hold two incomplete type representation for display.
         // `name` is the path of both types being compared. `sub`
         value.push_highlighted(name);
@@ -491,7 +491,7 @@ fn cmp_type_arg(&self,
                     path: String,
                     sub: &ty::subst::Substs<'tcx>,
                     other_path: String,
-                    other_ty: &ty::Ty<'tcx>) -> Option<()> {
+                    other_ty: &Ty<'tcx>) -> Option<()> {
         for (i, ta) in sub.types().enumerate() {
             if &ta == other_ty {
                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
@@ -522,7 +522,7 @@ fn push_comma(&self,
 
     /// Compare two given types, eliding parts that are the same between them and highlighting
     /// relevant differences, and return two representation of those types for highlighted printing.
-    fn cmp(&self, t1: ty::Ty<'tcx>, t2: ty::Ty<'tcx>)
+    fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>)
         -> (DiagnosticStyledString, DiagnosticStyledString)
     {
         match (&t1.sty, &t2.sty) {
@@ -743,7 +743,7 @@ fn values_str(&self, values: &ValuePairs<'tcx>)
     }
 
     fn expected_found_str_ty(&self,
-                             exp_found: &ty::error::ExpectedFound<ty::Ty<'tcx>>)
+                             exp_found: &ty::error::ExpectedFound<Ty<'tcx>>)
                              -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
         let exp_found = self.resolve_type_vars_if_possible(exp_found);
         if exp_found.references_error() {
index b58fa6b0e7cbdc3f3ca153adcde528c0bde086d9..94faec464b24414f0508fc75e053ef0eac244239 100644 (file)
@@ -12,7 +12,7 @@
 //! anonymous regions.
 use hir;
 use infer::InferCtxt;
-use ty::{self, Region};
+use ty::{self, Region, Ty};
 use hir::def_id::DefId;
 use hir::map as hir_map;
 
@@ -35,7 +35,7 @@ pub struct AnonymousArgInfo<'tcx> {
     // the argument corresponding to the anonymous region
     pub arg: &'tcx hir::Arg,
     // the type corresponding to the anonymopus region argument
-    pub arg_ty: ty::Ty<'tcx>,
+    pub arg_ty: Ty<'tcx>,
     // the ty::BoundRegion corresponding to the anonymous region
     pub bound_region: ty::BoundRegion,
     // corresponds to id the argument is the first parameter
index 6ccf7e42fd5fd7fba6e73e0f3e89344bad8e04ad..39bcd7035742e38e0058ee4ff0aeefb1c31a7c97 100644 (file)
@@ -644,7 +644,7 @@ pub fn default(&self, ty: Ty<'tcx>) -> Option<type_variable::Default<'tcx>> {
         }
     }
 
-    pub fn unsolved_variables(&self) -> Vec<ty::Ty<'tcx>> {
+    pub fn unsolved_variables(&self) -> Vec<Ty<'tcx>> {
         let mut variables = Vec::new();
 
         let unbound_ty_vars = self.type_variables
index 82f01c36fee7f6960d6942bae39cd20b4402ee5c..df97f2fb8bcd62cfc2eef5923faf83584fce2cd4 100644 (file)
@@ -22,7 +22,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
-#![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(i128_type)]
 #![cfg_attr(windows, feature(libc))]
@@ -36,6 +35,9 @@
 #![feature(trace_macros)]
 #![feature(test)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+
 #![recursion_limit="256"]
 
 extern crate arena;
index cb59d9870faacfd3042e0979c1af4b5258f38153..7a6f4fdbb03ac4c966df745375ff664ee1b6f349 100644 (file)
@@ -46,6 +46,14 @@ pub enum LangItem {
     }
 }
 
+impl LangItem {
+    fn name(self) -> &'static str {
+        match self {
+            $( $variant => $name, )*
+        }
+    }
+}
+
 pub struct LanguageItems {
     pub items: Vec<Option<DefId>>,
     pub missing: Vec<LangItem>,
@@ -65,42 +73,17 @@ pub fn items(&self) -> &[Option<DefId>] {
         &*self.items
     }
 
-    pub fn item_name(index: usize) -> &'static str {
-        let item: Option<LangItem> = LangItem::from_u32(index as u32);
-        match item {
-            $( Some($variant) => $name, )*
-            None => "???"
-        }
-    }
-
     pub fn require(&self, it: LangItem) -> Result<DefId, String> {
-        match self.items[it as usize] {
-            Some(id) => Ok(id),
-            None => {
-                Err(format!("requires `{}` lang_item",
-                            LanguageItems::item_name(it as usize)))
-            }
-        }
-    }
-
-    pub fn require_owned_box(&self) -> Result<DefId, String> {
-        self.require(OwnedBoxLangItem)
+        self.items[it as usize].ok_or_else(|| format!("requires `{}` lang_item", it.name()))
     }
 
     pub fn fn_trait_kind(&self, id: DefId) -> Option<ty::ClosureKind> {
-        let def_id_kinds = [
-            (self.fn_trait(), ty::ClosureKind::Fn),
-            (self.fn_mut_trait(), ty::ClosureKind::FnMut),
-            (self.fn_once_trait(), ty::ClosureKind::FnOnce),
-            ];
-
-        for &(opt_def_id, kind) in &def_id_kinds {
-            if Some(id) == opt_def_id {
-                return Some(kind);
-            }
+        match Some(id) {
+            x if x == self.fn_trait() => Some(ty::ClosureKind::Fn),
+            x if x == self.fn_mut_trait() => Some(ty::ClosureKind::FnMut),
+            x if x == self.fn_once_trait() => Some(ty::ClosureKind::FnOnce),
+            _ => None
         }
-
-        None
     }
 
     $(
@@ -162,7 +145,7 @@ fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
         // Check for duplicates.
         match self.items.items[item_index] {
             Some(original_def_id) if original_def_id != item_def_id => {
-                let name = LanguageItems::item_name(item_index);
+                let name = LangItem::from_u32(item_index as u32).unwrap().name();
                 let mut err = match self.tcx.hir.span_if_local(item_def_id) {
                     Some(span) => struct_span_err!(
                         self.tcx.sess,
@@ -327,20 +310,12 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
 
     PhantomDataItem,                 "phantom_data",            phantom_data;
 
-    // Deprecated:
-    CovariantTypeItem,               "covariant_type",          covariant_type;
-    ContravariantTypeItem,           "contravariant_type",      contravariant_type;
-    InvariantTypeItem,               "invariant_type",          invariant_type;
-    CovariantLifetimeItem,           "covariant_lifetime",      covariant_lifetime;
-    ContravariantLifetimeItem,       "contravariant_lifetime",  contravariant_lifetime;
-    InvariantLifetimeItem,           "invariant_lifetime",      invariant_lifetime;
-
     NonZeroItem,                     "non_zero",                non_zero;
 
     DebugTraitLangItem,              "debug_trait",             debug_trait;
 }
 
-impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> {
+impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
     pub fn require_lang_item(&self, lang_item: LangItem) -> DefId {
         self.lang_items().require(lang_item).unwrap_or_else(|msg| {
             self.sess.fatal(&msg)
index 80beaaed051dbff558f9cef84d70159ae3ad2205..d4fa03b508566aa489f2ed059ca2bf6b883233eb 100644 (file)
@@ -1487,12 +1487,12 @@ fn warn_about_unused(&self,
                     self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
                         &format!("variable `{}` is assigned to, but never used",
                                  name),
-                        &format!("to disable this warning, consider using `_{}` instead",
+                        &format!("to avoid this warning, consider using `_{}` instead",
                                  name));
                 } else if name != "self" {
                     self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp,
                         &format!("unused variable: `{}`", name),
-                        &format!("to disable this warning, consider using `_{}` instead",
+                        &format!("to avoid this warning, consider using `_{}` instead",
                                  name));
                 }
             }
index 5ca235b2ad3ec538fee18d5f65a94ce5ff667764..977102ec1adcaffd99dd37ae87b3fe1ed5bb7806 100644 (file)
@@ -427,6 +427,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> {
                     },
                     feature: Symbol::intern("rustc_private"),
                     rustc_depr: None,
+                    rustc_const_unstable: None,
                 });
                 annotator.parent_stab = Some(stability);
             }
index 38dfe010c153cc14af61ca38ad7cbc07c2e6f829..d43504b77ba0c40c9ef182b5f40cd398df9be471 100644 (file)
@@ -21,7 +21,7 @@
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use ty::subst::{Subst, Substs};
-use ty::{self, AdtDef, ClosureSubsts, Region, Ty, GeneratorInterior};
+use ty::{self, AdtDef, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use util::ppaux;
 use rustc_back::slice;
@@ -644,7 +644,7 @@ pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> {
 }
 
 impl<'tcx> TerminatorKind<'tcx> {
-    pub fn if_<'a, 'gcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
+    pub fn if_<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, cond: Operand<'tcx>,
                          t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
         static BOOL_SWITCH_FALSE: &'static [ConstInt] = &[ConstInt::U8(0)];
         TerminatorKind::SwitchInt {
@@ -1182,7 +1182,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 
 impl<'tcx> Operand<'tcx> {
     pub fn function_handle<'a>(
-        tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
         def_id: DefId,
         substs: &'tcx Substs<'tcx>,
         span: Span,
index 59f600f39077c33e53cdad551b39b5d5bc8b4afd..df2de17f1e4711409610e76c9a49a87217dfabbb 100644 (file)
@@ -1949,7 +1949,6 @@ pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &DepTrackingHash>,
 
 #[cfg(test)]
 mod tests {
-    use dep_graph::DepGraph;
     use errors;
     use getopts;
     use lint;
@@ -1982,7 +1981,6 @@ fn mk_set<V: Ord>(entries: Vec<V>) -> BTreeSet<V> {
     // When the user supplies --test we should implicitly supply --cfg test
     #[test]
     fn test_switch_implies_cfg_test() {
-        let dep_graph = DepGraph::new(false);
         let matches =
             &match optgroups().parse(&["--test".to_string()]) {
               Ok(m) => m,
@@ -1990,7 +1988,7 @@ fn test_switch_implies_cfg_test() {
             };
         let registry = errors::registry::Registry::new(&[]);
         let (sessopts, cfg) = build_session_options_and_crate_config(matches);
-        let sess = build_session(sessopts, &dep_graph, None, registry);
+        let sess = build_session(sessopts, None, registry);
         let cfg = build_configuration(&sess, cfg);
         assert!(cfg.contains(&(Symbol::intern("test"), None)));
     }
@@ -1999,7 +1997,6 @@ fn test_switch_implies_cfg_test() {
     // another --cfg test
     #[test]
     fn test_switch_implies_cfg_test_unless_cfg_test() {
-        let dep_graph = DepGraph::new(false);
         let matches =
             &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) {
               Ok(m) => m,
@@ -2009,7 +2006,7 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
             };
         let registry = errors::registry::Registry::new(&[]);
         let (sessopts, cfg) = build_session_options_and_crate_config(matches);
-        let sess = build_session(sessopts, &dep_graph, None, registry);
+        let sess = build_session(sessopts, None, registry);
         let cfg = build_configuration(&sess, cfg);
         let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test");
         assert!(test_items.next().is_some());
@@ -2018,14 +2015,13 @@ fn test_switch_implies_cfg_test_unless_cfg_test() {
 
     #[test]
     fn test_can_print_warnings() {
-        let dep_graph = DepGraph::new(false);
         {
             let matches = optgroups().parse(&[
                 "-Awarnings".to_string()
             ]).unwrap();
             let registry = errors::registry::Registry::new(&[]);
             let (sessopts, _) = build_session_options_and_crate_config(&matches);
-            let sess = build_session(sessopts, &dep_graph, None, registry);
+            let sess = build_session(sessopts, None, registry);
             assert!(!sess.diagnostic().can_emit_warnings);
         }
 
@@ -2036,7 +2032,7 @@ fn test_can_print_warnings() {
             ]).unwrap();
             let registry = errors::registry::Registry::new(&[]);
             let (sessopts, _) = build_session_options_and_crate_config(&matches);
-            let sess = build_session(sessopts, &dep_graph, None, registry);
+            let sess = build_session(sessopts, None, registry);
             assert!(sess.diagnostic().can_emit_warnings);
         }
 
@@ -2046,7 +2042,7 @@ fn test_can_print_warnings() {
             ]).unwrap();
             let registry = errors::registry::Registry::new(&[]);
             let (sessopts, _) = build_session_options_and_crate_config(&matches);
-            let sess = build_session(sessopts, &dep_graph, None, registry);
+            let sess = build_session(sessopts, None, registry);
             assert!(sess.diagnostic().can_emit_warnings);
         }
     }
index 1f9cb2b03100fba2fec8d091d2c3b554e2bed528..df5a2648e270ce92b6e517c109911e830fec4242 100644 (file)
@@ -11,7 +11,6 @@
 pub use self::code_stats::{CodeStats, DataTypeKind, FieldInfo};
 pub use self::code_stats::{SizeKind, TypeSizeInfo, VariantInfo};
 
-use dep_graph::DepGraph;
 use hir::def_id::{CrateNum, DefIndex};
 
 use lint;
@@ -58,7 +57,6 @@
 // Represents the data associated with a compilation
 // session for a single crate.
 pub struct Session {
-    pub dep_graph: DepGraph,
     pub target: config::Config,
     pub host: Target,
     pub opts: config::Options,
@@ -91,7 +89,7 @@ pub struct Session {
     // forms a unique global identifier for the crate. It is used to allow
     // multiple crates with the same name to coexist. See the
     // trans::back::symbol_names module for more information.
-    pub crate_disambiguator: RefCell<Symbol>,
+    pub crate_disambiguator: RefCell<Option<Symbol>>,
     pub features: RefCell<feature_gate::Features>,
 
     /// The maximum recursion limit for potentially infinitely recursive
@@ -169,7 +167,10 @@ enum DiagnosticBuilderMethod {
 
 impl Session {
     pub fn local_crate_disambiguator(&self) -> Symbol {
-        *self.crate_disambiguator.borrow()
+        match *self.crate_disambiguator.borrow() {
+            Some(sym) => sym,
+            None => bug!("accessing disambiguator before initialization"),
+        }
     }
     pub fn struct_span_warn<'a, S: Into<MultiSpan>>(&'a self,
                                                     sp: S,
@@ -501,9 +502,29 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
             kind)
     }
 
+    pub fn set_incr_session_load_dep_graph(&self, load: bool) {
+        let mut incr_comp_session = self.incr_comp_session.borrow_mut();
+
+        match *incr_comp_session {
+            IncrCompSession::Active { ref mut load_dep_graph, .. } => {
+                *load_dep_graph = load;
+            }
+            _ => {}
+        }
+    }
+
+    pub fn incr_session_load_dep_graph(&self) -> bool {
+        let incr_comp_session = self.incr_comp_session.borrow();
+        match *incr_comp_session {
+            IncrCompSession::Active { load_dep_graph, .. } => load_dep_graph,
+            _ => false,
+        }
+    }
+
     pub fn init_incr_comp_session(&self,
                                   session_dir: PathBuf,
-                                  lock_file: flock::Lock) {
+                                  lock_file: flock::Lock,
+                                  load_dep_graph: bool) {
         let mut incr_comp_session = self.incr_comp_session.borrow_mut();
 
         if let IncrCompSession::NotInitialized = *incr_comp_session { } else {
@@ -513,6 +534,7 @@ pub fn init_incr_comp_session(&self,
         *incr_comp_session = IncrCompSession::Active {
             session_directory: session_dir,
             lock_file,
+            load_dep_graph,
         };
     }
 
@@ -617,14 +639,12 @@ pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -
 }
 
 pub fn build_session(sopts: config::Options,
-                     dep_graph: &DepGraph,
                      local_crate_source_file: Option<PathBuf>,
                      registry: errors::registry::Registry)
                      -> Session {
     let file_path_mapping = sopts.file_path_mapping();
 
     build_session_with_codemap(sopts,
-                               dep_graph,
                                local_crate_source_file,
                                registry,
                                Rc::new(codemap::CodeMap::new(file_path_mapping)),
@@ -632,7 +652,6 @@ pub fn build_session(sopts: config::Options,
 }
 
 pub fn build_session_with_codemap(sopts: config::Options,
-                                  dep_graph: &DepGraph,
                                   local_crate_source_file: Option<PathBuf>,
                                   registry: errors::registry::Registry,
                                   codemap: Rc<codemap::CodeMap>,
@@ -672,14 +691,12 @@ pub fn build_session_with_codemap(sopts: config::Options,
                                       emitter);
 
     build_session_(sopts,
-                   dep_graph,
                    local_crate_source_file,
                    diagnostic_handler,
                    codemap)
 }
 
 pub fn build_session_(sopts: config::Options,
-                      dep_graph: &DepGraph,
                       local_crate_source_file: Option<PathBuf>,
                       span_diagnostic: errors::Handler,
                       codemap: Rc<codemap::CodeMap>)
@@ -715,7 +732,6 @@ pub fn build_session_(sopts: config::Options,
     let working_dir = file_path_mapping.map_prefix(working_dir);
 
     let sess = Session {
-        dep_graph: dep_graph.clone(),
         target: target_cfg,
         host,
         opts: sopts,
@@ -735,7 +751,7 @@ pub fn build_session_(sopts: config::Options,
         plugin_attributes: RefCell::new(Vec::new()),
         crate_types: RefCell::new(Vec::new()),
         dependency_formats: RefCell::new(FxHashMap()),
-        crate_disambiguator: RefCell::new(Symbol::intern("")),
+        crate_disambiguator: RefCell::new(None),
         features: RefCell::new(feature_gate::Features::new()),
         recursion_limit: Cell::new(64),
         type_length_limit: Cell::new(1048576),
@@ -793,6 +809,7 @@ pub enum IncrCompSession {
     Active {
         session_directory: PathBuf,
         lock_file: flock::Lock,
+        load_dep_graph: bool,
     },
     // This is the state after the session directory has been finalized. In this
     // state, the contents of the directory must not be modified any more.
index fb71d9cc49b9e1efe1b0585bfcb17cb6b907d24a..a1817f181066c54c8b5ed844d96c1161c9684fd8 100644 (file)
@@ -381,7 +381,7 @@ pub struct VtableObjectData<'tcx, N> {
 
 #[derive(Clone, PartialEq, Eq)]
 pub struct VtableFnPointerData<'tcx, N> {
-    pub fn_ty: ty::Ty<'tcx>,
+    pub fn_ty: Ty<'tcx>,
     pub nested: Vec<N>
 }
 
index 7d543f689c24d179283eaa80904b2906b4070bab..d9c6843fad73a64d5cc92ff1eb39071607bd18a2 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use ty::{self, Ty, TypeFoldable, Substs};
+use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
 use util::ppaux;
 
 use std::fmt;
@@ -57,12 +57,12 @@ pub fn def_id(&self) -> DefId {
     }
 
     #[inline]
-    pub fn def_ty<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
+    pub fn def_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         tcx.type_of(self.def_id())
     }
 
     #[inline]
-    pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
+    pub fn attrs<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
         tcx.get_attrs(self.def_id())
     }
 }
@@ -103,7 +103,7 @@ pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>)
         Instance { def: InstanceDef::Item(def_id), substs: substs }
     }
 
-    pub fn mono(tcx: ty::TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
+    pub fn mono(tcx: TyCtxt<'a, 'tcx, 'b>, def_id: DefId) -> Instance<'tcx> {
         Instance::new(def_id, tcx.global_tcx().empty_substs_for_def_id(def_id))
     }
 
index 0106d98b64130e1938929322e0eb03e1ff007bac..84d7745a64f0a2218f81ff4d646da86b9553f602 100644 (file)
@@ -386,7 +386,7 @@ pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
         }
     }
 
-    pub fn to_ty<'a, 'tcx>(&self, tcx: &ty::TyCtxt<'a, 'tcx, 'tcx>,
+    pub fn to_ty<'a, 'tcx>(&self, tcx: &TyCtxt<'a, 'tcx, 'tcx>,
                            signed: bool) -> Ty<'tcx> {
         match (*self, signed) {
             (I1, false) => tcx.types.u8,
index d4a020657616a05c93cd023cc9a2708e3a0811f8..c13141008a42623fae4d1e577dd5e65f41cceb2e 100644 (file)
 #![deny(warnings)]
 #![forbid(unsafe_code)]
 
-#![feature(const_fn)]
 #![feature(i128_type)]
 #![feature(slice_patterns)]
 #![feature(try_from)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_min_value))]
+#![cfg_attr(not(stage0), feature(const_max_value))]
+
 #[macro_use]
 extern crate rustc_bitflags;
 
index b49b1d1c2138ab43179f9db651dbaaed2ecccefd..45654b0f870201fcbb8aa37240e71ea2fba9275a 100644 (file)
@@ -16,7 +16,7 @@
 
 pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
-    base.features = "+v7,+thumb2,+vfp3,+d16,-neon".to_string();
+    base.features = "+v7,+thumb-mode,+thumb2,+vfp3,+d16,-neon".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args
         .get_mut(&LinkerFlavor::Gcc).unwrap().push("-march=armv7-a".to_string());
index 6527ac0e927213feb66bf36b7737980c9b3aef6e..6fb49a0908ff4cd5744f9d16f923fe21e48a33eb 100644 (file)
@@ -34,7 +34,7 @@
 use rustc::middle::mem_categorization::ImmutabilityBlame;
 use rustc::middle::region;
 use rustc::middle::free_region::RegionRelations;
-use rustc::ty::{self, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin};
 
@@ -275,7 +275,7 @@ pub fn loan_path(&self) -> Rc<LoanPath<'tcx>> {
 #[derive(Eq)]
 pub struct LoanPath<'tcx> {
     kind: LoanPathKind<'tcx>,
-    ty: ty::Ty<'tcx>,
+    ty: Ty<'tcx>,
 }
 
 impl<'tcx> PartialEq for LoanPath<'tcx> {
@@ -299,11 +299,11 @@ pub enum LoanPathKind<'tcx> {
 }
 
 impl<'tcx> LoanPath<'tcx> {
-    fn new(kind: LoanPathKind<'tcx>, ty: ty::Ty<'tcx>) -> LoanPath<'tcx> {
+    fn new(kind: LoanPathKind<'tcx>, ty: Ty<'tcx>) -> LoanPath<'tcx> {
         LoanPath { kind: kind, ty: ty }
     }
 
-    fn to_type(&self) -> ty::Ty<'tcx> { self.ty }
+    fn to_type(&self) -> Ty<'tcx> { self.ty }
 }
 
 // FIXME (pnkfelix): See discussion here
index 9fedee80d46a8e748804199cc2b621075ed8b787..0c3606cab10e1f8a65cbbd6b448e794658c320f4 100644 (file)
 #![feature(slice_patterns)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_min_value))]
+
 extern crate arena;
 #[macro_use] extern crate syntax;
 #[macro_use] extern crate log;
index 93b70ef8e4a5856a1e13a3f1529bd003373bae56..0533f10104a5a8b588204dd3b9b48641cf9e480a 100644 (file)
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(const_fn)]
 #![feature(i128)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_min_value))]
+#![cfg_attr(not(stage0), feature(const_max_value))]
+
 extern crate rustc_apfloat;
 
 extern crate syntax;
index f74af6ee1632e793f8f6fef0922f9262443e2eb1..7665bfd5b1117316c0a758338ad103adca34e2b5 100644 (file)
@@ -132,6 +132,11 @@ pub trait BitwiseOperator {
     fn join(&self, pred1: usize, pred2: usize) -> usize;
 }
 
+pub struct Intersect;
+impl BitwiseOperator for Intersect {
+    #[inline]
+    fn join(&self, a: usize, b: usize) -> usize { a & b }
+}
 pub struct Union;
 impl BitwiseOperator for Union {
     #[inline]
index a5f83ce05f5e5108e84ce29a08ee7668cb18601f..474622f3669131a0c54623a53376a8e942f3d864 100644 (file)
@@ -114,6 +114,13 @@ pub fn new() -> Graph<N, E> {
         }
     }
 
+    pub fn with_capacity(nodes: usize, edges: usize) -> Graph<N, E> {
+        Graph {
+            nodes: SnapshotVec::with_capacity(nodes),
+            edges: SnapshotVec::with_capacity(edges),
+        }
+    }
+
     // # Simple accessors
 
     #[inline]
index 47fa21e3bf0b2bf6a1e47f4d6c78b94c1aca9246..c790463e47adb4f2ce3e897c2229e22dc9f7d88f 100644 (file)
@@ -15,7 +15,7 @@
 use std::ops::{Deref, DerefMut, Range};
 use std::slice;
 use bitslice::{BitSlice, Word};
-use bitslice::{bitwise, Union, Subtract};
+use bitslice::{bitwise, Union, Subtract, Intersect};
 use indexed_vec::Idx;
 
 /// Represents a set (or packed family of sets), of some element type
@@ -164,6 +164,10 @@ pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
         bitwise(self.words_mut(), other.words(), &Subtract)
     }
 
+    pub fn intersect(&mut self, other: &IdxSet<T>) -> bool {
+        bitwise(self.words_mut(), other.words(), &Intersect)
+    }
+
     pub fn iter(&self) -> Iter<T> {
         Iter {
             cur: None,
index dac074ab91e1bfe11c67876f0d3dce2bc7bfc492..2da91918288bab77ff8266086a662ea150fc4aad 100644 (file)
@@ -66,6 +66,13 @@ pub fn new() -> SnapshotVec<D> {
         }
     }
 
+    pub fn with_capacity(n: usize) -> SnapshotVec<D> {
+        SnapshotVec {
+            values: Vec::with_capacity(n),
+            undo_log: Vec::new(),
+        }
+    }
+
     fn in_snapshot(&self) -> bool {
         !self.undo_log.is_empty()
     }
index c41d5beec6877ab61570ae2f6fcfa17601e1b080..ed012f87996d7a10ba3824ded6ffa76becff2295 100644 (file)
@@ -10,6 +10,7 @@
 
 #![cfg_attr(not(feature="llvm"), allow(dead_code))]
 
+use rustc::dep_graph::DepGraph;
 use rustc::hir::{self, map as hir_map};
 use rustc::hir::lowering::lower_crate;
 use rustc::ich::Fingerprint;
@@ -115,7 +116,7 @@ macro_rules! controller_entry_point {
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
-    let (outputs, trans): (OutputFilenames, OngoingCrateTranslation) = {
+    let (outputs, trans, dep_graph): (OutputFilenames, OngoingCrateTranslation, DepGraph) = {
         let krate = match phase_1_parse_input(control, sess, input) {
             Ok(krate) => krate,
             Err(mut parse_error) => {
@@ -144,7 +145,13 @@ macro_rules! controller_entry_point {
             ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
         let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
             phase_2_configure_and_expand(
-                sess, &cstore, krate, registry, &crate_name, addl_plugins, control.make_glob_map,
+                sess,
+                &cstore,
+                krate,
+                registry,
+                &crate_name,
+                addl_plugins,
+                control.make_glob_map,
                 |expanded_crate| {
                     let mut state = CompileState::state_after_expand(
                         input, sess, outdir, output, &cstore, expanded_crate, &crate_name,
@@ -251,7 +258,7 @@ macro_rules! controller_entry_point {
                 }
             }
 
-            Ok((outputs, trans))
+            Ok((outputs, trans, tcx.dep_graph.clone()))
         })??
     };
 
@@ -266,7 +273,7 @@ macro_rules! controller_entry_point {
             sess.code_stats.borrow().print_type_sizes();
         }
 
-        let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans);
+        let (phase5_result, trans) = phase_5_run_llvm_passes(sess, &dep_graph, trans);
 
         controller_entry_point!(after_llvm,
                                 sess,
@@ -624,7 +631,15 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     *sess.features.borrow_mut() = features;
 
     *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
-    *sess.crate_disambiguator.borrow_mut() = Symbol::intern(&compute_crate_disambiguator(sess));
+
+    let disambiguator = Symbol::intern(&compute_crate_disambiguator(sess));
+    *sess.crate_disambiguator.borrow_mut() = Some(disambiguator);
+    rustc_incremental::prepare_session_directory(
+        sess,
+        &crate_name,
+        &disambiguator.as_str(),
+    );
+    let dep_graph = DepGraph::new(sess.opts.build_dep_graph());
 
     time(time_passes, "recursion limit", || {
         middle::recursion_limit::update_limits(sess, &krate);
@@ -694,7 +709,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
     // item, much like we do for macro expansion. In other words, the hash reflects not just
     // its contents but the results of name resolution on those contents. Hopefully we'll push
     // this back at some point.
-    let _ignore = sess.dep_graph.in_ignore();
+    let _ignore = dep_graph.in_ignore();
     let mut crate_loader = CrateLoader::new(sess, &cstore, crate_name);
     let resolver_arenas = Resolver::arenas();
     let mut resolver = Resolver::new(sess,
@@ -847,13 +862,13 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
 
     // Lower ast -> hir.
     let hir_forest = time(time_passes, "lowering ast -> hir", || {
-        let hir_crate = lower_crate(sess, cstore, &krate, &mut resolver);
+        let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, &mut resolver);
 
         if sess.opts.debugging_opts.hir_stats {
             hir_stats::print_hir_stats(&hir_crate);
         }
 
-        hir_map::Forest::new(hir_crate, &sess.dep_graph)
+        hir_map::Forest::new(hir_crate, &dep_graph)
     });
 
     time(time_passes,
@@ -1134,9 +1149,10 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 /// as a side effect.
 #[cfg(feature="llvm")]
 pub fn phase_5_run_llvm_passes(sess: &Session,
+                               dep_graph: &DepGraph,
                                trans: write::OngoingCrateTranslation)
                                -> (CompileResult, trans::CrateTranslation) {
-    let trans = trans.join(sess);
+    let trans = trans.join(sess, dep_graph);
 
     if sess.opts.debugging_opts.incremental_info {
         write::dump_incremental_data(&trans);
@@ -1144,7 +1160,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
 
     time(sess.time_passes(),
          "serialize work products",
-         move || rustc_incremental::save_work_products(sess));
+         move || rustc_incremental::save_work_products(sess, dep_graph));
 
     (sess.compile_status(), trans)
 }
index 099dda17823e67f864b112e437ae8ba72c65ec77..522b9eb22320e9d00bc7f806a32236d80e24c67b 100644 (file)
@@ -64,7 +64,6 @@
 use rustc_resolve as resolve;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
-use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::CompileIncomplete;
 use rustc::session::config::{Input, PrintRequest, OutputType, ErrorOutputType};
@@ -294,13 +293,12 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         },
     };
 
-    let dep_graph = DepGraph::new(sopts.build_dep_graph());
     let cstore = Rc::new(CStore::new(box ::MetadataLoader));
 
     let loader = file_loader.unwrap_or(box RealFileLoader);
     let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
     let mut sess = session::build_session_with_codemap(
-        sopts, &dep_graph, input_file_path, descriptions, codemap, emitter_dest,
+        sopts, input_file_path, descriptions, codemap, emitter_dest,
     );
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@@ -318,7 +316,13 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
 
     let plugins = sess.opts.debugging_opts.extra_plugins.clone();
     let control = callbacks.build_controller(&sess, &matches);
-    (driver::compile_input(&sess, &cstore, &input, &odir, &ofile, Some(plugins), &control),
+    (driver::compile_input(&sess,
+                           &cstore,
+                           &input,
+                           &odir,
+                           &ofile,
+                           Some(plugins),
+                           &control),
      Some(sess))
 }
 
@@ -580,9 +584,7 @@ fn no_input(&mut self,
                     describe_lints(&ls, false);
                     return None;
                 }
-                let dep_graph = DepGraph::new(sopts.build_dep_graph());
                 let mut sess = build_session(sopts.clone(),
-                    &dep_graph,
                     None,
                     descriptions.clone());
                 rustc_trans::init(&sess);
index d2fb9903683676a5e6b853183108de3d203166c0..d0edcbc326098eb738d0ac37347eb37c11d561fb 100644 (file)
@@ -11,7 +11,6 @@
 //! # Standalone Tests for the Inference Module
 
 use driver;
-use rustc::dep_graph::DepGraph;
 use rustc_lint;
 use rustc_resolve::MakeGlobMap;
 use rustc_trans;
@@ -102,11 +101,8 @@ fn test_env<F>(source_string: &str,
     options.unstable_features = UnstableFeatures::Allow;
     let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
 
-    let dep_graph = DepGraph::new(false);
-    let _ignore = dep_graph.in_ignore();
     let cstore = Rc::new(CStore::new(box ::MetadataLoader));
     let sess = session::build_session_(options,
-                                       &dep_graph,
                                        None,
                                        diagnostic_handler,
                                        Rc::new(CodeMap::new(FilePathMapping::empty())));
@@ -130,7 +126,6 @@ fn test_env<F>(source_string: &str,
                                              |_| Ok(()))
             .expect("phase 2 aborted")
     };
-    let _ignore = dep_graph.in_ignore();
 
     let arena = DroplessArena::new();
     let arenas = ty::GlobalArenas::new();
index 8870033095c9c2a1106ddd91d3d88ca049367cb3..3c1e02f8a5adde4c72a4519cc474b84a833de246 100644 (file)
@@ -40,4 +40,5 @@
 pub use persist::save_trans_partition;
 pub use persist::save_work_products;
 pub use persist::in_incr_comp_dir;
+pub use persist::prepare_session_directory;
 pub use persist::finalize_session_directory;
index 434c82095bd9a98d0e21cbf8a3639d934646202c..f3f35a50fe0b3638a17c774548256328055c5e1d 100644 (file)
 //! unsupported file system and emit a warning in that case. This is not yet
 //! implemented.
 
-use rustc::hir::def_id::{CrateNum, LOCAL_CRATE};
+use rustc::hir::def_id::CrateNum;
 use rustc::hir::svh::Svh;
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
@@ -193,13 +193,21 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 /// a dep-graph and work products from a previous session.
 /// If the call fails, the fn may leave behind an invalid session directory.
 /// The garbage collection will take care of it.
-pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
+pub fn prepare_session_directory(sess: &Session,
+                                 crate_name: &str,
+                                 crate_disambiguator: &str) {
+    if sess.opts.incremental.is_none() {
+        return
+    }
+
     debug!("prepare_session_directory");
 
     // {incr-comp-dir}/{crate-name-and-disambiguator}
-    let crate_dir = crate_path_tcx(tcx, LOCAL_CRATE);
+    let crate_dir = crate_path(sess, crate_name, crate_disambiguator);
     debug!("crate-dir: {}", crate_dir.display());
-    try!(create_dir(tcx.sess, &crate_dir, "crate"));
+    if create_dir(sess, &crate_dir, "crate").is_err() {
+        return
+    }
 
     // Hack: canonicalize the path *after creating the directory*
     // because, on windows, long paths can cause problems;
@@ -208,9 +216,9 @@ pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
     let crate_dir = match crate_dir.canonicalize() {
         Ok(v) => v,
         Err(err) => {
-            tcx.sess.err(&format!("incremental compilation: error canonicalizing path `{}`: {}",
-                                  crate_dir.display(), err));
-            return Err(());
+            sess.err(&format!("incremental compilation: error canonicalizing path `{}`: {}",
+                              crate_dir.display(), err));
+            return
         }
     };
 
@@ -225,11 +233,16 @@ pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
 
         // Lock the new session directory. If this fails, return an
         // error without retrying
-        let (directory_lock, lock_file_path) = try!(lock_directory(tcx.sess, &session_dir));
+        let (directory_lock, lock_file_path) = match lock_directory(sess, &session_dir) {
+            Ok(e) => e,
+            Err(_) => return,
+        };
 
         // Now that we have the lock, we can actually create the session
         // directory
-        try!(create_dir(tcx.sess, &session_dir, "session"));
+        if create_dir(sess, &session_dir, "session").is_err() {
+            return
+        }
 
         // Find a suitable source directory to copy from. Ignore those that we
         // have already tried before.
@@ -243,14 +256,14 @@ pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
             debug!("no source directory found. Continuing with empty session \
                     directory.");
 
-            tcx.sess.init_incr_comp_session(session_dir, directory_lock);
-            return Ok(false)
+            sess.init_incr_comp_session(session_dir, directory_lock, false);
+            return
         };
 
         debug!("attempting to copy data from source: {}",
                source_directory.display());
 
-        let print_file_copy_stats = tcx.sess.opts.debugging_opts.incremental_info;
+        let print_file_copy_stats = sess.opts.debugging_opts.incremental_info;
 
         // Try copying over all files from the source directory
         if let Ok(allows_links) = copy_files(&session_dir, &source_directory,
@@ -259,7 +272,7 @@ pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
                    source_directory.display());
 
             if !allows_links {
-                tcx.sess.warn(&format!("Hard linking files in the incremental \
+                sess.warn(&format!("Hard linking files in the incremental \
                                         compilation cache failed. Copying files \
                                         instead. Consider moving the cache \
                                         directory to a file system which supports \
@@ -268,8 +281,8 @@ pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
                     );
             }
 
-            tcx.sess.init_incr_comp_session(session_dir, directory_lock);
-            return Ok(true)
+            sess.init_incr_comp_session(session_dir, directory_lock, true);
+            return
         } else {
              debug!("copying failed - trying next directory");
 
@@ -280,13 +293,13 @@ pub fn prepare_session_directory(tcx: TyCtxt) -> Result<bool, ()> {
             // Try to remove the session directory we just allocated. We don't
             // know if there's any garbage in it from the failed copy action.
             if let Err(err) = safe_remove_dir_all(&session_dir) {
-                tcx.sess.warn(&format!("Failed to delete partly initialized \
-                                        session dir `{}`: {}",
-                                       session_dir.display(),
-                                       err));
+                sess.warn(&format!("Failed to delete partly initialized \
+                                    session dir `{}`: {}",
+                                   session_dir.display(),
+                                   err));
             }
 
-            delete_session_dir_lock_file(tcx.sess, &lock_file_path);
+            delete_session_dir_lock_file(sess, &lock_file_path);
             mem::drop(directory_lock);
         }
     }
index 2c43896ec73d242d9170957f423373baa109006d..ba638289fdf03168b9c5ee60f2a22cdcaa11f60d 100644 (file)
 /// more general overview.
 pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 incremental_hashes_map: &IncrementalHashesMap) {
-    if tcx.sess.opts.incremental.is_none() {
-        return;
+    if tcx.sess.incr_session_load_dep_graph() {
+        let _ignore = tcx.dep_graph.in_ignore();
+        load_dep_graph_if_exists(tcx, incremental_hashes_map);
     }
-
-    match prepare_session_directory(tcx) {
-        Ok(true) => {
-            // We successfully allocated a session directory and there is
-            // something in it to load, so continue
-        }
-        Ok(false) => {
-            // We successfully allocated a session directory, but there is no
-            // dep-graph data in it to load (because this is the first
-            // compilation session with this incr. comp. dir.)
-            return
-        }
-        Err(()) => {
-            // Something went wrong while trying to allocate the session
-            // directory. Don't try to use it any further.
-            return
-        }
-    }
-
-    let _ignore = tcx.dep_graph.in_ignore();
-    load_dep_graph_if_exists(tcx, incremental_hashes_map);
 }
 
 fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
index 5c1582daa78fa07119caa53219831e699ed60e88..fb3308132261f37d722dbdb5e771353388502515 100644 (file)
@@ -22,6 +22,7 @@
 mod work_product;
 mod file_format;
 
+pub use self::fs::prepare_session_directory;
 pub use self::fs::finalize_session_directory;
 pub use self::fs::in_incr_comp_dir;
 pub use self::load::load_dep_graph;
index 339e2bdc15734960534873ae46a39402f11a37f9..65fbaf1ad047a484da1c659d956e324283fdcfb1 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::dep_graph::DepNode;
+use rustc::dep_graph::{DepGraph, DepNode};
 use rustc::hir::def_id::DefId;
 use rustc::hir::svh::Svh;
 use rustc::ich::Fingerprint;
@@ -79,21 +79,21 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             &current_metadata_hashes);
 }
 
-pub fn save_work_products(sess: &Session) {
+pub fn save_work_products(sess: &Session, dep_graph: &DepGraph) {
     if sess.opts.incremental.is_none() {
         return;
     }
 
     debug!("save_work_products()");
-    let _ignore = sess.dep_graph.in_ignore();
+    let _ignore = dep_graph.in_ignore();
     let path = work_products_path(sess);
-    save_in(sess, path, |e| encode_work_products(sess, e));
+    save_in(sess, path, |e| encode_work_products(dep_graph, e));
 
     // We also need to clean out old work-products, as not all of them are
     // deleted during invalidation. Some object files don't change their
     // content, they are just not needed anymore.
-    let new_work_products = sess.dep_graph.work_products();
-    let previous_work_products = sess.dep_graph.previous_work_products();
+    let new_work_products = dep_graph.work_products();
+    let previous_work_products = dep_graph.previous_work_products();
 
     for (id, wp) in previous_work_products.iter() {
         if !new_work_products.contains_key(id) {
@@ -309,8 +309,9 @@ pub fn encode_metadata_hashes(tcx: TyCtxt,
     Ok(())
 }
 
-pub fn encode_work_products(sess: &Session, encoder: &mut Encoder) -> io::Result<()> {
-    let work_products: Vec<_> = sess.dep_graph
+pub fn encode_work_products(dep_graph: &DepGraph,
+                            encoder: &mut Encoder) -> io::Result<()> {
+    let work_products: Vec<_> = dep_graph
         .work_products()
         .iter()
         .map(|(id, work_product)| {
index e20d7a006b0ddb0844ec0a88f54eba4624447c36..70d96e3a83d376bed6bd6dbd219e299b7f2960b9 100644 (file)
@@ -11,7 +11,7 @@
 //! This module contains files for saving intermediate work-products.
 
 use persist::fs::*;
-use rustc::dep_graph::{WorkProduct, WorkProductId};
+use rustc::dep_graph::{WorkProduct, WorkProductId, DepGraph};
 use rustc::session::Session;
 use rustc::session::config::OutputType;
 use rustc::util::fs::link_or_copy;
@@ -19,6 +19,7 @@
 use std::fs as std_fs;
 
 pub fn save_trans_partition(sess: &Session,
+                            dep_graph: &DepGraph,
                             cgu_name: &str,
                             partition_hash: u64,
                             files: &[(OutputType, PathBuf)]) {
@@ -60,7 +61,7 @@ pub fn save_trans_partition(sess: &Session,
         saved_files,
     };
 
-    sess.dep_graph.insert_work_product(&work_product_id, work_product);
+    dep_graph.insert_work_product(&work_product_id, work_product);
 }
 
 pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
index 91646ce9f8b963ed58d4698d6ed319c5426f16f5..439cc3a4b844eafe0860a84c02e7d3e2545e03f2 100644 (file)
@@ -85,20 +85,12 @@ fn get_lints(&self) -> LintArray {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedMut {
-    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
-        if let hir::ExprMatch(_, ref arms, _) = e.node {
-            for a in arms {
-                self.check_unused_mut_pat(cx, &a.pats)
-            }
-        }
+    fn check_arm(&mut self, cx: &LateContext, a: &hir::Arm) {
+        self.check_unused_mut_pat(cx, &a.pats)
     }
 
-    fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
-        if let hir::StmtDecl(ref d, _) = s.node {
-            if let hir::DeclLocal(ref l) = d.node {
-                self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
-            }
-        }
+    fn check_local(&mut self, cx: &LateContext, l: &hir::Local) {
+        self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
     }
 
     fn check_fn(&mut self,
index b1b3e92347a213468421455ec178ffe7f74aef8c..ade2612855e02e8462deb2dc7e7a48d3eefeb8a5 100644 (file)
@@ -14,7 +14,7 @@
 use schema::*;
 
 use rustc::hir;
-use rustc::ty;
+use rustc::ty::{self, TyCtxt};
 
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct Ast<'tcx> {
@@ -59,7 +59,7 @@ pub fn encode_body(&mut self, body_id: hir::BodyId) -> Lazy<Ast<'tcx>> {
 }
 
 struct NestedBodyCollector<'a, 'tcx: 'a> {
-    tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     bodies_found: Vec<&'tcx hir::Body>,
 }
 
index a6e31bcddd2427c54add2d692b6641905a4b2081..dfddbfe485dd961fd2fd373d78b3c22e4a7cd391 100644 (file)
@@ -16,7 +16,7 @@
 use build::CFG;
 use rustc::middle::region;
 use rustc::mir::*;
-use rustc::ty;
+use rustc::ty::TyCtxt;
 
 impl<'tcx> CFG<'tcx> {
     pub fn block_data(&self, blk: BasicBlock) -> &BasicBlockData<'tcx> {
@@ -46,7 +46,7 @@ pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
     }
 
     pub fn push_end_region<'a, 'gcx:'a+'tcx>(&mut self,
-                                             tcx: ty::TyCtxt<'a, 'gcx, 'tcx>,
+                                             tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                              block: BasicBlock,
                                              source_info: SourceInfo,
                                              region_scope: region::Scope) {
index eeae4bce335ca692680d7e7496b9d0711da17ff6..f0b6a4fcfd9d757404f34de0ab43785035e91149 100644 (file)
@@ -22,7 +22,7 @@
 use rustc_const_math::{ConstInt, ConstIsize};
 use rustc::middle::const_val::ConstVal;
 use rustc::middle::region;
-use rustc::ty;
+use rustc::ty::{self, Ty};
 use rustc::mir::*;
 use syntax::ast;
 use syntax_pos::Span;
@@ -291,7 +291,7 @@ fn expr_as_rvalue(&mut self,
     }
 
     pub fn build_binary_op(&mut self, mut block: BasicBlock,
-                           op: BinOp, span: Span, ty: ty::Ty<'tcx>,
+                           op: BinOp, span: Span, ty: Ty<'tcx>,
                            lhs: Operand<'tcx>, rhs: Operand<'tcx>) -> BlockAnd<Rvalue<'tcx>> {
         let source_info = self.source_info(span);
         let bool_ty = self.hir.bool_ty();
@@ -378,7 +378,7 @@ pub fn build_binary_op(&mut self, mut block: BasicBlock,
     }
 
     // Helper to get a `-1` value of the appropriate type
-    fn neg_1_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'tcx> {
+    fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let literal = match ty.sty {
             ty::TyInt(ity) => {
                 let val = match ity {
@@ -410,7 +410,7 @@ fn neg_1_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'tcx> {
     }
 
     // Helper to get the minimum value of the appropriate type
-    fn minval_literal(&mut self, span: Span, ty: ty::Ty<'tcx>) -> Operand<'tcx> {
+    fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let literal = match ty.sty {
             ty::TyInt(ity) => {
                 let val = match ity {
index a4421b216c311b4d50134c8e4885123d708216e7..19a595622b92edf62b9a4394407a4e5dffa4a1d9 100644 (file)
 use super::drop_flag_effects_for_location;
 use super::on_lookup_result_bits;
 
+mod storage_liveness;
+
+pub use self::storage_liveness::*;
+
 #[allow(dead_code)]
 pub(super) mod borrows;
 
diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs
new file mode 100644 (file)
index 0000000..98615c6
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use super::*;
+
+use rustc::mir::*;
+use dataflow::BitDenotation;
+
+#[derive(Copy, Clone)]
+pub struct MaybeStorageLive<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> MaybeStorageLive<'a, 'tcx> {
+    pub fn new(mir: &'a Mir<'tcx>)
+               -> Self {
+        MaybeStorageLive { mir: mir }
+    }
+
+    pub fn mir(&self) -> &Mir<'tcx> {
+        self.mir
+    }
+}
+
+impl<'a, 'tcx> BitDenotation for MaybeStorageLive<'a, 'tcx> {
+    type Idx = Local;
+    fn name() -> &'static str { "maybe_storage_live" }
+    fn bits_per_block(&self) -> usize {
+        self.mir.local_decls.len()
+    }
+
+    fn start_block_effect(&self, _sets: &mut BlockSets<Local>) {
+        // Nothing is live on function entry
+    }
+
+    fn statement_effect(&self,
+                        sets: &mut BlockSets<Local>,
+                        loc: Location) {
+        let stmt = &self.mir[loc.block].statements[loc.statement_index];
+
+        match stmt.kind {
+            StatementKind::StorageLive(l) => sets.gen(&l),
+            StatementKind::StorageDead(l) => sets.kill(&l),
+            _ => (),
+        }
+    }
+
+    fn terminator_effect(&self,
+                         _sets: &mut BlockSets<Local>,
+                         _loc: Location) {
+        // Terminators have no effect
+    }
+
+    fn propagate_call_return(&self,
+                             _in_out: &mut IdxSet<Local>,
+                             _call_bb: mir::BasicBlock,
+                             _dest_bb: mir::BasicBlock,
+                             _dest_lval: &mir::Lvalue) {
+        // Nothing to do when a call returns successfully
+    }
+}
+
+impl<'a, 'tcx> BitwiseOperator for MaybeStorageLive<'a, 'tcx> {
+    #[inline]
+    fn join(&self, pred1: usize, pred2: usize) -> usize {
+        pred1 | pred2 // "maybe" means we union effects of both preds
+    }
+}
+
+impl<'a, 'tcx> DataflowOperator for MaybeStorageLive<'a, 'tcx> {
+    #[inline]
+    fn bottom_value() -> bool {
+        false // bottom = dead
+    }
+}
index 9f9909a8f57a99f9b1d4cf74e5319d0432fcb254..9fa5691d647b70015204c5c98d93cc11ee61c4c9 100644 (file)
@@ -24,6 +24,7 @@
 use std::path::PathBuf;
 use std::usize;
 
+pub use self::impls::{MaybeStorageLive};
 pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals};
 pub use self::impls::{DefinitelyInitializedLvals};
 pub use self::impls::borrows::{Borrows, BorrowData, BorrowIndex};
@@ -351,6 +352,29 @@ fn apply_local_effect(&mut self,
                           flow_state: &mut Self::FlowState);
 }
 
+pub fn state_for_location<T: BitDenotation>(loc: Location,
+                                            analysis: &T,
+                                            result: &DataflowResults<T>)
+    -> IdxSetBuf<T::Idx> {
+    let mut entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
+
+    {
+        let mut sets = BlockSets {
+            on_entry: &mut entry.clone(),
+            kill_set: &mut entry.clone(),
+            gen_set: &mut entry,
+        };
+
+        for stmt in 0..loc.statement_index {
+            let mut stmt_loc = loc;
+            stmt_loc.statement_index = stmt;
+            analysis.statement_effect(&mut sets, stmt_loc);
+        }
+    }
+
+    entry
+}
+
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
 {
     flow_state: DataflowState<O>,
index 4b71a429f847a39c36d73e4679bbbb028be21658..26436d54ac88647b2697c50df164f337760ffb7b 100644 (file)
@@ -384,7 +384,7 @@ fn main() {
 You can also have this error while using a cell type:
 
 ```compile_fail,E0492
-#![feature(const_fn)]
+#![feature(const_cell_new)]
 
 use std::cell::Cell;
 
@@ -412,7 +412,7 @@ struct C { a: Cell<usize> }
 wrapper:
 
 ```
-#![feature(const_fn)]
+#![feature(const_cell_new)]
 
 use std::cell::Cell;
 use std::marker::Sync;
index 067bd458d97ddb3e176a21a4064cef7a8028ac65..3162242de66c51b8be59e7ce5c1adc27d22ea8a0 100644 (file)
@@ -19,7 +19,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, AdtDef, ClosureSubsts, Region, Ty, GeneratorInterior};
+use rustc::ty::{AdtDef, ClosureSubsts, Region, Ty, GeneratorInterior};
 use rustc::hir;
 use syntax::ast;
 use syntax_pos::Span;
@@ -117,7 +117,7 @@ pub enum ExprKind<'tcx> {
         value: ExprRef<'tcx>,
     },
     Call {
-        ty: ty::Ty<'tcx>,
+        ty: Ty<'tcx>,
         fun: ExprRef<'tcx>,
         args: Vec<ExprRef<'tcx>>,
     },
index 00ee417e02b5534ab984e243da49c1c86891aff5..3c9d95ca215744a240ed87b4ad50597b5edd80ab 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::transform::MirSource;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
 use rustc_const_math::{ConstInt, ConstUsize};
@@ -36,7 +36,7 @@ pub fn provide(providers: &mut Providers) {
     providers.mir_shims = make_shim;
 }
 
-fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        instance: ty::InstanceDef<'tcx>)
                        -> &'tcx Mir<'tcx>
 {
@@ -154,7 +154,7 @@ fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>, span: Span)
         .collect()
 }
 
-fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              def_id: DefId,
                              ty: Option<Ty<'tcx>>)
                              -> Mir<'tcx>
@@ -235,7 +235,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 pub struct DropShimElaborator<'a, 'tcx: 'a> {
     pub mir: &'a Mir<'tcx>,
     pub patch: MirPatch<'tcx>,
-    pub tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub param_env: ty::ParamEnv<'tcx>,
 }
 
@@ -250,7 +250,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> {
 
     fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
     fn mir(&self) -> &'a Mir<'tcx> { self.mir }
-    fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
     fn param_env(&self) -> ty::ParamEnv<'tcx> { self.param_env }
 
     fn drop_style(&self, _path: Self::Path, mode: DropFlagMode) -> DropStyle {
@@ -280,9 +280,9 @@ fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::P
 }
 
 /// Build a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`.
-fn build_clone_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               def_id: DefId,
-                              self_ty: ty::Ty<'tcx>)
+                              self_ty: Ty<'tcx>)
                               -> Mir<'tcx>
 {
     debug!("build_clone_shim(def_id={:?})", def_id);
@@ -306,7 +306,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 struct CloneShimBuilder<'a, 'tcx: 'a> {
-    tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     def_id: DefId,
     local_decls: IndexVec<Local, LocalDecl<'tcx>>,
     blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
@@ -315,7 +315,7 @@ struct CloneShimBuilder<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
-    fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Self {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Self {
         let sig = tcx.fn_sig(def_id);
         let sig = tcx.erase_late_bound_regions(&sig);
         let span = tcx.def_span(def_id);
@@ -382,7 +382,7 @@ fn copy_shim(&mut self) {
         self.block(vec![ret_statement], TerminatorKind::Return, false);
     }
 
-    fn make_lvalue(&mut self, mutability: Mutability, ty: ty::Ty<'tcx>) -> Lvalue<'tcx> {
+    fn make_lvalue(&mut self, mutability: Mutability, ty: Ty<'tcx>) -> Lvalue<'tcx> {
         let span = self.span;
         Lvalue::Local(
             self.local_decls.push(temp_decl(mutability, ty, span))
@@ -391,7 +391,7 @@ fn make_lvalue(&mut self, mutability: Mutability, ty: ty::Ty<'tcx>) -> Lvalue<'t
 
     fn make_clone_call(
         &mut self,
-        ty: ty::Ty<'tcx>,
+        ty: Ty<'tcx>,
         rcvr_field: Lvalue<'tcx>,
         next: BasicBlock,
         cleanup: BasicBlock
@@ -487,7 +487,7 @@ fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
         }
     }
 
-    fn array_shim(&mut self, ty: ty::Ty<'tcx>, len: u64) {
+    fn array_shim(&mut self, ty: Ty<'tcx>, len: u64) {
         let tcx = self.tcx;
         let span = self.span;
         let rcvr = Lvalue::Local(Local::new(1+0)).deref();
@@ -613,7 +613,7 @@ fn array_shim(&mut self, ty: ty::Ty<'tcx>, len: u64) {
         self.block(vec![], TerminatorKind::Resume, true);
     }
 
-    fn tuple_shim(&mut self, tys: &ty::Slice<ty::Ty<'tcx>>) {
+    fn tuple_shim(&mut self, tys: &ty::Slice<Ty<'tcx>>) {
         let rcvr = Lvalue::Local(Local::new(1+0)).deref();
 
         let mut returns = Vec::new();
@@ -666,7 +666,7 @@ fn tuple_shim(&mut self, tys: &ty::Slice<ty::Ty<'tcx>>) {
 ///
 /// If `untuple_args` is a vec of types, the second argument of the
 /// function will be untupled as these types.
-fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
+fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              def_id: DefId,
                              rcvr_adjustment: Adjustment,
                              call_kind: CallKind,
index 1077f3b0146168ccd48e1a0e166324306a8bbcdc..c833904adbaea6b7dab2067a375887e9ff8f37e3 100644 (file)
@@ -192,7 +192,7 @@ fn mir(&self) -> &'a Mir<'tcx> {
         self.ctxt.mir
     }
 
-    fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.ctxt.tcx
     }
 
index a52656becd74534190b114501df7e4bff8d6be39..78fe7b26ebfe0063434fe785a4dd08207b2329e6 100644 (file)
@@ -38,7 +38,8 @@
 //! This pass computes the meaning of the state field and the MIR locals which are live
 //! across a suspension point. There are however two hardcoded generator states:
 //!     0 - Generator have not been resumed yet
-//!     1 - Generator has been poisoned
+//!     1 - Generator has returned / is completed
+//!     2 - Generator has been poisoned
 //!
 //! It also rewrites `return x` and `yield y` as setting a new generator state and returning
 //! GeneratorState::Complete(x) and GeneratorState::Yielded(y) respectively.
 //! the action to take.
 //!
 //! One of them is the implementation of Generator::resume.
-//! For generators which have already returned it panics.
 //! For generators with state 0 (unresumed) it starts the execution of the generator.
-//! For generators with state 1 (poisoned) it panics.
+//! For generators with state 1 (returned) and state 2 (poisoned) it panics.
 //! Otherwise it continues the execution from the last suspension point.
 //!
 //! The other function is the drop glue for the generator.
-//! For generators which have already returned it does nothing.
 //! For generators with state 0 (unresumed) it drops the upvars of the generator.
-//! For generators with state 1 (poisoned) it does nothing.
+//! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
 //! Otherwise it drops all the values in scope at the last suspension point.
 
 use rustc::hir;
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::transform::{MirPass, MirSource};
-use rustc::mir::visit::{LvalueContext, MutVisitor};
+use rustc::mir::visit::{LvalueContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, GeneratorInterior};
 use rustc::ty::subst::{Kind, Substs};
 use util::dump_mir;
 use util::liveness;
 use rustc_const_math::ConstInt;
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_data_structures::indexed_set::IdxSetBuf;
 use std::collections::HashMap;
 use std::borrow::Cow;
 use std::iter::once;
 use std::mem;
 use transform::simplify;
 use transform::no_landing_pads::no_landing_pads;
+use dataflow::{self, MaybeStorageLive, state_for_location};
 
 pub struct StateTransform;
 
@@ -126,6 +127,13 @@ fn self_arg() -> Local {
     Local::new(1)
 }
 
+struct SuspensionPoint {
+    state: u32,
+    resume: BasicBlock,
+    drop: Option<BasicBlock>,
+    storage_liveness: liveness::LocalSet,
+}
+
 struct TransformVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     state_adt_ref: &'tcx AdtDef,
@@ -137,18 +145,14 @@ struct TransformVisitor<'a, 'tcx: 'a> {
     // Mapping from Local to (type of local, generator struct index)
     remap: HashMap<Local, (Ty<'tcx>, usize)>,
 
-    // The number of generator states. 0 is unresumed, 1 is poisoned. So this is initialized to 2
-    bb_target_count: u32,
+    // A map from a suspension point in a block to the locals which have live storage at that point
+    storage_liveness: HashMap<BasicBlock, liveness::LocalSet>,
 
-    // Map from a (which block to resume execution at, which block to use to drop the generator)
-    // to a generator state
-    bb_targets: HashMap<(BasicBlock, Option<BasicBlock>), u32>,
+    // A list of suspension points, generated during the transform
+    suspension_points: Vec<SuspensionPoint>,
 
     // The original RETURN_POINTER local
     new_ret_local: Local,
-
-    // The block to resume execution when for Return
-    return_block: BasicBlock,
 }
 
 impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
@@ -225,33 +229,39 @@ fn visit_basic_block_data(&mut self,
 
         let ret_val = match data.terminator().kind {
             TerminatorKind::Return => Some((1,
-                self.return_block,
+                None,
                 Operand::Consume(Lvalue::Local(self.new_ret_local)),
                 None)),
             TerminatorKind::Yield { ref value, resume, drop } => Some((0,
-                resume,
+                Some(resume),
                 value.clone(),
                 drop)),
             _ => None
         };
 
         if let Some((state_idx, resume, v, drop)) = ret_val {
-            let bb_idx = {
-                let bb_targets = &mut self.bb_targets;
-                let bb_target = &mut self.bb_target_count;
-                *bb_targets.entry((resume, drop)).or_insert_with(|| {
-                    let target = *bb_target;
-                    *bb_target = target.checked_add(1).unwrap();
-                    target
-                })
-            };
             let source_info = data.terminator().source_info;
-            data.statements.push(self.set_state(bb_idx, source_info));
+            // We must assign the value first in case it gets declared dead below
             data.statements.push(Statement {
                 source_info,
                 kind: StatementKind::Assign(Lvalue::Local(RETURN_POINTER),
                     self.make_state(state_idx, v)),
             });
+            let state = if let Some(resume) = resume { // Yield
+                let state = 3 + self.suspension_points.len() as u32;
+
+                self.suspension_points.push(SuspensionPoint {
+                    state,
+                    resume,
+                    drop,
+                    storage_liveness: self.storage_liveness.get(&block).unwrap().clone(),
+                });
+
+                state
+            } else { // Return
+                 1 // state for returned
+            };
+            data.statements.push(self.set_state(state, source_info));
             data.terminator.as_mut().unwrap().kind = TerminatorKind::Return;
         }
 
@@ -286,16 +296,11 @@ fn make_generator_state_argument_indirect<'a, 'tcx>(
 
 fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
                             mir: &mut Mir<'tcx>) -> Local {
-    let source_info = SourceInfo {
-        span: mir.span,
-        scope: ARGUMENT_VISIBILITY_SCOPE,
-    };
-
     let new_ret = LocalDecl {
         mutability: Mutability::Mut,
         ty: ret_ty,
         name: None,
-        source_info,
+        source_info: source_info(mir),
         internal: false,
         is_user_variable: false,
     };
@@ -311,33 +316,84 @@ fn replace_result_variable<'tcx>(ret_ty: Ty<'tcx>,
     new_ret_local
 }
 
+struct StorageIgnored(liveness::LocalSet);
+
+impl<'tcx> Visitor<'tcx> for StorageIgnored {
+    fn visit_statement(&mut self,
+                       _block: BasicBlock,
+                       statement: &Statement<'tcx>,
+                       _location: Location) {
+        match statement.kind {
+            StatementKind::StorageLive(l) |
+            StatementKind::StorageDead(l) => { self.0.remove(&l); }
+            _ => (),
+        }
+    }
+}
+
 fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                mir: &Mir<'tcx>,
-                                               source: MirSource) -> liveness::LocalSet {
+                                               source: MirSource) ->
+                                               (liveness::LocalSet,
+                                                HashMap<BasicBlock, liveness::LocalSet>) {
+    let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
+    let node_id = source.item_id();
+    let analysis = MaybeStorageLive::new(mir);
+    let storage_live =
+        dataflow::do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
+                              |bd, p| &bd.mir().local_decls[p]);
+
+    let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
+    ignored.visit_mir(mir);
+
     let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
-    let result = liveness::liveness_of_locals(mir);
-    liveness::dump_mir(tcx, "generator_liveness", source, mir, &result);
+    let liveness = liveness::liveness_of_locals(mir);
+    liveness::dump_mir(tcx, "generator_liveness", source, mir, &liveness);
+
+    let mut storage_liveness_map = HashMap::new();
 
     for (block, data) in mir.basic_blocks().iter_enumerated() {
         if let TerminatorKind::Yield { .. } = data.terminator().kind {
-            set.union(&result.outs[block]);
+            let loc = Location {
+                block: block,
+                statement_index: data.statements.len(),
+            };
+
+            let storage_liveness = state_for_location(loc, &analysis, &storage_live);
+
+            storage_liveness_map.insert(block, storage_liveness.clone());
+
+            let mut live_locals = storage_liveness;
+
+            // Mark locals without storage statements as always having live storage
+            live_locals.union(&ignored.0);
+
+            // Locals live are live at this point only if they are used across suspension points
+            // and their storage is live
+            live_locals.intersect(&liveness.outs[block]);
+
+            // Add the locals life at this suspension point to the set of locals which live across
+            // any suspension points
+            set.union(&live_locals);
         }
     }
 
     // The generator argument is ignored
     set.remove(&self_arg());
 
-    set
+    (set, storage_liveness_map)
 }
 
 fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             source: MirSource,
                             interior: GeneratorInterior<'tcx>,
                             mir: &mut Mir<'tcx>)
-    -> (HashMap<Local, (Ty<'tcx>, usize)>, GeneratorLayout<'tcx>)
+    -> (HashMap<Local, (Ty<'tcx>, usize)>,
+        GeneratorLayout<'tcx>,
+        HashMap<BasicBlock, liveness::LocalSet>)
 {
     // Use a liveness analysis to compute locals which are live across a suspension point
-    let live_locals = locals_live_across_suspend_points(tcx, mir, source);
+    let (live_locals, storage_liveness) = locals_live_across_suspend_points(tcx, mir, source);
 
     // Erase regions from the types passed in from typeck so we can compare them with
     // MIR types
@@ -381,12 +437,31 @@ fn compute_layout<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         fields: vars
     };
 
-    (remap, layout)
+    (remap, layout, storage_liveness)
 }
 
-fn insert_entry_point<'tcx>(mir: &mut Mir<'tcx>,
-                            block: BasicBlockData<'tcx>) {
-    mir.basic_blocks_mut().raw.insert(0, block);
+fn insert_switch<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                           mir: &mut Mir<'tcx>,
+                           cases: Vec<(u32, BasicBlock)>,
+                           transform: &TransformVisitor<'a, 'tcx>) {
+    let return_block = insert_return_block(mir);
+
+    let switch = TerminatorKind::SwitchInt {
+        discr: Operand::Consume(transform.make_field(transform.state_field, tcx.types.u32)),
+        switch_ty: tcx.types.u32,
+        values: Cow::from(cases.iter().map(|&(i, _)| ConstInt::U32(i)).collect::<Vec<_>>()),
+        targets: cases.iter().map(|&(_, d)| d).chain(once(return_block)).collect(),
+    };
+
+    let source_info = source_info(mir);
+    mir.basic_blocks_mut().raw.insert(0, BasicBlockData {
+        statements: Vec::new(),
+        terminator: Some(Terminator {
+            source_info,
+            kind: switch,
+        }),
+        is_cleanup: false,
+    });
 
     let blocks = mir.basic_blocks_mut().iter_mut();
 
@@ -458,46 +533,16 @@ fn create_generator_drop_shim<'a, 'tcx>(
                 drop_clean: BasicBlock) -> Mir<'tcx> {
     let mut mir = mir.clone();
 
-    let source_info = SourceInfo {
-        span: mir.span,
-        scope: ARGUMENT_VISIBILITY_SCOPE,
-    };
+    let source_info = source_info(&mir);
 
-    let return_block = BasicBlock::new(mir.basic_blocks().len());
-    mir.basic_blocks_mut().push(BasicBlockData {
-        statements: Vec::new(),
-        terminator: Some(Terminator {
-            source_info,
-            kind: TerminatorKind::Return,
-        }),
-        is_cleanup: false,
-    });
-
-    let mut cases: Vec<_> = transform.bb_targets.iter().filter_map(|(&(_, u), &s)| {
-        u.map(|d| (s, d))
-    }).collect();
+    let mut cases = create_cases(&mut mir, transform, |point| point.drop);
 
     cases.insert(0, (0, drop_clean));
 
-    // The poisoned state 1 falls through to the default case which is just to return
+    // The returned state (1) and the poisoned state (2) falls through to
+    // the default case which is just to return
 
-    let switch = TerminatorKind::SwitchInt {
-        discr: Operand::Consume(transform.make_field(transform.state_field, tcx.types.u32)),
-        switch_ty: tcx.types.u32,
-        values: Cow::from(cases.iter().map(|&(i, _)| {
-                ConstInt::U32(i)
-            }).collect::<Vec<_>>()),
-        targets: cases.iter().map(|&(_, d)| d).chain(once(return_block)).collect(),
-    };
-
-    insert_entry_point(&mut mir, BasicBlockData {
-        statements: Vec::new(),
-        terminator: Some(Terminator {
-            source_info,
-            kind: switch,
-        }),
-        is_cleanup: false,
-    });
+    insert_switch(tcx, &mut mir, cases, &transform);
 
     for block in mir.basic_blocks_mut() {
         let kind = &mut block.terminator_mut().kind;
@@ -507,11 +552,6 @@ fn create_generator_drop_shim<'a, 'tcx>(
     }
 
     // Replace the return variable
-    let source_info = SourceInfo {
-        span: mir.span,
-        scope: ARGUMENT_VISIBILITY_SCOPE,
-    };
-
     mir.return_ty = tcx.mk_nil();
     mir.local_decls[RETURN_POINTER] = LocalDecl {
         mutability: Mutability::Mut,
@@ -548,8 +588,23 @@ fn create_generator_drop_shim<'a, 'tcx>(
     mir
 }
 
-fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                        mir: &mut Mir<'tcx>) {
+fn insert_return_block<'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
+    let return_block = BasicBlock::new(mir.basic_blocks().len());
+    let source_info = source_info(mir);
+    mir.basic_blocks_mut().push(BasicBlockData {
+        statements: Vec::new(),
+        terminator: Some(Terminator {
+            source_info,
+            kind: TerminatorKind::Return,
+        }),
+        is_cleanup: false,
+    });
+    return_block
+}
+
+fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                mir: &mut Mir<'tcx>,
+                                message: AssertMessage<'tcx>) -> BasicBlock {
     let assert_block = BasicBlock::new(mir.basic_blocks().len());
     let term = TerminatorKind::Assert {
         cond: Operand::Constant(box Constant {
@@ -563,16 +618,12 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             },
         }),
         expected: true,
-        msg: AssertMessage::GeneratorResumedAfterReturn,
+        msg: message,
         target: assert_block,
         cleanup: None,
     };
 
-    let source_info = SourceInfo {
-        span: mir.span,
-        scope: ARGUMENT_VISIBILITY_SCOPE,
-    };
-
+    let source_info = source_info(mir);
     mir.basic_blocks_mut().push(BasicBlockData {
         statements: Vec::new(),
         terminator: Some(Terminator {
@@ -581,11 +632,13 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }),
         is_cleanup: false,
     });
+
+    assert_block
 }
 
 fn create_generator_resume_function<'a, 'tcx>(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
-        mut transform: TransformVisitor<'a, 'tcx>,
+        transform: TransformVisitor<'a, 'tcx>,
         def_id: DefId,
         source: MirSource,
         mir: &mut Mir<'tcx>) {
@@ -597,61 +650,16 @@ fn create_generator_resume_function<'a, 'tcx>(
         }
     }
 
-    let source_info = SourceInfo {
-        span: mir.span,
-        scope: ARGUMENT_VISIBILITY_SCOPE,
-    };
-
-    let poisoned_block = BasicBlock::new(mir.basic_blocks().len());
-
-    let term = TerminatorKind::Assert {
-        cond: Operand::Constant(box Constant {
-            span: mir.span,
-            ty: tcx.types.bool,
-            literal: Literal::Value {
-                value: tcx.mk_const(ty::Const {
-                    val: ConstVal::Bool(false),
-                    ty: tcx.types.bool
-                }),
-            },
-        }),
-        expected: true,
-        msg: AssertMessage::GeneratorResumedAfterPanic,
-        target: transform.return_block,
-        cleanup: None,
-    };
-
-    mir.basic_blocks_mut().push(BasicBlockData {
-        statements: Vec::new(),
-        terminator: Some(Terminator {
-            source_info,
-            kind: term,
-        }),
-        is_cleanup: false,
-    });
-
-    transform.bb_targets.insert((poisoned_block, None), 1);
+    let mut cases = create_cases(mir, &transform, |point| Some(point.resume));
 
-    let switch = TerminatorKind::SwitchInt {
-        discr: Operand::Consume(transform.make_field(transform.state_field, tcx.types.u32)),
-        switch_ty: tcx.types.u32,
-        values: Cow::from(transform.bb_targets.values().map(|&i| {
-                ConstInt::U32(i)
-            }).collect::<Vec<_>>()),
-        targets: transform.bb_targets.keys()
-            .map(|&(k, _)| k)
-            .chain(once(transform.return_block))
-            .collect(),
-    };
+    // Jump to the entry point on the 0 state
+    cases.insert(0, (0, BasicBlock::new(0)));
+    // Panic when resumed on the returned (1) state
+    cases.insert(1, (1, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterReturn)));
+    // Panic when resumed on the poisoned (2) state
+    cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic)));
 
-    insert_entry_point(mir, BasicBlockData {
-        statements: Vec::new(),
-        terminator: Some(Terminator {
-            source_info,
-            kind: switch,
-        }),
-        is_cleanup: false,
-    });
+    insert_switch(tcx, mir, cases, &transform);
 
     make_generator_state_argument_indirect(tcx, def_id, mir);
 
@@ -664,21 +672,15 @@ fn create_generator_resume_function<'a, 'tcx>(
     dump_mir(tcx, None, "generator_resume", &0, source, mir);
 }
 
-fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
-    let source_info = SourceInfo {
+fn source_info<'a, 'tcx>(mir: &Mir<'tcx>) -> SourceInfo {
+    SourceInfo {
         span: mir.span,
         scope: ARGUMENT_VISIBILITY_SCOPE,
-    };
+    }
+}
 
-    let return_block = BasicBlock::new(mir.basic_blocks().len());
-    mir.basic_blocks_mut().push(BasicBlockData {
-        statements: Vec::new(),
-        terminator: Some(Terminator {
-            source_info,
-            kind: TerminatorKind::Return,
-        }),
-        is_cleanup: false,
-    });
+fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
+    let return_block = insert_return_block(mir);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
     let drop_clean = BasicBlock::new(mir.basic_blocks().len());
@@ -687,6 +689,7 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
         target: return_block,
         unwind: None,
     };
+    let source_info = source_info(mir);
     mir.basic_blocks_mut().push(BasicBlockData {
         statements: Vec::new(),
         terminator: Some(Terminator {
@@ -699,6 +702,46 @@ fn insert_clean_drop<'a, 'tcx>(mir: &mut Mir<'tcx>) -> BasicBlock {
     drop_clean
 }
 
+fn create_cases<'a, 'tcx, F>(mir: &mut Mir<'tcx>,
+                          transform: &TransformVisitor<'a, 'tcx>,
+                          target: F) -> Vec<(u32, BasicBlock)>
+    where F: Fn(&SuspensionPoint) -> Option<BasicBlock> {
+    let source_info = source_info(mir);
+
+    transform.suspension_points.iter().filter_map(|point| {
+        // Find the target for this suspension point, if applicable
+        target(point).map(|target| {
+            let block = BasicBlock::new(mir.basic_blocks().len());
+            let mut statements = Vec::new();
+
+            // Create StorageLive instructions for locals with live storage
+            for i in 0..(mir.local_decls.len()) {
+                let l = Local::new(i);
+                if point.storage_liveness.contains(&l) && !transform.remap.contains_key(&l) {
+                    statements.push(Statement {
+                        source_info,
+                        kind: StatementKind::StorageLive(l),
+                    });
+                }
+            }
+
+            // Then jump to the real target
+            mir.basic_blocks_mut().push(BasicBlockData {
+                statements,
+                terminator: Some(Terminator {
+                    source_info,
+                    kind: TerminatorKind::Goto {
+                        target,
+                    },
+                }),
+                is_cleanup: false,
+            });
+
+            (point.state, block)
+        })
+    }).collect()
+}
+
 impl MirPass for StateTransform {
     fn run_pass<'a, 'tcx>(&self,
                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -736,16 +779,11 @@ fn run_pass<'a, 'tcx>(&self,
 
         // Extract locals which are live across suspension point into `layout`
         // `remap` gives a mapping from local indices onto generator struct indices
-        let (remap, layout) = compute_layout(tcx, source, interior, mir);
+        // `storage_liveness` tells us which locals have live storage at suspension points
+        let (remap, layout, storage_liveness) = compute_layout(tcx, source, interior, mir);
 
         let state_field = mir.upvar_decls.len();
 
-        let mut bb_targets = HashMap::new();
-
-        // If we jump to the entry point, we should go to the initial 0 generator state.
-        // FIXME: Could this result in the need for destruction for state 0?
-        bb_targets.insert((BasicBlock::new(0), None), 0);
-
         // Run the transformation which converts Lvalues from Local to generator struct
         // accesses for locals in `remap`.
         // It also rewrites `return x` and `yield y` as writing a new generator state and returning
@@ -755,14 +793,10 @@ fn run_pass<'a, 'tcx>(&self,
             state_adt_ref,
             state_substs,
             remap,
-            bb_target_count: 2,
-            bb_targets,
+            storage_liveness,
+            suspension_points: Vec::new(),
             new_ret_local,
             state_field,
-
-            // For returns we will resume execution at the next added basic block.
-            // This happens in `insert_panic_on_resume_after_return`
-            return_block: BasicBlock::new(mir.basic_blocks().len()),
         };
         transform.visit_mir(mir);
 
@@ -773,9 +807,6 @@ fn run_pass<'a, 'tcx>(&self,
         mir.spread_arg = None;
         mir.generator_layout = Some(layout);
 
-        // Panic if we resumed after returning
-        insert_panic_on_resume_after_return(tcx, mir);
-
         // Insert `drop(generator_struct)` which is used to drop upvars for generators in
         // the unresumed (0) state.
         // This is expanded to a drop ladder in `elaborate_generator_drops`.
index f8c26dc99c633fc062d228676432dff4457ab8ff..fa6a98224ee814d4f53f2667cea7460c7ca4a82e 100644 (file)
@@ -30,6 +30,7 @@
 use rustc::mir::visit::{LvalueContext, Visitor};
 use rustc::middle::lang_items;
 use syntax::abi::Abi;
+use syntax::attr;
 use syntax::feature_gate::UnstableFeatures;
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -713,14 +714,14 @@ fn visit_terminator_kind(&mut self,
             self.visit_operand(func, location);
 
             let fn_ty = func.ty(self.mir, self.tcx);
-            let (mut is_shuffle, mut is_const_fn) = (false, false);
+            let (mut is_shuffle, mut is_const_fn) = (false, None);
             if let ty::TyFnDef(def_id, _) = fn_ty.sty {
                 match self.tcx.fn_sig(def_id).abi() {
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
                         assert!(!self.tcx.is_const_fn(def_id));
                         match &self.tcx.item_name(def_id)[..] {
-                            "size_of" | "min_align_of" => is_const_fn = true,
+                            "size_of" | "min_align_of" => is_const_fn = Some(def_id),
 
                             name if name.starts_with("simd_shuffle") => {
                                 is_shuffle = true;
@@ -730,7 +731,9 @@ fn visit_terminator_kind(&mut self,
                         }
                     }
                     _ => {
-                        is_const_fn = self.tcx.is_const_fn(def_id);
+                        if self.tcx.is_const_fn(def_id) {
+                            is_const_fn = Some(def_id);
+                        }
                     }
                 }
             }
@@ -751,25 +754,38 @@ fn visit_terminator_kind(&mut self,
             }
 
             // Const fn calls.
-            if is_const_fn {
-                // We are in a const or static initializer,
-                if self.mode != Mode::Fn &&
-
-                    // feature-gate is not enabled,
-                    !self.tcx.sess.features.borrow().const_fn &&
-
-                    // this doesn't come from a crate with the feature-gate enabled,
-                    self.def_id.is_local() &&
-
-                    // this doesn't come from a macro that has #[allow_internal_unstable]
-                    !self.span.allows_unstable()
-                {
-                    let mut err = self.tcx.sess.struct_span_err(self.span,
-                        "const fns are an unstable feature");
-                    help!(&mut err,
-                          "in Nightly builds, add `#![feature(const_fn)]` \
-                           to the crate attributes to enable");
-                    err.emit();
+            if let Some(def_id) = is_const_fn {
+                // find corresponding rustc_const_unstable feature
+                if let Some(&attr::Stability {
+                    rustc_const_unstable: Some(attr::RustcConstUnstable {
+                        feature: ref feature_name
+                    }),
+                .. }) = self.tcx.lookup_stability(def_id) {
+
+                    // We are in a const or static initializer,
+                    if self.mode != Mode::Fn &&
+
+                        // feature-gate is not enabled,
+                        !self.tcx.sess.features.borrow()
+                            .declared_lib_features
+                            .iter()
+                            .any(|&(ref sym, _)| sym == feature_name) &&
+
+                        // this doesn't come from a crate with the feature-gate enabled,
+                        self.def_id.is_local() &&
+
+                        // this doesn't come from a macro that has #[allow_internal_unstable]
+                        !self.span.allows_unstable()
+                    {
+                        let mut err = self.tcx.sess.struct_span_err(self.span,
+                            &format!("`{}` is not yet stable as a const fn",
+                                     self.tcx.item_path_str(def_id)));
+                        help!(&mut err,
+                              "in Nightly builds, add `#![feature({})]` \
+                               to the crate attributes to enable",
+                              feature_name);
+                        err.emit();
+                    }
                 }
             } else {
                 self.qualif = Qualif::NOT_CONST;
index 4a11ac11680906c076346e0728e1e5ee06e1b819..3b9772079adb9c90546cdec00bb07b5137010d8f 100644 (file)
@@ -13,7 +13,7 @@
 use rustc::mir::*;
 use rustc::middle::const_val::{ConstInt, ConstVal};
 use rustc::middle::lang_items;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Substs};
 use rustc::ty::util::IntTypeExt;
 use rustc_data_structures::indexed_vec::Idx;
@@ -84,7 +84,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug {
 
     fn patch(&mut self) -> &mut MirPatch<'tcx>;
     fn mir(&self) -> &'a Mir<'tcx>;
-    fn tcx(&self) -> ty::TyCtxt<'a, 'tcx, 'tcx>;
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
     fn param_env(&self) -> ty::ParamEnv<'tcx>;
 
     fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle;
@@ -133,7 +133,7 @@ fn lvalue_ty(&self, lvalue: &Lvalue<'tcx>) -> Ty<'tcx> {
         lvalue.ty(self.elaborator.mir(), self.tcx()).to_ty(self.tcx())
     }
 
-    fn tcx(&self) -> ty::TyCtxt<'b, 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.elaborator.tcx()
     }
 
index efb56ab5a6cac64231d53b5b5915d0629a33c280..08266e86f97933e491a861022f369ecb70ebc5b5 100644 (file)
@@ -107,14 +107,32 @@ pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMet
 pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)>) {
     let envs = vec![("PATH".into(), command_path(sess))];
 
+    // If our linker looks like a batch script on Windows then to execute this
+    // we'll need to spawn `cmd` explicitly. This is primarily done to handle
+    // emscripten where the linker is `emcc.bat` and needs to be spawned as
+    // `cmd /c emcc.bat ...`.
+    //
+    // This worked historically but is needed manually since #42436 (regression
+    // was tagged as #42791) and some more info can be found on #44443 for
+    // emscripten itself.
+    let cmd = |linker: &str| {
+        if cfg!(windows) && linker.ends_with(".bat") {
+            let mut cmd = Command::new("cmd");
+            cmd.arg("/c").arg(linker);
+            cmd
+        } else {
+            Command::new(linker)
+        }
+    };
+
     if let Some(ref linker) = sess.opts.cg.linker {
-        (linker.clone(), Command::new(linker), envs)
+        (linker.clone(), cmd(linker), envs)
     } else if sess.target.target.options.is_like_msvc {
         let (cmd, envs) = msvc_link_exe_cmd(sess);
         ("link.exe".to_string(), cmd, envs)
     } else {
         let linker = &sess.target.target.options.linker;
-        (linker.clone(), Command::new(&linker), envs)
+        (linker.clone(), cmd(linker), envs)
     }
 }
 
index 72e1fc34789540b7e055f4f4ae66da7ff69521ba..68140011e7ec3843136fa75f8c601f57ccd5e0a3 100644 (file)
@@ -13,6 +13,7 @@
 use back::linker::LinkerInfo;
 use back::symbol_export::ExportedSymbols;
 use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
+use rustc::dep_graph::DepGraph;
 use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
 use rustc::session::config::{self, OutputFilenames, OutputType, OutputTypes, Passes, SomePasses,
                              AllPasses, Sanitizer};
@@ -807,6 +808,7 @@ pub fn start_async_translation(sess: &Session,
 }
 
 fn copy_module_artifacts_into_incr_comp_cache(sess: &Session,
+                                              dep_graph: &DepGraph,
                                               compiled_modules: &CompiledModules,
                                               crate_output: &OutputFilenames) {
     if sess.opts.incremental.is_none() {
@@ -826,7 +828,11 @@ fn copy_module_artifacts_into_incr_comp_cache(sess: &Session,
             files.push((OutputType::Bitcode, path));
         }
 
-        save_trans_partition(sess, &module.name, module.symbol_name_hash, &files);
+        save_trans_partition(sess,
+                             dep_graph,
+                             &module.name,
+                             module.symbol_name_hash,
+                             &files);
     }
 }
 
@@ -1822,7 +1828,7 @@ pub struct OngoingCrateTranslation {
 }
 
 impl OngoingCrateTranslation {
-    pub fn join(self, sess: &Session) -> CrateTranslation {
+    pub fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
         self.shared_emitter_main.check(sess, true);
         let compiled_modules = match self.future.join() {
             Ok(compiled_modules) => compiled_modules,
@@ -1838,6 +1844,7 @@ pub fn join(self, sess: &Session) -> CrateTranslation {
         }
 
         copy_module_artifacts_into_incr_comp_cache(sess,
+                                                   dep_graph,
                                                    &compiled_modules,
                                                    &self.output_filenames);
         produce_final_output_artifacts(sess,
index 3bf709ff7ba9d227fa679e3d2edc7fa022c5754e..f0d8c7e9bfbca2cbcd3f04780bc1d4c07877a6c4 100644 (file)
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem};
 use rustc::traits;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, TypeFoldable, TyCtxt};
+use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::mir::{self, Location};
 use rustc::mir::visit::Visitor as MirVisitor;
@@ -648,7 +648,7 @@ fn visit_static(&mut self,
 }
 
 fn visit_drop_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                            ty: ty::Ty<'tcx>,
+                            ty: Ty<'tcx>,
                             is_direct_call: bool,
                             output: &mut Vec<TransItem<'tcx>>)
 {
@@ -657,7 +657,7 @@ fn visit_drop_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 }
 
 fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                          ty: ty::Ty<'tcx>,
+                          ty: Ty<'tcx>,
                           is_direct_call: bool,
                           output: &mut Vec<TransItem<'tcx>>)
 {
@@ -776,10 +776,10 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
 /// Finally, there is also the case of custom unsizing coercions, e.g. for
 /// smart pointers such as `Rc` and `Arc`.
 fn find_vtable_types_for_unsizing<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                            source_ty: ty::Ty<'tcx>,
-                                            target_ty: ty::Ty<'tcx>)
-                                            -> (ty::Ty<'tcx>, ty::Ty<'tcx>) {
-    let ptr_vtable = |inner_source: ty::Ty<'tcx>, inner_target: ty::Ty<'tcx>| {
+                                            source_ty: Ty<'tcx>,
+                                            target_ty: Ty<'tcx>)
+                                            -> (Ty<'tcx>, Ty<'tcx>) {
+    let ptr_vtable = |inner_source: Ty<'tcx>, inner_target: Ty<'tcx>| {
         if !scx.type_is_sized(inner_source) {
             (inner_source, inner_target)
         } else {
@@ -836,8 +836,8 @@ fn create_fn_trans_item<'a, 'tcx>(instance: Instance<'tcx>) -> TransItem<'tcx> {
 /// Creates a `TransItem` for each method that is referenced by the vtable for
 /// the given trait/impl pair.
 fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
-                                                   trait_ty: ty::Ty<'tcx>,
-                                                   impl_ty: ty::Ty<'tcx>,
+                                                   trait_ty: Ty<'tcx>,
+                                                   impl_ty: Ty<'tcx>,
                                                    output: &mut Vec<TransItem<'tcx>>) {
     assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_regions() &&
             !impl_ty.needs_subst() && !impl_ty.has_escaping_regions());
index 77bddc7731b5bee0a3a65203102f9bc7f2e2dee6..4211be362ef19e0a0bcd7d96326701e11ef31160 100644 (file)
@@ -104,7 +104,7 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
     /// Cache instances of monomorphic and polymorphic items
     instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
     /// Cache generated vtables
-    vtables: RefCell<FxHashMap<(ty::Ty<'tcx>,
+    vtables: RefCell<FxHashMap<(Ty<'tcx>,
                                 Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
     /// Cache of constant strings,
     const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
@@ -512,7 +512,7 @@ pub fn instances<'a>(&'a self) -> &'a RefCell<FxHashMap<Instance<'tcx>, ValueRef
     }
 
     pub fn vtables<'a>(&'a self)
-        -> &'a RefCell<FxHashMap<(ty::Ty<'tcx>,
+        -> &'a RefCell<FxHashMap<(Ty<'tcx>,
                                   Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>> {
         &self.local().vtables
     }
index 8f9146283effe103f5dd8193e8e167c412bd9458..3c8ff45499780e5481ad8d4381da880340add6dc 100644 (file)
@@ -22,7 +22,7 @@
 
 use llvm::{self, ValueRef};
 use llvm::AttributePlace::Function;
-use rustc::ty;
+use rustc::ty::Ty;
 use rustc::session::config::Sanitizer;
 use abi::{Abi, FnType};
 use attributes;
@@ -119,7 +119,7 @@ pub fn declare_cfn(ccx: &CrateContext, name: &str, fn_type: Type) -> ValueRef {
 /// If there’s a value with the same name already declared, the function will
 /// update the declaration and return existing ValueRef instead.
 pub fn declare_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
-                            fn_type: ty::Ty<'tcx>) -> ValueRef {
+                            fn_type: Ty<'tcx>) -> ValueRef {
     debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type);
     let sig = common::ty_fn_sig(ccx, fn_type);
     let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
@@ -164,7 +164,7 @@ pub fn define_global(ccx: &CrateContext, name: &str, ty: Type) -> Option<ValueRe
 /// can happen with #[no_mangle] or #[export_name], for example.
 pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                            name: &str,
-                           fn_type: ty::Ty<'tcx>) -> ValueRef {
+                           fn_type: Ty<'tcx>) -> ValueRef {
     if get_defined_value(ccx, name).is_some() {
         ccx.sess().fatal(&format!("symbol `{}` already defined", name))
     } else {
@@ -179,7 +179,7 @@ pub fn define_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 /// can happen with #[no_mangle] or #[export_name], for example.
 pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                     name: &str,
-                                    fn_type: ty::Ty<'tcx>) -> ValueRef {
+                                    fn_type: Ty<'tcx>) -> ValueRef {
     let llfn = define_fn(ccx, name, fn_type);
     unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) };
     llfn
index 8dd0b4e466ce491bedcb291c963218b64317aaf6..3939497971337f152304f2d95b6dd1acb23a5350 100644 (file)
@@ -16,8 +16,7 @@
 
 use llvm;
 use llvm::{ValueRef};
-use rustc::traits;
-use rustc::ty::{self, Ty, TypeFoldable};
+use rustc::ty::{self, Ty};
 use rustc::ty::layout::LayoutTyper;
 use common::*;
 use meth;
 use value::Value;
 use builder::Builder;
 
-pub fn needs_drop_glue<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>) -> bool {
-    assert!(t.is_normalized_for_trans());
-
-    let t = scx.tcx().erase_regions(&t);
-
-    // FIXME (#22815): note that type_needs_drop conservatively
-    // approximates in some cases and may say a type expression
-    // requires drop glue when it actually does not.
-    //
-    // (In this case it is not clear whether any harm is done, i.e.
-    // erroneously returning `true` in some cases where we could have
-    // returned `false` does not appear unsound. The impact on
-    // code quality is unknown at this time.)
-
-    if !scx.type_needs_drop(t) {
-        return false;
-    }
-    match t.sty {
-        ty::TyAdt(def, _) if def.is_box() => {
-            let typ = t.boxed_ty();
-            if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) {
-                let layout = t.layout(scx.tcx(), ty::ParamEnv::empty(traits::Reveal::All)).unwrap();
-                if layout.size(scx).bytes() == 0 {
-                    // `Box<ZeroSizeType>` does not allocate.
-                    false
-                } else {
-                    true
-                }
-            } else {
-                true
-            }
-        }
-        _ => true
-    }
-}
-
 pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
                                        -> (ValueRef, ValueRef) {
     debug!("calculate size of DST: {}; with lost info: {:?}",
index 63fd37c2b98bf62816b9f61cf23cca78b02937f8..256200a6e9572f1d10144f1dadbedafe07f6b4c5 100644 (file)
@@ -21,7 +21,6 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+#![cfg_attr(not(stage0), feature(const_once_new))]
+
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
index 6eedd53974e70482a76cca732d4c90ea6c2a6719..9abfbb3279ce0315f9e404c2fa7701f0a6d99032 100644 (file)
@@ -18,7 +18,7 @@
 use monomorphize;
 use type_::Type;
 use value::Value;
-use rustc::ty;
+use rustc::ty::{self, Ty};
 
 #[derive(Copy, Clone, Debug)]
 pub struct VirtualIndex(usize);
@@ -63,7 +63,7 @@ pub fn get_usize(self, bcx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef
 /// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
 /// `trait_ref` would map `T:Trait`.
 pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                            ty: ty::Ty<'tcx>,
+                            ty: Ty<'tcx>,
                             trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>)
                             -> ValueRef
 {
index 3e802c8be5bf4f3569648b76e06162b128e05e26..1105da436189fe29e0f8d0d966d1a7a122532f58 100644 (file)
@@ -11,7 +11,7 @@
 use llvm::{self, ValueRef, BasicBlockRef};
 use rustc::middle::lang_items;
 use rustc::middle::const_val::{ConstEvalErr, ConstInt, ErrKind};
-use rustc::ty::{self, TypeFoldable};
+use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutTyper};
 use rustc::mir;
 use abi::{Abi, FnType, ArgType};
@@ -119,7 +119,7 @@ fn trans_terminator(&mut self,
             fn_ty: FnType<'tcx>,
             fn_ptr: ValueRef,
             llargs: &[ValueRef],
-            destination: Option<(ReturnDest, ty::Ty<'tcx>, mir::BasicBlock)>,
+            destination: Option<(ReturnDest, Ty<'tcx>, mir::BasicBlock)>,
             cleanup: Option<mir::BasicBlock>
         | {
             if let Some(cleanup) = cleanup {
index 9a7f1524d209f7b0b16e82c159f1197395577acb..309177d9ff6a2602d0be37c971509997acfa3281 100644 (file)
@@ -10,7 +10,6 @@
 
 use abi::Abi;
 use common::*;
-use glue;
 
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::DropInPlaceFnLangItem;
@@ -189,7 +188,7 @@ pub fn resolve<'a, 'tcx>(
             _ => {
                 if Some(def_id) == scx.tcx().lang_items().drop_in_place_fn() {
                     let ty = substs.type_at(0);
-                    if glue::needs_drop_glue(scx, ty) {
+                    if scx.type_needs_drop(ty) {
                         debug!(" => nontrivial drop glue");
                         ty::InstanceDef::DropGlue(def_id, Some(ty))
                     } else {
index 90e17906328fbabaa80b047598e614bfef825cca..5e8abe59ad9a474c801d49b600704974a7311a98 100644 (file)
@@ -19,7 +19,6 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
@@ -28,6 +27,8 @@
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+
 extern crate rustc;
 extern crate syntax;
 extern crate syntax_pos;
index 9bee26a52c0d7777b96192047931591418fd686b..610d07efa359df0d82dca7a02c8c7ee38bfeb57b 100644 (file)
@@ -268,7 +268,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
 ///
 pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
     rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
-    ty: ty::Ty<'tcx>,
+    ty: Ty<'tcx>,
     span: Span,
     scope: region::Scope)
     -> Result<(), ErrorReported>
index fa8d3b9bcc1cb41cc2eb5df9f32285a90d9c9b96..3861a358b23e0bace364eff331501ac590090dc7 100644 (file)
@@ -423,8 +423,8 @@ fn match_intrinsic_type_to_type<'a, 'tcx>(
         tcx: TyCtxt<'a, 'tcx, 'tcx>,
         position: &str,
         span: Span,
-        structural_to_nominal: &mut FxHashMap<&'a intrinsics::Type, ty::Ty<'tcx>>,
-        expected: &'a intrinsics::Type, t: ty::Ty<'tcx>)
+        structural_to_nominal: &mut FxHashMap<&'a intrinsics::Type, Ty<'tcx>>,
+        expected: &'a intrinsics::Type, t: Ty<'tcx>)
 {
     use intrinsics::Type::*;
 
index 31ceed5b965bff71377c4b3f9e121c702167fecd..0afc482cb79db769a0ac7988169322826bfa51ec 100644 (file)
@@ -15,7 +15,7 @@
 use hir::def_id::DefId;
 use rustc::ty::subst::Substs;
 use rustc::traits;
-use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
+use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
 use rustc::ty::subst::Subst;
 use rustc::infer::{self, InferOk};
 
@@ -102,7 +102,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     pub fn method_exists(&self,
                          span: Span,
                          method_name: ast::Name,
-                         self_ty: ty::Ty<'tcx>,
+                         self_ty: Ty<'tcx>,
                          call_expr_id: ast::NodeId,
                          allow_private: bool)
                          -> bool {
@@ -136,7 +136,7 @@ pub fn method_exists(&self,
     /// * `supplied_method_types`: the explicit method type parameters, if any (`T1..Tn`)
     /// * `self_expr`:             the self expression (`foo`)
     pub fn lookup_method(&self,
-                         self_ty: ty::Ty<'tcx>,
+                         self_ty: Ty<'tcx>,
                          segment: &hir::PathSegment,
                          span: Span,
                          call_expr: &'gcx hir::Expr,
@@ -206,7 +206,7 @@ pub fn lookup_method(&self,
     fn lookup_probe(&self,
                     span: Span,
                     method_name: ast::Name,
-                    self_ty: ty::Ty<'tcx>,
+                    self_ty: Ty<'tcx>,
                     call_expr: &'gcx hir::Expr,
                     scope: ProbeScope)
                     -> probe::PickResult<'tcx> {
@@ -229,8 +229,8 @@ pub fn lookup_method_in_trait(&self,
                                   span: Span,
                                   m_name: ast::Name,
                                   trait_def_id: DefId,
-                                  self_ty: ty::Ty<'tcx>,
-                                  opt_input_types: Option<&[ty::Ty<'tcx>]>)
+                                  self_ty: Ty<'tcx>,
+                                  opt_input_types: Option<&[Ty<'tcx>]>)
                                   -> Option<InferOk<'tcx, MethodCallee<'tcx>>> {
         debug!("lookup_in_trait_adjusted(self_ty={:?}, \
                 m_name={}, trait_def_id={:?})",
@@ -347,7 +347,7 @@ pub fn lookup_method_in_trait(&self,
     pub fn resolve_ufcs(&self,
                         span: Span,
                         method_name: ast::Name,
-                        self_ty: ty::Ty<'tcx>,
+                        self_ty: Ty<'tcx>,
                         expr_id: ast::NodeId)
                         -> Result<Def, MethodError<'tcx>> {
         let mode = probe::Mode::Path;
index acdd58f4ecfe43c92d640b92800653e38ae56b24..d179b390a291868130709077558d33211a1ce055 100644 (file)
@@ -45,7 +45,7 @@
 use middle::expr_use_visitor as euv;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::Categorization;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::infer::UpvarRegion;
 use syntax::ast;
 use syntax_pos::Span;
@@ -586,7 +586,7 @@ fn mutate(&mut self,
     }
 }
 
-fn var_name(tcx: ty::TyCtxt, var_hir_id: hir::HirId) -> ast::Name {
+fn var_name(tcx: TyCtxt, var_hir_id: hir::HirId) -> ast::Name {
     let var_node_id = tcx.hir.hir_to_node_id(var_hir_id);
     tcx.hir.name(var_node_id)
 }
index 9c19aef5992e698bd324f5e56199200eacee4de3..f17df8b22f3934e0c4943524d1d73148bf083bac 100644 (file)
@@ -449,7 +449,7 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
                                          fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
                                          method_sig: &hir::MethodSig,
                                          method: &ty::AssociatedItem,
-                                         self_ty: ty::Ty<'tcx>)
+                                         self_ty: Ty<'tcx>)
     {
         // check that the type of the method's receiver matches the
         // method's first parameter.
index 1735ec7cc698c29788d0cdc51a0aa3de97536420..b0f3ff3ef35bf13b0ba9270dc98b8b2d8a78771a 100644 (file)
@@ -1580,7 +1580,7 @@ pub enum SizedByDefault { Yes, No, }
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
 pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
-                                        param_ty: ty::Ty<'tcx>,
+                                        param_ty: Ty<'tcx>,
                                         ast_bounds: &[hir::TyParamBound],
                                         sized_by_default: SizedByDefault,
                                         span: Span)
@@ -1673,7 +1673,7 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>(
     // ABIs are handled at all correctly.
     if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic
             && !tcx.sess.features.borrow().simd_ffi {
-        let check = |ast_ty: &hir::Ty, ty: ty::Ty| {
+        let check = |ast_ty: &hir::Ty, ty: Ty| {
             if ty.is_simd() {
                 tcx.sess.struct_span_err(ast_ty.span,
                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
index 09c7487e635601924d223763cc3ab9dd3dd0615d..5f55b9b06ef1b122d804e090a99b53c6be398b38 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::fold::{TypeFoldable, TypeVisitor};
 use rustc::util::nodemap::FxHashSet;
 
@@ -86,7 +86,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
     }
 }
 
-pub fn identify_constrained_type_params<'tcx>(tcx: ty::TyCtxt,
+pub fn identify_constrained_type_params<'tcx>(tcx: TyCtxt,
                                               predicates: &[ty::Predicate<'tcx>],
                                               impl_trait_ref: Option<ty::TraitRef<'tcx>>,
                                               input_parameters: &mut FxHashSet<Parameter>)
@@ -136,7 +136,7 @@ pub fn identify_constrained_type_params<'tcx>(tcx: ty::TyCtxt,
 /// which is determined by 1, which requires `U`, that is determined
 /// by 0. I should probably pick a less tangled example, but I can't
 /// think of any.
-pub fn setup_constraining_predicates<'tcx>(tcx: ty::TyCtxt,
+pub fn setup_constraining_predicates<'tcx>(tcx: TyCtxt,
                                            predicates: &mut [ty::Predicate<'tcx>],
                                            impl_trait_ref: Option<ty::TraitRef<'tcx>>,
                                            input_parameters: &mut FxHashSet<Parameter>)
index 6062ac96ada787624dd189a60c0c0699c824db3b..ac3d575b64882de9516d892a213abd16fb46e293 100644 (file)
@@ -98,15 +98,6 @@ fn lang_items(tcx: TyCtxt) -> Vec<(ast::NodeId, Vec<ty::Variance>)> {
     let all = vec![
         (lang_items.phantom_data(), vec![ty::Covariant]),
         (lang_items.unsafe_cell_type(), vec![ty::Invariant]),
-
-        // Deprecated:
-        (lang_items.covariant_type(), vec![ty::Covariant]),
-        (lang_items.contravariant_type(), vec![ty::Contravariant]),
-        (lang_items.invariant_type(), vec![ty::Invariant]),
-        (lang_items.covariant_lifetime(), vec![ty::Covariant]),
-        (lang_items.contravariant_lifetime(), vec![ty::Contravariant]),
-        (lang_items.invariant_lifetime(), vec![ty::Invariant]),
-
         ];
 
     all.into_iter() // iterating over (Option<DefId>, Variance)
index 7531458d9f9d6c32cd76d71b1260ea1f61e7e9c0..3be09373408997ae564453bf53790673ea48a748 100644 (file)
@@ -35,7 +35,7 @@
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc::traits::Reveal;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, AdtKind};
+use rustc::ty::{self, Ty, AdtKind};
 use rustc::middle::stability;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_typeck::hir_ty_to_ty;
@@ -978,7 +978,7 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
     }
 }
 
-impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region<'tcx>> {
+impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
     fn clean(&self, cx: &DocContext) -> WherePredicate {
         let ty::OutlivesPredicate(ref ty, ref lt) = *self;
 
@@ -1901,7 +1901,7 @@ fn clean(&self, cx: &DocContext) -> Type {
     }
 }
 
-impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
+impl<'tcx> Clean<Type> for Ty<'tcx> {
     fn clean(&self, cx: &DocContext) -> Type {
         match self.sty {
             ty::TyNever => Never,
index d7ce5e262ce381b07cd0f412da0dff4b4ad80704..fd0167be2b98f4e57680b52f32ad9c48e4a7ae1b 100644 (file)
@@ -11,7 +11,6 @@
 use rustc_lint;
 use rustc_driver::{driver, target_features, abort_on_err};
 use rustc_driver::pretty::ReplaceBodyWithLoop;
-use rustc::dep_graph::DepGraph;
 use rustc::session::{self, config};
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
@@ -144,11 +143,9 @@ pub fn run_core(search_paths: SearchPaths,
                                                                false,
                                                                Some(codemap.clone()));
 
-    let dep_graph = DepGraph::new(false);
-    let _ignore = dep_graph.in_ignore();
     let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
-        sessopts, &dep_graph, cpath, diagnostic_handler, codemap
+        sessopts, cpath, diagnostic_handler, codemap,
     );
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
index e6b236deac4eed88911e35dbd9870f11ed038fb3..081f950e40db222a331587be16d83da373d9a8c4 100644 (file)
 
 /// Highlights `src`, returning the HTML output.
 pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>,
-                                extension: Option<&str>) -> String {
+                                extension: Option<&str>,
+                                tooltip: Option<(&str, &str)>) -> String {
     debug!("highlighting: ================\n{}\n==============", src);
     let sess = parse::ParseSess::new(FilePathMapping::empty());
     let fm = sess.codemap().new_filemap("<stdin>".to_string(), src.to_string());
 
     let mut out = Vec::new();
+    if let Some((tooltip, class)) = tooltip {
+        write!(out, "<div class='information'><div class='tooltip {}'>⚠<span \
+                     class='tooltiptext'>{}</span></div></div>",
+               class, tooltip).unwrap();
+    }
     write_header(class, id, &mut out).unwrap();
 
     let mut classifier = Classifier::new(lexer::StringReader::new(&sess, fm), sess.codemap());
index 8d913c7552813aa185468092fd8b4ee335071eb4..80d1f0b01cc261dfdd6df65cfdb1029bf6f2a04a 100644 (file)
@@ -160,10 +160,15 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'a, I> {
 
     fn next(&mut self) -> Option<Self::Item> {
         let event = self.inner.next();
+        let compile_fail;
+        let ignore;
         if let Some(Event::Start(Tag::CodeBlock(lang))) = event {
-            if !LangString::parse(&lang).rust {
+            let parse_result = LangString::parse(&lang);
+            if !parse_result.rust {
                 return Some(Event::Start(Tag::CodeBlock(lang)));
             }
+            compile_fail = parse_result.compile_fail;
+            ignore = parse_result.ignore;
         } else {
             return event;
         }
@@ -222,11 +227,22 @@ fn dont_escape(c: u8) -> bool {
                     url, test_escaped, channel
                 ))
             });
+            let tooltip = if ignore {
+                Some(("Be careful when using this code, it's not being tested!", "ignore"))
+            } else if compile_fail {
+                Some(("This code doesn't compile so be extra careful!", "compile_fail"))
+            } else {
+                None
+            };
             s.push_str(&highlight::render_with_highlighting(
                         &text,
-                        Some("rust-example-rendered"),
+                        Some(&format!("rust-example-rendered{}",
+                                      if ignore { " ignore" }
+                                      else if compile_fail { " compile_fail" }
+                                      else { "" })),
                         None,
-                        playground_button.as_ref().map(String::as_str)));
+                        playground_button.as_ref().map(String::as_str),
+                        tooltip));
             Some(Event::Html(s.into()))
         })
     }
@@ -556,12 +572,18 @@ pub fn render(w: &mut fmt::Formatter,
             let origtext = str::from_utf8(text).unwrap();
             let origtext = origtext.trim_left();
             debug!("docblock: ==============\n{:?}\n=======", text);
+            let mut compile_fail = false;
+            let mut ignore = false;
+
             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 {
+                let parse_result = LangString::parse(rlang);
+                compile_fail = parse_result.compile_fail;
+                ignore = parse_result.ignore;
+                if !parse_result.rust {
                     (my_opaque.dfltblk)(ob, orig_text, lang,
                                         opaque as *const hoedown_renderer_data,
                                         line);
@@ -616,11 +638,22 @@ fn dont_escape(c: u8) -> bool {
                         url, test_escaped, channel
                     ))
                 });
+                let tooltip = if ignore {
+                    Some(("Be careful when using this code, it's not being tested!", "ignore"))
+                } else if compile_fail {
+                    Some(("This code doesn't compile so be extra careful!", "compile_fail"))
+                } else {
+                    None
+                };
                 s.push_str(&highlight::render_with_highlighting(
                                &text,
-                               Some("rust-example-rendered"),
+                               Some(&format!("rust-example-rendered{}",
+                                             if ignore { " ignore" }
+                                             else if compile_fail { " compile_fail" }
+                                             else { "" })),
                                None,
-                               playground_button.as_ref().map(String::as_str)));
+                               playground_button.as_ref().map(String::as_str),
+                               tooltip));
                 hoedown_buffer_put(ob, s.as_ptr(), s.len());
             })
         }
@@ -911,10 +944,8 @@ fn parse(string: &str) -> LangString {
         let mut seen_rust_tags = false;
         let mut seen_other_tags = false;
         let mut data = LangString::all_false();
-        let mut allow_compile_fail = false;
         let mut allow_error_code_check = false;
         if UnstableFeatures::from_environment().is_nightly_build() {
-            allow_compile_fail = true;
             allow_error_code_check = true;
         }
 
@@ -938,7 +969,7 @@ fn parse(string: &str) -> LangString {
                     data.test_harness = true;
                     seen_rust_tags = !seen_other_tags || seen_rust_tags;
                 }
-                "compile_fail" if allow_compile_fail => {
+                "compile_fail" => {
                     data.compile_fail = true;
                     seen_rust_tags = !seen_other_tags || seen_rust_tags;
                     data.no_run = true;
index 49d4bd2324033dbaeb3c3d327aee8c6afd96e7eb..c09ce4c4bd31ad949c1475f0803b42a2b3f081d2 100644 (file)
 
 use serialize::json::{ToJson, Json, as_json};
 use syntax::{abi, ast};
-use syntax::feature_gate::UnstableFeatures;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::middle::privacy::AccessLevels;
 use rustc::middle::stability;
 use rustc::hir;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
-use rustc::session::config::nightly_options::is_nightly_build;
 use rustc_data_structures::flock;
 
 use clean::{self, AttributesExt, GetDefId, SelfTy, Mutability, Span};
@@ -1764,9 +1762,13 @@ fn render_markdown(w: &mut fmt::Formatter,
                    prefix: &str,
                    scx: &SharedContext)
                    -> fmt::Result {
-    let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown));
     // We only emit warnings if the user has opted-in to Pulldown rendering.
     let output = if render_type == RenderType::Pulldown {
+        // Save the state of USED_ID_MAP so it only gets updated once even
+        // though we're rendering twice.
+        let orig_used_id_map = USED_ID_MAP.with(|map| map.borrow().clone());
+        let hoedown_output = format!("{}", Markdown(md_text, RenderType::Hoedown));
+        USED_ID_MAP.with(|map| *map.borrow_mut() = orig_used_id_map);
         let pulldown_output = format!("{}", Markdown(md_text, RenderType::Pulldown));
         let mut differences = html_diff::get_differences(&pulldown_output, &hoedown_output);
         differences.retain(|s| {
@@ -1787,7 +1789,7 @@ fn render_markdown(w: &mut fmt::Formatter,
 
         pulldown_output
     } else {
-        hoedown_output
+        format!("{}", Markdown(md_text, RenderType::Hoedown))
     };
 
     write!(w, "<div class='docblock'>{}{}</div>", prefix, output)
@@ -1817,6 +1819,7 @@ fn render_assoc_const_value(item: &clean::Item) -> String {
                 None,
                 None,
                 None,
+                None,
             )
         }
         _ => String::new(),
@@ -2192,14 +2195,9 @@ fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
 fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                  f: &clean::Function) -> fmt::Result {
-    // FIXME(#24111): remove when `const_fn` is stabilized
-    let vis_constness = match UnstableFeatures::from_environment() {
-        UnstableFeatures::Allow => f.constness,
-        _ => hir::Constness::NotConst
-    };
     let name_len = format!("{}{}{}{:#}fn {}{:#}",
                            VisSpace(&it.visibility),
-                           ConstnessSpace(vis_constness),
+                           ConstnessSpace(f.constness),
                            UnsafetySpace(f.unsafety),
                            AbiSpace(f.abi),
                            it.name.as_ref().unwrap(),
@@ -2209,7 +2207,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     write!(w, "{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(&it.visibility),
-           constness = ConstnessSpace(vis_constness),
+           constness = ConstnessSpace(f.constness),
            unsafety = UnsafetySpace(f.unsafety),
            abi = AbiSpace(f.abi),
            name = it.name.as_ref().unwrap(),
@@ -2591,14 +2589,8 @@ fn method(w: &mut fmt::Formatter,
                 href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
             }
         };
-        // FIXME(#24111): remove when `const_fn` is stabilized
-        let vis_constness = if is_nightly_build() {
-            constness
-        } else {
-            hir::Constness::NotConst
-        };
         let mut head_len = format!("{}{}{:#}fn {}{:#}",
-                                   ConstnessSpace(vis_constness),
+                                   ConstnessSpace(constness),
                                    UnsafetySpace(unsafety),
                                    AbiSpace(abi),
                                    name,
@@ -2611,7 +2603,7 @@ fn method(w: &mut fmt::Formatter,
         };
         write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
                    {generics}{decl}{where_clause}",
-               ConstnessSpace(vis_constness),
+               ConstnessSpace(constness),
                UnsafetySpace(unsafety),
                AbiSpace(abi),
                href = href,
@@ -3656,7 +3648,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
             write!(fmt, "<span id=\"{0}\">{0:1$}</span>\n", i, cols)?;
         }
         write!(fmt, "</pre>")?;
-        write!(fmt, "{}", highlight::render_with_highlighting(s, None, None, None))?;
+        write!(fmt, "{}",
+               highlight::render_with_highlighting(s, None, None, None, None))?;
         Ok(())
     }
 }
@@ -3666,6 +3659,7 @@ fn item_macro(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     w.write_str(&highlight::render_with_highlighting(&t.source,
                                                      Some("macro"),
                                                      None,
+                                                     None,
                                                      None))?;
     document(w, cx, it)
 }
index 8ec9cd8660a80dfa9656f8ba83183f99db76a61c..da4430d8a1539fc62170d39d7f25b82532f6a293 100644 (file)
             collapseDocs(i_e.previousSibling.childNodes[0]);
         });
     });
+
+    onEach(document.getElementsByClassName('rust-example-rendered'), function(e) {
+        if (hasClass(e, 'compile_fail')) {
+            e.addEventListener("mouseover", function(event) {
+                e.previousElementSibling.childNodes[0].style.color = '#f00';
+            });
+            e.addEventListener("mouseout", function(event) {
+                e.previousElementSibling.childNodes[0].style.color = '';
+            });
+        } else if (hasClass(e, 'ignore')) {
+            e.addEventListener("mouseover", function(event) {
+                e.previousElementSibling.childNodes[0].style.color = '#ff9200';
+            });
+            e.addEventListener("mouseout", function(event) {
+                e.previousElementSibling.childNodes[0].style.color = '';
+            });
+        }
+    });
 }());
 
 // Sets the focus on the search bar at the top of the page
index ca55d0e5d2a8ef4cfbc6b64be5c5bb8a424f21d9..c15051376bf2766ee7f94efe155b02c8a696aff4 100644 (file)
@@ -612,7 +612,6 @@ pre.rust .question-mark {
        font-weight: bold;
 }
 
-pre.rust { position: relative; }
 a.test-arrow {
        display: inline-block;
        position: absolute;
@@ -813,3 +812,44 @@ span.since {
                display: none;
        }
 }
+
+.information {
+       position: absolute;
+       left: -1px;
+       margin-top: 7px;
+}
+
+.tooltip {
+       position: relative;
+       display: inline-block;
+       cursor: pointer;
+}
+
+.tooltip .tooltiptext {
+       width: 120px;
+       display: none;
+       background-color: black;
+       color: #fff;
+       text-align: center;
+       padding: 5px 3px;
+       border-radius: 6px;
+       margin-left: 5px;
+       top: -5px;
+       left: 105%;
+       z-index: 1;
+}
+
+.tooltip:hover .tooltiptext {
+       display: inline;
+}
+
+.tooltip .tooltiptext::after {
+       content: " ";
+       position: absolute;
+       top: 50%;
+       left: 11px;
+       margin-top: -5px;
+       border-width: 5px;
+       border-style: solid;
+       border-color: transparent black transparent transparent;
+}
index c5f4272b932fca74a3cd985a710aa09c7f3fd2f6..42d0ec704f45f01f98fef03255209bf0b4d06453 100644 (file)
@@ -202,4 +202,36 @@ a.test-arrow:hover{
 
 :target > code {
        background: #FDFFD3;
-}
\ No newline at end of file
+}
+
+pre.compile_fail {
+       border-left: 2px solid rgba(255,0,0,.4);
+}
+
+pre.compile_fail:hover, .information:hover + pre.compile_fail {
+       border-left: 2px solid #f00;
+}
+
+pre.ignore {
+       border-left: 2px solid rgba(255,142,0,.4);
+}
+
+pre.ignore:hover, .information:hover + pre.ignore {
+       border-left: 2px solid #ff9200;
+}
+
+.tooltip.compile_fail {
+       color: rgba(255,0,0,.3);
+}
+
+.information > .compile_fail:hover {
+       color: #f00;
+}
+
+.tooltip.ignore {
+       color: rgba(255,142,0,.3);
+}
+
+.information > .ignore:hover {
+       color: rgba(255,142,0,1);
+}
index 9b76a713b1769541561b0727fd74b2d3c463b6b9..95c0f5f5d63645a0834fee8d0e7bd07290a4ac83 100644 (file)
@@ -22,7 +22,6 @@
 
 use testing;
 use rustc_lint;
-use rustc::dep_graph::DepGraph;
 use rustc::hir;
 use rustc::hir::intravisit;
 use rustc::session::{self, CompileIncomplete, config};
@@ -83,11 +82,9 @@ pub fn run(input: &str,
     let handler =
         errors::Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone()));
 
-    let dep_graph = DepGraph::new(false);
-    let _ignore = dep_graph.in_ignore();
     let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
-        sessopts, &dep_graph, Some(input_path.clone()), handler, codemap.clone()
+        sessopts, Some(input_path.clone()), handler, codemap.clone(),
     );
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@@ -100,7 +97,14 @@ pub fn run(input: &str,
     let krate = ReplaceBodyWithLoop::new().fold_crate(krate);
     let driver::ExpansionResult { defs, mut hir_forest, .. } = {
         phase_2_configure_and_expand(
-            &sess, &cstore, krate, None, "rustdoc-test", None, MakeGlobMap::No, |_| Ok(())
+            &sess,
+            &cstore,
+            krate,
+            None,
+            "rustdoc-test",
+            None,
+            MakeGlobMap::No,
+            |_| Ok(()),
         ).expect("phase_2_configure_and_expand aborted in rustdoc!")
     };
 
@@ -120,8 +124,6 @@ pub fn run(input: &str,
                                        render_type);
 
     {
-        let dep_graph = DepGraph::new(false);
-        let _ignore = dep_graph.in_ignore();
         let map = hir::map::map_crate(&mut hir_forest, defs);
         let krate = map.krate();
         let mut hir_collector = HirCollector {
@@ -237,10 +239,9 @@ fn drop(&mut self) {
     // Compile the code
     let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
 
-    let dep_graph = DepGraph::new(false);
     let cstore = Rc::new(CStore::new(box rustc_trans::LlvmMetadataLoader));
     let mut sess = session::build_session_(
-        sessopts, &dep_graph, None, diagnostic_handler, codemap
+        sessopts, None, diagnostic_handler, codemap,
     );
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
index fbb69ca974930ae3e442882485a57fda24bc856e..96af22725782460e9f23e0d9f01e21306f222885 100644 (file)
@@ -588,6 +588,9 @@ fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
 impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
     /// Creates an empty `HashMap`.
     ///
+    /// The hash map is initially created with a capacity of 0, so it will not allocate until it
+    /// is first inserted into.
+    ///
     /// # Examples
     ///
     /// ```
index 9771363d545cd41083caf0b3785a1dacf53db91f..51698ce7c17ca6caafc765cf14007946d44e84ec 100644 (file)
@@ -125,6 +125,9 @@ pub struct HashSet<T, S = RandomState> {
 impl<T: Hash + Eq> HashSet<T, RandomState> {
     /// Creates an empty `HashSet`.
     ///
+    /// The hash set is initially created with a capacity of 0, so it will not allocate until it
+    /// is first inserted into.
+    ///
     /// # Examples
     ///
     /// ```
index a438b4afdd0c9f37679de65a647725e5bb9b3710..2a916b819cca32290a091321bc65d66ba533a262 100644 (file)
@@ -560,14 +560,26 @@ pub fn write(&mut self, write: bool) -> &mut OpenOptions {
     ///
     /// One maybe obvious note when using append-mode: make sure that all data
     /// that belongs together is written to the file in one operation. This
-    /// can be done by concatenating strings before passing them to `write()`,
+    /// can be done by concatenating strings before passing them to [`write()`],
     /// or using a buffered writer (with a buffer of adequate size),
-    /// and calling `flush()` when the message is complete.
+    /// and calling [`flush()`] when the message is complete.
     ///
     /// If a file is opened with both read and append access, beware that after
     /// opening, and after every write, the position for reading may be set at the
     /// end of the file. So, before writing, save the current position (using
-    /// `seek(SeekFrom::Current(0))`, and restore it before the next read.
+    /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`, and restore it before the next read.
+    ///
+    /// ## Note
+    ///
+    /// This function doesn't create the file if it doesn't exist. Use the [`create`]
+    /// method to do so.
+    ///
+    /// [`write()`]: ../../std/fs/struct.File.html#method.write
+    /// [`flush()`]: ../../std/fs/struct.File.html#method.flush
+    /// [`seek`]: ../../std/fs/struct.File.html#method.seek
+    /// [`SeekFrom`]: ../../std/io/enum.SeekFrom.html
+    /// [`Current`]: ../../std/io/enum.SeekFrom.html#variant.Current
+    /// [`create`]: #method.create
     ///
     /// # Examples
     ///
@@ -605,9 +617,12 @@ pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
     /// This option indicates whether a new file will be created if the file
     /// does not yet already exist.
     ///
-    /// In order for the file to be created, `write` or `append` access must
+    /// In order for the file to be created, [`write`] or [`append`] access must
     /// be used.
     ///
+    /// [`write`]: #method.write
+    /// [`append`]: #method.append
+    ///
     /// # Examples
     ///
     /// ```no_run
@@ -630,12 +645,15 @@ pub fn create(&mut self, create: bool) -> &mut OpenOptions {
     /// whether a file exists and creating a new one, the file may have been
     /// created by another process (a TOCTOU race condition / attack).
     ///
-    /// If `.create_new(true)` is set, `.create()` and `.truncate()` are
+    /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are
     /// ignored.
     ///
     /// The file must be opened with write or append access in order to create
     /// a new file.
     ///
+    /// [`.create()`]: #method.create
+    /// [`.truncate()`]: #method.truncate
+    ///
     /// # Examples
     ///
     /// ```no_run
index 33bf0d68126d4c43f2ba4b24cc5cabcb102ae54c..aa1337a9da050f9a6117bbe6b0ea2c51bf7b2055 100644 (file)
 #![feature(raw)]
 #![feature(repr_simd)]
 #![feature(rustc_attrs)]
+#![cfg_attr(not(stage0), feature(rustc_const_unstable))]
 #![feature(shared)]
 #![feature(sip_hash_13)]
 #![feature(slice_bytes)]
 #![feature(doc_cfg)]
 #![cfg_attr(test, feature(update_panic_count))]
 
+#![cfg_attr(not(stage0), feature(const_max_value))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_isize_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_usize_new))]
+#![cfg_attr(all(not(stage0), windows), feature(const_atomic_ptr_new))]
+#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))]
+#![cfg_attr(not(stage0), feature(const_cell_new))]
+#![cfg_attr(not(stage0), feature(const_once_new))]
+#![cfg_attr(not(stage0), feature(const_ptr_null))]
+#![cfg_attr(not(stage0), feature(const_ptr_null_mut))]
+
 #![default_lib_allocator]
 
 // Always use alloc_system during stage0 since we don't know if the alloc_*
index 0abf8179cc971ff1fdc9092636c87e0a72fa00e5..eea604943af8bd8f2f7177de7c80781fc7432053 100644 (file)
@@ -10,7 +10,7 @@
 
 #![unstable(feature = "ip", reason = "extra functionality has not been \
                                       scrutinized to the level that it should \
-                                      be stable",
+                                      be to be stable",
             issue = "27709")]
 
 use cmp::Ordering;
@@ -342,6 +342,42 @@ pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
         }
     }
 
+    /// Creates a new IPv4 address with the address pointing to localhost: 127.0.0.1.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip_constructors)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::localhost();
+    /// assert_eq!(addr, Ipv4Addr::new(127, 0, 0, 1));
+    /// ```
+    #[unstable(feature = "ip_constructors",
+               reason = "requires greater scrutiny before stabilization",
+               issue = "44582")]
+    pub fn localhost() -> Ipv4Addr {
+        Ipv4Addr::new(127, 0, 0, 1)
+    }
+
+    /// Creates a new IPv4 address representing an unspecified address: 0.0.0.0
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip_constructors)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// let addr = Ipv4Addr::unspecified();
+    /// assert_eq!(addr, Ipv4Addr::new(0, 0, 0, 0));
+    /// ```
+    #[unstable(feature = "ip_constructors",
+               reason = "requires greater scrutiny before stabilization",
+               issue = "44582")]
+    pub fn unspecified() -> Ipv4Addr {
+        Ipv4Addr::new(0, 0, 0, 0)
+    }
+
     /// Returns the four eight-bit integers that make up this address.
     ///
     /// # Examples
@@ -788,6 +824,42 @@ pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
         Ipv6Addr { inner: addr }
     }
 
+    /// Creates a new IPv6 address representing localhost: `::1`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip_constructors)]
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::localhost();
+    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+    /// ```
+    #[unstable(feature = "ip_constructors",
+               reason = "requires greater scrutiny before stabilization",
+               issue = "44582")]
+    pub fn localhost() -> Ipv6Addr {
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)
+    }
+
+    /// Creates a new IPv6 address representing the unspecified address: `::`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip_constructors)]
+    /// use std::net::Ipv6Addr;
+    ///
+    /// let addr = Ipv6Addr::unspecified();
+    /// assert_eq!(addr, Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+    /// ```
+    #[unstable(feature = "ip_constructors",
+               reason = "requires greater scrutiny before stabilization",
+               issue = "44582")]
+    pub fn unspecified() -> Ipv6Addr {
+        Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)
+    }
+
     /// Returns the eight 16-bit segments that make up this address.
     ///
     /// # Examples
@@ -1681,6 +1753,22 @@ fn test_int_to_ipv6() {
         assert_eq!(Ipv6Addr::from(0x112233445566778899aabbccddeeff11u128), a);
     }
 
+    #[test]
+    fn ipv4_from_constructors() {
+        assert_eq!(Ipv4Addr::localhost(), Ipv4Addr::new(127, 0, 0, 1));
+        assert!(Ipv4Addr::localhost().is_loopback());
+        assert_eq!(Ipv4Addr::unspecified(), Ipv4Addr::new(0, 0, 0, 0));
+        assert!(Ipv4Addr::unspecified().is_unspecified());
+    }
+
+    #[test]
+    fn ipv6_from_contructors() {
+        assert_eq!(Ipv6Addr::localhost(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1));
+        assert!(Ipv6Addr::localhost().is_loopback());
+        assert_eq!(Ipv6Addr::unspecified(), Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0));
+        assert!(Ipv6Addr::unspecified().is_unspecified());
+    }
+
     #[test]
     fn ipv4_from_octets() {
         assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
index 5467eff202b02847cd45ca92966ffbd7ce6df08e..943a83a95fb2333eba161c9e8fed1be74c391a04 100644 (file)
@@ -167,7 +167,7 @@ pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
     /// connection request.
     ///
     /// [`SocketAddr`]: ../../std/net/enum.SocketAddr.html
-    #[unstable(feature = "tcpstream_connect_timeout", issue = "43079")]
+    #[stable(feature = "tcpstream_connect_timeout", since = "1.22.0")]
     pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
         net_imp::TcpStream::connect_timeout(addr, timeout).map(TcpStream)
     }
index 35001833383c0253da750d37385d77e52cb42a0c..a8a242846d7cedb6522ec40e27a501d485adb573 100644 (file)
 /// {
 ///     let mut socket = UdpSocket::bind("127.0.0.1:34254")?;
 ///
-///     // read from the socket
+///     // Receives a single datagram message on the socket. If `buf` is too small to hold
+///     // the message, it will be cut off.
 ///     let mut buf = [0; 10];
 ///     let (amt, src) = socket.recv_from(&mut buf)?;
 ///
-///     // send a reply to the socket we received data from
+///     // Redeclare `buf` as slice of the received data and send reverse data back to origin.
 ///     let buf = &mut buf[..amt];
 ///     buf.reverse();
 ///     socket.send_to(buf, &src)?;
@@ -103,8 +104,12 @@ pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
     }
 
-    /// Receives data from the socket. On success, returns the number of bytes
-    /// read and the address from whence the data came.
+    /// Receives a single datagram message on the socket. On success, returns the number
+    /// of bytes read and the origin.
+    ///
+    /// The function must be called with valid byte array `buf` of sufficient size to
+    /// hold the message bytes. If a message is too long to fit in the supplied buffer,
+    /// excess bytes may be discarded.
     ///
     /// # Examples
     ///
@@ -115,19 +120,25 @@ pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
     /// let mut buf = [0; 10];
     /// let (number_of_bytes, src_addr) = socket.recv_from(&mut buf)
     ///                                         .expect("Didn't receive data");
+    /// let filled_buf = &mut buf[..number_of_bytes];
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         self.0.recv_from(buf)
     }
 
-    /// Receives data from the socket, without removing it from the queue.
+    /// Receives a single datagram message on the socket, without removing it from the
+    /// queue. On success, returns the number of bytes read and the origin.
+    ///
+    /// The function must be called with valid byte array `buf` of sufficient size to
+    /// hold the message bytes. If a message is too long to fit in the supplied buffer,
+    /// excess bytes may be discarded.
     ///
     /// Successive calls return the same data. This is accomplished by passing
     /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
     ///
-    /// On success, returns the number of bytes peeked and the address from
-    /// whence the data came.
+    /// Do not use this function to implement busy waiting, instead use `libc::poll` to
+    /// synchronize IO events on one or more sockets.
     ///
     /// # Examples
     ///
@@ -138,6 +149,7 @@ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
     /// let mut buf = [0; 10];
     /// let (number_of_bytes, src_addr) = socket.peek_from(&mut buf)
     ///                                         .expect("Didn't receive data");
+    /// let filled_buf = &mut buf[..number_of_bytes];
     /// ```
     #[stable(feature = "peek", since = "1.18.0")]
     pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
@@ -586,8 +598,11 @@ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
     /// receive data from the specified address.
     ///
     /// If `addr` yields multiple addresses, `connect` will be attempted with
-    /// each of the addresses until a connection is successful. If none of
-    /// the addresses are able to be connected, the error returned from the
+    /// each of the addresses until the underlying OS function returns no
+    /// error. Note that usually, a successful `connect` call does not specify
+    /// that there is a remote server listening on the port, rather, such an
+    /// error would only be detected after the first send. If the OS returns an
+    /// error for each of the specified addresses, the error returned from the
     /// last connection attempt (the last address) is returned.
     ///
     /// # Examples
@@ -602,20 +617,10 @@ pub fn take_error(&self) -> io::Result<Option<io::Error>> {
     /// socket.connect("127.0.0.1:8080").expect("connect function failed");
     /// ```
     ///
-    /// Create a UDP socket bound to `127.0.0.1:3400` and connect the socket to
-    /// `127.0.0.1:8080`. If that connection fails, then the UDP socket will
-    /// connect to `127.0.0.1:8081`:
-    ///
-    /// ```no_run
-    /// use std::net::{SocketAddr, UdpSocket};
-    ///
-    /// let socket = UdpSocket::bind("127.0.0.1:3400").expect("couldn't bind to address");
-    /// let connect_addrs = [
-    ///     SocketAddr::from(([127, 0, 0, 1], 8080)),
-    ///     SocketAddr::from(([127, 0, 0, 1], 8081)),
-    /// ];
-    /// socket.connect(&connect_addrs[..]).expect("connect function failed");
-    /// ```
+    /// Unlike in the TCP case, passing an array of addresses to the `connect`
+    /// function of a UDP socket is not a useful thing to do: The OS will be
+    /// unable to determine whether something is listening on the remote
+    /// address without the application sending data.
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
         super::each_addr(addr, |addr| self.0.connect(addr))
@@ -642,8 +647,12 @@ pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.send(buf)
     }
 
-    /// Receives data on the socket from the remote address to which it is
-    /// connected.
+    /// Receives a single datagram message on the socket from the remote address to
+    /// which it is connected. On success, returns the number of bytes read.
+    ///
+    /// The function must be called with valid byte array `buf` of sufficient size to
+    /// hold the message bytes. If a message is too long to fit in the supplied buffer,
+    /// excess bytes may be discarded.
     ///
     /// The [`connect`] method will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
@@ -659,7 +668,7 @@ pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
     /// socket.connect("127.0.0.1:8080").expect("connect function failed");
     /// let mut buf = [0; 10];
     /// match socket.recv(&mut buf) {
-    ///     Ok(received) => println!("received {} bytes", received),
+    ///     Ok(received) => println!("received {} bytes {:?}", received, &buf[..received]),
     ///     Err(e) => println!("recv function failed: {:?}", e),
     /// }
     /// ```
@@ -668,13 +677,25 @@ pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.recv(buf)
     }
 
-    /// Receives data on the socket from the remote address to which it is
-    /// connected, without removing that data from the queue. On success,
-    /// returns the number of bytes peeked.
+    /// Receives single datagram on the socket from the remote address to which it is
+    /// connected, without removing the message from input queue. On success, returns
+    /// the number of bytes peeked.
+    ///
+    /// The function must be called with valid byte array `buf` of sufficient size to
+    /// hold the message bytes. If a message is too long to fit in the supplied buffer,
+    /// excess bytes may be discarded.
     ///
     /// Successive calls return the same data. This is accomplished by passing
     /// `MSG_PEEK` as a flag to the underlying `recv` system call.
     ///
+    /// Do not use this function to implement busy waiting, instead use `libc::poll` to
+    /// synchronize IO events on one or more sockets.
+    ///
+    /// The [`connect`] method will connect this socket to a remote address. This
+    /// method will fail if the socket is not connected.
+    ///
+    /// [`connect`]: #method.connect
+    ///
     /// # Errors
     ///
     /// This method will fail if the socket is not connected. The `connect` method
index 403685a4b8e0be9de12f829cd28171b53db39e15..015106fc2e598f637a72a341f1e39aaa70c094fc 100644 (file)
@@ -156,6 +156,7 @@ struct Finish {
 impl Once {
     /// Creates a new `Once` value.
     #[stable(feature = "once_new", since = "1.2.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_once_new"))]
     pub const fn new() -> Once {
         Once {
             state: AtomicUsize::new(INCOMPLETE),
index 7dfcc996e18e2e8202b7f6c061800ea005356204..9535ddfe5cada5143c22cee3dbf9a1f9a48ba84a 100644 (file)
@@ -32,6 +32,7 @@
 pub type HANDLE = LPVOID;
 pub type HINSTANCE = HANDLE;
 pub type HMODULE = HINSTANCE;
+pub type HRESULT = LONG;
 pub type BOOL = c_int;
 pub type BYTE = u8;
 pub type BOOLEAN = BYTE;
@@ -197,6 +198,8 @@ fn clone(&self) -> Self { *self }
 pub const ERROR_IO_PENDING: DWORD = 997;
 pub const ERROR_TIMEOUT: DWORD = 0x5B4;
 
+pub const E_NOTIMPL: HRESULT = 0x80004001u32 as HRESULT;
+
 pub const INVALID_HANDLE_VALUE: HANDLE = !0 as HANDLE;
 
 pub const FACILITY_NT_BIT: DWORD = 0x1000_0000;
@@ -1163,8 +1166,8 @@ pub fn select(nfds: c_int,
                   timeout: *const timeval) -> c_int;
 }
 
-// Functions that aren't available on Windows XP, but we still use them and just
-// provide some form of a fallback implementation.
+// Functions that aren't available on every version of Windows that we support,
+// but we still use them and just provide some form of a fallback implementation.
 compat_fn! {
     kernel32:
 
@@ -1182,6 +1185,10 @@ pub fn GetFinalPathNameByHandleW(_hFile: HANDLE,
     pub fn SetThreadStackGuarantee(_size: *mut c_ulong) -> BOOL {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0
     }
+    pub fn SetThreadDescription(hThread: HANDLE,
+                                lpThreadDescription: LPCWSTR) -> HRESULT {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
+    }
     pub fn SetFileInformationByHandle(_hFile: HANDLE,
                     _FileInformationClass: FILE_INFO_BY_HANDLE_CLASS,
                     _lpFileInformation: LPVOID,
index 6aea9d1fb560f118379fe7d0c4c8dbd7c26ece2a..c47baaa2434025fe4476fd8ac4b6dc3431c31dad 100644 (file)
@@ -19,6 +19,8 @@
 use sys_common::thread::*;
 use time::Duration;
 
+use super::to_u16s;
+
 pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
 
 pub struct Thread {
@@ -55,11 +57,12 @@ extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
         }
     }
 
-    pub fn set_name(_name: &CStr) {
-        // Windows threads are nameless
-        // The names in MSVC debugger are obtained using a "magic" exception,
-        // which requires a use of MS C++ extensions.
-        // See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+    pub fn set_name(name: &CStr) {
+        if let Ok(utf8) = name.to_str() {
+            if let Ok(utf16) = to_u16s(utf8) {
+                unsafe { c::SetThreadDescription(c::GetCurrentThread(), utf16.as_ptr()); };
+            };
+        };
     }
 
     pub fn join(self) {
index adbbc1b0ac5885b6f7aaaa9a3923ac4a97be47a7..03907eed9006faded2c730b1b93654d7fc150d49 100644 (file)
@@ -637,12 +637,13 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
     }
 }
 
-/// Represents the #[stable], #[unstable] and #[rustc_deprecated] attributes.
+/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
 #[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
     pub rustc_depr: Option<RustcDeprecation>,
+    pub rustc_const_unstable: Option<RustcConstUnstable>,
 }
 
 /// The available stability levels.
@@ -659,6 +660,11 @@ pub struct RustcDeprecation {
     pub reason: Symbol,
 }
 
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct RustcConstUnstable {
+    pub feature: Symbol,
+}
+
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
 pub struct Deprecation {
     pub since: Option<Symbol>,
@@ -678,9 +684,15 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
 {
     let mut stab: Option<Stability> = None;
     let mut rustc_depr: Option<RustcDeprecation> = None;
+    let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
 
     'outer: for attr in attrs_iter {
-        if attr.path != "rustc_deprecated" && attr.path != "unstable" && attr.path != "stable" {
+        if ![
+            "rustc_deprecated",
+            "rustc_const_unstable",
+            "unstable",
+            "stable",
+        ].iter().any(|&s| attr.path == s) {
             continue // not a stability level
         }
 
@@ -703,21 +715,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                 }
             };
 
-            match &*meta.name.as_str() {
-                "rustc_deprecated" => {
-                    if rustc_depr.is_some() {
-                        span_err!(diagnostic, item_sp, E0540,
-                                  "multiple rustc_deprecated attributes");
-                        break
-                    }
-
-                    let mut since = None;
-                    let mut reason = None;
+            macro_rules! get_meta {
+                ($($name:ident),+) => {
+                    $(
+                        let mut $name = None;
+                    )+
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
                             match &*mi.name().as_str() {
-                                "since" => if !get(mi, &mut since) { continue 'outer },
-                                "reason" => if !get(mi, &mut reason) { continue 'outer },
+                                $(
+                                    stringify!($name)
+                                        => if !get(mi, &mut $name) { continue 'outer },
+                                )+
                                 _ => {
                                     handle_errors(diagnostic, mi.span,
                                                   AttrError::UnknownMetaItem(mi.name()));
@@ -729,6 +738,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             continue 'outer
                         }
                     }
+                }
+            }
+
+            match &*meta.name.as_str() {
+                "rustc_deprecated" => {
+                    if rustc_depr.is_some() {
+                        span_err!(diagnostic, item_sp, E0540,
+                                  "multiple rustc_deprecated attributes");
+                        continue 'outer
+                    }
+
+                    get_meta!(since, reason);
 
                     match (since, reason) {
                         (Some(since), Some(reason)) => {
@@ -747,6 +768,23 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                         }
                     }
                 }
+                "rustc_const_unstable" => {
+                    if rustc_const_unstable.is_some() {
+                        span_err!(diagnostic, item_sp, E0553,
+                                  "multiple rustc_const_unstable attributes");
+                        continue 'outer
+                    }
+
+                    get_meta!(feature);
+                    if let Some(feature) = feature {
+                        rustc_const_unstable = Some(RustcConstUnstable {
+                            feature
+                        });
+                    } else {
+                        span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
+                        continue
+                    }
+                }
                 "unstable" => {
                     if stab.is_some() {
                         handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
@@ -791,6 +829,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                 },
                                 feature,
                                 rustc_depr: None,
+                                rustc_const_unstable: None,
                             })
                         }
                         (None, _, _) => {
@@ -836,6 +875,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                 },
                                 feature,
                                 rustc_depr: None,
+                                rustc_const_unstable: None,
                             })
                         }
                         (None, _) => {
@@ -867,6 +907,17 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         }
     }
 
+    // Merge the const-unstable info into the stability info
+    if let Some(rustc_const_unstable) = rustc_const_unstable {
+        if let Some(ref mut stab) = stab {
+            stab.rustc_const_unstable = Some(rustc_const_unstable);
+        } else {
+            span_err!(diagnostic, item_sp, E0630,
+                      "rustc_const_unstable attribute must be paired with \
+                       either stable or unstable attribute");
+        }
+    }
+
     stab
 }
 
index 2ea3fe51d30b201076afabec5076af93b5f7053f..46dec73c9627d03e00303bc2cbc073fb2c2d652c 100644 (file)
@@ -357,8 +357,11 @@ fn main() {
     E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
     E0550, // multiple deprecated attributes
     E0551, // incorrect meta item
+    E0553, // multiple rustc_const_unstable attributes
     E0555, // malformed feature attribute, expected #![feature(...)]
     E0556, // malformed feature, expected just one word
     E0584, // file for module `..` found at both .. and ..
     E0589, // invalid `repr(align)` attribute
+    E0629, // missing 'feature' (rustc_const_unstable)
+    E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
 }
index cac2ff975d64b2f00c67ca115d2b55a36699c569..c139cfeaebf4a42c115293c80fd7849073d5dc68 100644 (file)
@@ -792,7 +792,7 @@ pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
     pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
         self.parse_sess.span_diagnostic.span_bug(sp, msg);
     }
-    pub fn trace_macros_diag(&self) {
+    pub fn trace_macros_diag(&mut self) {
         for (sp, notes) in self.expansions.iter() {
             let mut db = self.parse_sess.span_diagnostic.span_note_diag(*sp, "trace_macro");
             for note in notes {
@@ -800,6 +800,8 @@ pub fn trace_macros_diag(&self) {
             }
             db.emit();
         }
+        // Fixme: does this result in errors?
+        self.expansions.clear();
     }
     pub fn bug(&self, msg: &str) -> ! {
         self.parse_sess.span_diagnostic.bug(msg);
index 2f7d5685b6efecb42c669116745c93d8da219162..de9c085cc78177e62f24198c68152e0eca80b708 100644 (file)
@@ -384,13 +384,14 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expan
         if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit {
             let info = self.cx.current_expansion.mark.expn_info().unwrap();
             let suggested_limit = self.cx.ecfg.recursion_limit * 2;
-            let mut err = self.cx.struct_span_fatal(info.call_site,
+            let mut err = self.cx.struct_span_err(info.call_site,
                 &format!("recursion limit reached while expanding the macro `{}`",
                          info.callee.name()));
             err.help(&format!(
                 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                 suggested_limit));
             err.emit();
+            self.cx.trace_macros_diag();
             panic!(FatalError);
         }
 
@@ -439,11 +440,13 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
             }
             ProcMacroDerive(..) | BuiltinDerive(..) => {
                 self.cx.span_err(attr.span, &format!("`{}` is a derive mode", attr.path));
+                self.cx.trace_macros_diag();
                 kind.dummy(attr.span)
             }
             _ => {
                 let msg = &format!("macro `{}` may not be used in attributes", attr.path);
                 self.cx.span_err(attr.span, msg);
+                self.cx.trace_macros_diag();
                 kind.dummy(attr.span)
             }
         }
@@ -482,6 +485,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s),
                                                              false, false) {
                     self.cx.span_err(path.span, &msg);
+                    self.cx.trace_macros_diag();
                     return kind.dummy(span);
                 }
                 kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
@@ -497,6 +501,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                                                              allow_internal_unstable,
                                                              allow_internal_unsafe) {
                     self.cx.span_err(path.span, &msg);
+                    self.cx.trace_macros_diag();
                     return kind.dummy(span);
                 }
                 kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
@@ -506,6 +511,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 if ident.name == keywords::Invalid.name() {
                     self.cx.span_err(path.span,
                                     &format!("macro {}! expects an ident argument", path));
+                    self.cx.trace_macros_diag();
                     return kind.dummy(span);
                 };
 
@@ -526,11 +532,13 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
             MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
                 self.cx.span_err(path.span,
                                  &format!("`{}` can only be used in attributes", path));
+                self.cx.trace_macros_diag();
                 return kind.dummy(span);
             }
 
             ProcMacroDerive(..) | BuiltinDerive(..) => {
                 self.cx.span_err(path.span, &format!("`{}` is a derive mode", path));
+                self.cx.trace_macros_diag();
                 return kind.dummy(span);
             }
 
@@ -539,6 +547,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                     let msg =
                         format!("macro {}! expects no ident argument, given '{}'", path, ident);
                     self.cx.span_err(path.span, &msg);
+                    self.cx.trace_macros_diag();
                     return kind.dummy(span);
                 }
 
@@ -564,6 +573,7 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
             let msg = format!("non-{kind} macro in {kind} position: {name}",
                               name = path.segments[0].identifier.name, kind = kind.name());
             self.cx.span_err(path.span, &msg);
+            self.cx.trace_macros_diag();
             kind.dummy(span)
         })
     }
@@ -617,6 +627,7 @@ fn expand_derive_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -
             _ => {
                 let msg = &format!("macro `{}` may not be used for derive attributes", attr.path);
                 self.cx.span_err(span, msg);
+                self.cx.trace_macros_diag();
                 kind.dummy(span)
             }
         }
@@ -629,6 +640,7 @@ fn parse_expansion(&mut self, toks: TokenStream, kind: ExpansionKind, path: &Pat
             Ok(expansion) => expansion,
             Err(mut err) => {
                 err.emit();
+                self.cx.trace_macros_diag();
                 return kind.dummy(span);
             }
         };
@@ -739,6 +751,7 @@ fn collect_attr(&mut self,
         if !traits.is_empty() &&
            (kind == ExpansionKind::TraitItems || kind == ExpansionKind::ImplItems) {
             self.cx.span_err(traits[0].span, "`derive` can be only be applied to items");
+            self.cx.trace_macros_diag();
             return kind.expect_from_annotatables(::std::iter::once(item));
         }
         self.collect(kind, InvocationKind::Attr { attr: attr, traits: traits, item: item })
index 6d58af497f091256ec603e4b0bf926dd2059e13f..5e58f003c2be7479c27d827dea1d25a62e6f0a43 100644 (file)
@@ -172,7 +172,9 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt,
     }
 
     let best_fail_msg = parse_failure_msg(best_fail_tok.expect("ran no matchers"));
-    cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
+    cx.span_err(best_fail_spot.substitute_dummy(sp), &best_fail_msg);
+    cx.trace_macros_diag();
+    DummyResult::any(sp)
 }
 
 // Note that macro-by-example's input is also matched against a token tree:
index 3d4ded2ae815fd03d0a9bbc7813e57cb267c1c7e..38e20b9fe4065c6b2703fe07e861159949421883 100644 (file)
@@ -137,6 +137,7 @@ pub fn new() -> Features {
 
     // rustc internal
     (active, rustc_diagnostic_macros, "1.0.0", None),
+    (active, rustc_const_unstable, "1.0.0", None),
     (active, advanced_slice_patterns, "1.0.0", Some(23121)),
     (active, box_syntax, "1.0.0", Some(27779)),
     (active, placement_in_syntax, "1.0.0", Some(27779)),
@@ -622,6 +623,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                              "the `#[rustc_on_unimplemented]` attribute \
                                               is an experimental feature",
                                              cfg_fn!(on_unimplemented))),
+    ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
+                                             "rustc_const_unstable",
+                                             "the `#[rustc_const_unstable]` attribute \
+                                              is an internal feature",
+                                             cfg_fn!(rustc_const_unstable))),
     ("global_allocator", Normal, Gated(Stability::Unstable,
                                        "global_allocator",
                                        "the `#[global_allocator]` attribute is \
index cba5c812b07ce94b46dc8aa9b21fb8781b94680f..27fbca19dcc4ca3a0211eb262ae3885df99ceb19 100644 (file)
@@ -434,6 +434,12 @@ fn from(span: Span) -> MultiSpan {
     }
 }
 
+impl From<Vec<Span>> for MultiSpan {
+    fn from(spans: Vec<Span>) -> MultiSpan {
+        MultiSpan::from_spans(spans)
+    }
+}
+
 pub const NO_EXPANSION: SyntaxContext = SyntaxContext::empty();
 
 /// Identifies an offset of a multi-byte character in a FileMap
index 7de6e58c784d57ad7083ae25409c538ad740e8d4..fa85432fb8e3f571a27f98f4169cf043429c0fc5 100644 (file)
@@ -16,7 +16,8 @@
 //  which is a reduction of this code to more directly show the reason
 //  for the error message we see here.)
 
-#![feature(const_fn, rustc_private)]
+#![feature(rustc_private)]
+#![feature(const_atomic_usize_new)]
 
 extern crate arena;
 
index 0745ac02d0723e620e82856f217cf666e1a21175..18476494300b21febeca61fd40a4b3bf37af454e 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
-
 fn f(x: usize) -> usize {
     x
 }
diff --git a/src/test/compile-fail/const-fn-feature-flags.rs b/src/test/compile-fail/const-fn-feature-flags.rs
new file mode 100644 (file)
index 0000000..823cb89
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test use of const fns in std using individual feature gates.
+
+use std::cell::Cell;
+
+const CELL: Cell<i32> = Cell::new(42); //~ERROR not yet stable as a const fn
+    //~^HELP #![feature(const_cell_new)]
+
+fn main() {
+    let v = CELL.get();
+    CELL.set(v+1);
+
+    assert_eq!(CELL.get(), v);
+}
+
diff --git a/src/test/compile-fail/const-fn-stability-calls.rs b/src/test/compile-fail/const-fn-stability-calls.rs
deleted file mode 100644 (file)
index 6090776..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test use of const fn from another crate without a feature gate.
-
-// aux-build:const_fn_lib.rs
-
-extern crate const_fn_lib;
-
-use const_fn_lib::foo;
-
-static FOO: usize = foo(); //~ ERROR const fns are an unstable feature
-const BAR: usize = foo(); //~ ERROR const fns are an unstable feature
-
-macro_rules! constant {
-    ($n:ident: $t:ty = $v:expr) => {
-        const $n: $t = $v;
-    }
-}
-
-constant! {
-    BAZ: usize = foo() //~ ERROR const fns are an unstable feature
-}
-
-fn main() {
-//    let x: [usize; foo()] = [];
-}
index e701718028a7a05349d952f07cb98270b091db4e..c0f0e3650d9fbaf136d4816ed818a40de2c8e886 100644 (file)
@@ -13,7 +13,7 @@
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
diff --git a/src/test/compile-fail/feature-gate-rustc_const_unstable.rs b/src/test/compile-fail/feature-gate-rustc_const_unstable.rs
new file mode 100644 (file)
index 0000000..38a3e15
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test internal const fn feature gate.
+
+#![feature(staged_api)]
+#![feature(const_fn)]
+//#![feature(rustc_const_unstable)]
+
+#[stable(feature="zing", since="1.0.0")]
+#[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
+pub const fn bazinga() {}
+
+fn main() {
+}
+
index d2df0d9ef270204834ffaf8f1d96c204292d30ec..3f41401eb69c12275b58d7968e2526f8bc0204d7 100644 (file)
@@ -10,8 +10,6 @@
 
 // RFC 736 (and Issue 21407): functional struct update should respect privacy.
 
-#![feature(const_fn)]
-
 // The `foo` module attempts to maintains an invariant that each `S`
 // has a unique `u64` id.
 use self::foo::S;
index 327b6946822987d1c0ed16ed71164a583e4b04eb..1464fcd9a1cd92b0235db76ef57651e1b7c603ac 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_unsafe_cell_new)]
 
 use std::cell::UnsafeCell;
 
index 0fd31454596e645ece7c87be14ea4a34f29f3518..1bf165c89d329dfd73aeb4ede06b69ec5c957204 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_cell_new, const_unsafe_cell_new)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
 // On platforms *without* `#[thread_local]`, use
index bd32317ae78086b3e709bd9a19a1859aed2f35b9..ef53be757800565b2fb1a07bfed7a3687b7ad75c 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(box_syntax)]
-#![feature(const_fn)]
-#![allow(warnings)]
+#![feature(box_syntax, const_refcell_new)]
 
 use std::cell::RefCell;
 
@@ -18,5 +16,6 @@
 static boxed: Box<RefCell<isize>> = box RefCell::new(0);
 //~^ ERROR allocations are not allowed in statics
 //~| ERROR `std::cell::RefCell<isize>: std::marker::Sync` is not satisfied
+//~| WARN unsupported constant expr
 
 fn main() { }
index 26d00755da33b0f28d45971354fff0fc0f16cfc4..3c76740d2b5dd3ab8c080170abb0fbcf88588bd3 100644 (file)
@@ -110,3 +110,11 @@ fn foo(mut a: isize) {
     let mut a = 3;
     let mut b = vec![2];
 }
+
+// make sure the lint attribute can be turned off on let statements
+#[deny(unused_mut)]
+fn bar() {
+    #[allow(unused_mut)]
+    let mut a = 3;
+    let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
+}
index d35f2cbb584c767958051215f4ad1dc1e962ed9b..263ac427b7676a25a11f5979c9061584bb677f72 100644 (file)
@@ -10,7 +10,7 @@
 
 // Various checks that stability attributes are used correctly, per RFC 507
 
-#![feature(staged_api)]
+#![feature(const_fn, staged_api, rustc_const_unstable)]
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -88,8 +88,11 @@ fn multiple3() { }
 #[stable(feature = "a", since = "b")]
 #[rustc_deprecated(since = "b", reason = "text")]
 #[rustc_deprecated(since = "b", reason = "text")]
-fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
+#[rustc_const_unstable(feature = "a")]
+#[rustc_const_unstable(feature = "b")]
+pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
 //~^ ERROR Invalid stability or deprecation version found
+//~| ERROR multiple rustc_const_unstable attributes
 
 #[rustc_deprecated(since = "a", reason = "text")]
 fn deprecated_without_unstable_or_stable() { }
index 7b7bda302250fd8a30c62432d9a588567c320c11..7a24510b7d409cff2fcee302de0ce3049fd0c895 100644 (file)
@@ -15,7 +15,7 @@
 #![allow(dead_code, unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
-#![feature(const_fn)]
+#![feature(const_unsafe_cell_new)]
 #![feature(static_mutex)]
 
 // This test makes sure that the compiler doesn't crash when trying to assign
index 2e3fb785748f3f5345aa01515a11f17b1272fc44..461df49b468f94dca3cfc47f0ced18404da9b32a 100644 (file)
@@ -58,9 +58,8 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
     opts.maybe_sysroot = Some(sysroot);
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
-    let dep_graph = DepGraph::new(opts.build_dep_graph());
     let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
-    let sess = build_session(opts, &dep_graph, None, descriptions);
+    let sess = build_session(opts, None, descriptions);
     rustc_trans::init(&sess);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     (sess, cstore)
index 2815863fe9961ed41a390abbd0dfc2be231b456b..439c1080f47311ca1d06e65cb484a487ea022bc4 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![allow(dead_code)]
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 // check dtor calling order when casting enums.
 
index 8dc7d79ec2a7772c5c6d4162cd767d94ac118a2f..7cde780cc54ba928a42154c0fe0507f1be25f525 100644 (file)
@@ -12,7 +12,7 @@
 // `Item` originates in a where-clause, not the declaration of
 // `T`. Issue #20300.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::marker::{PhantomData};
 use std::sync::atomic::{AtomicUsize};
index b0d5a6b12727b16225778adc037b0943931a7cc2..be06e8dd5700b19e383e01ec50c36204e4b449b7 100644 (file)
@@ -13,4 +13,4 @@
 #![crate_type="rlib"]
 #![feature(const_fn)]
 
-pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable
+pub const fn foo() -> usize { 22 }
index cf7fdd7f983f0e545d1851629925d84459fa0c4d..36891a1ecadb87362408b17b3a3cbe2634e6ea0c 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic;
 
index e9457886be80d890a5e8287823777ab2508e1ed9..bce87ef5a2668ddf89da2984b65c81d464feec3a 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(cfg_target_thread_local, const_fn, thread_local)]
+#![feature(const_cell_new)]
 #![crate_type = "lib"]
 
 #[cfg(target_thread_local)]
index a63a232e1b5be8e09ee2cbf1434554662d2f89d8..47b44863a74758227aea9eb1417e0327367b16dc 100644 (file)
@@ -13,7 +13,7 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering};
index ca17942917281329f9fa745760e845f3749a3f3a..54be4955baf5bddb11400ac471bcccaf3c80267d 100644 (file)
@@ -13,7 +13,7 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/src/test/run-pass/const-fn-cross-crate.rs b/src/test/run-pass/const-fn-cross-crate.rs
deleted file mode 100644 (file)
index 7b4b751..0000000
+++ /dev/null
@@ -1,26 +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.
-
-// aux-build:const_fn_lib.rs
-
-// A very basic test of const fn functionality.
-
-#![feature(const_fn)]
-
-extern crate const_fn_lib;
-
-use const_fn_lib::foo;
-
-const FOO: usize = foo();
-
-fn main() {
-    assert_eq!(FOO, 22);
-    let _: [i32; foo()] = [42; 22];
-}
diff --git a/src/test/run-pass/const-fn-feature-flags.rs b/src/test/run-pass/const-fn-feature-flags.rs
new file mode 100644 (file)
index 0000000..1e27a3e
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test use of const fns in std using individual feature gates.
+
+#![feature(const_cell_new)]
+
+use std::cell::Cell;
+
+const CELL: Cell<i32> = Cell::new(42);
+
+fn main() {
+    let v = CELL.get();
+    CELL.set(v+1);
+
+    assert_eq!(CELL.get(), v);
+}
+
diff --git a/src/test/run-pass/const-fn-stability-calls.rs b/src/test/run-pass/const-fn-stability-calls.rs
new file mode 100644 (file)
index 0000000..c5f97d5
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test use of const fn from another crate without a feature gate.
+
+// aux-build:const_fn_lib.rs
+
+extern crate const_fn_lib;
+
+use const_fn_lib::foo;
+
+static FOO: usize = foo();
+const BAR: usize = foo();
+
+macro_rules! constant {
+    ($n:ident: $t:ty = $v:expr) => {
+        const $n: $t = $v;
+    }
+}
+
+constant! {
+    BAZ: usize = foo()
+}
+
+fn main() {
+    let x: [usize; foo()] = [42; foo()];
+}
index 06fbe9bf4f63958372c055f193e81dd09fe87a97..d5547ea5add0016aa9930b1e5491384c7d8267f8 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_size_of, const_align_of)]
 
 use std::mem;
 
diff --git a/src/test/run-pass/generator/match-bindings.rs b/src/test/run-pass/generator/match-bindings.rs
new file mode 100644 (file)
index 0000000..9c6b057
--- /dev/null
@@ -0,0 +1,30 @@
+// 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(generators)]
+
+enum Enum {
+    A(String),
+    B
+}
+
+fn main() {
+    || {
+        loop {
+            if let true = true {
+                match Enum::A(String::new()) {
+                    Enum::A(_var) => {}
+                    Enum::B => {}
+                }
+            }
+            yield;
+        }
+    };
+}
\ No newline at end of file
index 993e5e1c1e6e90f0eaa8f0f96f79de320ae0634c..66f70cdaeb08b65138e1d41872f1dbec2d40005b 100644 (file)
@@ -11,8 +11,7 @@
 // pretty-expanded FIXME #23616
 
 #![feature(core)]
-#![feature(const_fn)]
-
+#![feature(const_unsafe_cell_new)]
 
 use std::marker;
 use std::cell::UnsafeCell;
index 744e63f159b6566dc17ceb4187399bf043e2f495..1b8fbc1ad2f5c5f6b0df46c75a708e8417a43061 100644 (file)
@@ -12,7 +12,7 @@
 
 
 #![feature(core)]
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 extern crate issue_17718_aux as other;
 
index 699189a4e6aedd88657acc9e56aedbb1b121e14e..23d06c4324da6ac065cb239c71e5cef932670aa8 100644 (file)
@@ -12,7 +12,7 @@
 // created via FRU and control-flow breaks in the middle of
 // construction.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
index 402460e7253d31b8c5b5f057792bbce232d67c58..3e252b8629e12af728be3563f1498be2797a6cdd 100644 (file)
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
-
 // Check that the destructors of simple enums are run on unwinding
 
+#![feature(const_atomic_usize_new)]
+
 use std::sync::atomic::{Ordering, AtomicUsize};
 use std::thread;
 
index cd81f68969377d60d8a794a3866d208e5565daca..dab42e48e164522ce6a4ff686869ee123614e0a3 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
index 458b6c16e62a776a8234c77013accf9a13a34c0f..9141b5f29ceb9000608083d60330b78c6bdf20a6 100644 (file)
@@ -14,7 +14,7 @@
 // the contents implement Drop and we hit a panic in the middle of
 // construction.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering};
index 1ad43f5f17fb9b483fa35750524535b78a38f518..c5dc8ccd2eeaf9a3c6207e52f2cc4a3a6fc97a03 100644 (file)
@@ -10,7 +10,8 @@
 
 // ignore-emscripten no threads support
 
-#![feature(panic_handler, const_fn, std_panic)]
+#![feature(panic_handler, std_panic)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::panic;
index 196e08a63a7f0fafecb1ac889681a7398e5264a7..8bf2683cd9feb0a3fc119db2012d8c8e57849f9a 100644 (file)
@@ -7,7 +7,8 @@
 // <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(panic_handler, const_fn, std_panic)]
+#![feature(panic_handler, std_panic)]
+#![feature(const_atomic_usize_new)]
 
 // ignore-emscripten no threads support
 
index b67eb205396b29cff30bdf088bc3877469b2c534..cf93133d205939c5b28aa835bc56fc50488616fc 100644 (file)
@@ -11,7 +11,7 @@
 // Checks that functional-record-update order-of-eval is as expected
 // even when no Drop-implementations are involved.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
index 20d27d8b309bbb9c35795c129ffa4d61c906d7de..d442923478f1faed7243a3bb56de8ce3970bbdd2 100644 (file)
@@ -11,7 +11,7 @@
 // Checks that struct-literal expression order-of-eval is as expected
 // even when no Drop-implementations are involved.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
index 4387a43f03b6a952026e5c3fb953cfac26b33f5d..c6a1859de30b8c9df6e1f4f12c3007ef437c6e00 100644 (file)
@@ -10,9 +10,9 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
 #![feature(rand)]
 #![feature(sort_unstable)]
+#![feature(const_atomic_usize_new)]
 
 use std::__rand::{thread_rng, Rng};
 use std::cell::Cell;
diff --git a/src/test/rustdoc/codeblock-title.rs b/src/test/rustdoc/codeblock-title.rs
new file mode 100644 (file)
index 0000000..accefd6
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// ignore-tidy-linelength
+
+// @has foo/fn.bar.html '//*[@class="tooltip compile_fail"]/span' "This code doesn't compile so be extra careful!"
+// @has foo/fn.bar.html '//*[@class="tooltip ignore"]/span' "Be careful when using this code, it's not being tested!"
+
+/// foo
+///
+/// ```compile_fail
+/// foo();
+/// ```
+///
+/// ```ignore (tidy)
+/// goo();
+/// ```
+///
+/// ```
+/// let x = 0;
+/// ```
+pub fn bar() -> usize { 2 }
diff --git a/src/test/rustdoc/const-fn.rs b/src/test/rustdoc/const-fn.rs
new file mode 100644 (file)
index 0000000..c323681
--- /dev/null
@@ -0,0 +1,27 @@
+// 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(const_fn)]
+#![crate_name = "foo"]
+
+// @has foo/fn.bar.html
+// @has - '//*[@class="rust fn"]' 'pub const fn bar() -> '
+/// foo
+pub const fn bar() -> usize {
+    2
+}
+
+// @has foo/struct.Foo.html
+// @has - '//*[@class="method"]' 'const fn new()'
+pub struct Foo(usize);
+
+impl Foo {
+    pub const fn new() -> Foo { Foo(0) }
+}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs
new file mode 100644 (file)
index 0000000..0fef709
--- /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.
+struct Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
+    where &'a (): Sized,
+          &'b u32: Sized
+{
+    x.push(y);
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr
new file mode 100644 (file)
index 0000000..59bf5d1
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-earlybound-regions.rs:18:12
+   |
+14 | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>)
+   |                           -------      ------- these two types are declared with different lifetimes...
+...
+18 |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.rs
new file mode 100644 (file)
index 0000000..a91d0b5
--- /dev/null
@@ -0,0 +1,18 @@
+// 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 Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
+    x.push(y);
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr
new file mode 100644 (file)
index 0000000..8783512
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-latebound-regions.rs:15:12
+   |
+14 | fn foo<'a, 'b>(mut x: Vec<Ref<'a>>, y: Ref<'b>) {
+   |                           -------      ------- these two types are declared with different lifetimes...
+15 |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
index ca590db90e43f4a2dacb43b1b492ec2f508b1619..1b46e94584e6b33d507b03b99fa0dc8734102a11 100644 (file)
@@ -4,3 +4,5 @@ error: unexpected end of macro invocation
 12 |     assert_eq!(1, 1,);
    |                    ^
 
+error: aborting due to previous error
+
index ffabcaeb0493c4e16a2c69d388c8888257110a95..33d2cb0ed82429207921e38d6e35563e82c83175 100644 (file)
@@ -4,3 +4,5 @@ error: unexpected end of macro invocation
 12 |     assert_ne!(1, 2,);
    |                    ^
 
+error: aborting due to previous error
+
diff --git a/src/test/ui/macros/trace_faulty_macros.rs b/src/test/ui/macros/trace_faulty_macros.rs
new file mode 100644 (file)
index 0000000..eb7292b
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z trace-macros
+
+#![recursion_limit="4"]
+
+macro_rules! my_faulty_macro {
+    () => {
+        my_faulty_macro!(bcd);
+    };
+}
+
+macro_rules! pat_macro {
+    () => {
+        pat_macro!(A{a:a, b:0, c:_, ..});
+    };
+    ($a:pat) => {
+        $a
+    };
+}
+
+macro_rules! my_recursive_macro {
+    () => {
+        my_recursive_macro!();
+    };
+}
+
+macro_rules! my_macro {
+    () => {
+
+    };
+}
+
+fn main() {
+    my_faulty_macro!();
+    my_recursive_macro!();
+    test!();
+    non_exisiting!();
+    derive!(Debug);
+    let a = pat_macro!();
+}
+
+#[my_macro]
+fn use_bang_macro_as_attr(){}
+
+#[derive(Debug)]
+fn use_derive_macro_as_attr(){}
diff --git a/src/test/ui/macros/trace_faulty_macros.stderr b/src/test/ui/macros/trace_faulty_macros.stderr
new file mode 100644 (file)
index 0000000..f4aeb83
--- /dev/null
@@ -0,0 +1,47 @@
+error: no rules expected the token `bcd`
+  --> $DIR/trace_faulty_macros.rs:17:26
+   |
+17 |         my_faulty_macro!(bcd);
+   |                          ^^^
+...
+43 |     my_faulty_macro!();
+   |     ------------------- in this macro invocation
+
+note: trace_macro
+  --> $DIR/trace_faulty_macros.rs:43:5
+   |
+43 |     my_faulty_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expanding `my_faulty_macro! {  }`
+   = note: to `my_faulty_macro ! ( bcd ) ;`
+   = note: expanding `my_faulty_macro! { bcd }`
+
+error: recursion limit reached while expanding the macro `my_recursive_macro`
+  --> $DIR/trace_faulty_macros.rs:32:9
+   |
+32 |         my_recursive_macro!();
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+...
+44 |     my_recursive_macro!();
+   |     ---------------------- in this macro invocation
+   |
+   = help: consider adding a `#![recursion_limit="8"]` attribute to your crate
+
+note: trace_macro
+  --> $DIR/trace_faulty_macros.rs:44:5
+   |
+44 |     my_recursive_macro!();
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+   = note: expanding `my_recursive_macro! {  }`
+   = note: to `my_recursive_macro ! (  ) ;`
+
index 8e8b3c24c76b083c62a4c4ffa7ef11730bf222bd..995a198271c11f10b6e983b6501d010edc4f7467 100644 (file)
@@ -13,7 +13,7 @@
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
index 65db2a56b7d819a2d8c0e9312430bea8167d1198..5bcaa71f73c294f56ccff246999026988d1d0fa2 100644 (file)
@@ -12,7 +12,7 @@
 //
 // (Compare against compile-fail/dropck_arr_cycle_checked.rs)
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
index d4c0eb21342fa80f1b58565d630704de4fc02931..718720ebf83839042e037999a41b6637c3368efe 100644 (file)
@@ -10,7 +10,7 @@ note: lint level defined here
 18 | #![warn(unused)]
    |         ^^^^^^
    = note: #[warn(unused_variables)] implied by #[warn(unused)]
-   = note: to disable this warning, consider using `_theOtherTwo` instead
+   = note: to avoid this warning, consider using `_theOtherTwo` instead
 
 warning: variable `theTwo` should have a snake case name such as `the_two`
   --> $DIR/issue-24690.rs:22:9
index 310ab20489a35b84ea2eb6b6f238a4791da77a04..d99f3bb19dbad6bba56befb803c0654221f675bc 100644 (file)
@@ -23,7 +23,7 @@
 // conditions above to be satisfied, meaning that if the dropck is
 // sound, it should reject this code.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
index 8dd70945fb049df3f9dc7685cdc58d94e05e8ffc..52d48656f93eeeb2c568e6c1048e64168e5b209f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8dd70945fb049df3f9dc7685cdc58d94e05e8ffc
+Subproject commit 52d48656f93eeeb2c568e6c1048e64168e5b209f
index adea17e1b22231a9036a619264b72565e3a3962f..0ddd53c4bc2a76df565a1c1fc0cc6f19f254b51e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit adea17e1b22231a9036a619264b72565e3a3962f
+Subproject commit 0ddd53c4bc2a76df565a1c1fc0cc6f19f254b51e
index e759e0bc13ac1eac340d4956e06f88a36f9d84ac..e57c105008ade1a337ba612173813ca5ccb11b6c 100644 (file)
@@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
 clap = "2.25.0"
 
 [dependencies.mdbook]
-version = "0.0.22"
+version = "0.0.25"
 default-features = false
index 41e88aa245f42e55efc94f0a3581bb30671be8cf..a0c3e811a7aa2cc5b69c177f6e08ef11db258672 100644 (file)
 extern crate clap;
 
 use std::env;
-use std::error::Error;
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 
 use clap::{App, ArgMatches, SubCommand, AppSettings};
 
 use mdbook::MDBook;
+use mdbook::errors::Result;
 
 fn main() {
     let d_message = "-d, --dest-dir=[dest-dir]
@@ -49,34 +49,21 @@ fn main() {
         ::std::process::exit(101);
     }
 }
-
 // Build command implementation
-fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
-    let book = build_mdbook_struct(args);
+pub fn build(args: &ArgMatches) -> Result<()> {
+    let book_dir = get_book_dir(args);
+    let book = MDBook::new(&book_dir).read_config()?;
 
     let mut book = match args.value_of("dest-dir") {
-        Some(dest_dir) => book.set_dest(Path::new(dest_dir)),
-        None => book
+        Some(dest_dir) => book.with_destination(dest_dir),
+        None => book,
     };
 
-    try!(book.build());
+    book.build()?;
 
     Ok(())
 }
 
-fn build_mdbook_struct(args: &ArgMatches) -> mdbook::MDBook {
-    let book_dir = get_book_dir(args);
-    let mut book = MDBook::new(&book_dir).read_config();
-
-    // By default mdbook will attempt to create non-existent files referenced
-    // from SUMMARY.md files. This is problematic on CI where we mount the
-    // source directory as readonly. To avoid any issues, we'll disabled
-    // mdbook's implicit file creation feature.
-    book.create_missing = false;
-
-    book
-}
-
 fn get_book_dir(args: &ArgMatches) -> PathBuf {
     if let Some(dir) = args.value_of("dir") {
         // Check if path is relative from current dir, or absolute...
diff --git a/src/tools/rustfmt b/src/tools/rustfmt
new file mode 160000 (submodule)
index 0000000..a1fd68d
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit a1fd68da464fc51585f351c81fc2b867211c197e
index 731a3d96cff9d9521c848200e667744dcb2f2310..56c0b21cd53c7b7e1a1f25aa392033b29cf52573 100644 (file)
@@ -64,6 +64,7 @@ fn filter_dirs(path: &Path) -> bool {
         "src/tools/rls",
         "src/tools/clippy",
         "src/tools/rust-installer",
+        "src/tools/rustfmt",
     ];
     skip.iter().any(|p| path.ends_with(p))
 }