]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #40009 - clarcharr:box_to_buf, r=alexcrichton
authorbors <bors@rust-lang.org>
Wed, 15 Mar 2017 04:24:10 +0000 (04:24 +0000)
committerbors <bors@rust-lang.org>
Wed, 15 Mar 2017 04:24:10 +0000 (04:24 +0000)
Leftovers from #39594; From<Box> impls

These are a few more impls that follow the same reasoning as those from #39594.

What's included:
* `From<Box<str>> for String`
* `From<Box<[T]>> for Vec<T>`
* `From<Box<CStr>> for CString`
* `From<Box<OsStr>> for OsString`
* `From<Box<Path>> for PathBuf`
* `Into<Box<str>> for String`
* `Into<Box<[T]>> for Vec<T>`
* `Into<Box<CStr>> for CString`
* `Into<Box<OsStr>> for OsString`
* `Into<Box<Path>> for PathBuf`
* `<Box<CStr>>::into_c_string`
* `<Box<OsStr>>::into_os_string`
* `<Box<Path>>::into_path_buf`
* Tracking issue for latter three methods + three from previous PR.

Currently, the opposite direction isn't doable with `From` (only `Into`) because of the separation between `liballoc` and `libcollections`. I'm holding off on those for a later PR.

185 files changed:
.gitmodules
.travis.yml
appveyor.yml
cargo [new submodule]
configure
src/Cargo.lock
src/Cargo.toml
src/bootstrap/bootstrap.py
src/bootstrap/channel.rs
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/bootstrap/dist.rs
src/bootstrap/doc.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/step.rs
src/bootstrap/util.rs
src/ci/docker/dist-fuchsia/Dockerfile [new file with mode: 0644]
src/ci/docker/dist-fuchsia/build-toolchain.sh [new file with mode: 0755]
src/ci/docker/dist-fuchsia/shared.sh [new file with mode: 0644]
src/ci/docker/run.sh
src/ci/run.sh
src/liballoc/boxed.rs
src/libcollections/vec_deque.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/vec_deque.rs
src/libcore/fmt/mod.rs
src/libcore/iter/mod.rs
src/libproc_macro/lib.rs
src/librustc/dep_graph/graph.rs
src/librustc/dep_graph/mod.rs
src/librustc/dep_graph/safe.rs [new file with mode: 0644]
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.rs
src/librustc/infer/README.md
src/librustc/infer/region_inference/README.md
src/librustc/infer/region_inference/graphviz.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/cstore.rs
src/librustc/mir/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/select.rs
src/librustc/ty/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/util.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_data_structures/indexed_vec.rs
src/librustc_data_structures/lib.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/target_features.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/persist/load.rs
src/librustc_lint/unused.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/callgraph.rs [new file with mode: 0644]
src/librustc_mir/lib.rs
src/librustc_mir/mir_map.rs
src/librustc_mir/transform/inline.rs [new file with mode: 0644]
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/simplify.rs
src/librustc_passes/hir_stats.rs
src/librustc_plugin/registry.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_save_analysis/data.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_save_analysis/external_data.rs
src/librustc_save_analysis/json_dumper.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/base.rs
src/librustc_trans/context.rs
src/librustc_trans/mir/block.rs
src/librustc_trans/mir/operand.rs
src/librustc_typeck/check/autoderef.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/librustdoc/html/format.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/librustdoc/visit_ast.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/table.rs
src/libstd/ffi/c_str.rs
src/libstd/ffi/os_str.rs
src/libstd/lib.rs
src/libstd/sys/redox/os_str.rs
src/libstd/sys/unix/os_str.rs
src/libstd/sys/windows/os_str.rs
src/libstd/sys_common/gnu/libbacktrace.rs
src/libstd/sys_common/wtf8.rs
src/libsyntax/ast.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/hygiene.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/symbol.rs
src/libsyntax/test.rs
src/libsyntax/util/node_count.rs
src/libsyntax/visit.rs
src/libsyntax_ext/concat_idents.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_ext/lib.rs
src/libsyntax_ext/proc_macro_registrar.rs
src/llvm
src/rustllvm/llvm-auto-clean-trigger [deleted file]
src/rustllvm/llvm-rebuild-trigger [new file with mode: 0644]
src/test/codegen/packed.rs
src/test/compile-fail-fulldeps/auxiliary/pub_and_stability.rs
src/test/compile-fail/catch-in-match.rs [new file with mode: 0644]
src/test/compile-fail/catch-in-while.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-catch_expr.rs [new file with mode: 0644]
src/test/compile-fail/issue-40288-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-40288.rs [new file with mode: 0644]
src/test/compile-fail/lint-unused-unsafe.rs [deleted file]
src/test/compile-fail/object-lifetime-default-elision.rs
src/test/compile-fail/object-lifetime-default-from-box-error.rs
src/test/compile-fail/privacy/restricted/lookup-ignores-private.rs
src/test/compile-fail/privacy/restricted/struct-literal-field.rs
src/test/compile-fail/privacy/restricted/test.rs
src/test/compile-fail/privacy/restricted/ty-params.rs
src/test/compile-fail/regions-close-over-type-parameter-multiple.rs
src/test/compile-fail/regions-proc-bound-capture.rs
src/test/compile-fail/regions-trait-object-subtyping.rs
src/test/compile-fail/resolve-bad-visibility.rs
src/test/compile-fail/variance-contravariant-arg-object.rs
src/test/compile-fail/variance-covariant-arg-object.rs
src/test/compile-fail/variance-invariant-arg-object.rs
src/test/debuginfo/c-style-enum.rs
src/test/debuginfo/limited-debuginfo.rs
src/test/debuginfo/simple-struct.rs
src/test/debuginfo/simple-tuple.rs
src/test/mir-opt/issue-38669.rs
src/test/run-make/dep-info-doesnt-run-much/Makefile [new file with mode: 0644]
src/test/run-make/dep-info-doesnt-run-much/foo.rs [new file with mode: 0644]
src/test/run-make/extern-fn-with-packed-struct/test.rs
src/test/run-make/pretty-expanded-hygiene/input.pp.rs
src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs [deleted file]
src/test/run-pass-fulldeps/mir-pass.rs [deleted file]
src/test/run-pass/catch-expr.rs [new file with mode: 0644]
src/test/run-pass/coerce-unsize-subtype.rs [new file with mode: 0644]
src/test/run-pass/packed-struct-vec.rs
src/test/ui/codemap_tests/issue-38812-2.rs [deleted file]
src/test/ui/codemap_tests/issue-38812-2.stderr [deleted file]
src/test/ui/codemap_tests/issue-38812.rs [deleted file]
src/test/ui/codemap_tests/issue-38812.stderr [deleted file]
src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
src/test/ui/resolve/enums-are-namespaced-xc.stderr
src/test/ui/resolve/levenshtein.stderr
src/test/ui/resolve/privacy-struct-ctor.rs
src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
src/test/ui/resolve/unboxed-closure-sugar-nonexistent-trait.stderr
src/test/ui/span/issue-40157.rs [new file with mode: 0644]
src/test/ui/span/issue-40157.stderr [new file with mode: 0644]
src/test/ui/span/lint-unused-unsafe.rs [new file with mode: 0644]
src/test/ui/span/lint-unused-unsafe.stderr [new file with mode: 0644]
src/test/ui/span/suggestion-non-ascii.rs [new file with mode: 0644]
src/test/ui/span/suggestion-non-ascii.stderr [new file with mode: 0644]
src/test/ui/type-check/issue-38812-2.rs [new file with mode: 0644]
src/test/ui/type-check/issue-38812-2.stderr [new file with mode: 0644]
src/test/ui/type-check/issue-38812.rs [new file with mode: 0644]
src/test/ui/type-check/issue-38812.stderr [new file with mode: 0644]
src/test/ui/type-check/issue-40294.rs [new file with mode: 0644]
src/test/ui/type-check/issue-40294.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/cargo [deleted submodule]
src/tools/rustbook/Cargo.toml

index bdc14d8c3be714d9b64838f619e0c62f842d45c0..9bc2a6a70eb45471df4b3d90f5946a8676a1bbe8 100644 (file)
@@ -22,7 +22,7 @@
        path = src/doc/nomicon
        url = https://github.com/rust-lang-nursery/nomicon
 [submodule "src/tools/cargo"]
-       path = src/tools/cargo
+       path = cargo
        url = https://github.com/rust-lang/cargo
 [submodule "reference"]
        path = src/doc/reference
index fa6c9cf0748647c5d2a48593f1c2f6e127ebda8d..988ef66f8faddbbdcc97a48163549267cb122c67 100644 (file)
@@ -20,6 +20,7 @@ matrix:
     - env: IMAGE=dist-armv7-aarch64-linux DEPLOY=1
     - env: IMAGE=dist-freebsd DEPLOY=1
     - env: IMAGE=dist-i586-gnu-i686-musl DEPLOY=1
+    - env: IMAGE=dist-fuchsia DEPLOY=1
     - env: IMAGE=dist-mips-linux DEPLOY=1
     - env: IMAGE=dist-mips64-linux DEPLOY=1
     - env: IMAGE=dist-powerpc-linux DEPLOY=1
@@ -44,6 +45,9 @@ matrix:
         RUST_CHECK_TARGET=check
         RUST_CONFIGURE_ARGS=--build=x86_64-apple-darwin
         SRC=.
+        RUSTC_RETRY_LINKER_ON_SEGFAULT=1
+        SCCACHE_ERROR_LOG=/tmp/sccache.log
+        RUST_LOG=sccache=debug
       os: osx
       osx_image: xcode8.2
       install: &osx_install_sccache >
@@ -53,6 +57,9 @@ matrix:
         RUST_CHECK_TARGET=check
         RUST_CONFIGURE_ARGS=--build=i686-apple-darwin
         SRC=.
+        RUSTC_RETRY_LINKER_ON_SEGFAULT=1
+        SCCACHE_ERROR_LOG=/tmp/sccache.log
+        RUST_LOG=sccache=debug
       os: osx
       osx_image: xcode8.2
       install: *osx_install_sccache
@@ -62,18 +69,22 @@ matrix:
         RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended"
         SRC=.
         DEPLOY=1
+        RUSTC_RETRY_LINKER_ON_SEGFAULT=1
+        SCCACHE_ERROR_LOG=/tmp/sccache.log
+        RUST_LOG=sccache=debug
       os: osx
       osx_image: xcode8.2
       install: >
         travis_retry curl -o /usr/local/bin/sccache https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-02-25-sccache-x86_64-apple-darwin &&
-          chmod +x /usr/local/bin/sccache &&
-          brew uninstall --ignore-dependencies openssl &&
-          brew install openssl --universal --without-test
+          chmod +x /usr/local/bin/sccache
     - 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"
         SRC=.
         DEPLOY=1
+        RUSTC_RETRY_LINKER_ON_SEGFAULT=1
+        SCCACHE_ERROR_LOG=/tmp/sccache.log
+        RUST_LOG=sccache=debug
       os: osx
       osx_image: xcode8.2
       install: *osx_install_sccache
@@ -88,6 +99,9 @@ matrix:
         RUST_CONFIGURE_ARGS="--enable-extended"
         SRC=.
         DEPLOY_ALT=1
+        RUSTC_RETRY_LINKER_ON_SEGFAULT=1
+        SCCACHE_ERROR_LOG=/tmp/sccache.log
+        RUST_LOG=sccache=debug
       os: osx
       osx_image: xcode8.2
       install: *osx_install_sccache
@@ -128,6 +142,8 @@ after_failure:
       echo "#### Build failed; Disk usage after running script:";
       df -h;
       du . | sort -nr | head -n100
+  - cat obj/tmp/sccache.log
+  - cat /tmp/sccache.log
 
 # Save tagged docker images we created and load them if they're available
 before_cache:
index 9a0a4d81f9b1efd66ccb4574253a7b536c60a67e..94a5efb3a2ffbb98012917fe1001864c0abb2d81 100644 (file)
@@ -130,17 +130,24 @@ install:
   - set PATH=%PATH%;%CD%\handle
   - handle.exe -accepteula -help
 
+  # Attempt to debug sccache failures
+  - set RUST_LOG=sccache=debug
+  - set SCCACHE_ERROR_LOG=%CD%/sccache.log
+
 test_script:
   - appveyor-retry sh -c 'git submodule deinit -f . && git submodule update --init'
   - set SRC=.
   - set NO_CCACHE=1
   - sh src/ci/run.sh
 
+on_failure:
+  - cat %CD%/sccache.log
+
 cache:
-  - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
-  - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
-  - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
-  - "x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-auto-clean-trigger"
+  - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
+  - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
+  - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
+  - "x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
 
 branches:
   only:
diff --git a/cargo b/cargo
new file mode 160000 (submodule)
index 0000000..4a3c0a6
--- /dev/null
+++ b/cargo
@@ -0,0 +1 @@
+Subproject commit 4a3c0a63b07e9a4feb41cb11de37c92a09db5a60
index be8628de62832f0b01b8ca60b0c8a97696850c9a..35b376d5f27b8c498d3691e720c9d3dcde558f45 100755 (executable)
--- a/configure
+++ b/configure
@@ -384,207 +384,6 @@ need_cmd sed
 need_cmd file
 need_cmd make
 
-msg "inspecting environment"
-
-CFG_OSTYPE=$(uname -s)
-CFG_CPUTYPE=$(uname -m)
-
-if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
-then
-    # Darwin's `uname -s` lies and always returns i386. We have to use sysctl
-    # instead.
-    if sysctl hw.optional.x86_64 | grep -q ': 1'
-    then
-        CFG_CPUTYPE=x86_64
-    fi
-fi
-
-# The goal here is to come up with the same triple as LLVM would,
-# at least for the subset of platforms we're willing to target.
-
-case $CFG_OSTYPE in
-
-    Linux)
-        CFG_OSTYPE=unknown-linux-gnu
-        ;;
-
-    FreeBSD)
-        CFG_OSTYPE=unknown-freebsd
-        ;;
-
-    DragonFly)
-        CFG_OSTYPE=unknown-dragonfly
-        ;;
-
-    Bitrig)
-        CFG_OSTYPE=unknown-bitrig
-        ;;
-
-    OpenBSD)
-        CFG_OSTYPE=unknown-openbsd
-       ;;
-
-    NetBSD)
-           CFG_OSTYPE=unknown-netbsd
-           ;;
-
-    Darwin)
-        CFG_OSTYPE=apple-darwin
-        ;;
-
-    SunOS)
-        CFG_OSTYPE=sun-solaris
-        CFG_CPUTYPE=$(isainfo -n)
-        ;;
-
-    Haiku)
-        CFG_OSTYPE=unknown-haiku
-        ;;
-
-    MINGW*)
-        # msys' `uname` does not print gcc configuration, but prints msys
-        # configuration. so we cannot believe `uname -m`:
-        # msys1 is always i686 and msys2 is always x86_64.
-        # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
-        # MINGW64 on x86_64.
-        CFG_CPUTYPE=i686
-        CFG_OSTYPE=pc-windows-gnu
-        if [ "$MSYSTEM" = MINGW64 ]
-        then
-            CFG_CPUTYPE=x86_64
-        fi
-        ;;
-
-    MSYS*)
-        CFG_OSTYPE=pc-windows-gnu
-        ;;
-
-# Thad's Cygwin identifiers below
-
-#   Vista 32 bit
-    CYGWIN_NT-6.0)
-        CFG_OSTYPE=pc-windows-gnu
-        CFG_CPUTYPE=i686
-        ;;
-
-#   Vista 64 bit
-    CYGWIN_NT-6.0-WOW64)
-        CFG_OSTYPE=pc-windows-gnu
-        CFG_CPUTYPE=x86_64
-        ;;
-
-#   Win 7 32 bit
-    CYGWIN_NT-6.1)
-        CFG_OSTYPE=pc-windows-gnu
-        CFG_CPUTYPE=i686
-        ;;
-
-#   Win 7 64 bit
-    CYGWIN_NT-6.1-WOW64)
-        CFG_OSTYPE=pc-windows-gnu
-        CFG_CPUTYPE=x86_64
-        ;;
-
-#   Win 8 # uname -s on 64-bit cygwin does not contain WOW64, so simply use uname -m to detect arch (works in my install)
-    CYGWIN_NT-6.3)
-       CFG_OSTYPE=pc-windows-gnu
-       ;;
-# We do not detect other OS such as XP/2003 using 64 bit using uname.
-# If we want to in the future, we will need to use Cygwin - Chuck's csih helper in /usr/lib/csih/winProductName.exe or alternative.
-    *)
-        err "unknown OS type: $CFG_OSTYPE"
-        ;;
-esac
-
-
-case $CFG_CPUTYPE in
-
-    i386 | i486 | i686 | i786 | x86)
-        CFG_CPUTYPE=i686
-        ;;
-
-    xscale | arm)
-        CFG_CPUTYPE=arm
-        ;;
-
-    armv6l)
-        CFG_CPUTYPE=arm
-        CFG_OSTYPE="${CFG_OSTYPE}eabihf"
-        ;;
-
-    armv7l)
-        CFG_CPUTYPE=armv7
-        CFG_OSTYPE="${CFG_OSTYPE}eabihf"
-        ;;
-
-    aarch64 | arm64)
-        CFG_CPUTYPE=aarch64
-        ;;
-
-    powerpc | ppc)
-        CFG_CPUTYPE=powerpc
-        ;;
-
-    powerpc64 | ppc64)
-        CFG_CPUTYPE=powerpc64
-        ;;
-
-    powerpc64le | ppc64le)
-        CFG_CPUTYPE=powerpc64le
-        ;;
-
-    s390x)
-        CFG_CPUTYPE=s390x
-        ;;
-
-    x86_64 | x86-64 | x64 | amd64)
-        CFG_CPUTYPE=x86_64
-        ;;
-
-    mips | mips64)
-        if [ "$CFG_CPUTYPE" = "mips64" ]; then
-            CFG_OSTYPE="${CFG_OSTYPE}abi64"
-        fi
-        ENDIAN=$(printf '\1' | od -dAn)
-        if [ "$ENDIAN" -eq 1 ]; then
-            CFG_CPUTYPE="${CFG_CPUTYPE}el"
-        elif [ "$ENDIAN" -ne 256 ]; then
-            err "unknown endianness: $ENDIAN (expecting 1 for little or 256 for big)"
-        fi
-        ;;
-
-    BePC)
-        CFG_CPUTYPE=i686
-        ;;
-
-    *)
-        err "unknown CPU type: $CFG_CPUTYPE"
-esac
-
-# Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
-if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
-then
-    # $SHELL does not exist in standard 'sh', so probably only exists
-    # if configure is running in an interactive bash shell. /usr/bin/env
-    # exists *everywhere*.
-    BIN_TO_PROBE="$SHELL"
-    if [ ! -r "$BIN_TO_PROBE" ]; then
-        if [ -r "/usr/bin/env" ]; then
-            BIN_TO_PROBE="/usr/bin/env"
-        else
-            warn "Cannot check if the userland is i686 or x86_64"
-        fi
-    fi
-    file -L "$BIN_TO_PROBE" | grep -q "x86[_-]64"
-    if [ $? != 0 ]; then
-        msg "i686 userland on x86_64 Linux kernel"
-        CFG_CPUTYPE=i686
-    fi
-fi
-
-
-DEFAULT_BUILD="${CFG_CPUTYPE}-${CFG_OSTYPE}"
-
 CFG_SRC_DIR="$(abs_path $(dirname $0))/"
 CFG_SRC_DIR_RELATIVE="$(dirname $0)/"
 CFG_BUILD_DIR="$(pwd)/"
@@ -638,6 +437,7 @@ opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
 opt local-rebuild 0 "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version"
 opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
 opt llvm-link-shared 0 "prefer shared linking to LLVM (llvm-config --link-shared)"
+opt llvm-clean-rebuild 0 "delete LLVM build directory on rebuild"
 opt rpath 1 "build rpaths into rustc itself"
 opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
 # This is used by the automation to produce single-target nightlies
@@ -673,7 +473,7 @@ valopt infodir "${CFG_PREFIX}/share/info" "install additional info"
 valopt llvm-root "" "set LLVM root"
 valopt python "" "set path to python"
 valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
-valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
+valopt build "" "GNUs ./configure syntax LLVM build triple"
 valopt android-cross-path "" "Android NDK standalone path (deprecated)"
 valopt i686-linux-android-ndk "" "i686-linux-android NDK standalone path"
 valopt arm-linux-androideabi-ndk "" "arm-linux-androideabi NDK standalone path"
@@ -821,76 +621,6 @@ if [ $(echo $python_version | grep -c '^Python 2\.7') -ne 1 ]; then
     err "Found $python_version, but Python 2.7 is required"
 fi
 
-# If we have no git directory then we are probably a tarball distribution
-# and shouldn't attempt to load submodules
-if [ ! -e ${CFG_SRC_DIR}.git ]
-then
-    probe CFG_GIT          git
-    msg "git: no git directory. disabling submodules"
-    CFG_DISABLE_MANAGE_SUBMODULES=1
-else
-    probe_need CFG_GIT     git
-fi
-
-# Use `md5sum` on GNU platforms, or `md5 -q` on BSD
-probe CFG_MD5              md5
-probe CFG_MD5SUM           md5sum
-if [ -n "$CFG_MD5" ]
-then
-    CFG_HASH_COMMAND="$CFG_MD5 -q | cut -c 1-8"
-elif [ -n "$CFG_MD5SUM" ]
-then
-    CFG_HASH_COMMAND="$CFG_MD5SUM | cut -c 1-8"
-else
-    err 'could not find one of: md5 md5sum'
-fi
-putvar CFG_HASH_COMMAND
-
-probe CFG_CLANG            clang++
-probe CFG_CCACHE           ccache
-probe CFG_GCC              gcc
-probe CFG_LD               ld
-probe CFG_VALGRIND         valgrind
-probe CFG_PERF             perf
-probe CFG_ISCC             iscc
-probe CFG_ANTLR4           antlr4
-probe CFG_GRUN             grun
-probe CFG_FLEX             flex
-probe CFG_BISON            bison
-probe CFG_GDB              gdb
-probe CFG_LLDB             lldb
-
-if [ -n "$CFG_ENABLE_NINJA" ]
-then
-  probe CFG_NINJA            ninja
-  if [ -z "$CFG_NINJA" ]
-  then
-    # On Debian and Fedora, the `ninja` binary is an IRC bot, so the build tool was
-    # renamed. Handle this case.
-    probe CFG_NINJA            ninja-build
-  fi
-fi
-
-# For building LLVM
-if [ -z "$CFG_LLVM_ROOT" ]
-then
-  probe_need CFG_CMAKE cmake
-fi
-
-# On MacOS X, invoking `javac` pops up a dialog if the JDK is not
-# installed. Since `javac` is only used if `antlr4` is available,
-# probe for it only in this case.
-if [ -n "$CFG_ANTLR4" ]
-then
-   CFG_ANTLR4_JAR="\"$(find /usr/ -name antlr-complete.jar 2>/dev/null | head -n 1)\""
-   if [ "x" = "x$CFG_ANTLR4_JAR" ]
-   then
-     CFG_ANTLR4_JAR="\"$(find ~ -name antlr-complete.jar 2>/dev/null | head -n 1)\""
-   fi
-   putvar CFG_ANTLR4_JAR      $CFG_ANTLR4_JAR
-   probe CFG_JAVAC            javac
-fi
-
 # the valgrind rpass tests will fail if you don't have a valgrind, but they're
 # only disabled if you opt out.
 if [ -z "$CFG_VALGRIND" ]
@@ -905,41 +635,6 @@ then
     fi
 fi
 
-if [ -n "$CFG_LLDB" ]
-then
-    # Store LLDB's version
-    CFG_LLDB_VERSION=$($CFG_LLDB --version 2>/dev/null | head -1)
-    putvar CFG_LLDB_VERSION
-
-    # If CFG_LLDB_PYTHON_DIR is not already set from the outside and valid, try to read it from
-    # LLDB via the -P commandline options.
-    if [ -z "$CFG_LLDB_PYTHON_DIR" ] || [ ! -d "$CFG_LLDB_PYTHON_DIR" ]
-    then
-        CFG_LLDB_PYTHON_DIR=$($CFG_LLDB -P)
-
-        # If CFG_LLDB_PYTHON_DIR is not a valid directory, set it to something more readable
-        if [ ! -d "$CFG_LLDB_PYTHON_DIR" ]
-        then
-            CFG_LLDB_PYTHON_DIR="LLDB_PYTHON_DIRECTORY_NOT_FOUND"
-        fi
-
-        putvar CFG_LLDB_PYTHON_DIR
-    fi
-fi
-
-# LLDB tests on OSX require /usr/bin/python, not something like Homebrew's
-# /usr/local/bin/python. We're loading a compiled module for LLDB tests which is
-# only compatible with the system.
-case $CFG_BUILD in
-    *-apple-darwin)
-        CFG_LLDB_PYTHON=/usr/bin/python
-        ;;
-    *)
-        CFG_LLDB_PYTHON=$CFG_PYTHON
-        ;;
-esac
-putvar CFG_LLDB_PYTHON
-
 # Do some sanity checks if running on buildbot
 # (these env vars are set by rust-buildbot)
 if [ -n "$RUST_DIST_SERVER" -a -n "$ALLOW_NONZERO_RLIMIT_CORE" ]; then
@@ -952,10 +647,6 @@ if [ -n "$RUST_DIST_SERVER" -a -n "$ALLOW_NONZERO_RLIMIT_CORE" ]; then
    fi
 fi
 
-step_msg "looking for target specific programs"
-
-probe CFG_ADB        adb
-
 BIN_SUF=
 if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
 then
@@ -1021,10 +712,6 @@ CFG_MANDIR=${CFG_MANDIR%/}
 CFG_DOCDIR=${CFG_DOCDIR%/}
 CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
 CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
-CFG_SUPPORTED_TARGET=""
-for target_file in ${CFG_SRC_DIR}mk/cfg/*.mk; do
-  CFG_SUPPORTED_TARGET="${CFG_SUPPORTED_TARGET} $(basename "$target_file" .mk)"
-done
 
 # copy build-triples to host-triples so that builds are a subset of hosts
 V_TEMP=""
@@ -1064,31 +751,6 @@ putvar CFG_MANDIR
 putvar CFG_DOCDIR
 putvar CFG_USING_LIBCPP
 
-# Avoid spurious warnings from clang by feeding it original source on
-# ccache-miss rather than preprocessed input.
-if [ -n "$CFG_ENABLE_CCACHE" ] && [ -n "$CFG_USING_CLANG" ]
-then
-    CFG_CCACHE_CPP2=1
-    putvar CFG_CCACHE_CPP2
-fi
-
-if [ -n "$CFG_ENABLE_CCACHE" ]
-then
-    CFG_CCACHE_BASEDIR=${CFG_SRC_DIR}
-    putvar CFG_CCACHE_BASEDIR
-fi
-
-
-putvar CFG_LLVM_SRC_DIR
-
-for t in $CFG_HOST
-do
-    CFG_LLVM_BUILD_DIR=$(echo CFG_LLVM_BUILD_DIR_${t} | tr - _)
-    CFG_LLVM_INST_DIR=$(echo CFG_LLVM_INST_DIR_${t} | tr - _)
-    putvar $CFG_LLVM_BUILD_DIR
-    putvar $CFG_LLVM_INST_DIR
-done
-
 msg
 copy_if_changed ${CFG_SRC_DIR}src/bootstrap/mk/Makefile.in ./Makefile
 move_if_changed config.tmp config.mk
index f4174693a5771872cef659c99a00c2272e5b268e..b34007db8ac7af314b10f246cd54147df60fef6b 100644 (file)
@@ -6,23 +6,6 @@ dependencies = [
  "libc 0.0.0",
 ]
 
-[[package]]
-name = "advapi32-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "aho-corasick"
 version = "0.6.2"
@@ -84,17 +67,12 @@ dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "bufstream"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "build-manifest"
 version = "0.1.0"
@@ -110,81 +88,10 @@ dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "cargo"
-version = "0.18.0"
-dependencies = [
- "advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "bufstream 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargotest 0.1.0",
- "crates-io 0.7.0",
- "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2-curl 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_ignored 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "cargotest"
-version = "0.1.0"
-dependencies = [
- "bufstream 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo 0.18.0",
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "cargotest2"
 version = "0.1.0"
 
-[[package]]
-name = "cfg-if"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "clap"
 version = "2.20.5"
@@ -192,7 +99,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -232,7 +139,7 @@ version = "0.0.0"
 dependencies = [
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -240,58 +147,6 @@ dependencies = [
 name = "core"
 version = "0.0.0"
 
-[[package]]
-name = "crates-io"
-version = "0.7.0"
-dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "crossbeam"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "curl"
-version = "0.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-probe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "curl-sys"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "docopt"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "dtoa"
 version = "0.4.1"
@@ -302,15 +157,15 @@ name = "env_logger"
 version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "env_logger"
-version = "0.4.0"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -323,7 +178,7 @@ name = "filetime"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -334,48 +189,15 @@ dependencies = [
  "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "flate2"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "fmt_macros"
 version = "0.0.0"
 
-[[package]]
-name = "foreign-types"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "fs2"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "gcc"
 version = "0.3.43"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "gdi32-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "getopts"
 version = "0.0.0"
@@ -385,70 +207,22 @@ name = "getopts"
 version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "git2"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-probe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "git2-curl"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "glob"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "graphviz"
 version = "0.0.0"
 
-[[package]]
-name = "hamcrest"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "handlebars"
 version = "0.25.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "idna"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -467,7 +241,7 @@ dependencies = [
 
 [[package]]
 name = "lazy_static"
-version = "0.2.2"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -479,45 +253,8 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.20"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "libgit2-sys"
-version = "0.6.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "libssh2-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "libssh2-sys"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "libz-sys"
-version = "1.0.13"
+version = "0.2.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
-]
 
 [[package]]
 name = "linkchecker"
@@ -529,37 +266,24 @@ version = "0.0.0"
 
 [[package]]
 name = "log"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "matches"
-version = "0.1.4"
+version = "0.3.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "mdbook"
-version = "0.0.17"
+version = "0.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "memchr"
-version = "0.1.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -567,105 +291,12 @@ name = "memchr"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "miniz-sys"
-version = "0.1.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "miow"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "net2"
-version = "0.2.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num"
-version = "0.1.36"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-bigint 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-complex 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-rational 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num-bigint"
-version = "0.1.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num-complex"
-version = "0.1.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num-integer"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num-iter"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num-rational"
-version = "0.1.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "num-bigint 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "num-traits"
-version = "0.1.36"
+version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -673,15 +304,7 @@ name = "num_cpus"
 version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "num_cpus"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -689,35 +312,6 @@ name = "open"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "openssl"
-version = "0.9.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "openssl-probe"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
-name = "openssl-sys"
-version = "0.9.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "panic_abort"
 version = "0.0.0"
@@ -741,11 +335,6 @@ name = "pest"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "pkg-config"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "proc_macro"
 version = "0.0.0"
@@ -762,15 +351,6 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
-[[package]]
-name = "psapi-sys"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "pulldown-cmark"
 version = "0.0.8"
@@ -793,11 +373,6 @@ name = "quick-error"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "quote"
-version = "0.3.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "rand"
 version = "0.0.0"
@@ -805,26 +380,6 @@ dependencies = [
  "core 0.0.0",
 ]
 
-[[package]]
-name = "rand"
-version = "0.3.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "regex"
-version = "0.1.80"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "regex"
 version = "0.2.1"
@@ -837,11 +392,6 @@ dependencies = [
  "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "regex-syntax"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "regex-syntax"
 version = "0.4.0"
@@ -852,7 +402,7 @@ name = "rustbook"
 version = "0.1.0"
 dependencies = [
  "clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "mdbook 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1218,70 +768,26 @@ dependencies = [
  "syntax_pos 0.0.0",
 ]
 
-[[package]]
-name = "semver"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "serde"
-version = "0.9.7"
+version = "0.9.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "serde_codegen_internals"
-version = "0.14.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_derive"
-version = "0.9.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "serde_ignored"
-version = "0.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "serde_json"
-version = "0.9.7"
+version = "0.9.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serialize"
 version = "0.0.0"
 
-[[package]]
-name = "shell-escape"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "std"
 version = "0.0.0"
@@ -1318,24 +824,6 @@ name = "strsim"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "syn"
-version = "0.11.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "synom 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "synom"
-version = "0.11.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "syntax"
 version = "0.0.0"
@@ -1367,43 +855,17 @@ dependencies = [
  "serialize 0.0.0",
 ]
 
-[[package]]
-name = "tar"
-version = "0.4.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "tempdir"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "term"
 version = "0.0.0"
 
-[[package]]
-name = "term"
-version = "0.4.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "term_size"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1415,30 +877,13 @@ dependencies = [
  "term 0.0.0",
 ]
 
-[[package]]
-name = "thread-id"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "thread-id"
 version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "thread_local"
-version = "0.2.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1464,25 +909,12 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "unicode-bidi"
-version = "0.2.5"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "unicode-normalization"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "unicode-segmentation"
 version = "1.1.0"
@@ -1493,11 +925,6 @@ name = "unicode-width"
 version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "unicode-xid"
-version = "0.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "unreachable"
 version = "0.1.1"
@@ -1506,29 +933,6 @@ dependencies = [
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "url"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "user32-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
-name = "utf8-ranges"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "utf8-ranges"
 version = "1.0.0"
@@ -1554,119 +958,49 @@ name = "winapi-build"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "ws2_32-sys"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [metadata]
-"checksum advapi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e06588080cb19d0acb6739808aafa5f26bfb2ca015b2b6370028b44cf7cb8a9a"
-"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
 "checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
 "checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
-"checksum bufstream 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b48dbe2ff0e98fa2f03377d204a9637d3c9816cd431bfe05a8abbd0ea11d074"
-"checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum clap 2.20.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7db281b0520e97fbd15cd615dcd8f8bcad0c26f5f7d5effe705f090f39e9a758"
 "checksum cmake 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "e1acc68a3f714627af38f9f5d09706a28584ba60dfe2cca68f40bf779f941b25"
-"checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
-"checksum curl 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c90e1240ef340dd4027ade439e5c7c2064dd9dc652682117bd50d1486a3add7b"
-"checksum curl-sys 0.3.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d909dc402ae80b6f7b0118c039203436061b9d9a3ca5d2c2546d93e0a61aaa"
-"checksum docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab32ea6e284d87987066f21a9e809a73c14720571ef34516f0890b3d355ccfd8"
 "checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
-"checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"
+"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
 "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922"
-"checksum flate2 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "d4e4d0c15ef829cbc1b7cda651746be19cceeb238be7b1049227b14891df9e25"
-"checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
-"checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf"
 "checksum gcc 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "c07c758b972368e703a562686adb39125707cc1ef3399da8c019fc6c2498a75d"
-"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
-"checksum git2 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "046ae03385257040b2a35e56d9669d950dd911ba2bf48202fbef73ee6aab27b2"
-"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 hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf088f042a467089e9baa4972f57f9247e42a0cc549ba264c7a04fbb8ecb89d4"
 "checksum handlebars 0.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b2249f6f0dc5a3bb2b3b1a8f797dfccbc4b053344d773d654ad565e51427d335"
-"checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
-"checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
-"checksum libgit2-sys 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d951fd5eccae07c74e8c2c1075b05ea1e43be7f8952245af8c2840d1480b1d95"
-"checksum libssh2-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "91e135645c2e198a39552c8c7686bb5b83b1b99f64831c040a6c2798a1195934"
-"checksum libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e5ee912a45d686d393d5ac87fac15ba0ba18daae14e8e7543c63ebf7fb7e970c"
-"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
-"checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1"
-"checksum mdbook 0.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dbba458ca886cb082d026afd704eeeeb0531f7e4ffd6c619f72dc309c1c18fe4"
-"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
+"checksum lazy_static 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7291b1dd97d331f752620b02dfdbc231df7fc01bf282a00769e1cdb963c460dc"
+"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
+"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
+"checksum mdbook 0.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "06a68e8738e42b38a02755d3ce5fa12d559e17acb238e4326cbc3cc056e65280"
 "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"
-"checksum miow 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3a78d2605eb97302c10cf944b8d96b0a2a890c52957caf92fcd1f24f69049579"
-"checksum net2 0.2.26 (registry+https://github.com/rust-lang/crates.io-index)" = "5edf9cb6be97212423aed9413dd4729d62b370b5e1c571750e882cebbbc1e3e2"
-"checksum num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "bde7c03b09e7c6a301ee81f6ddf66d7a28ec305699e3d3b056d2fc56470e3120"
-"checksum num-bigint 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "88b14378471f7c2adc5262f05b4701ef53e8da376453a8d8fee48e51db745e49"
-"checksum num-complex 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c78e054dd19c3fd03419ade63fa661e9c49bb890ce3beb4eee5b7baf93f92f"
-"checksum num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "fb24d9bfb3f222010df27995441ded1e954f8f69cd35021f6bef02ca9552fb92"
-"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c"
-"checksum num-rational 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "54ff603b8334a72fbb27fe66948aac0abaaa40231b3cecd189e76162f6f38aaf"
-"checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c"
+"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
 "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3"
-"checksum num_cpus 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a225d1e2717567599c24f88e49f00856c6e825a12125181ee42c4257e3688d39"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
-"checksum openssl 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f9871ecf7629da3760599e3e547d35940cff3cead49159b49f81cd1250f24f1d"
-"checksum openssl-probe 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "756d49c8424483a3df3b5d735112b4da22109ced9a8294f1f5cdf80fb3810919"
-"checksum openssl-sys 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5dd48381e9e8a6dce9c4c402db143b2e243f5f872354532f7a009c289b3998ca"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
-"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
-"checksum psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "abcd5d1a07d360e29727f757a9decb3ce8bc6e0efa8969cfaad669a8317a2478"
 "checksum pulldown-cmark 0.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1058d7bb927ca067656537eec4e02c2b4b70eaaa129664c5b90c111e20326f41"
 "checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c"
-"checksum quote 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7375cf7ad34a92e8fd18dd9c42f58b9a11def59ab48bec955bf359a788335592"
-"checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
-"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
-"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
-"checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
-"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0ed773960f90a78567fcfbe935284adf50c5d7cf119aa2cf43bb0b4afa69bb"
-"checksum serde_codegen_internals 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d52006899f910528a10631e5b727973fe668f3228109d1707ccf5bad5490b6e"
-"checksum serde_derive 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "789ee9f3cd78c850948b94121020147f5220b47dafbf230d7098a93a58f726cf"
-"checksum serde_ignored 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4b3f5576874721d14690657e9f0ed286e72a52be2f6fdc0cf2f024182bd8f64"
-"checksum serde_json 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb96d30e4e6f9fc52e08f51176d078b6f79b981dc3ed4134f7b850be9f446a8"
-"checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
+"checksum serde 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a702319c807c016e51f672e5c77d6f0b46afddd744b5e437d6b8436b888b458f"
+"checksum serde_json 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "dbc45439552eb8fb86907a2c41c1fd0ef97458efb87ff7f878db466eb581824e"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
-"checksum syn 0.11.8 (registry+https://github.com/rust-lang/crates.io-index)" = "37c279fb816210c9bb28b2c292664581e7b87b4561e86b94df462664d8620bb8"
-"checksum synom 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27e31aa4b09b9f4cb12dff3c30ba503e17b1a624413d764d32dab76e3920e5bc"
-"checksum tar 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "1eb3bf6ec92843ca93f4fcfb5fc6dfe30534815b147885db4b5759b8e2ff7d52"
-"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
-"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
 "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
-"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
-"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
 "checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7"
 "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
-"checksum toml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08272367dd2e766db3fa38f068067d17aa6a9dfd7259af24b3927db92f1e0c2f"
-"checksum unicode-bidi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a078ebdd62c0e71a709c3d53d2af693fe09fe93fbff8344aebe289b78f9032"
-"checksum unicode-normalization 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e28fa37426fceeb5cf8f41ee273faa7c82c47dc8fba5853402841e665fcd86ff"
+"checksum toml 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3474f3c6eaf32eedb4f4a66a26214f020f828a6d96c37e38a35e3a379bbcfd11"
 "checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
-"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
-"checksum url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ba8a749fb4479b043733416c244fa9d1d3af3d7c23804944651c8a448cb87e"
-"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47"
-"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
 "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122"
 "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
-"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
index c5ca80accbf02c774b8d31aa1545835bd0082c99..0dafbb8428e3ebf6cd1d44d149805c914cff3e46 100644 (file)
@@ -13,7 +13,6 @@ members = [
   "tools/build-manifest",
   "tools/qemu-test-client",
   "tools/qemu-test-server",
-  "tools/cargo",
 ]
 
 # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
index 7dd53f41a214adb838a281bdef446e56590931be..b326f95e505fb8b8c2e314d5877e70a31d6f5333 100644 (file)
@@ -296,8 +296,10 @@ class RustBuild(object):
 
     def get_mk(self, key):
         for line in iter(self.config_mk.splitlines()):
-            if line.startswith(key):
-                return line[line.find(':=') + 2:].strip()
+            if line.startswith(key + ' '):
+                var = line[line.find(':=') + 2:].strip()
+                if var != '':
+                    return var
         return None
 
     def cargo(self):
@@ -438,6 +440,8 @@ class RustBuild(object):
                 sys.exit(err)
         elif ostype == 'Darwin':
             ostype = 'apple-darwin'
+        elif ostype == 'Haiku':
+            ostype = 'unknown-haiku'
         elif ostype.startswith('MINGW'):
             # msys' `uname` does not print gcc configuration, but prints msys
             # configuration. so we cannot believe `uname -m`:
@@ -465,9 +469,12 @@ class RustBuild(object):
             cputype = 'i686'
         elif cputype in {'xscale', 'arm'}:
             cputype = 'arm'
-        elif cputype == 'armv7l':
+        elif cputype in {'armv6l', 'armv7l', 'armv8l'}:
             cputype = 'arm'
             ostype += 'eabihf'
+        elif cputype == 'armv7l':
+            cputype = 'armv7'
+            ostype += 'eabihf'
         elif cputype == 'aarch64':
             cputype = 'aarch64'
         elif cputype == 'arm64':
@@ -488,12 +495,20 @@ class RustBuild(object):
                 raise ValueError('unknown byteorder: ' + sys.byteorder)
             # only the n64 ABI is supported, indicate it
             ostype += 'abi64'
-        elif cputype in {'powerpc', 'ppc', 'ppc64'}:
+        elif cputype in {'powerpc', 'ppc'}:
             cputype = 'powerpc'
+        elif cputype in {'powerpc64', 'ppc64'}:
+            cputype = 'powerpc64'
+        elif cputype in {'powerpc64le', 'ppc64le'}:
+            cputype = 'powerpc64le'
         elif cputype == 'sparcv9':
             pass
         elif cputype in {'amd64', 'x86_64', 'x86-64', 'x64'}:
             cputype = 'x86_64'
+        elif cputype == 's390x':
+            cputype = 's390x'
+        elif cputype == 'BePC':
+            cputype = 'i686'
         else:
             err = "unknown cpu type: " + cputype
             if self.verbose:
index c126c076a3d4eccf862197263a520d6b04d5007c..2607ce412f1081bd83e470c4dd81ffa1a2396443 100644 (file)
@@ -42,9 +42,22 @@ struct Info {
 
 impl GitInfo {
     pub fn new(dir: &Path) -> GitInfo {
-        if !dir.join(".git").is_dir() {
+        // See if this even begins to look like a git dir
+        if !dir.join(".git").exists() {
             return GitInfo { inner: None }
         }
+
+        // Make sure git commands work
+        let out = Command::new("git")
+                          .arg("rev-parse")
+                          .current_dir(dir)
+                          .output()
+                          .expect("failed to spawn git");
+        if !out.status.success() {
+            return GitInfo { inner: None }
+        }
+
+        // Ok, let's scrape some info
         let ver_date = output(Command::new("git").current_dir(dir)
                                       .arg("log").arg("-1")
                                       .arg("--date=short")
index dfe96b51799c0f5813442a69fbc020513370e5b6..68b3623a53f255243ade5a90f8b328b390405e58 100644 (file)
@@ -550,7 +550,7 @@ fn find_tests(dir: &Path,
         let filename = e.file_name().into_string().unwrap();
         if (target.contains("windows") && filename.ends_with(".exe")) ||
            (!target.contains("windows") && !filename.contains(".")) ||
-           (target.contains("emscripten") && filename.contains(".js")){
+           (target.contains("emscripten") && filename.ends_with(".js")) {
             dst.push(e.path());
         }
     }
index 46d8d4b4aab2d6717017f75d660f0d424ad52976..3459c1d2b8425f89385e2a8ccb4023daf08f6fe9 100644 (file)
@@ -417,7 +417,10 @@ pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
     // build.clear_if_dirty(&out_dir, &libstd_stamp(build, stage, &host, target));
 
     let mut cargo = build.cargo(&compiler, Mode::Tool, target, "build");
-    let dir = build.src.join("src/tools").join(tool);
+    let mut dir = build.src.join(tool);
+    if !dir.exists() {
+        dir = build.src.join("src/tools").join(tool);
+    }
     cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
 
     // We don't want to build tools dynamically as they'll be running across
index 438ce6103d624f814ddae98fe9afbea1830f407a..dcd49c51e3a99b026da705ebd963714e31b6ea5a 100644 (file)
@@ -59,6 +59,8 @@ pub struct Config {
     pub llvm_static_stdcpp: bool,
     pub llvm_link_shared: bool,
     pub llvm_targets: Option<String>,
+    pub llvm_link_jobs: Option<u32>,
+    pub llvm_clean_rebuild: bool,
 
     // rust codegen options
     pub rust_optimize: bool,
@@ -179,6 +181,8 @@ struct Llvm {
     version_check: Option<bool>,
     static_libstdcpp: Option<bool>,
     targets: Option<String>,
+    link_jobs: Option<u32>,
+    clean_rebuild: Option<bool>,
 }
 
 #[derive(RustcDecodable, Default, Clone)]
@@ -332,7 +336,9 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
             set(&mut config.llvm_version_check, llvm.version_check);
             set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
+            set(&mut config.llvm_clean_rebuild, llvm.clean_rebuild);
             config.llvm_targets = llvm.targets.clone();
+            config.llvm_link_jobs = llvm.link_jobs;
         }
 
         if let Some(ref rust) = toml.rust {
@@ -436,6 +442,7 @@ macro_rules! check {
                 ("LLVM_VERSION_CHECK", self.llvm_version_check),
                 ("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp),
                 ("LLVM_LINK_SHARED", self.llvm_link_shared),
+                ("LLVM_CLEAN_REBUILD", self.llvm_clean_rebuild),
                 ("OPTIMIZE", self.rust_optimize),
                 ("DEBUG_ASSERTIONS", self.rust_debug_assertions),
                 ("DEBUGINFO", self.rust_debuginfo),
@@ -460,14 +467,13 @@ macro_rules! check {
             }
 
             match key {
-                "CFG_BUILD" => self.build = value.to_string(),
-                "CFG_HOST" => {
-                    self.host = value.split(" ").map(|s| s.to_string())
-                                     .collect();
-                }
-                "CFG_TARGET" => {
-                    self.target = value.split(" ").map(|s| s.to_string())
-                                       .collect();
+                "CFG_BUILD" if value.len() > 0 => self.build = value.to_string(),
+                "CFG_HOST" if value.len() > 0 => {
+                    self.host.extend(value.split(" ").map(|s| s.to_string()));
+
+                }
+                "CFG_TARGET" if value.len() > 0 => {
+                    self.target.extend(value.split(" ").map(|s| s.to_string()));
                 }
                 "CFG_MUSL_ROOT" if value.len() > 0 => {
                     self.musl_root = Some(parse_configure_path(value));
index 30763e38a336fa4569c41e6b91a371880ef6a71c..5a00e90f370b5f78bfc0183981c524683a98c7c4 100644 (file)
 # Rust team and file an issue if you need assistance in porting!
 #targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX"
 
+# Cap the number of parallel linker invocations when compiling LLVM.
+# This can be useful when building LLVM with debug info, which significantly
+# increases the size of binaries and consequently the memory required by
+# each linker process.
+# If absent or 0, linker invocations are treated like any other job and
+# controlled by rustbuild's -j parameter.
+#link-jobs = 0
+
+# Delete LLVM build directory on LLVM rebuild.
+# This option defaults to `false` for local development, but CI may want to
+# always perform clean full builds (possibly accelerated by (s)ccache).
+#clean-rebuild = false
+
 # =============================================================================
 # General build configuration options
 # =============================================================================
index 67e4dad83ce8855bd93384a9ecc2b39e491624e7..7c463bec5ff7c3829aba8318630fd5c0b6f7293a 100644 (file)
@@ -392,6 +392,7 @@ pub fn rust_src(build: &Build) {
     let src_dirs = [
         "man",
         "src",
+        "cargo",
     ];
 
     let filter_fn = move |path: &Path| {
@@ -533,11 +534,11 @@ pub fn cargo(build: &Build, stage: u32, target: &str) {
     println!("Dist cargo stage{} ({})", stage, target);
     let compiler = Compiler::new(stage, &build.config.build);
 
-    let src = build.src.join("src/tools/cargo");
+    let src = build.src.join("cargo");
     let etc = src.join("src/etc");
-    let release_num = &build.crates["cargo"].version;
-    let name = format!("cargo-{}", build.package_vers(release_num));
-    let version = build.cargo_info.version(build, release_num);
+    let release_num = build.cargo_release_num();
+    let name = format!("cargo-{}", build.package_vers(&release_num));
+    let version = build.cargo_info.version(build, &release_num);
 
     let tmp = tmpdir(build);
     let image = tmp.join("cargo-image");
@@ -594,7 +595,7 @@ pub fn extended(build: &Build, stage: u32, target: &str) {
     println!("Dist extended stage{} ({})", stage, target);
 
     let dist = distdir(build);
-    let cargo_vers = &build.crates["cargo"].version;
+    let cargo_vers = build.cargo_release_num();
     let rustc_installer = dist.join(format!("{}-{}.tar.gz",
                                             pkgname(build, "rustc"),
                                             target));
@@ -943,7 +944,7 @@ pub fn hash_and_sign(build: &Build) {
     cmd.arg(distdir(build));
     cmd.arg(today.trim());
     cmd.arg(build.rust_package_vers());
-    cmd.arg(build.cargo_info.version(build, &build.crates["cargo"].version));
+    cmd.arg(build.package_vers(&build.cargo_release_num()));
     cmd.arg(addr);
 
     t!(fs::create_dir_all(distdir(build)));
index d19e5b1b88456030eb959e9810535cdcdd198e18..db8ed579cecdb26f028739d30ca2404b0b220771 100644 (file)
 
 use std::fs::{self, File};
 use std::io::prelude::*;
+use std::io;
+use std::path::Path;
 use std::process::Command;
 
 use {Build, Compiler, Mode};
-use util::cp_r;
+use util::{cp_r, symlink_dir};
 use build_helper::up_to_date;
 
 /// Invoke `rustbook` as compiled in `stage` for `target` for the doc book
@@ -141,7 +143,22 @@ pub fn std(build: &Build, stage: u32, target: &str) {
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
 
-    build.clear_if_dirty(&out_dir, &rustdoc);
+    // Here what we're doing is creating a *symlink* (directory junction on
+    // Windows) to the final output location. This is not done as an
+    // optimization but rather for correctness. We've got three trees of
+    // documentation, one for std, one for test, and one for rustc. It's then
+    // our job to merge them all together.
+    //
+    // Unfortunately rustbuild doesn't know nearly as well how to merge doc
+    // trees as rustdoc does itself, so instead of actually having three
+    // separate trees we just have rustdoc output to the same location across
+    // all of them.
+    //
+    // This way rustdoc generates output directly into the output, and rustdoc
+    // will also directly handle merging.
+    let my_out = build.crate_doc_out(target);
+    build.clear_if_dirty(&my_out, &rustdoc);
+    t!(symlink_dir_force(&my_out, &out_dir));
 
     let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc");
     cargo.arg("--manifest-path")
@@ -151,9 +168,7 @@ pub fn std(build: &Build, stage: u32, target: &str) {
     // We don't want to build docs for internal std dependencies unless
     // in compiler-docs mode. When not in that mode, we whitelist the crates
     // for which docs must be built.
-    if build.config.compiler_docs {
-        cargo.arg("-p").arg("std");
-    } else {
+    if !build.config.compiler_docs {
         cargo.arg("--no-deps");
         for krate in &["alloc", "collections", "core", "std", "std_unicode"] {
             cargo.arg("-p").arg(krate);
@@ -166,7 +181,7 @@ pub fn std(build: &Build, stage: u32, target: &str) {
 
 
     build.run(&mut cargo);
-    cp_r(&out_dir, &out)
+    cp_r(&my_out, &out);
 }
 
 /// Compile all libtest documentation.
@@ -187,13 +202,16 @@ pub fn test(build: &Build, stage: u32, target: &str) {
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
 
-    build.clear_if_dirty(&out_dir, &rustdoc);
+    // See docs in std above for why we symlink
+    let my_out = build.crate_doc_out(target);
+    build.clear_if_dirty(&my_out, &rustdoc);
+    t!(symlink_dir_force(&my_out, &out_dir));
 
     let mut cargo = build.cargo(&compiler, Mode::Libtest, target, "doc");
     cargo.arg("--manifest-path")
          .arg(build.src.join("src/libtest/Cargo.toml"));
     build.run(&mut cargo);
-    cp_r(&out_dir, &out)
+    cp_r(&my_out, &out);
 }
 
 /// Generate all compiler documentation.
@@ -213,15 +231,34 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
     let out_dir = build.stage_out(&compiler, Mode::Librustc)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
-    if !up_to_date(&rustdoc, &out_dir.join("rustc/index.html")) && out_dir.exists() {
-        t!(fs::remove_dir_all(&out_dir));
-    }
+
+    // See docs in std above for why we symlink
+    let my_out = build.crate_doc_out(target);
+    build.clear_if_dirty(&my_out, &rustdoc);
+    t!(symlink_dir_force(&my_out, &out_dir));
+
     let mut cargo = build.cargo(&compiler, Mode::Librustc, target, "doc");
     cargo.arg("--manifest-path")
          .arg(build.src.join("src/rustc/Cargo.toml"))
          .arg("--features").arg(build.rustc_features());
+
+    if build.config.compiler_docs {
+        // src/rustc/Cargo.toml contains bin crates called rustc and rustdoc
+        // which would otherwise overwrite the docs for the real rustc and
+        // rustdoc lib crates.
+        cargo.arg("-p").arg("rustc_driver")
+             .arg("-p").arg("rustdoc");
+    } else {
+        // Like with libstd above if compiler docs aren't enabled then we're not
+        // documenting internal dependencies, so we have a whitelist.
+        cargo.arg("--no-deps");
+        for krate in &["proc_macro"] {
+            cargo.arg("-p").arg(krate);
+        }
+    }
+
     build.run(&mut cargo);
-    cp_r(&out_dir, &out)
+    cp_r(&my_out, &out);
 }
 
 /// Generates the HTML rendered error-index by running the
@@ -240,3 +277,19 @@ pub fn error_index(build: &Build, target: &str) {
 
     build.run(&mut index);
 }
+
+fn symlink_dir_force(src: &Path, dst: &Path) -> io::Result<()> {
+    if let Ok(m) = fs::symlink_metadata(dst) {
+        if m.file_type().is_dir() {
+            try!(fs::remove_dir_all(dst));
+        } else {
+            // handle directory junctions on windows by falling back to
+            // `remove_dir`.
+            try!(fs::remove_file(dst).or_else(|_| {
+                fs::remove_dir(dst)
+            }));
+        }
+    }
+
+    symlink_dir(src, dst)
+}
index 071d0b0b09009035fb9a886c2d45272fc2011518..72aec15e532b581f7d8d3c774112a9db0cbdc7de 100644 (file)
 extern crate rustc_serialize;
 extern crate toml;
 
-use std::collections::HashMap;
 use std::cmp;
+use std::collections::HashMap;
 use std::env;
 use std::ffi::OsString;
 use std::fs::{self, File};
+use std::io::Read;
 use std::path::{Component, PathBuf, Path};
 use std::process::Command;
 
@@ -231,7 +232,7 @@ pub fn new(flags: Flags, config: Config) -> Build {
             None => false,
         };
         let rust_info = channel::GitInfo::new(&src);
-        let cargo_info = channel::GitInfo::new(&src.join("src/tools/cargo"));
+        let cargo_info = channel::GitInfo::new(&src.join("cargo"));
 
         Build {
             flags: flags,
@@ -707,6 +708,13 @@ fn doc_out(&self, target: &str) -> PathBuf {
         self.out.join(target).join("doc")
     }
 
+    /// Output directory for all crate documentation for a target (temporary)
+    ///
+    /// The artifacts here are then copied into `doc_out` above.
+    fn crate_doc_out(&self, target: &str) -> PathBuf {
+        self.out.join(target).join("crate-docs")
+    }
+
     /// Returns true if no custom `llvm-config` is set for the specified target.
     ///
     /// If no custom `llvm-config` was specified then Rust's llvm will be used.
@@ -995,6 +1003,21 @@ fn rust_version(&self) -> String {
         self.rust_info.version(self, channel::CFG_RELEASE_NUM)
     }
 
+    /// Returns the `a.b.c` version that Cargo is at.
+    fn cargo_release_num(&self) -> String {
+        let mut toml = String::new();
+        t!(t!(File::open(self.src.join("cargo/Cargo.toml"))).read_to_string(&mut toml));
+        for line in toml.lines() {
+            let prefix = "version = \"";
+            let suffix = "\"";
+            if line.starts_with(prefix) && line.ends_with(suffix) {
+                return line[prefix.len()..line.len() - suffix.len()].to_string()
+            }
+        }
+
+        panic!("failed to find version in cargo's Cargo.toml")
+    }
+
     /// Returns whether unstable features should be enabled for the compiler
     /// we're building.
     fn unstable_features(&self) -> bool {
index 483f45fdd621877a2e6772277111f13d3c47280d..6cc1ca8d02ed04e33eaa9baa12dc82d7bbd290e8 100644 (file)
@@ -41,9 +41,9 @@ pub fn llvm(build: &Build, target: &str) {
         }
     }
 
-    let clean_trigger = build.src.join("src/rustllvm/llvm-auto-clean-trigger");
-    let mut clean_trigger_contents = String::new();
-    t!(t!(File::open(&clean_trigger)).read_to_string(&mut clean_trigger_contents));
+    let rebuild_trigger = build.src.join("src/rustllvm/llvm-rebuild-trigger");
+    let mut rebuild_trigger_contents = String::new();
+    t!(t!(File::open(&rebuild_trigger)).read_to_string(&mut rebuild_trigger_contents));
 
     let out_dir = build.llvm_out(target);
     let done_stamp = out_dir.join("llvm-finished-building");
@@ -51,18 +51,15 @@ pub fn llvm(build: &Build, target: &str) {
         let mut done_contents = String::new();
         t!(t!(File::open(&done_stamp)).read_to_string(&mut done_contents));
 
-        // LLVM was already built previously.
-        // We don't track changes in LLVM sources, so we need to choose between reusing
-        // what was built previously, or cleaning the directory and doing a fresh build.
-        // The choice depends on contents of the clean-trigger file.
-        // If the contents are the same as during the previous build, then no action is required.
-        // If the contents differ from the previous build, then cleaning is triggered.
-        if done_contents == clean_trigger_contents {
+        // If LLVM was already built previously and contents of the rebuild-trigger file
+        // didn't change from the previous build, then no action is required.
+        if done_contents == rebuild_trigger_contents {
             return
-        } else {
-            t!(fs::remove_dir_all(&out_dir));
         }
     }
+    if build.config.llvm_clean_rebuild {
+        drop(fs::remove_dir_all(&out_dir));
+    }
 
     println!("Building LLVM for {}", target);
     let _time = util::timeit();
@@ -115,6 +112,12 @@ pub fn llvm(build: &Build, target: &str) {
         cfg.define("LLVM_BUILD_32_BITS", "ON");
     }
 
+    if let Some(num_linkers) = build.config.llvm_link_jobs {
+        if num_linkers > 0 {
+            cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string());
+        }
+    }
+
     // http://llvm.org/docs/HowToCrossCompileLLVM.html
     if target != build.config.build {
         // FIXME: if the llvm root for the build triple is overridden then we
@@ -148,7 +151,7 @@ pub fn llvm(build: &Build, target: &str) {
     //        tools and libs on all platforms.
     cfg.build();
 
-    t!(t!(File::create(&done_stamp)).write_all(clean_trigger_contents.as_bytes()));
+    t!(t!(File::create(&done_stamp)).write_all(rebuild_trigger_contents.as_bytes()));
 }
 
 fn check_llvm_version(build: &Build, llvm_config: &Path) {
index a5c0d11d21985bd227582d1dfccf4409d495cb20..6b047c62d99bef2984a8836c7feacb3e918e69a0 100644 (file)
@@ -559,7 +559,7 @@ fn crate_rule<'a, 'b>(build: &'a Build,
     rules.build("tool-qemu-test-client", "src/tools/qemu-test-client")
          .dep(|s| s.name("libstd"))
          .run(move |s| compile::tool(build, s.stage, s.target, "qemu-test-client"));
-    rules.build("tool-cargo", "src/tools/cargo")
+    rules.build("tool-cargo", "cargo")
          .dep(|s| s.name("libstd"))
          .dep(|s| s.stage(0).host(s.target).name("openssl"))
          .dep(move |s| {
@@ -633,14 +633,18 @@ fn crate_rule<'a, 'b>(build: &'a Build,
     for (krate, path, default) in krates("test") {
         rules.doc(&krate.doc_step, path)
              .dep(|s| s.name("libtest-link"))
+             // Needed so rustdoc generates relative links to std.
+             .dep(|s| s.name("doc-crate-std"))
              .default(default && build.config.compiler_docs)
              .run(move |s| doc::test(build, s.stage, s.target));
     }
     for (krate, path, default) in krates("rustc-main") {
         rules.doc(&krate.doc_step, path)
              .dep(|s| s.name("librustc-link"))
+             // Needed so rustdoc generates relative links to std.
+             .dep(|s| s.name("doc-crate-std"))
              .host(true)
-             .default(default && build.config.compiler_docs)
+             .default(default && build.config.docs)
              .run(move |s| doc::rustc(build, s.stage, s.target));
     }
 
@@ -1213,20 +1217,20 @@ fn build(args: &[&str],
             name: "std".to_string(),
             deps: Vec::new(),
             path: cwd.join("src/std"),
-            doc_step: "doc-std".to_string(),
+            doc_step: "doc-crate-std".to_string(),
             build_step: "build-crate-std".to_string(),
-            test_step: "test-std".to_string(),
-            bench_step: "bench-std".to_string(),
+            test_step: "test-crate-std".to_string(),
+            bench_step: "bench-crate-std".to_string(),
             version: String::new(),
         });
         build.crates.insert("test".to_string(), ::Crate {
             name: "test".to_string(),
             deps: Vec::new(),
             path: cwd.join("src/test"),
-            doc_step: "doc-test".to_string(),
+            doc_step: "doc-crate-test".to_string(),
             build_step: "build-crate-test".to_string(),
-            test_step: "test-test".to_string(),
-            bench_step: "bench-test".to_string(),
+            test_step: "test-crate-test".to_string(),
+            bench_step: "bench-crate-test".to_string(),
             version: String::new(),
         });
         build.crates.insert("rustc-main".to_string(), ::Crate {
@@ -1234,10 +1238,10 @@ fn build(args: &[&str],
             deps: Vec::new(),
             version: String::new(),
             path: cwd.join("src/rustc-main"),
-            doc_step: "doc-rustc-main".to_string(),
+            doc_step: "doc-crate-rustc-main".to_string(),
             build_step: "build-crate-rustc-main".to_string(),
-            test_step: "test-rustc-main".to_string(),
-            bench_step: "bench-rustc-main".to_string(),
+            test_step: "test-crate-rustc-main".to_string(),
+            bench_step: "bench-crate-rustc-main".to_string(),
         });
         return build
     }
index fc63655d79b6c3b414cd2e4404dc6bfe2883b621..dab20f44bc361d4e18cdeb0d50fa1236ebe320c2 100644 (file)
@@ -16,6 +16,7 @@
 use std::env;
 use std::ffi::OsString;
 use std::fs;
+use std::io;
 use std::path::{Path, PathBuf};
 use std::process::Command;
 use std::time::Instant;
@@ -183,3 +184,141 @@ fn drop(&mut self) {
                  time.subsec_nanos() / 1_000_000);
     }
 }
+
+/// Symlinks two directories, using junctions on Windows and normal symlinks on
+/// Unix.
+pub fn symlink_dir(src: &Path, dest: &Path) -> io::Result<()> {
+    let _ = fs::remove_dir(dest);
+    return symlink_dir_inner(src, dest);
+
+    #[cfg(not(windows))]
+    fn symlink_dir_inner(src: &Path, dest: &Path) -> io::Result<()> {
+        use std::os::unix::fs;
+        fs::symlink(src, dest)
+    }
+
+    // Creating a directory junction on windows involves dealing with reparse
+    // points and the DeviceIoControl function, and this code is a skeleton of
+    // what can be found here:
+    //
+    // http://www.flexhex.com/docs/articles/hard-links.phtml
+    //
+    // Copied from std
+    #[cfg(windows)]
+    #[allow(bad_style)]
+    fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
+        use std::ptr;
+        use std::ffi::OsStr;
+        use std::os::windows::ffi::OsStrExt;
+
+        const MAXIMUM_REPARSE_DATA_BUFFER_SIZE: usize = 16 * 1024;
+        const GENERIC_WRITE: DWORD = 0x40000000;
+        const OPEN_EXISTING: DWORD = 3;
+        const FILE_FLAG_OPEN_REPARSE_POINT: DWORD = 0x00200000;
+        const FILE_FLAG_BACKUP_SEMANTICS: DWORD = 0x02000000;
+        const FSCTL_SET_REPARSE_POINT: DWORD = 0x900a4;
+        const IO_REPARSE_TAG_MOUNT_POINT: DWORD = 0xa0000003;
+        const FILE_SHARE_DELETE: DWORD = 0x4;
+        const FILE_SHARE_READ: DWORD = 0x1;
+        const FILE_SHARE_WRITE: DWORD = 0x2;
+
+        type BOOL = i32;
+        type DWORD = u32;
+        type HANDLE = *mut u8;
+        type LPCWSTR = *const u16;
+        type LPDWORD = *mut DWORD;
+        type LPOVERLAPPED = *mut u8;
+        type LPSECURITY_ATTRIBUTES = *mut u8;
+        type LPVOID = *mut u8;
+        type WCHAR = u16;
+        type WORD = u16;
+
+        #[repr(C)]
+        struct REPARSE_MOUNTPOINT_DATA_BUFFER {
+            ReparseTag: DWORD,
+            ReparseDataLength: DWORD,
+            Reserved: WORD,
+            ReparseTargetLength: WORD,
+            ReparseTargetMaximumLength: WORD,
+            Reserved1: WORD,
+            ReparseTarget: WCHAR,
+        }
+
+        extern "system" {
+            fn CreateFileW(lpFileName: LPCWSTR,
+                           dwDesiredAccess: DWORD,
+                           dwShareMode: DWORD,
+                           lpSecurityAttributes: LPSECURITY_ATTRIBUTES,
+                           dwCreationDisposition: DWORD,
+                           dwFlagsAndAttributes: DWORD,
+                           hTemplateFile: HANDLE)
+                           -> HANDLE;
+            fn DeviceIoControl(hDevice: HANDLE,
+                               dwIoControlCode: DWORD,
+                               lpInBuffer: LPVOID,
+                               nInBufferSize: DWORD,
+                               lpOutBuffer: LPVOID,
+                               nOutBufferSize: DWORD,
+                               lpBytesReturned: LPDWORD,
+                               lpOverlapped: LPOVERLAPPED) -> BOOL;
+        }
+
+        fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
+            Ok(s.as_ref().encode_wide().chain(Some(0)).collect())
+        }
+
+        // We're using low-level APIs to create the junction, and these are more
+        // picky about paths. For example, forward slashes cannot be used as a
+        // path separator, so we should try to canonicalize the path first.
+        let target = try!(fs::canonicalize(target));
+
+        try!(fs::create_dir(junction));
+
+        let path = try!(to_u16s(junction));
+
+        unsafe {
+            let h = CreateFileW(path.as_ptr(),
+                                GENERIC_WRITE,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+                                0 as *mut _,
+                                OPEN_EXISTING,
+                                FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
+                                ptr::null_mut());
+
+            let mut data = [0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+            let mut db = data.as_mut_ptr()
+                            as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
+            let buf = &mut (*db).ReparseTarget as *mut _;
+            let mut i = 0;
+            // FIXME: this conversion is very hacky
+            let v = br"\??\";
+            let v = v.iter().map(|x| *x as u16);
+            for c in v.chain(target.as_os_str().encode_wide().skip(4)) {
+                *buf.offset(i) = c;
+                i += 1;
+            }
+            *buf.offset(i) = 0;
+            i += 1;
+            (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
+            (*db).ReparseTargetMaximumLength = (i * 2) as WORD;
+            (*db).ReparseTargetLength = ((i - 1) * 2) as WORD;
+            (*db).ReparseDataLength =
+                    (*db).ReparseTargetLength as DWORD + 12;
+
+            let mut ret = 0;
+            let res = DeviceIoControl(h as *mut _,
+                                      FSCTL_SET_REPARSE_POINT,
+                                      data.as_ptr() as *mut _,
+                                      (*db).ReparseDataLength + 8,
+                                      ptr::null_mut(), 0,
+                                      &mut ret,
+                                      ptr::null_mut());
+
+            if res == 0 {
+                Err(io::Error::last_os_error())
+            } else {
+                Ok(())
+            }
+        }
+    }
+}
diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile
new file mode 100644 (file)
index 0000000..25a47c5
--- /dev/null
@@ -0,0 +1,47 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  ninja-build \
+  file \
+  curl \
+  ca-certificates \
+  python2.7-dev \
+  git \
+  sudo \
+  bzip2 \
+  xz-utils \
+  swig \
+  libedit-dev \
+  libncurses5-dev
+
+RUN curl -L https://cmake.org/files/v3.8/cmake-3.8.0-rc1-Linux-x86_64.tar.gz | \
+      tar xzf - -C /usr/local --strip-components=1
+
+WORKDIR /tmp
+COPY shared.sh build-toolchain.sh /tmp/
+RUN /tmp/build-toolchain.sh
+
+RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
+    dpkg -i dumb-init_*.deb && \
+    rm dumb-init_*.deb
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+
+RUN curl -o /usr/local/bin/sccache \
+      https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-02-25-sccache-x86_64-unknown-linux-musl && \
+      chmod +x /usr/local/bin/sccache
+
+ENV \
+    AR_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-ar \
+    CC_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang \
+    CXX_x86_64_unknown_fuchsia=x86_64-unknown-fuchsia-clang++ \
+    AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \
+    CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \
+    CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++
+
+ENV TARGETS=x86_64-unknown-fuchsia
+ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
+
+ENV RUST_CONFIGURE_ARGS --target=$TARGETS
+ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
diff --git a/src/ci/docker/dist-fuchsia/build-toolchain.sh b/src/ci/docker/dist-fuchsia/build-toolchain.sh
new file mode 100755 (executable)
index 0000000..cad73ee
--- /dev/null
@@ -0,0 +1,116 @@
+#!/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
+source shared.sh
+
+# Download sources
+SRCS=(
+  "https://fuchsia.googlesource.com/magenta magenta ac69119"
+  "https://fuchsia.googlesource.com/third_party/llvm llvm 5463083"
+  "https://fuchsia.googlesource.com/third_party/clang llvm/tools/clang 4ff7b4b"
+  "https://fuchsia.googlesource.com/third_party/lld llvm/tools/lld fd465a3"
+  "https://fuchsia.googlesource.com/third_party/lldb llvm/tools/lldb 6bb11f8"
+  "https://fuchsia.googlesource.com/third_party/compiler-rt llvm/runtimes/compiler-rt 52d4ecc"
+  "https://fuchsia.googlesource.com/third_party/libcxx llvm/runtimes/libcxx e891cc8"
+  "https://fuchsia.googlesource.com/third_party/libcxxabi llvm/runtimes/libcxxabi f0f0257"
+  "https://fuchsia.googlesource.com/third_party/libunwind llvm/runtimes/libunwind 50bddc1"
+)
+
+fetch() {
+  mkdir -p $2
+  pushd $2 > /dev/null
+  curl -sL $1/+archive/$3.tar.gz | tar xzf -
+  popd > /dev/null
+}
+
+for i in "${SRCS[@]}"; do
+  fetch $i
+done
+
+# Build toolchain
+cd llvm
+mkdir build
+cd build
+hide_output cmake -GNinja \
+  -DFUCHSIA_SYSROOT=${PWD}/../../magenta/third_party/ulib/musl \
+  -DLLVM_ENABLE_LTO=OFF \
+  -DCLANG_BOOTSTRAP_PASSTHROUGH=LLVM_ENABLE_LTO \
+  -C ../tools/clang/cmake/caches/Fuchsia.cmake \
+  ..
+hide_output ninja stage2-distribution
+hide_output ninja stage2-install-distribution
+cd ../..
+
+# Build sysroot
+rm -rf llvm/runtimes/compiler-rt
+./magenta/scripts/download-toolchain
+
+build_sysroot() {
+  local arch="$1"
+
+  case "${arch}" in
+    x86_64) tgt="magenta-pc-x86-64" ;;
+    aarch64) tgt="magenta-qemu-arm64" ;;
+  esac
+
+  hide_output make -C magenta -j$(getconf _NPROCESSORS_ONLN) $tgt
+  dst=/usr/local/${arch}-unknown-fuchsia
+  mkdir -p $dst
+  cp -r magenta/build-${tgt}/sysroot/include $dst/
+  cp -r magenta/build-${tgt}/sysroot/lib $dst/
+
+  cd llvm
+  mkdir build-runtimes-${arch}
+  cd build-runtimes-${arch}
+  hide_output cmake -GNinja \
+    -DCMAKE_C_COMPILER=clang \
+    -DCMAKE_CXX_COMPILER=clang++ \
+    -DCMAKE_AR=/usr/local/bin/llvm-ar \
+    -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib \
+    -DCMAKE_INSTALL_PREFIX= \
+    -DLLVM_MAIN_SRC_DIR=${PWD}/.. \
+    -DLLVM_BINARY_DIR=${PWD}/../build \
+    -DLLVM_ENABLE_WERROR=OFF \
+    -DCMAKE_BUILD_TYPE=Release \
+    -DLLVM_INCLUDE_TESTS=ON \
+    -DCMAKE_SYSTEM_NAME=Fuchsia \
+    -DCMAKE_C_COMPILER_TARGET=${arch}-fuchsia \
+    -DCMAKE_CXX_COMPILER_TARGET=${arch}-fuchsia \
+    -DUNIX=1 \
+    -DLIBCXX_HAS_MUSL_LIBC=ON \
+    -DLIBCXXABI_USE_LLVM_UNWINDER=ON \
+    -DCMAKE_SYSROOT=${dst} \
+    -DCMAKE_C_COMPILER_FORCED=TRUE \
+    -DCMAKE_CXX_COMPILER_FORCED=TRUE \
+    -DLLVM_ENABLE_LIBCXX=ON \
+    -DCMAKE_EXE_LINKER_FLAGS="-nodefaultlibs -lc" \
+    -DCMAKE_SHARED_LINKER_FLAGS="$(clang --target=${arch}-fuchsia -print-libgcc-file-name)" \
+    ../runtimes
+  hide_output env DESTDIR="${dst}" ninja install
+  cd ../..
+}
+
+build_sysroot "x86_64"
+build_sysroot "aarch64"
+
+rm -rf magenta llvm
+
+for arch in x86_64 aarch64; do
+  for tool in clang clang++; do
+    cat >/usr/local/bin/${arch}-unknown-fuchsia-${tool} <<EOF
+#!/bin/sh
+${tool} --target=${arch}-unknown-fuchsia --sysroot=/usr/local/${arch}-unknown-fuchsia "\$@"
+EOF
+    chmod +x /usr/local/bin/${arch}-unknown-fuchsia-${tool}
+  done
+  ln -s /usr/local/bin/llvm-ar /usr/local/bin/${arch}-unknown-fuchsia-ar
+done
diff --git a/src/ci/docker/dist-fuchsia/shared.sh b/src/ci/docker/dist-fuchsia/shared.sh
new file mode 100644 (file)
index 0000000..e26c6eb
--- /dev/null
@@ -0,0 +1,25 @@
+# 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.
+
+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
+}
index 1e61f2169106cdf63a2678db2a36c587df43ff35..b5a713dc38259997b22b54bb351687101fb0c989 100755 (executable)
@@ -30,13 +30,17 @@ retry docker \
 objdir=$root_dir/obj
 
 mkdir -p $HOME/.cargo
-mkdir -p $objdir
+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_ERROR_LOG=/tmp/sccache/sccache.log"
+    args="$args --env SCCACHE_LOG_LEVEL=debug"
+    args="$args --env RUST_LOG=sccache=debug"
+    args="$args --volume $objdir/tmp:/tmp/sccache"
 else
     mkdir -p $HOME/.cache/sccache
     args="$args --env SCCACHE_DIR=/sccache --volume $HOME/.cache/sccache:/sccache"
@@ -54,6 +58,7 @@ exec docker \
   --env DEPLOY_ALT=$DEPLOY_ALT \
   --env LOCAL_USER_ID=`id -u` \
   --volume "$HOME/.cargo:/cargo" \
+  --privileged \
   --rm \
   rust-ci \
   /checkout/src/ci/run.sh
index 4c4836d7ca2301f9ded0d7766af01ee05056dd72..19bea9ced064289478dfc5cd05b2d9ed7104012e 100755 (executable)
@@ -28,6 +28,7 @@ RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-quiet-tests"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-manage-submodules"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-locked-deps"
 RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-cargo-openssl-static"
+RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --enable-llvm-clean-rebuild"
 
 if [ "$DIST_SRC" = "" ]; then
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --disable-dist-src"
index d0fce7061286880bd0b0c7006ec1b350d73d6510..43b0d72186a29233d45484a6ac033a4971a70559 100644 (file)
@@ -225,6 +225,8 @@ fn drop(&mut self) {
 impl<T> Box<T> {
     /// Allocates memory on the heap and then places `x` into it.
     ///
+    /// This doesn't actually allocate if `T` is zero-sized.
+    ///
     /// # Examples
     ///
     /// ```
index 8d42045ff16372cbaccdfc7b80124488d4c444b2..1985be7f901c6889c2c763be7aa0190f81138cb0 100644 (file)
@@ -22,7 +22,7 @@
 use core::fmt;
 use core::iter::{repeat, FromIterator, FusedIterator};
 use core::mem;
-use core::ops::{Index, IndexMut};
+use core::ops::{Index, IndexMut, Place, Placer, InPlace};
 use core::ptr;
 use core::ptr::Shared;
 use core::slice;
@@ -1087,14 +1087,7 @@ pub fn pop_front(&mut self) -> Option<T> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_front(&mut self, value: T) {
-        if self.is_full() {
-            let old_cap = self.cap();
-            self.buf.double();
-            unsafe {
-                self.handle_cap_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
-        }
+        self.grow_if_necessary();
 
         self.tail = self.wrap_sub(self.tail, 1);
         let tail = self.tail;
@@ -1117,14 +1110,7 @@ pub fn push_front(&mut self, value: T) {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_back(&mut self, value: T) {
-        if self.is_full() {
-            let old_cap = self.cap();
-            self.buf.double();
-            unsafe {
-                self.handle_cap_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
-        }
+        self.grow_if_necessary();
 
         let head = self.head;
         self.head = self.wrap_add(self.head, 1);
@@ -1257,14 +1243,7 @@ pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
     #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn insert(&mut self, index: usize, value: T) {
         assert!(index <= self.len(), "index out of bounds");
-        if self.is_full() {
-            let old_cap = self.cap();
-            self.buf.double();
-            unsafe {
-                self.handle_cap_increase(old_cap);
-            }
-            debug_assert!(!self.is_full());
-        }
+        self.grow_if_necessary();
 
         // Move the least number of elements in the ring buffer and insert
         // the given object
@@ -1762,11 +1741,74 @@ pub fn retain<F>(&mut self, mut f: F)
             self.truncate(len - del);
         }
     }
+
+    // This may panic or abort
+    #[inline]
+    fn grow_if_necessary(&mut self) {
+        if self.is_full() {
+            let old_cap = self.cap();
+            self.buf.double();
+            unsafe {
+                self.handle_cap_increase(old_cap);
+            }
+            debug_assert!(!self.is_full());
+        }
+    }
+
+    /// Returns a place for insertion at the back of the `VecDeque`.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_back`](#method.push_back),
+    /// but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut buf = VecDeque::new();
+    /// buf.place_back() <- 3;
+    /// buf.place_back() <- 4;
+    /// assert_eq!(&buf, &[3, 4]);
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "placement protocol is subject to change",
+               issue = "30172")]
+    pub fn place_back(&mut self) -> PlaceBack<T> {
+        PlaceBack { vec_deque: self }
+    }
+
+    /// Returns a place for insertion at the front of the `VecDeque`.
+    ///
+    /// Using this method with placement syntax is equivalent to [`push_front`](#method.push_front),
+    /// but may be more efficient.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(collection_placement)]
+    /// #![feature(placement_in_syntax)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut buf = VecDeque::new();
+    /// buf.place_front() <- 3;
+    /// buf.place_front() <- 4;
+    /// assert_eq!(&buf, &[4, 3]);
+    /// ```
+    #[unstable(feature = "collection_placement",
+               reason = "placement protocol is subject to change",
+               issue = "30172")]
+    pub fn place_front(&mut self) -> PlaceFront<T> {
+        PlaceFront { vec_deque: self }
+    }
 }
 
 impl<T: Clone> VecDeque<T> {
     /// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
-    /// either by removing excess elements or by appending copies of a value to the back.
+    /// either by removing excess elements or by appending clones of `value` to the back.
     ///
     /// # Examples
     ///
@@ -2442,6 +2484,98 @@ fn from(other: VecDeque<T>) -> Self {
     }
 }
 
+/// A place for insertion at the back of a `VecDeque`.
+///
+/// See [`VecDeque::place_back`](struct.VecDeque.html#method.place_back) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+#[derive(Debug)]
+pub struct PlaceBack<'a, T: 'a> {
+    vec_deque: &'a mut VecDeque<T>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for PlaceBack<'a, T> {
+    type Place = PlaceBack<'a, T>;
+
+    fn make_place(self) -> Self {
+        self.vec_deque.grow_if_necessary();
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for PlaceBack<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        unsafe { self.vec_deque.ptr().offset(self.vec_deque.head as isize) }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for PlaceBack<'a, T> {
+    type Owner = &'a mut T;
+
+    unsafe fn finalize(mut self) -> &'a mut T {
+        let head = self.vec_deque.head;
+        self.vec_deque.head = self.vec_deque.wrap_add(head, 1);
+        &mut *(self.vec_deque.ptr().offset(head as isize))
+    }
+}
+
+/// A place for insertion at the front of a `VecDeque`.
+///
+/// See [`VecDeque::place_front`](struct.VecDeque.html#method.place_front) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol are subject to change",
+           issue = "30172")]
+#[derive(Debug)]
+pub struct PlaceFront<'a, T: 'a> {
+    vec_deque: &'a mut VecDeque<T>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Placer<T> for PlaceFront<'a, T> {
+    type Place = PlaceFront<'a, T>;
+
+    fn make_place(self) -> Self {
+        self.vec_deque.grow_if_necessary();
+        self
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> Place<T> for PlaceFront<'a, T> {
+    fn pointer(&mut self) -> *mut T {
+        let tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
+        unsafe { self.vec_deque.ptr().offset(tail as isize) }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, T> InPlace<T> for PlaceFront<'a, T> {
+    type Owner = &'a mut T;
+
+    unsafe fn finalize(mut self) -> &'a mut T {
+        self.vec_deque.tail = self.vec_deque.wrap_sub(self.vec_deque.tail, 1);
+        &mut *(self.vec_deque.ptr().offset(self.vec_deque.tail as isize))
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use test;
@@ -2797,4 +2931,5 @@ fn create_vec_and_test_convert(cap: usize, offset: usize, len: usize) {
             }
         }
     }
+
 }
index 849d2401691691eb013d0e57736fd29db0d5a496..d97d9b8ab83f67935fcec4a60e48c83f0e924a4c 100644 (file)
@@ -32,6 +32,7 @@
 extern crate collections;
 extern crate test;
 extern crate std_unicode;
+extern crate core;
 
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
index 1541061a1984214bf70a4260b2ab35136b98d894..f2935c05d4f7a90ac3112b0481fdac7057562652 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::collections::VecDeque;
 use std::fmt::Debug;
-use std::collections::vec_deque::Drain;
+use std::collections::vec_deque::{Drain};
 
 use self::Taggy::*;
 use self::Taggypar::*;
@@ -1000,3 +1000,25 @@ fn test_is_empty() {
     assert!(v.iter_mut().is_empty());
     assert!(v.into_iter().is_empty());
 }
+
+#[test]
+fn test_placement_in() {
+    let mut buf: VecDeque<isize> = VecDeque::new();
+    buf.place_back() <- 1;
+    buf.place_back() <- 2;
+    assert_eq!(buf, [1,2]);
+
+    buf.place_front() <- 3;
+    buf.place_front() <- 4;
+    assert_eq!(buf, [4,3,1,2]);
+
+    {
+        let ptr_head = buf.place_front() <- 5;
+        assert_eq!(*ptr_head, 5);
+    }
+    {
+        let ptr_tail = buf.place_back() <- 6;
+        assert_eq!(*ptr_tail, 6);
+    }
+    assert_eq!(buf, [5,4,3,1,2,6]);
+}
index dc5a662cdb0445fea0fca104923710cb80fbaec8..1657342ff6ac6f8aa567307edc13e9c727147309 100644 (file)
@@ -529,6 +529,26 @@ pub trait Debug {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Display {
     /// Formats the value using the given formatter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fmt;
+    ///
+    /// struct Position {
+    ///     longitude: f32,
+    ///     latitude: f32,
+    /// }
+    ///
+    /// impl fmt::Display for Position {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f, "({}, {})", self.longitude, self.latitude)
+    ///     }
+    /// }
+    ///
+    /// assert_eq!("(1.987, 2.983)".to_owned(),
+    ///            format!("{}", Position { longitude: 1.987, latitude: 2.983, }));
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn fmt(&self, f: &mut Formatter) -> Result;
 }
@@ -930,7 +950,6 @@ pub fn write(output: &mut Write, args: Arguments) -> Result {
 }
 
 impl<'a> Formatter<'a> {
-
     // First up is the collection of functions used to execute a format string
     // at runtime. This consumes all of the compile-time statics generated by
     // the format! syntax extension.
index d9b8c5ea589fd57aa74a840b889ae5aad9deb4de..df4aef088712c38d7e961d03933aa71c5410db4b 100644 (file)
 mod sources;
 mod traits;
 
-/// An double-ended iterator with the direction inverted.
+/// A double-ended iterator with the direction inverted.
 ///
 /// This `struct` is created by the [`rev()`] method on [`Iterator`]. See its
 /// documentation for more.
index 8d7fe655c23b2a9b8cf4e30274160660aea1d51a..0ab0550469bad07248a69d92acb6328bdbc0eae6 100644 (file)
@@ -21,7 +21,7 @@
 //! This functionality is intended to be expanded over time as more surface
 //! area for macro authors is stabilized.
 //!
-//! See [the book](../../book/procedural-macros.html) for more.
+//! See [the book](../book/procedural-macros.html) for more.
 
 #![crate_name = "proc_macro"]
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
 #![crate_type = "dylib"]
 #![deny(warnings)]
 #![deny(missing_docs)]
+#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+       html_root_url = "https://doc.rust-lang.org/nightly/",
+       html_playground_url = "https://play.rust-lang.org/",
+       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
+       test(no_crate_inject, attr(deny(warnings))),
+       test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
 #![feature(rustc_private)]
 #![feature(staged_api)]
index e6736ccafbad9271d7f799f4ac6f0d1853918d47..8be5d4327e72ec2c134e7746ecaa11985fc69b3c 100644 (file)
@@ -18,6 +18,7 @@
 use super::dep_node::{DepNode, WorkProductId};
 use super::query::DepGraphQuery;
 use super::raii;
+use super::safe::DepGraphSafe;
 use super::thread::{DepGraphThreadData, DepMessage};
 
 #[derive(Clone)]
@@ -76,11 +77,38 @@ pub fn with_ignore<OP,R>(&self, op: OP) -> R
         op()
     }
 
-    pub fn with_task<OP,R>(&self, key: DepNode<DefId>, op: OP) -> R
-        where OP: FnOnce() -> R
+    /// Starts a new dep-graph task. Dep-graph tasks are specified
+    /// using a free function (`task`) and **not** a closure -- this
+    /// is intentional because we want to exercise tight control over
+    /// what state they have access to. In particular, we want to
+    /// prevent implicit 'leaks' of tracked state into the task (which
+    /// could then be read without generating correct edges in the
+    /// dep-graph -- see the [README] for more details on the
+    /// dep-graph). To this end, the task function gets exactly two
+    /// pieces of state: the context `cx` and an argument `arg`. Both
+    /// of these bits of state must be of some type that implements
+    /// `DepGraphSafe` and hence does not leak.
+    ///
+    /// The choice of two arguments is not fundamental. One argument
+    /// would work just as well, since multiple values can be
+    /// collected using tuples. However, using two arguments works out
+    /// to be quite convenient, since it is common to need a context
+    /// (`cx`) and some argument (e.g., a `DefId` identifying what
+    /// item to process).
+    ///
+    /// For cases where you need some other number of arguments:
+    ///
+    /// - If you only need one argument, just use `()` for the `arg`
+    ///   parameter.
+    /// - If you need 3+ arguments, use a tuple for the
+    ///   `arg` parameter.
+    ///
+    /// [README]: README.md
+    pub fn with_task<C, A, R>(&self, key: DepNode<DefId>, cx: C, arg: A, task: fn(C, A) -> R) -> R
+        where C: DepGraphSafe, A: DepGraphSafe
     {
         let _task = self.in_task(key);
-        op()
+        task(cx, arg)
     }
 
     pub fn read(&self, v: DepNode<DefId>) {
index 7331756f35b8e95da63c8e6667f02de9a7b0caf1..a9f0a44e4208c031f7ade3e7bd5756ba3d103b9a 100644 (file)
@@ -15,6 +15,7 @@
 mod graph;
 mod query;
 mod raii;
+mod safe;
 mod shadow;
 mod thread;
 mod visit;
@@ -25,6 +26,8 @@
 pub use self::graph::DepGraph;
 pub use self::graph::WorkProduct;
 pub use self::query::DepGraphQuery;
+pub use self::safe::AssertDepGraphSafe;
+pub use self::safe::DepGraphSafe;
 pub use self::visit::visit_all_bodies_in_krate;
 pub use self::visit::visit_all_item_likes_in_krate;
 pub use self::raii::DepTask;
diff --git a/src/librustc/dep_graph/safe.rs b/src/librustc/dep_graph/safe.rs
new file mode 100644 (file)
index 0000000..f85f033
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use hir::BodyId;
+use hir::def_id::DefId;
+use syntax::ast::NodeId;
+use ty::TyCtxt;
+
+/// The `DepGraphSafe` trait is used to specify what kinds of values
+/// are safe to "leak" into a task. The idea is that this should be
+/// only be implemented for things like the tcx as well as various id
+/// types, which will create reads in the dep-graph whenever the trait
+/// loads anything that might depend on the input program.
+pub trait DepGraphSafe {
+}
+
+/// A `BodyId` on its own doesn't give access to any particular state.
+/// You must fetch the state from the various maps or generate
+/// on-demand queries, all of which create reads.
+impl DepGraphSafe for BodyId {
+}
+
+/// A `NodeId` on its own doesn't give access to any particular state.
+/// You must fetch the state from the various maps or generate
+/// on-demand queries, all of which create reads.
+impl DepGraphSafe for NodeId {
+}
+
+/// A `DefId` on its own doesn't give access to any particular state.
+/// You must fetch the state from the various maps or generate
+/// on-demand queries, all of which create reads.
+impl DepGraphSafe for DefId {
+}
+
+/// The type context itself can be used to access all kinds of tracked
+/// state, but those accesses should always generate read events.
+impl<'a, 'gcx, 'tcx> DepGraphSafe for TyCtxt<'a, 'gcx, 'tcx> {
+}
+
+/// Tuples make it easy to build up state.
+impl<A, B> DepGraphSafe for (A, B)
+    where A: DepGraphSafe, B: DepGraphSafe
+{
+}
+
+/// No data here! :)
+impl DepGraphSafe for () {
+}
+
+/// A convenient override that lets you pass arbitrary state into a
+/// task. Every use should be accompanied by a comment explaining why
+/// it makes sense (or how it could be refactored away in the future).
+pub struct AssertDepGraphSafe<T>(pub T);
+
+impl<T> DepGraphSafe for AssertDepGraphSafe<T> {
+}
index 257cdb960d5293ba3e9c4fd4b7a1a21270916915..d92eaee6f0c8ec9e72902fa48a3b5c54aac5b969 100644 (file)
@@ -79,10 +79,12 @@ pub struct LoweringContext<'a> {
     trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem>,
     impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
     bodies: BTreeMap<hir::BodyId, hir::Body>,
+    exported_macros: Vec<hir::MacroDef>,
 
     trait_impls: BTreeMap<DefId, Vec<NodeId>>,
     trait_default_impl: BTreeMap<DefId, NodeId>,
 
+    catch_scopes: Vec<NodeId>,
     loop_scopes: Vec<NodeId>,
     is_in_loop_condition: bool,
 
@@ -121,6 +123,8 @@ pub fn lower_crate(sess: &Session,
         bodies: BTreeMap::new(),
         trait_impls: BTreeMap::new(),
         trait_default_impl: BTreeMap::new(),
+        exported_macros: Vec::new(),
+        catch_scopes: Vec::new(),
         loop_scopes: Vec::new(),
         is_in_loop_condition: false,
         type_def_lifetime_params: DefIdMap(),
@@ -170,9 +174,10 @@ struct ItemLowerer<'lcx, 'interner: 'lcx> {
 
         impl<'lcx, 'interner> Visitor<'lcx> for ItemLowerer<'lcx, 'interner> {
             fn visit_item(&mut self, item: &'lcx Item) {
-                let hir_item = self.lctx.lower_item(item);
-                self.lctx.items.insert(item.id, hir_item);
-                visit::walk_item(self, item);
+                if let Some(hir_item) = self.lctx.lower_item(item) {
+                    self.lctx.items.insert(item.id, hir_item);
+                    visit::walk_item(self, item);
+                }
             }
 
             fn visit_trait_item(&mut self, item: &'lcx TraitItem) {
@@ -195,14 +200,13 @@ fn visit_impl_item(&mut self, item: &'lcx ImplItem) {
 
         let module = self.lower_mod(&c.module);
         let attrs = self.lower_attrs(&c.attrs);
-        let exported_macros = c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect();
         let body_ids = body_ids(&self.bodies);
 
         hir::Crate {
             module: module,
             attrs: attrs,
             span: c.span,
-            exported_macros: exported_macros,
+            exported_macros: hir::HirVec::from(self.exported_macros),
             items: self.items,
             trait_items: self.trait_items,
             impl_items: self.impl_items,
@@ -259,6 +263,21 @@ fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span
         span
     }
 
+    fn with_catch_scope<T, F>(&mut self, catch_id: NodeId, f: F) -> T
+        where F: FnOnce(&mut LoweringContext) -> T
+    {
+        let len = self.catch_scopes.len();
+        self.catch_scopes.push(catch_id);
+
+        let result = f(self);
+        assert_eq!(len + 1, self.catch_scopes.len(),
+            "catch scopes should be added and removed in stack order");
+
+        self.catch_scopes.pop().unwrap();
+
+        result
+    }
+
     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
         where F: FnOnce(&mut LoweringContext) -> T
     {
@@ -293,15 +312,17 @@ fn with_loop_condition_scope<T, F>(&mut self, f: F) -> T
         result
     }
 
-    fn with_new_loop_scopes<T, F>(&mut self, f: F) -> T
+    fn with_new_scopes<T, F>(&mut self, f: F) -> T
         where F: FnOnce(&mut LoweringContext) -> T
     {
         let was_in_loop_condition = self.is_in_loop_condition;
         self.is_in_loop_condition = false;
 
+        let catch_scopes = mem::replace(&mut self.catch_scopes, Vec::new());
         let loop_scopes = mem::replace(&mut self.loop_scopes, Vec::new());
         let result = f(self);
-        mem::replace(&mut self.loop_scopes, loop_scopes);
+        self.catch_scopes = catch_scopes;
+        self.loop_scopes = loop_scopes;
 
         self.is_in_loop_condition = was_in_loop_condition;
 
@@ -1063,7 +1084,7 @@ fn lower_item_kind(&mut self,
                                self.record_body(value, None))
             }
             ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
-                self.with_new_loop_scopes(|this| {
+                self.with_new_scopes(|this| {
                     let body = this.lower_block(body);
                     let body = this.expr_block(body, ThinVec::new());
                     let body_id = this.record_body(body, Some(decl));
@@ -1134,7 +1155,7 @@ fn lower_item_kind(&mut self,
                                bounds,
                                items)
             }
-            ItemKind::Mac(_) => panic!("Shouldn't still be around"),
+            ItemKind::MacroDef(..) | ItemKind::Mac(..) => panic!("Shouldn't still be around"),
         }
     }
 
@@ -1256,42 +1277,45 @@ fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         }
     }
 
-    fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
-        hir::MacroDef {
-            name: m.ident.name,
-            attrs: self.lower_attrs(&m.attrs),
-            id: m.id,
-            span: m.span,
-            body: m.body.clone().into(),
-        }
-    }
-
     fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
-        if let ItemKind::Use(ref view_path) = i.node {
-            if let ViewPathList(_, ref imports) = view_path.node {
-                return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
-                    .map(|id| hir::ItemId { id: id }).collect();
+        match i.node {
+            ItemKind::Use(ref view_path) => {
+                if let ViewPathList(_, ref imports) = view_path.node {
+                    return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
+                        .map(|id| hir::ItemId { id: id }).collect();
+                }
             }
+            ItemKind::MacroDef(..) => return SmallVector::new(),
+            _ => {}
         }
         SmallVector::one(hir::ItemId { id: i.id })
     }
 
-    pub fn lower_item(&mut self, i: &Item) -> hir::Item {
+    pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
         let mut name = i.ident.name;
         let attrs = self.lower_attrs(&i.attrs);
         let mut vis = self.lower_visibility(&i.vis);
+        if let ItemKind::MacroDef(ref tts) = i.node {
+            if i.attrs.iter().any(|attr| attr.name() == "macro_export") {
+                self.exported_macros.push(hir::MacroDef {
+                    name: name, attrs: attrs, id: i.id, span: i.span, body: tts.clone().into(),
+                });
+            }
+            return None;
+        }
+
         let node = self.with_parent_def(i.id, |this| {
             this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
         });
 
-        hir::Item {
+        Some(hir::Item {
             id: i.id,
             name: name,
             attrs: attrs,
             node: node,
             vis: vis,
             span: i.span,
-        }
+        })
     }
 
     fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem {
@@ -1660,13 +1684,17 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                                       this.lower_opt_sp_ident(opt_ident),
                                       hir::LoopSource::Loop))
                 }
+                ExprKind::Catch(ref body) => {
+                    // FIXME(cramertj): Add catch to HIR
+                    self.with_catch_scope(e.id, |this| hir::ExprBlock(this.lower_block(body)))
+                }
                 ExprKind::Match(ref expr, ref arms) => {
                     hir::ExprMatch(P(self.lower_expr(expr)),
                                    arms.iter().map(|x| self.lower_arm(x)).collect(),
                                    hir::MatchSource::Normal)
                 }
                 ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => {
-                    self.with_new_loop_scopes(|this| {
+                    self.with_new_scopes(|this| {
                         this.with_parent_def(e.id, |this| {
                             let expr = this.lower_expr(body);
                             hir::ExprClosure(this.lower_capture_clause(capture_clause),
@@ -2064,6 +2092,12 @@ fn make_struct(this: &mut LoweringContext,
                     //     Err(err) => #[allow(unreachable_code)]
                     //                 return Carrier::from_error(From::from(err)),
                     // }
+
+                    // FIXME(cramertj): implement breaking to catch
+                    if !self.catch_scopes.is_empty() {
+                        bug!("`?` in catch scopes is unimplemented")
+                    }
+
                     let unstable_span = self.allow_internal_unstable("?", e.span);
 
                     // Carrier::translate(<expr>)
index ccaf663c7ad2ab03a844ca80e107b9a2e8c2719f..f15e063e81e337ce6e53e9df924fc67a234ebf4e 100644 (file)
@@ -108,7 +108,7 @@ fn visit_item(&mut self, i: &'a Item) {
             ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()),
             ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) =>
                 DefPathData::ValueNs(i.ident.name.as_str()),
-            ItemKind::Mac(..) if i.id == DUMMY_NODE_ID => return, // Scope placeholder
+            ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()),
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
             ItemKind::Use(ref view_path) => {
                 match view_path.node {
@@ -269,10 +269,6 @@ fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
         self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
     }
 
-    fn visit_macro_def(&mut self, macro_def: &'a MacroDef) {
-        self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.ident.name.as_str()));
-    }
-
     fn visit_stmt(&mut self, stmt: &'a Stmt) {
         match stmt.node {
             StmtKind::Mac(..) => self.visit_macro_invoc(stmt.id, false),
index c835189820e5140aa02ddf5c060d14d4244f2b0c..68e64b8b7bfc827a03bfffd75abd246f7e2d4569 100644 (file)
@@ -152,7 +152,7 @@ course, it depends on the program.
 
 The main case which fails today that I would like to support is:
 
-```text
+```rust
 fn foo<T>(x: T, y: T) { ... }
 
 fn bar() {
@@ -168,6 +168,8 @@ because the type variable `T` is merged with the type variable for
 `X`, and thus inherits its UB/LB of `@mut int`.  This leaves no
 flexibility for `T` to later adjust to accommodate `@int`.
 
+Note: `@` and `@mut` are replaced with `Rc<T>` and `Rc<RefCell<T>>` in current Rust.
+
 ### What to do when not all bounds are present
 
 In the prior discussion we assumed that A.ub was not top and B.lb was
index 80da861139b42fd9acc50f686746219a5f091c4a..b564faf3d0c24c9500c3a56950e3b9f89ca9f8c5 100644 (file)
@@ -121,17 +121,19 @@ every expression, block, and pattern (patterns are considered to
 "execute" by testing the value they are applied to and creating any
 relevant bindings).  So, for example:
 
-    fn foo(x: isize, y: isize) { // -+
-    //  +------------+       //  |
-    //  |      +-----+       //  |
-    //  |  +-+ +-+ +-+       //  |
-    //  |  | | | | | |       //  |
-    //  v  v v v v v v       //  |
-        let z = x + y;       //  |
-        ...                  //  |
-    }                        // -+
-
-    fn bar() { ... }
+```rust
+fn foo(x: isize, y: isize) { // -+
+//  +------------+           //  |
+//  |      +-----+           //  |
+//  |  +-+ +-+ +-+           //  |
+//  |  | | | | | |           //  |
+//  v  v v v v v v           //  |
+    let z = x + y;           //  |
+    ...                      //  |
+}                            // -+
+
+fn bar() { ... }
+```
 
 In this example, there is a region for the fn body block as a whole,
 and then a subregion for the declaration of the local variable.
@@ -160,7 +162,9 @@ this, we get a lot of spurious errors around nested calls, in
 particular when combined with `&mut` functions. For example, a call
 like this one
 
-    self.foo(self.bar())
+```rust
+self.foo(self.bar())
+```
 
 where both `foo` and `bar` are `&mut self` functions will always yield
 an error.
@@ -168,20 +172,22 @@ an error.
 Here is a more involved example (which is safe) so we can see what's
 going on:
 
-    struct Foo { f: usize, g: usize }
-    ...
-    fn add(p: &mut usize, v: usize) {
-        *p += v;
-    }
-    ...
-    fn inc(p: &mut usize) -> usize {
-        *p += 1; *p
-    }
-    fn weird() {
-        let mut x: Box<Foo> = box Foo { ... };
-        'a: add(&mut (*x).f,
-                'b: inc(&mut (*x).f)) // (..)
-    }
+```rust
+struct Foo { f: usize, g: usize }
+// ...
+fn add(p: &mut usize, v: usize) {
+    *p += v;
+}
+// ...
+fn inc(p: &mut usize) -> usize {
+    *p += 1; *p
+}
+fn weird() {
+    let mut x: Box<Foo> = box Foo { /* ... */ };
+    'a: add(&mut (*x).f,
+            'b: inc(&mut (*x).f)) // (..)
+}
+```
 
 The important part is the line marked `(..)` which contains a call to
 `add()`. The first argument is a mutable borrow of the field `f`.  The
@@ -197,16 +203,18 @@ can see that this error is unnecessary. Let's examine the lifetimes
 involved with `'a` in detail. We'll break apart all the steps involved
 in a call expression:
 
-    'a: {
-        'a_arg1: let a_temp1: ... = add;
-        'a_arg2: let a_temp2: &'a mut usize = &'a mut (*x).f;
-        'a_arg3: let a_temp3: usize = {
-            let b_temp1: ... = inc;
-            let b_temp2: &'b = &'b mut (*x).f;
-            'b_call: b_temp1(b_temp2)
-        };
-        'a_call: a_temp1(a_temp2, a_temp3) // (**)
-    }
+```rust
+'a: {
+    'a_arg1: let a_temp1: ... = add;
+    'a_arg2: let a_temp2: &'a mut usize = &'a mut (*x).f;
+    'a_arg3: let a_temp3: usize = {
+        let b_temp1: ... = inc;
+        let b_temp2: &'b = &'b mut (*x).f;
+        'b_call: b_temp1(b_temp2)
+    };
+    'a_call: a_temp1(a_temp2, a_temp3) // (**)
+}
+```
 
 Here we see that the lifetime `'a` includes a number of substatements.
 In particular, there is this lifetime I've called `'a_call` that
@@ -225,19 +233,21 @@ it will not be *dereferenced* during the evaluation of the second
 argument, it can still be *invalidated* by that evaluation. Consider
 this similar but unsound example:
 
-    struct Foo { f: usize, g: usize }
-    ...
-    fn add(p: &mut usize, v: usize) {
-        *p += v;
-    }
-    ...
-    fn consume(x: Box<Foo>) -> usize {
-        x.f + x.g
-    }
-    fn weird() {
-        let mut x: Box<Foo> = box Foo { ... };
-        'a: add(&mut (*x).f, consume(x)) // (..)
-    }
+```rust
+struct Foo { f: usize, g: usize }
+// ...
+fn add(p: &mut usize, v: usize) {
+    *p += v;
+}
+// ...
+fn consume(x: Box<Foo>) -> usize {
+    x.f + x.g
+}
+fn weird() {
+    let mut x: Box<Foo> = box Foo { ... };
+    'a: add(&mut (*x).f, consume(x)) // (..)
+}
+```
 
 In this case, the second argument to `add` actually consumes `x`, thus
 invalidating the first argument.
index 95ce8d39ff488b0c7fc099d60528988f94b4ed37..a67049f72852bd99b81ee062c1fed836c875e842 100644 (file)
@@ -91,7 +91,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
         };
 
         if output_template.is_empty() {
-            bug!("empty string provided as RUST_REGION_GRAPH");
+            panic!("empty string provided as RUST_REGION_GRAPH");
         }
 
         if output_template.contains('%') {
index 32bc81e947037afaef2030b2f9250f35dd6da22f..9279f24a57ab32d3892a5bd1b0ac54171efd69f5 100644 (file)
@@ -806,6 +806,12 @@ fn visit_nested_body(&mut self, body: hir::BodyId) {
         self.tables = old_tables;
     }
 
+    fn visit_body(&mut self, body: &'tcx hir::Body) {
+        run_lints!(self, check_body, late_passes, body);
+        hir_visit::walk_body(self, body);
+        run_lints!(self, check_body_post, late_passes, body);
+    }
+
     fn visit_item(&mut self, it: &'tcx hir::Item) {
         self.with_lint_attrs(&it.attrs, |cx| {
             run_lints!(cx, check_item, late_passes, it);
index e9f603db15d6214b538c29a71a5aa55454641997..e81d09773701cb7f3e5c90fe8f607bf0d89f844c 100644 (file)
@@ -133,6 +133,8 @@ pub trait LintPass {
 // FIXME: eliminate the duplication with `Visitor`. But this also
 // contains a few lint-specific methods with no equivalent in `Visitor`.
 pub trait LateLintPass<'a, 'tcx>: LintPass {
+    fn check_body(&mut self, _: &LateContext, _: &'tcx hir::Body) { }
+    fn check_body_post(&mut self, _: &LateContext, _: &'tcx hir::Body) { }
     fn check_name(&mut self, _: &LateContext, _: Span, _: ast::Name) { }
     fn check_crate(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Crate) { }
     fn check_crate_post(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx hir::Crate) { }
index 4a7027b8997a5854befdef64121af1d4b96a373e..e9fb4632fa178c4cb6029adb0faae13aecd2d718 100644 (file)
@@ -136,7 +136,7 @@ pub struct NativeLibrary {
 }
 
 pub enum LoadedMacro {
-    MacroRules(ast::MacroDef),
+    MacroDef(ast::Item),
     ProcMacro(Rc<SyntaxExtension>),
 }
 
index ed72fe1801663a4bc0987622180c8cb82ae4b11e..fea576f7067807bf2933906496e5e5610b6df142 100644 (file)
@@ -19,6 +19,7 @@
 use hir::def_id::DefId;
 use ty::subst::Substs;
 use ty::{self, AdtDef, ClosureSubsts, Region, Ty};
+use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use util::ppaux;
 use rustc_back::slice;
 use hir::InlineAsm;
@@ -63,8 +64,7 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 }
 
 /// Lowered representation of a single function.
-// Do not implement clone for Mir, which can be accidently done and kind of expensive.
-#[derive(RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub struct Mir<'tcx> {
     /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
     /// that indexes into this vector.
@@ -1333,3 +1333,347 @@ pub fn dominates(&self, other: &Location, dominators: &Dominators<BasicBlock>) -
         }
     }
 }
+
+
+/*
+ * TypeFoldable implementations for MIR types
+ */
+
+impl<'tcx> TypeFoldable<'tcx> for Mir<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        Mir {
+            basic_blocks: self.basic_blocks.fold_with(folder),
+            visibility_scopes: self.visibility_scopes.clone(),
+            promoted: self.promoted.fold_with(folder),
+            return_ty: self.return_ty.fold_with(folder),
+            local_decls: self.local_decls.fold_with(folder),
+            arg_count: self.arg_count,
+            upvar_decls: self.upvar_decls.clone(),
+            spread_arg: self.spread_arg,
+            span: self.span,
+            cache: cache::Cache::new()
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.basic_blocks.visit_with(visitor) ||
+        self.promoted.visit_with(visitor)     ||
+        self.return_ty.visit_with(visitor)    ||
+        self.local_decls.visit_with(visitor)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        LocalDecl {
+            ty: self.ty.fold_with(folder),
+            ..self.clone()
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.ty.visit_with(visitor)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for BasicBlockData<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        BasicBlockData {
+            statements: self.statements.fold_with(folder),
+            terminator: self.terminator.fold_with(folder),
+            is_cleanup: self.is_cleanup
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.statements.visit_with(visitor) || self.terminator.visit_with(visitor)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Statement<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        use mir::StatementKind::*;
+
+        let kind = match self.kind {
+            Assign(ref lval, ref rval) => Assign(lval.fold_with(folder), rval.fold_with(folder)),
+            SetDiscriminant { ref lvalue, variant_index } => SetDiscriminant {
+                lvalue: lvalue.fold_with(folder),
+                variant_index: variant_index
+            },
+            StorageLive(ref lval) => StorageLive(lval.fold_with(folder)),
+            StorageDead(ref lval) => StorageDead(lval.fold_with(folder)),
+            InlineAsm { ref asm, ref outputs, ref inputs } => InlineAsm {
+                asm: asm.clone(),
+                outputs: outputs.fold_with(folder),
+                inputs: inputs.fold_with(folder)
+            },
+            Nop => Nop,
+        };
+        Statement {
+            source_info: self.source_info,
+            kind: kind
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        use mir::StatementKind::*;
+
+        match self.kind {
+            Assign(ref lval, ref rval) => { lval.visit_with(visitor) || rval.visit_with(visitor) }
+            SetDiscriminant { ref lvalue, .. } |
+            StorageLive(ref lvalue) |
+            StorageDead(ref lvalue) => lvalue.visit_with(visitor),
+            InlineAsm { ref outputs, ref inputs, .. } =>
+                outputs.visit_with(visitor) || inputs.visit_with(visitor),
+            Nop => false,
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        use mir::TerminatorKind::*;
+
+        let kind = match self.kind {
+            Goto { target } => Goto { target: target },
+            SwitchInt { ref discr, switch_ty, ref values, ref targets } => SwitchInt {
+                discr: discr.fold_with(folder),
+                switch_ty: switch_ty.fold_with(folder),
+                values: values.clone(),
+                targets: targets.clone()
+            },
+            Drop { ref location, target, unwind } => Drop {
+                location: location.fold_with(folder),
+                target: target,
+                unwind: unwind
+            },
+            DropAndReplace { ref location, ref value, target, unwind } => DropAndReplace {
+                location: location.fold_with(folder),
+                value: value.fold_with(folder),
+                target: target,
+                unwind: unwind
+            },
+            Call { ref func, ref args, ref destination, cleanup } => {
+                let dest = destination.as_ref().map(|&(ref loc, dest)| {
+                    (loc.fold_with(folder), dest)
+                });
+
+                Call {
+                    func: func.fold_with(folder),
+                    args: args.fold_with(folder),
+                    destination: dest,
+                    cleanup: cleanup
+                }
+            },
+            Assert { ref cond, expected, ref msg, target, cleanup } => {
+                let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
+                    AssertMessage::BoundsCheck {
+                        len: len.fold_with(folder),
+                        index: index.fold_with(folder),
+                    }
+                } else {
+                    msg.clone()
+                };
+                Assert {
+                    cond: cond.fold_with(folder),
+                    expected: expected,
+                    msg: msg,
+                    target: target,
+                    cleanup: cleanup
+                }
+            },
+            Resume => Resume,
+            Return => Return,
+            Unreachable => Unreachable,
+        };
+        Terminator {
+            source_info: self.source_info,
+            kind: kind
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        use mir::TerminatorKind::*;
+
+        match self.kind {
+            SwitchInt { ref discr, switch_ty, .. } =>
+                discr.visit_with(visitor) || switch_ty.visit_with(visitor),
+            Drop { ref location, ..} => location.visit_with(visitor),
+            DropAndReplace { ref location, ref value, ..} =>
+                location.visit_with(visitor) || value.visit_with(visitor),
+            Call { ref func, ref args, ref destination, .. } => {
+                let dest = if let Some((ref loc, _)) = *destination {
+                    loc.visit_with(visitor)
+                } else { false };
+                dest || func.visit_with(visitor) || args.visit_with(visitor)
+            },
+            Assert { ref cond, ref msg, .. } => {
+                if cond.visit_with(visitor) {
+                    if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
+                        len.visit_with(visitor) || index.visit_with(visitor)
+                    } else {
+                        false
+                    }
+                } else {
+                    false
+                }
+            },
+            Goto { .. } |
+            Resume |
+            Return |
+            Unreachable => false
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Lvalue<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        match self {
+            &Lvalue::Projection(ref p) => Lvalue::Projection(p.fold_with(folder)),
+            _ => self.clone()
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        if let &Lvalue::Projection(ref p) = self {
+            p.visit_with(visitor)
+        } else {
+            false
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        use mir::Rvalue::*;
+        match *self {
+            Use(ref op) => Use(op.fold_with(folder)),
+            Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
+            Ref(region, bk, ref lval) => Ref(region.fold_with(folder), bk, lval.fold_with(folder)),
+            Len(ref lval) => Len(lval.fold_with(folder)),
+            Cast(kind, ref op, ty) => Cast(kind, op.fold_with(folder), ty.fold_with(folder)),
+            BinaryOp(op, ref rhs, ref lhs) =>
+                BinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
+            CheckedBinaryOp(op, ref rhs, ref lhs) =>
+                CheckedBinaryOp(op, rhs.fold_with(folder), lhs.fold_with(folder)),
+            UnaryOp(op, ref val) => UnaryOp(op, val.fold_with(folder)),
+            Discriminant(ref lval) => Discriminant(lval.fold_with(folder)),
+            Box(ty) => Box(ty.fold_with(folder)),
+            Aggregate(ref kind, ref fields) => {
+                let kind = match *kind {
+                    AggregateKind::Array(ty) => AggregateKind::Array(ty.fold_with(folder)),
+                    AggregateKind::Tuple => AggregateKind::Tuple,
+                    AggregateKind::Adt(def, v, substs, n) =>
+                        AggregateKind::Adt(def, v, substs.fold_with(folder), n),
+                    AggregateKind::Closure(id, substs) =>
+                        AggregateKind::Closure(id, substs.fold_with(folder))
+                };
+                Aggregate(kind, fields.fold_with(folder))
+            }
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        use mir::Rvalue::*;
+        match *self {
+            Use(ref op) => op.visit_with(visitor),
+            Repeat(ref op, _) => op.visit_with(visitor),
+            Ref(region, _, ref lval) => region.visit_with(visitor) || lval.visit_with(visitor),
+            Len(ref lval) => lval.visit_with(visitor),
+            Cast(_, ref op, ty) => op.visit_with(visitor) || ty.visit_with(visitor),
+            BinaryOp(_, ref rhs, ref lhs) |
+            CheckedBinaryOp(_, ref rhs, ref lhs) =>
+                rhs.visit_with(visitor) || lhs.visit_with(visitor),
+            UnaryOp(_, ref val) => val.visit_with(visitor),
+            Discriminant(ref lval) => lval.visit_with(visitor),
+            Box(ty) => ty.visit_with(visitor),
+            Aggregate(ref kind, ref fields) => {
+                (match *kind {
+                    AggregateKind::Array(ty) => ty.visit_with(visitor),
+                    AggregateKind::Tuple => false,
+                    AggregateKind::Adt(_, _, substs, _) => substs.visit_with(visitor),
+                    AggregateKind::Closure(_, substs) => substs.visit_with(visitor)
+                }) || fields.visit_with(visitor)
+            }
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        match *self {
+            Operand::Consume(ref lval) => Operand::Consume(lval.fold_with(folder)),
+            Operand::Constant(ref c) => Operand::Constant(c.fold_with(folder)),
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        match *self {
+            Operand::Consume(ref lval) => lval.visit_with(visitor),
+            Operand::Constant(ref c) => c.visit_with(visitor)
+        }
+    }
+}
+
+impl<'tcx, B, V> TypeFoldable<'tcx> for Projection<'tcx, B, V>
+    where B: TypeFoldable<'tcx>, V: TypeFoldable<'tcx>
+{
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        use mir::ProjectionElem::*;
+
+        let base = self.base.fold_with(folder);
+        let elem = match self.elem {
+            Deref => Deref,
+            Field(f, ty) => Field(f, ty.fold_with(folder)),
+            Index(ref v) => Index(v.fold_with(folder)),
+            ref elem => elem.clone()
+        };
+
+        Projection {
+            base: base,
+            elem: elem
+        }
+    }
+
+    fn super_visit_with<Vs: TypeVisitor<'tcx>>(&self, visitor: &mut Vs) -> bool {
+        use mir::ProjectionElem::*;
+
+        self.base.visit_with(visitor) ||
+            match self.elem {
+                Field(_, ty) => ty.visit_with(visitor),
+                Index(ref v) => v.visit_with(visitor),
+                _ => false
+            }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Constant<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        Constant {
+            span: self.span.clone(),
+            ty: self.ty.fold_with(folder),
+            literal: self.literal.fold_with(folder)
+        }
+    }
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.ty.visit_with(visitor) || self.literal.visit_with(visitor)
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for Literal<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        match *self {
+            Literal::Item { def_id, substs } => Literal::Item {
+                def_id: def_id,
+                substs: substs.fold_with(folder)
+            },
+            _ => self.clone()
+        }
+    }
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        match *self {
+            Literal::Item { substs, .. } => substs.visit_with(visitor),
+            _ => false
+        }
+    }
+}
index 99db5f9b62435bc707d76bc3668ce7dda9f2bd83..0e5c786cd8dcf424de39c6de5aa044f6ab53b3fc 100644 (file)
     ObjectSafetyViolation,
 };
 
+use errors::DiagnosticBuilder;
 use fmt_macros::{Parser, Piece, Position};
+use hir::{intravisit, Local, Pat};
+use hir::intravisit::{Visitor, NestedVisitorMap};
+use hir::map::NodeExpr;
 use hir::def_id::DefId;
 use infer::{self, InferCtxt};
 use infer::type_variable::TypeVariableOrigin;
 use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL;
+use std::fmt;
+use syntax::ast;
 use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
 use ty::error::ExpectedFound;
 use ty::fast_reject;
 use ty::subst::Subst;
 use util::nodemap::{FxHashMap, FxHashSet};
 
-use std::fmt;
-use syntax::ast;
-use hir::{intravisit, Local, Pat};
-use hir::intravisit::{Visitor, NestedVisitorMap};
 use syntax_pos::{DUMMY_SP, Span};
-use errors::DiagnosticBuilder;
+
 
 #[derive(Debug, PartialEq, Eq, Hash)]
 pub struct TraitErrorKey<'tcx> {
@@ -848,15 +850,18 @@ fn need_type_info(&self, obligation: &PredicateObligation<'tcx>, ty: Ty<'tcx>) {
 
         err.span_label(cause.span, &format!("cannot infer type for `{}`", name));
 
-        let expr = self.tcx.hir.expect_expr(cause.body_id);
-
         let mut local_visitor = FindLocalByTypeVisitor {
             infcx: &self,
             target_ty: &ty,
             found_pattern: None,
         };
 
-        local_visitor.visit_expr(expr);
+        // #40294: cause.body_id can also be a fn declaration.
+        // Currently, if it's anything other than NodeExpr, we just ignore it
+        match self.tcx.hir.find(cause.body_id) {
+            Some(NodeExpr(expr)) => local_visitor.visit_expr(expr),
+            _ => ()
+        }
 
         if let Some(pattern) = local_visitor.found_pattern {
             let pattern_span = pattern.span;
index 4c4ace0d8baf9629d64a1cb7a0c805405e27d731..38ea1e4a19b91f536e989da9610cc1547384e700 100644 (file)
@@ -2461,7 +2461,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 let new_trait = tcx.mk_dynamic(
                     ty::Binder(tcx.mk_existential_predicates(iter)), r_b);
                 let InferOk { obligations, .. } =
-                    self.infcx.sub_types(false, &obligation.cause, new_trait, target)
+                    self.infcx.eq_types(false, &obligation.cause, new_trait, target)
                     .map_err(|_| Unimplemented)?;
                 self.inferred_obligations.extend(obligations);
 
@@ -2520,7 +2520,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
             // [T; n] -> [T].
             (&ty::TyArray(a, _), &ty::TySlice(b)) => {
                 let InferOk { obligations, .. } =
-                    self.infcx.sub_types(false, &obligation.cause, a, b)
+                    self.infcx.eq_types(false, &obligation.cause, a, b)
                     .map_err(|_| Unimplemented)?;
                 self.inferred_obligations.extend(obligations);
             }
@@ -2583,7 +2583,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 });
                 let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
                 let InferOk { obligations, .. } =
-                    self.infcx.sub_types(false, &obligation.cause, new_struct, target)
+                    self.infcx.eq_types(false, &obligation.cause, new_struct, target)
                     .map_err(|_| Unimplemented)?;
                 self.inferred_obligations.extend(obligations);
 
index be04b0e6577f054033e650bf15cf209008f25a77..3c37c7353d683b739e76b4a4358dd911984481ec 100644 (file)
@@ -2302,6 +2302,20 @@ pub fn item_mir(self, did: DefId) -> Ref<'gcx, Mir<'gcx>> {
         queries::mir::get(self, DUMMY_SP, did).borrow()
     }
 
+    /// Given the DefId of an item, returns its MIR, borrowed immutably.
+    /// Returns None if there is no MIR for the DefId
+    pub fn maybe_item_mir(self, did: DefId) -> Option<Ref<'gcx, Mir<'gcx>>> {
+        if did.is_local() && !self.maps.mir.borrow().contains_key(&did) {
+            return None;
+        }
+
+        if !did.is_local() && !self.sess.cstore.is_item_mir_available(did) {
+            return None;
+        }
+
+        Some(self.item_mir(did))
+    }
+
     /// If `type_needs_drop` returns true, then `ty` is definitely
     /// non-copy and *might* have a destructor attached; if it returns
     /// false, then `ty` definitely has no destructor (i.e. no drop glue).
index 48f6fcd11b8acf18b1e221e751e68f90d5113fa7..49824e8a738d7a74e5a5204d31cfa1a5cbc6ef70 100644 (file)
@@ -12,6 +12,7 @@
 use ty::{self, Lift, Ty, TyCtxt};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
+use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
 use std::rc::Rc;
 use syntax::abi;
@@ -834,3 +835,13 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         self.expected.visit_with(visitor) || self.found.visit_with(visitor)
     }
 }
+
+impl<'tcx, T: TypeFoldable<'tcx>, I: Idx> TypeFoldable<'tcx> for IndexVec<I, T> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        self.iter().map(|x| x.fold_with(folder)).collect()
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.iter().any(|t| t.visit_with(visitor))
+    }
+}
index be1582066e393c4b99b6884e6b8f9a5c9dbe85ab..a81c3a177f8854070966720631c65aac9e59c62e 100644 (file)
@@ -654,11 +654,12 @@ pub fn layout<'lcx>(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'lcx>)
         }
 
         tcx.layout_depth.set(depth+1);
-        let layout = Layout::compute_uncached(self, infcx)?;
+        let layout = Layout::compute_uncached(self, infcx);
+        tcx.layout_depth.set(depth);
+        let layout = layout?;
         if can_cache {
             tcx.layout_cache.borrow_mut().insert(self, layout);
         }
-        tcx.layout_depth.set(depth);
         Ok(layout)
     }
 
index 47b614a81ae251e9009fbb0543832a0082d2e19f..b441a231874a6def39ca5a95e1da7f07aa93869d 100644 (file)
 pub type LoanDataFlow<'a, 'tcx> = DataFlowContext<'a, 'tcx, LoanDataFlowOperator>;
 
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.dep_graph.with_task(DepNode::BorrowCheckKrate, || {
+    tcx.dep_graph.with_task(DepNode::BorrowCheckKrate, tcx, (), check_crate_task);
+
+    fn check_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
         tcx.visit_all_bodies_in_krate(|body_owner_def_id, body_id| {
-            tcx.dep_graph.with_task(DepNode::BorrowCheck(body_owner_def_id), || {
-                borrowck_fn(tcx, body_id);
-            });
+            tcx.dep_graph.with_task(DepNode::BorrowCheck(body_owner_def_id),
+                                    tcx,
+                                    body_id,
+                                    borrowck_fn);
         });
-    });
+    }
 }
 
 /// Collection of conclusions determined via borrow checker analyses.
index 00cea9cbdf6b7100aac27aa01164f32810c28afe..3f478d7c165d13b1b903e35e0f72f2b53678d5d6 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::collections::range::RangeArgument;
 use std::fmt::Debug;
 use std::iter::{self, FromIterator};
 use std::slice;
@@ -145,6 +146,18 @@ pub fn iter_enumerated_mut(&mut self) -> Enumerated<I, slice::IterMut<T>>
         self.raw.iter_mut().enumerate().map(IntoIdx { _marker: PhantomData })
     }
 
+    #[inline]
+    pub fn drain<'a, R: RangeArgument<usize>>(
+        &'a mut self, range: R) -> impl Iterator<Item=T> + 'a {
+        self.raw.drain(range)
+    }
+
+    #[inline]
+    pub fn drain_enumerated<'a, R: RangeArgument<usize>>(
+        &'a mut self, range: R) -> impl Iterator<Item=(I, T)> + 'a {
+        self.raw.drain(range).enumerate().map(IntoIdx { _marker: PhantomData })
+    }
+
     #[inline]
     pub fn last(&self) -> Option<I> {
         self.len().checked_sub(1).map(I::new)
@@ -164,6 +177,16 @@ pub fn swap(&mut self, a: usize, b: usize) {
     pub fn truncate(&mut self, a: usize) {
         self.raw.truncate(a)
     }
+
+    #[inline]
+    pub fn get(&self, index: I) -> Option<&T> {
+        self.raw.get(index.index())
+    }
+
+    #[inline]
+    pub fn get_mut(&mut self, index: I) -> Option<&mut T> {
+        self.raw.get_mut(index.index())
+    }
 }
 
 impl<I: Idx, T> Index<I> for IndexVec<I, T> {
index 3dce4398f3b91838a6eec3ef2a3ae3d93ca02c81..f278325ebec74b81281a3ae5d0604b1a686b3366 100644 (file)
@@ -38,6 +38,7 @@
 #![feature(associated_consts)]
 #![feature(unsize)]
 #![feature(i128_type)]
+#![feature(conservative_impl_trait)]
 
 #![cfg_attr(unix, feature(libc))]
 #![cfg_attr(test, feature(test))]
index 9619ba8472404bb70e0a1fffca1e620841dbe528..2126a5a7c71bd5e5f201713fe1770df063b6585f 100644 (file)
@@ -43,7 +43,6 @@
 use serialize::json;
 
 use std::env;
-use std::mem;
 use std::ffi::{OsString, OsStr};
 use std::fs;
 use std::io::{self, Write};
@@ -125,6 +124,10 @@ macro_rules! controller_entry_point {
         };
 
         write_out_deps(sess, &outputs, &crate_name);
+        if sess.opts.output_types.contains_key(&OutputType::DepInfo) &&
+            sess.opts.output_types.keys().count() == 1 {
+            return Ok(())
+        }
 
         let arena = DroplessArena::new();
         let arenas = GlobalArenas::new();
@@ -604,7 +607,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
 
     let whitelisted_legacy_custom_derives = registry.take_whitelisted_custom_derives();
     let Registry { syntax_exts, early_lint_passes, late_lint_passes, lint_groups,
-                   llvm_passes, attributes, mir_passes, .. } = registry;
+                   llvm_passes, attributes, .. } = registry;
 
     sess.track_errors(|| {
         let mut ls = sess.lint_store.borrow_mut();
@@ -620,7 +623,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         }
 
         *sess.plugin_llvm_passes.borrow_mut() = llvm_passes;
-        sess.mir_passes.borrow_mut().extend(mir_passes);
         *sess.plugin_attributes.borrow_mut() = attributes.clone();
     })?;
 
@@ -705,8 +707,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         krate
     });
 
-    krate.exported_macros = mem::replace(&mut resolver.exported_macros, Vec::new());
-
     krate = time(time_passes, "maybe building test harness", || {
         syntax::test::modify_for_testing(&sess.parse_sess,
                                          &mut resolver,
@@ -1048,6 +1048,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
 
         // No lifetime analysis based on borrowing can be done from here on out.
+        passes.push_pass(box mir::transform::inline::Inline);
         passes.push_pass(box mir::transform::instcombine::InstCombine::new());
         passes.push_pass(box mir::transform::deaggregator::Deaggregator);
         passes.push_pass(box mir::transform::copy_prop::CopyPropagation);
index 9810f121ef2c125570c4df911f625e6b7ae2510a..62d75126557284b806dcdf173c991fedf7c14bbb 100644 (file)
@@ -738,7 +738,7 @@ fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) {
               Allow <foo>
     -D <foo>           Deny <foo>
     -F <foo>           Forbid <foo> \
-              (deny, and deny all overrides)
+              (deny <foo> and all attempts to override)
 
 ");
 
index 0744fbbd4e9255512c3cc90cfdd7d5666eb3bc0c..4f3abbb362ff90ff1b3a5315cff8408708b093ff 100644 (file)
@@ -25,7 +25,7 @@
 const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                  "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                  "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
-                                                 "sse4a\0", "rdrnd\0", "rdseed\0"];
+                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];
 
 /// Add `target_feature = "..."` cfgs for a variety of platform
 /// specific features (SSE, NEON etc.).
index 0b0a9e51cacb0f27901c66d4c99178ab51031bbb..431edb3c9bc4d44e828f44f2d9f2421295b6c6b7 100644 (file)
@@ -358,39 +358,45 @@ fn render_source_line(&self,
         let mut annotations_position = vec![];
         let mut line_len = 0;
         let mut p = 0;
-        let mut ann_iter = annotations.iter().peekable();
-        while let Some(annotation) = ann_iter.next() {
-            let peek = ann_iter.peek();
-            if let Some(next) = peek {
-                if overlaps(next, annotation) && !annotation.is_line() && !next.is_line()
+        for (i, annotation) in annotations.iter().enumerate() {
+            for (j, next) in annotations.iter().enumerate() {
+                if overlaps(next, annotation, 0)  // This label overlaps with another one and both
+                    && !annotation.is_line()      // take space (they have text and are not
+                    && !next.is_line()            // multiline lines).
                     && annotation.has_label()
+                    && j > i
+                    && p == 0  // We're currently on the first line, move the label one line down
                 {
                     // This annotation needs a new line in the output.
                     p += 1;
+                    break;
                 }
             }
             annotations_position.push((p, annotation));
-            if let Some(next) = peek {
-                let l = if let Some(ref label) = next.label {
-                    label.len() + 2
-                } else {
-                    0
-                };
-                if (overlaps(next, annotation)  // Do not allow two labels to be in the same line
-                    || next.end_col + l > annotation.start_col)  // if they overlap including
-                                                // padding, to avoid situations like:
-                                                //
-                                                //      fn foo(x: u32) {
-                                                //      -------^------
-                                                //      |      |
-                                                //      fn_spanx_span
-                                                //
-                    && !annotation.is_line()    // Do not add a new line if this annotation or the
-                    && !next.is_line()          // next are vertical line placeholders.
-                    && annotation.has_label()   // Both labels must have some text, otherwise
-                    && next.has_label()         // they are not overlapping.
-                {
-                    p += 1;
+            for (j, next) in annotations.iter().enumerate() {
+                if j > i  {
+                    let l = if let Some(ref label) = next.label {
+                        label.len() + 2
+                    } else {
+                        0
+                    };
+                    if overlaps(next, annotation, l) // Do not allow two labels to be in the same
+                                                     // line if they overlap including padding, to
+                                                     // avoid situations like:
+                                                     //
+                                                     //      fn foo(x: u32) {
+                                                     //      -------^------
+                                                     //      |      |
+                                                     //      fn_spanx_span
+                                                     //
+                        && !annotation.is_line()     // Do not add a new line if this annotation
+                        && !next.is_line()           // or the next are vertical line placeholders.
+                        && annotation.has_label()    // Both labels must have some text, otherwise
+                        && next.has_label()          // they are not overlapping.
+                    {
+                        p += 1;
+                        break;
+                    }
                 }
             }
             if line_len < p {
@@ -1088,8 +1094,8 @@ fn num_overlap(a_start: usize, a_end: usize, b_start: usize, b_end:usize, inclus
     (b_start..b_end + extra).contains(a_start) ||
     (a_start..a_end + extra).contains(b_start)
 }
-fn overlaps(a1: &Annotation, a2: &Annotation) -> bool {
-    num_overlap(a1.start_col, a1.end_col, a2.start_col, a2.end_col, false)
+fn overlaps(a1: &Annotation, a2: &Annotation, padding: usize) -> bool {
+    num_overlap(a1.start_col, a1.end_col + padding, a2.start_col, a2.end_col, false)
 }
 
 fn emit_to_destination(rendered_buffer: &Vec<Vec<StyledString>>,
index d7bd5ed23c2b0af883ce9687447d15d233f63755..4c889dad8ca5050b0803be1a360b84bfda96fbb0 100644 (file)
@@ -90,7 +90,8 @@ fn push_trailing(buf: &mut String,
                          hi_opt: Option<&Loc>) {
             let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize()));
             if let Some(line) = line_opt {
-                if line.len() > lo {
+                if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) {
+                    let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi));
                     buf.push_str(match hi_opt {
                         Some(hi) => &line[lo..hi],
                         None => &line[lo..],
index 03411e01a57980e4be577309158eaa431dff956e..2789250649674505d9568b537a7f2899f49d6df9 100644 (file)
@@ -192,7 +192,11 @@ pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 clean_work_products.insert(wp.clone());
             }
 
-            tcx.dep_graph.with_task(n, || ()); // create the node with no inputs
+            tcx.dep_graph.with_task(n, (), (), create_node);
+
+            fn create_node((): (), (): ()) {
+                // just create the node with no inputs
+            }
         }
     }
 
index 28ce9126019ebdebb86da7436e62674b52e30474..f9b7c68587678dea4a5f6a0edecbcfe8c5500583 100644 (file)
@@ -189,11 +189,38 @@ fn get_lints(&self) -> LintArray {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedUnsafe {
     fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+        /// Return the NodeId for an enclosing scope that is also `unsafe`
+        fn is_enclosed(cx: &LateContext, id: ast::NodeId) -> Option<(String, ast::NodeId)> {
+            let parent_id = cx.tcx.hir.get_parent_node(id);
+            if parent_id != id {
+                if cx.tcx.used_unsafe.borrow().contains(&parent_id) {
+                    Some(("block".to_string(), parent_id))
+                } else if let Some(hir::map::NodeItem(&hir::Item {
+                    node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
+                    ..
+                })) = cx.tcx.hir.find(parent_id) {
+                    Some(("fn".to_string(), parent_id))
+                } else {
+                    is_enclosed(cx, parent_id)
+                }
+            } else {
+                None
+            }
+        }
         if let hir::ExprBlock(ref blk) = e.node {
             // Don't warn about generated blocks, that'll just pollute the output.
             if blk.rules == hir::UnsafeBlock(hir::UserProvided) &&
                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
-                cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
+
+                let mut db = cx.struct_span_lint(UNUSED_UNSAFE, blk.span,
+                                                 "unnecessary `unsafe` block");
+
+                db.span_label(blk.span, &"unnecessary `unsafe` block");
+                if let Some((kind, id)) = is_enclosed(cx, blk.id) {
+                    db.span_note(cx.tcx.hir.span(id),
+                                 &format!("because it's nested under this `unsafe` {}", kind));
+                }
+                db.emit();
             }
         }
     }
index cf2219e0e3df51c5aaf58764232b247be88e0882..2a67b79eaa52e6022ef699ee90fcbad76e91380c 100644 (file)
@@ -414,12 +414,13 @@ fn load_macro(&self, id: DefId, sess: &Session) -> LoadedMacro {
         sess.imported_macro_spans.borrow_mut()
             .insert(local_span, (name.to_string(), data.get_span(id.index, sess)));
 
-        LoadedMacro::MacroRules(ast::MacroDef {
+        LoadedMacro::MacroDef(ast::Item {
             ident: ast::Ident::with_empty_ctxt(name),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
             attrs: attrs,
-            body: body.into(),
+            node: ast::ItemKind::MacroDef(body.into()),
+            vis: ast::Visibility::Inherited,
         })
     }
 
index 69b95702009213432d1528cd281e09e85e3bc761..42d9ab4d2bf274dde9f1c82b789c70b325220f0c 100644 (file)
@@ -55,7 +55,7 @@ fn expr_as_temp(&mut self,
 (https://github.com/rust-lang/rust/issues/39283)");
         }
 
-        if temp_lifetime.is_some() {
+        if !expr_ty.is_never() && temp_lifetime.is_some() {
             this.cfg.push(block, Statement {
                 source_info: source_info,
                 kind: StatementKind::StorageLive(temp.clone())
diff --git a/src/librustc_mir/callgraph.rs b/src/librustc_mir/callgraph.rs
new file mode 100644 (file)
index 0000000..6941628
--- /dev/null
@@ -0,0 +1,252 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! MIR-based callgraph.
+//!
+//! This only considers direct calls
+
+use rustc::hir::def_id::DefId;
+use rustc_data_structures::graph;
+
+use rustc::mir::*;
+use rustc::mir::visit::*;
+
+use rustc::ty;
+
+use rustc::util::nodemap::DefIdMap;
+
+pub struct CallGraph {
+    node_map: DefIdMap<graph::NodeIndex>,
+    graph: graph::Graph<DefId, ()>
+}
+
+impl CallGraph {
+    // FIXME: allow for construction of a callgraph that inspects
+    // cross-crate MIRs if available.
+    pub fn build<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> CallGraph {
+        let def_ids = tcx.maps.mir.borrow().keys();
+
+        let mut callgraph = CallGraph {
+            node_map: DefIdMap(),
+            graph: graph::Graph::new()
+        };
+
+        for def_id in def_ids {
+            if !def_id.is_local() { continue; }
+
+            let idx = callgraph.add_node(def_id);
+
+            let mut call_visitor = CallVisitor {
+                caller: idx,
+                graph: &mut callgraph
+            };
+
+            let mir = tcx.item_mir(def_id);
+            call_visitor.visit_mir(&mir);
+        }
+
+        callgraph
+    }
+
+    // Iterate over the strongly-connected components of the graph
+    pub fn scc_iter(&self) -> SCCIterator {
+        SCCIterator::new(&self.graph)
+    }
+
+    // Get the def_id for the given graph node
+    pub fn def_id(&self, node: graph::NodeIndex) -> DefId {
+        *self.graph.node_data(node)
+    }
+
+    fn add_node(&mut self, id: DefId) -> graph::NodeIndex {
+        let graph = &mut self.graph;
+        *self.node_map.entry(id).or_insert_with(|| {
+            graph.add_node(id)
+        })
+    }
+}
+
+struct CallVisitor<'a> {
+    caller: graph::NodeIndex,
+    graph: &'a mut CallGraph
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for CallVisitor<'a> {
+    fn visit_terminator_kind(&mut self, _block: BasicBlock,
+                             kind: &TerminatorKind<'tcx>, _loc: Location) {
+        if let TerminatorKind::Call {
+            func: Operand::Constant(ref f)
+            , .. } = *kind {
+            if let ty::TyFnDef(def_id, _, _) = f.ty.sty {
+                let callee = self.graph.add_node(def_id);
+                self.graph.graph.add_edge(self.caller, callee, ());
+            }
+        }
+    }
+}
+
+struct StackElement<'g> {
+    node: graph::NodeIndex,
+    lowlink: usize,
+    children: graph::AdjacentTargets<'g, DefId, ()>
+}
+
+/**
+ * Iterator over strongly-connected-components using Tarjan's algorithm[1]
+ *
+ * [1]: https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
+ */
+pub struct SCCIterator<'g> {
+    graph: &'g graph::Graph<DefId, ()>,
+    index: usize,
+    node_indices: Vec<Option<usize>>,
+    scc_stack: Vec<graph::NodeIndex>,
+    current_scc: Vec<graph::NodeIndex>,
+    visit_stack: Vec<StackElement<'g>>,
+}
+
+impl<'g> SCCIterator<'g> {
+    pub fn new(graph: &'g graph::Graph<DefId, ()>) -> SCCIterator<'g> {
+        if graph.len_nodes() == 0 {
+            return SCCIterator {
+                graph: graph,
+                index: 0,
+                node_indices: Vec::new(),
+                scc_stack: Vec::new(),
+                current_scc: Vec::new(),
+                visit_stack: Vec::new()
+            };
+        }
+
+        let first = graph::NodeIndex(0);
+
+        SCCIterator::with_entry(graph, first)
+    }
+
+    pub fn with_entry(graph: &'g graph::Graph<DefId, ()>,
+                      entry: graph::NodeIndex) -> SCCIterator<'g> {
+        let mut iter = SCCIterator {
+            graph: graph,
+            index: 0,
+            node_indices: Vec::with_capacity(graph.len_nodes()),
+            scc_stack: Vec::new(),
+            current_scc: Vec::new(),
+            visit_stack: Vec::new()
+        };
+
+        iter.visit_one(entry);
+
+        iter
+    }
+
+    fn get_next(&mut self) {
+        self.current_scc.clear();
+
+        while !self.visit_stack.is_empty() {
+            self.visit_children();
+
+            let node = self.visit_stack.pop().unwrap();
+
+            if let Some(last) = self.visit_stack.last_mut() {
+                if last.lowlink > node.lowlink {
+                    last.lowlink = node.lowlink;
+                }
+            }
+
+            debug!("TarjanSCC: Popped node {:?} : lowlink = {:?}; index = {:?}",
+                   node.node, node.lowlink, self.node_index(node.node).unwrap());
+
+            if node.lowlink != self.node_index(node.node).unwrap() {
+                continue;
+            }
+
+            loop {
+                let n = self.scc_stack.pop().unwrap();
+                self.current_scc.push(n);
+                self.set_node_index(n, !0);
+                if n == node.node { return; }
+            }
+        }
+    }
+
+    fn visit_one(&mut self, node: graph::NodeIndex) {
+        self.index += 1;
+        let idx =  self.index;
+        self.set_node_index(node, idx);
+        self.scc_stack.push(node);
+        self.visit_stack.push(StackElement {
+            node: node,
+            lowlink: self.index,
+            children: self.graph.successor_nodes(node)
+        });
+        debug!("TarjanSCC: Node {:?} : index = {:?}", node, idx);
+    }
+
+    fn visit_children(&mut self) {
+        while let Some(child) = self.visit_stack.last_mut().unwrap().children.next() {
+            if let Some(child_num) = self.node_index(child) {
+                let cur = self.visit_stack.last_mut().unwrap();
+                if cur.lowlink > child_num {
+                    cur.lowlink = child_num;
+                }
+            } else {
+                self.visit_one(child);
+            }
+        }
+    }
+
+    fn node_index(&self, node: graph::NodeIndex) -> Option<usize> {
+        self.node_indices.get(node.node_id()).and_then(|&idx| idx)
+    }
+
+    fn set_node_index(&mut self, node: graph::NodeIndex, idx: usize) {
+        let i = node.node_id();
+        if i >= self.node_indices.len() {
+            self.node_indices.resize(i + 1, None);
+        }
+        self.node_indices[i] = Some(idx);
+    }
+}
+
+impl<'g> Iterator for SCCIterator<'g> {
+    type Item = Vec<graph::NodeIndex>;
+
+    fn next(&mut self) -> Option<Vec<graph::NodeIndex>> {
+        self.get_next();
+
+        if self.current_scc.is_empty() {
+            // Try a new root for the next SCC, if the node_indices
+            // map is doesn't contain all nodes, use the smallest one
+            // with no entry, otherwise find the first empty node.
+            //
+            // FIXME: This should probably use a set of precomputed
+            // roots instead
+            if self.node_indices.len() < self.graph.len_nodes() {
+                let idx = graph::NodeIndex(self.node_indices.len());
+                self.visit_one(idx);
+            } else {
+                for idx in 0..self.node_indices.len() {
+                    if self.node_indices[idx].is_none() {
+                        let idx = graph::NodeIndex(idx);
+                        self.visit_one(idx);
+                        break;
+                    }
+                }
+            }
+            self.get_next();
+        }
+
+        if self.current_scc.is_empty() {
+            None
+        } else {
+            Some(self.current_scc.clone())
+        }
+    }
+}
index a97495a0ebcc43d09599dc6606455b2bc28477d4..f21f1881c832e17212dea3ee392641ce0d68589a 100644 (file)
@@ -46,6 +46,7 @@
 pub mod diagnostics;
 
 pub mod build;
+pub mod callgraph;
 pub mod def_use;
 pub mod graphviz;
 mod hair;
@@ -58,4 +59,4 @@
 pub fn provide(providers: &mut Providers) {
     mir_map::provide(providers);
     transform::qualify_consts::provide(providers);
-}
+}
\ No newline at end of file
index a41489ff89ff46a24d804ebb4f1fca59966f5d3d..58f23a5c81bd7fa1cc9f557bf0aab1a994b0cb40 100644 (file)
 use std::mem;
 
 pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
-    tcx.dep_graph.with_task(DepNode::MirKrate, || {
+    tcx.dep_graph.with_task(DepNode::MirKrate, tcx, (), build_mir_for_crate_task);
+
+    fn build_mir_for_crate_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
         tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
             tcx.item_mir(body_owner_def_id);
         });
-    });
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
new file mode 100644 (file)
index 0000000..80a9c06
--- /dev/null
@@ -0,0 +1,836 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Inlining pass for MIR functions
+
+use rustc::hir::def_id::DefId;
+
+use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::graph;
+
+use rustc::dep_graph::DepNode;
+use rustc::mir::*;
+use rustc::mir::transform::{MirMapPass, MirPassHook, MirSource, Pass};
+use rustc::mir::visit::*;
+use rustc::traits;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::subst::{Subst,Substs};
+use rustc::util::nodemap::{DefIdSet};
+
+use super::simplify::{remove_dead_blocks, CfgSimplifier};
+
+use syntax::{attr};
+use syntax::abi::Abi;
+
+use callgraph;
+
+const DEFAULT_THRESHOLD: usize = 50;
+const HINT_THRESHOLD: usize = 100;
+
+const INSTR_COST: usize = 5;
+const CALL_PENALTY: usize = 25;
+
+const UNKNOWN_SIZE_COST: usize = 10;
+
+pub struct Inline;
+
+impl<'tcx> MirMapPass<'tcx> for Inline {
+    fn run_pass<'a>(
+        &mut self,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        hooks: &mut [Box<for<'s> MirPassHook<'s>>]) {
+
+        if tcx.sess.opts.debugging_opts.mir_opt_level < 2 { return; }
+
+        let _ignore = tcx.dep_graph.in_ignore();
+
+        let callgraph = callgraph::CallGraph::build(tcx);
+
+        let mut inliner = Inliner {
+            tcx: tcx,
+        };
+
+        let def_ids = tcx.maps.mir.borrow().keys();
+        for &def_id in &def_ids {
+            if !def_id.is_local() { continue; }
+
+            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            let mut mir = if let Some(mir) = tcx.maps.mir.borrow().get(&def_id) {
+                mir.borrow_mut()
+            } else {
+                continue;
+            };
+
+            tcx.dep_graph.write(DepNode::Mir(def_id));
+
+            let id = tcx.hir.as_local_node_id(def_id).unwrap();
+            let src = MirSource::from_node(tcx, id);
+
+            for hook in &mut *hooks {
+                hook.on_mir_pass(tcx, src, &mut mir, self, false);
+            }
+        }
+
+        for scc in callgraph.scc_iter() {
+            inliner.inline_scc(&callgraph, &scc);
+        }
+
+        for def_id in def_ids {
+            if !def_id.is_local() { continue; }
+
+            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            let mut mir = tcx.maps.mir.borrow()[&def_id].borrow_mut();
+            tcx.dep_graph.write(DepNode::Mir(def_id));
+
+            let id = tcx.hir.as_local_node_id(def_id).unwrap();
+            let src = MirSource::from_node(tcx, id);
+
+            for hook in &mut *hooks {
+                hook.on_mir_pass(tcx, src, &mut mir, self, true);
+            }
+        }
+    }
+}
+
+impl<'tcx> Pass for Inline { }
+
+struct Inliner<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+}
+
+#[derive(Copy, Clone)]
+struct CallSite<'tcx> {
+    caller: DefId,
+    callee: DefId,
+    substs: &'tcx Substs<'tcx>,
+    bb: BasicBlock,
+    location: SourceInfo,
+}
+
+impl<'a, 'tcx> Inliner<'a, 'tcx> {
+    fn inline_scc(&mut self, callgraph: &callgraph::CallGraph, scc: &[graph::NodeIndex]) -> bool {
+        let mut callsites = Vec::new();
+        let mut in_scc = DefIdSet();
+
+        let mut inlined_into = DefIdSet();
+
+        for &node in scc {
+            let def_id = callgraph.def_id(node);
+
+            // Don't inspect functions from other crates
+            let id = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
+                id
+            } else {
+                continue;
+            };
+            let src = MirSource::from_node(self.tcx, id);
+            if let MirSource::Fn(_) = src {
+                if let Some(mir) = self.tcx.maybe_item_mir(def_id) {
+                    for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
+                        // Don't inline calls that are in cleanup blocks.
+                        if bb_data.is_cleanup { continue; }
+
+                        // Only consider direct calls to functions
+                        let terminator = bb_data.terminator();
+                        if let TerminatorKind::Call {
+                            func: Operand::Constant(ref f), .. } = terminator.kind {
+                            if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                                callsites.push(CallSite {
+                                    caller: def_id,
+                                    callee: callee_def_id,
+                                    substs: substs,
+                                    bb: bb,
+                                    location: terminator.source_info
+                                });
+                            }
+                        }
+                    }
+
+                    in_scc.insert(def_id);
+                }
+            }
+        }
+
+        // Move callsites that are in the the SCC to the end so
+        // they're inlined after calls to outside the SCC
+        let mut first_call_in_scc = callsites.len();
+
+        let mut i = 0;
+        while i < first_call_in_scc {
+            let f = callsites[i].caller;
+            if in_scc.contains(&f) {
+                first_call_in_scc -= 1;
+                callsites.swap(i, first_call_in_scc);
+            } else {
+                i += 1;
+            }
+        }
+
+        let mut local_change;
+        let mut changed = false;
+
+        loop {
+            local_change = false;
+            let mut csi = 0;
+            while csi < callsites.len() {
+                let callsite = callsites[csi];
+                csi += 1;
+
+                let _task = self.tcx.dep_graph.in_task(DepNode::Mir(callsite.caller));
+                self.tcx.dep_graph.write(DepNode::Mir(callsite.caller));
+
+                let callee_mir = {
+                    if let Some(callee_mir) = self.tcx.maybe_item_mir(callsite.callee) {
+                        if !self.should_inline(callsite, &callee_mir) {
+                            continue;
+                        }
+
+                        callee_mir.subst(self.tcx, callsite.substs)
+                    } else {
+                        continue;
+                    }
+
+                };
+
+                let mut caller_mir = {
+                    let map = self.tcx.maps.mir.borrow();
+                    let mir = map.get(&callsite.caller).unwrap();
+                    mir.borrow_mut()
+                };
+
+                let start = caller_mir.basic_blocks().len();
+
+                if !self.inline_call(callsite, &mut caller_mir, callee_mir) {
+                    continue;
+                }
+
+                inlined_into.insert(callsite.caller);
+
+                // Add callsites from inlined function
+                for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
+                    // Only consider direct calls to functions
+                    let terminator = bb_data.terminator();
+                    if let TerminatorKind::Call {
+                        func: Operand::Constant(ref f), .. } = terminator.kind {
+                        if let ty::TyFnDef(callee_def_id, substs, _) = f.ty.sty {
+                            // Don't inline the same function multiple times.
+                            if callsite.callee != callee_def_id {
+                                callsites.push(CallSite {
+                                    caller: callsite.caller,
+                                    callee: callee_def_id,
+                                    substs: substs,
+                                    bb: bb,
+                                    location: terminator.source_info
+                                });
+                            }
+                        }
+                    }
+                }
+
+                csi -= 1;
+                if scc.len() == 1 {
+                    callsites.swap_remove(csi);
+                } else {
+                    callsites.remove(csi);
+                }
+
+                local_change = true;
+                changed = true;
+            }
+
+            if !local_change {
+                break;
+            }
+        }
+
+        // Simplify functions we inlined into.
+        for def_id in inlined_into {
+            let _task = self.tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            self.tcx.dep_graph.write(DepNode::Mir(def_id));
+
+            let mut caller_mir = {
+                let map = self.tcx.maps.mir.borrow();
+                let mir = map.get(&def_id).unwrap();
+                mir.borrow_mut()
+            };
+
+            debug!("Running simplify cfg on {:?}", def_id);
+            CfgSimplifier::new(&mut caller_mir).simplify();
+            remove_dead_blocks(&mut caller_mir);
+        }
+        changed
+    }
+
+    fn should_inline(&self, callsite: CallSite<'tcx>,
+                     callee_mir: &'a Mir<'tcx>) -> bool {
+
+        let tcx = self.tcx;
+
+        // Don't inline closures that have captures
+        // FIXME: Handle closures better
+        if callee_mir.upvar_decls.len() > 0 {
+            return false;
+        }
+
+
+        let attrs = tcx.get_attrs(callsite.callee);
+        let hint = attr::find_inline_attr(None, &attrs[..]);
+
+        let hinted = match hint {
+            // Just treat inline(always) as a hint for now,
+            // there are cases that prevent inlining that we
+            // need to check for first.
+            attr::InlineAttr::Always => true,
+            attr::InlineAttr::Never => return false,
+            attr::InlineAttr::Hint => true,
+            attr::InlineAttr::None => false,
+        };
+
+        // Only inline local functions if they would be eligible for cross-crate
+        // inlining. This is to ensure that the final crate doesn't have MIR that
+        // reference unexported symbols
+        if callsite.callee.is_local() {
+            if callsite.substs.types().count() == 0 && !hinted {
+                return false;
+            }
+        }
+
+        let mut threshold = if hinted {
+            HINT_THRESHOLD
+        } else {
+            DEFAULT_THRESHOLD
+        };
+
+        // Significantly lower the threshold for inlining cold functions
+        if attr::contains_name(&attrs[..], "cold") {
+            threshold /= 5;
+        }
+
+        // Give a bonus functions with a small number of blocks,
+        // We normally have two or three blocks for even
+        // very small functions.
+        if callee_mir.basic_blocks().len() <= 3 {
+            threshold += threshold / 4;
+        }
+
+        // FIXME: Give a bonus to functions with only a single caller
+
+        let id = tcx.hir.as_local_node_id(callsite.caller).expect("Caller not local");
+        let param_env = ty::ParameterEnvironment::for_item(tcx, id);
+
+        let mut first_block = true;
+        let mut cost = 0;
+
+        // Traverse the MIR manually so we can account for the effects of
+        // inlining on the CFG.
+        let mut work_list = vec![START_BLOCK];
+        let mut visited = BitVector::new(callee_mir.basic_blocks().len());
+        while let Some(bb) = work_list.pop() {
+            if !visited.insert(bb.index()) { continue; }
+            let blk = &callee_mir.basic_blocks()[bb];
+
+            for stmt in &blk.statements {
+                // Don't count StorageLive/StorageDead in the inlining cost.
+                match stmt.kind {
+                    StatementKind::StorageLive(_) |
+                    StatementKind::StorageDead(_) |
+                    StatementKind::Nop => {}
+                    _ => cost += INSTR_COST
+                }
+            }
+            let term = blk.terminator();
+            let mut is_drop = false;
+            match term.kind {
+                TerminatorKind::Drop { ref location, target, unwind } |
+                TerminatorKind::DropAndReplace { ref location, target, unwind, .. } => {
+                    is_drop = true;
+                    work_list.push(target);
+                    // If the location doesn't actually need dropping, treat it like
+                    // a regular goto.
+                    let ty = location.ty(&callee_mir, tcx).subst(tcx, callsite.substs);
+                    let ty = ty.to_ty(tcx);
+                    if tcx.type_needs_drop_given_env(ty, &param_env) {
+                        cost += CALL_PENALTY;
+                        if let Some(unwind) = unwind {
+                            work_list.push(unwind);
+                        }
+                    } else {
+                        cost += INSTR_COST;
+                    }
+                }
+
+                TerminatorKind::Unreachable |
+                TerminatorKind::Call { destination: None, .. } if first_block => {
+                    // If the function always diverges, don't inline
+                    // unless the cost is zero
+                    threshold = 0;
+                }
+
+                TerminatorKind::Call {func: Operand::Constant(ref f), .. } => {
+                    if let ty::TyFnDef(.., f) = f.ty.sty {
+                        // Don't give intrinsics the extra penalty for calls
+                        if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic {
+                            cost += INSTR_COST;
+                        } else {
+                            cost += CALL_PENALTY;
+                        }
+                    }
+                }
+                TerminatorKind::Assert { .. } => cost += CALL_PENALTY,
+                _ => cost += INSTR_COST
+            }
+
+            if !is_drop {
+                for &succ in &term.successors()[..] {
+                    work_list.push(succ);
+                }
+            }
+
+            first_block = false;
+        }
+
+        // Count up the cost of local variables and temps, if we know the size
+        // use that, otherwise we use a moderately-large dummy cost.
+
+        let ptr_size = tcx.data_layout.pointer_size.bytes();
+
+        for v in callee_mir.vars_and_temps_iter() {
+            let v = &callee_mir.local_decls[v];
+            let ty = v.ty.subst(tcx, callsite.substs);
+            // Cost of the var is the size in machine-words, if we know
+            // it.
+            if let Some(size) = type_size_of(tcx, param_env.clone(), ty) {
+                cost += (size / ptr_size) as usize;
+            } else {
+                cost += UNKNOWN_SIZE_COST;
+            }
+        }
+
+        debug!("Inline cost for {:?} is {}", callsite.callee, cost);
+
+        if let attr::InlineAttr::Always = hint {
+            true
+        } else {
+            cost <= threshold
+        }
+    }
+
+
+    fn inline_call(&self, callsite: CallSite<'tcx>,
+                             caller_mir: &mut Mir<'tcx>, mut callee_mir: Mir<'tcx>) -> bool {
+
+        // Don't inline a function into itself
+        if callsite.caller == callsite.callee { return false; }
+
+        let _task = self.tcx.dep_graph.in_task(DepNode::Mir(callsite.caller));
+
+
+        let terminator = caller_mir[callsite.bb].terminator.take().unwrap();
+        match terminator.kind {
+            // FIXME: Handle inlining of diverging calls
+            TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => {
+
+                debug!("Inlined {:?} into {:?}", callsite.callee, callsite.caller);
+
+                let is_box_free = Some(callsite.callee) == self.tcx.lang_items.box_free_fn();
+
+                let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len());
+                let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len());
+                let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len());
+
+                for mut scope in callee_mir.visibility_scopes.iter().cloned() {
+                    if scope.parent_scope.is_none() {
+                        scope.parent_scope = Some(callsite.location.scope);
+                        scope.span = callee_mir.span;
+                    }
+
+                    scope.span = callsite.location.span;
+
+                    let idx = caller_mir.visibility_scopes.push(scope);
+                    scope_map.push(idx);
+                }
+
+                for loc in callee_mir.vars_and_temps_iter() {
+                    let mut local = callee_mir.local_decls[loc].clone();
+
+                    if let Some(ref mut source_info) = local.source_info {
+                        source_info.scope = scope_map[source_info.scope];
+
+                        source_info.span = callsite.location.span;
+                    }
+
+                    let idx = caller_mir.local_decls.push(local);
+                    local_map.push(idx);
+                }
+
+                for p in callee_mir.promoted.iter().cloned() {
+                    let idx = caller_mir.promoted.push(p);
+                    promoted_map.push(idx);
+                }
+
+                // If the call is something like `a[*i] = f(i)`, where
+                // `i : &mut usize`, then just duplicating the `a[*i]`
+                // Lvalue could result in two different locations if `f`
+                // writes to `i`. To prevent this we need to create a temporary
+                // borrow of the lvalue and pass the destination as `*temp` instead.
+                fn dest_needs_borrow(lval: &Lvalue) -> bool {
+                    match *lval {
+                        Lvalue::Projection(ref p) => {
+                            match p.elem {
+                                ProjectionElem::Deref |
+                                ProjectionElem::Index(_) => true,
+                                _ => dest_needs_borrow(&p.base)
+                            }
+                        }
+                        // Static variables need a borrow because the callee
+                        // might modify the same static.
+                        Lvalue::Static(_) => true,
+                        _ => false
+                    }
+                }
+
+                let dest = if dest_needs_borrow(&destination.0) {
+                    debug!("Creating temp for return destination");
+                    let dest = Rvalue::Ref(
+                        self.tcx.mk_region(ty::ReErased),
+                        BorrowKind::Mut,
+                        destination.0);
+
+                    let ty = dest.ty(caller_mir, self.tcx);
+
+                    let temp = LocalDecl::new_temp(ty);
+
+                    let tmp = caller_mir.local_decls.push(temp);
+                    let tmp = Lvalue::Local(tmp);
+
+                    let stmt = Statement {
+                        source_info: callsite.location,
+                        kind: StatementKind::Assign(tmp.clone(), dest)
+                    };
+                    caller_mir[callsite.bb]
+                        .statements.push(stmt);
+                    tmp.deref()
+                } else {
+                    destination.0
+                };
+
+                let return_block = destination.1;
+
+                let args : Vec<_> = if is_box_free {
+                    assert!(args.len() == 1);
+                    // box_free takes a Box, but is defined with a *mut T, inlining
+                    // needs to generate the cast.
+                    // FIXME: we should probably just generate correct MIR in the first place...
+
+                    let arg = if let Operand::Consume(ref lval) = args[0] {
+                        lval.clone()
+                    } else {
+                        bug!("Constant arg to \"box_free\"");
+                    };
+
+                    let ptr_ty = args[0].ty(caller_mir, self.tcx);
+                    vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)]
+                } else {
+                    // Copy the arguments if needed.
+                    self.make_call_args(args, &callsite, caller_mir)
+                };
+
+                let bb_len = caller_mir.basic_blocks().len();
+                let mut integrator = Integrator {
+                    block_idx: bb_len,
+                    args: &args,
+                    local_map: local_map,
+                    scope_map: scope_map,
+                    promoted_map: promoted_map,
+                    _callsite: callsite,
+                    destination: dest,
+                    return_block: return_block,
+                    cleanup_block: cleanup,
+                    in_cleanup_block: false
+                };
+
+
+                for (bb, mut block) in callee_mir.basic_blocks_mut().drain_enumerated(..) {
+                    integrator.visit_basic_block_data(bb, &mut block);
+                    caller_mir.basic_blocks_mut().push(block);
+                }
+
+                let terminator = Terminator {
+                    source_info: callsite.location,
+                    kind: TerminatorKind::Goto { target: BasicBlock::new(bb_len) }
+                };
+
+                caller_mir[callsite.bb].terminator = Some(terminator);
+
+                true
+            }
+            kind => {
+                caller_mir[callsite.bb].terminator = Some(Terminator {
+                    source_info: terminator.source_info,
+                    kind: kind
+                });
+                false
+            }
+        }
+    }
+
+    fn cast_box_free_arg(&self, arg: Lvalue<'tcx>, ptr_ty: Ty<'tcx>,
+                         callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Operand<'tcx> {
+        let arg = Rvalue::Ref(
+            self.tcx.mk_region(ty::ReErased),
+            BorrowKind::Mut,
+            arg.deref());
+
+        let ty = arg.ty(caller_mir, self.tcx);
+        let ref_tmp = LocalDecl::new_temp(ty);
+        let ref_tmp = caller_mir.local_decls.push(ref_tmp);
+        let ref_tmp = Lvalue::Local(ref_tmp);
+
+        let ref_stmt = Statement {
+            source_info: callsite.location,
+            kind: StatementKind::Assign(ref_tmp.clone(), arg)
+        };
+
+        caller_mir[callsite.bb]
+            .statements.push(ref_stmt);
+
+        let pointee_ty = match ptr_ty.sty {
+            ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty,
+            _ if ptr_ty.is_box() => ptr_ty.boxed_ty(),
+            _ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty)
+        };
+        let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty);
+
+        let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Consume(ref_tmp), ptr_ty);
+
+        let cast_tmp = LocalDecl::new_temp(ptr_ty);
+        let cast_tmp = caller_mir.local_decls.push(cast_tmp);
+        let cast_tmp = Lvalue::Local(cast_tmp);
+
+        let cast_stmt = Statement {
+            source_info: callsite.location,
+            kind: StatementKind::Assign(cast_tmp.clone(), raw_ptr)
+        };
+
+        caller_mir[callsite.bb]
+            .statements.push(cast_stmt);
+
+        Operand::Consume(cast_tmp)
+    }
+
+    fn make_call_args(&self, args: Vec<Operand<'tcx>>,
+                      callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Vec<Operand<'tcx>> {
+        let tcx = self.tcx;
+        // FIXME: Analysis of the usage of the arguments to avoid
+        // unnecessary temporaries.
+        args.into_iter().map(|a| {
+            if let Operand::Consume(Lvalue::Local(local)) = a {
+                if caller_mir.local_kind(local) == LocalKind::Temp {
+                    // Reuse the operand if it's a temporary already
+                    return a;
+                }
+            }
+
+            debug!("Creating temp for argument");
+            // Otherwise, create a temporary for the arg
+            let arg = Rvalue::Use(a);
+
+            let ty = arg.ty(caller_mir, tcx);
+
+            let arg_tmp = LocalDecl::new_temp(ty);
+            let arg_tmp = caller_mir.local_decls.push(arg_tmp);
+            let arg_tmp = Lvalue::Local(arg_tmp);
+
+            let stmt = Statement {
+                source_info: callsite.location,
+                kind: StatementKind::Assign(arg_tmp.clone(), arg)
+            };
+            caller_mir[callsite.bb].statements.push(stmt);
+            Operand::Consume(arg_tmp)
+        }).collect()
+    }
+}
+
+fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParameterEnvironment<'tcx>,
+                          ty: Ty<'tcx>) -> Option<u64> {
+    tcx.infer_ctxt(param_env, traits::Reveal::All).enter(|infcx| {
+        ty.layout(&infcx).ok().map(|layout| {
+            layout.size(&tcx.data_layout).bytes()
+        })
+    })
+}
+
+/**
+ * Integrator.
+ *
+ * Integrates blocks from the callee function into the calling function.
+ * Updates block indices, references to locals and other control flow
+ * stuff.
+ */
+struct Integrator<'a, 'tcx: 'a> {
+    block_idx: usize,
+    args: &'a [Operand<'tcx>],
+    local_map: IndexVec<Local, Local>,
+    scope_map: IndexVec<VisibilityScope, VisibilityScope>,
+    promoted_map: IndexVec<Promoted, Promoted>,
+    _callsite: CallSite<'tcx>,
+    destination: Lvalue<'tcx>,
+    return_block: BasicBlock,
+    cleanup_block: Option<BasicBlock>,
+    in_cleanup_block: bool,
+}
+
+impl<'a, 'tcx> Integrator<'a, 'tcx> {
+    fn update_target(&self, tgt: BasicBlock) -> BasicBlock {
+        let new = BasicBlock::new(tgt.index() + self.block_idx);
+        debug!("Updating target `{:?}`, new: `{:?}`", tgt, new);
+        new
+    }
+
+    fn update_local(&self, local: Local) -> Option<Local> {
+        let idx = local.index();
+        if idx < (self.args.len() + 1) {
+            return None;
+        }
+        let idx = idx - (self.args.len() + 1);
+        let local = Local::new(idx);
+        self.local_map.get(local).cloned()
+    }
+
+    fn arg_index(&self, arg: Local) -> Option<usize> {
+        let idx = arg.index();
+        if idx > 0 && idx <= self.args.len() {
+            Some(idx - 1)
+        } else {
+            None
+        }
+    }
+}
+
+impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
+    fn visit_lvalue(&mut self,
+                    lvalue: &mut Lvalue<'tcx>,
+                    _ctxt: LvalueContext<'tcx>,
+                    _location: Location) {
+        if let Lvalue::Local(ref mut local) = *lvalue {
+            if let Some(l) = self.update_local(*local) {
+                // Temp or Var; update the local reference
+                *local = l;
+                return;
+            }
+        }
+        if let Lvalue::Local(local) = *lvalue {
+            if local == RETURN_POINTER {
+                // Return pointer; update the lvalue itself
+                *lvalue = self.destination.clone();
+            } else if local.index() < (self.args.len() + 1) {
+                // Argument, once again update the the lvalue itself
+                let idx = local.index() - 1;
+                if let Operand::Consume(ref lval) = self.args[idx] {
+                    *lvalue = lval.clone();
+                } else {
+                    bug!("Arg operand `{:?}` is not an Lvalue use.", idx)
+                }
+            }
+        } else {
+            self.super_lvalue(lvalue, _ctxt, _location)
+        }
+    }
+
+    fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
+        if let Operand::Consume(Lvalue::Local(arg)) = *operand {
+            if let Some(idx) = self.arg_index(arg) {
+                let new_arg = self.args[idx].clone();
+                *operand = new_arg;
+                return;
+            }
+        }
+        self.super_operand(operand, location);
+    }
+
+    fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) {
+        self.in_cleanup_block = data.is_cleanup;
+        self.super_basic_block_data(block, data);
+        self.in_cleanup_block = false;
+    }
+
+    fn visit_terminator_kind(&mut self, block: BasicBlock,
+                             kind: &mut TerminatorKind<'tcx>, loc: Location) {
+        self.super_terminator_kind(block, kind, loc);
+
+        match *kind {
+            TerminatorKind::Goto { ref mut target} => {
+                *target = self.update_target(*target);
+            }
+            TerminatorKind::SwitchInt { ref mut targets, .. } => {
+                for tgt in targets {
+                    *tgt = self.update_target(*tgt);
+                }
+            }
+            TerminatorKind::Drop { ref mut target, ref mut unwind, .. } |
+            TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => {
+                *target = self.update_target(*target);
+                if let Some(tgt) = *unwind {
+                    *unwind = Some(self.update_target(tgt));
+                } else if !self.in_cleanup_block {
+                    // Unless this drop is in a cleanup block, add an unwind edge to
+                    // the orignal call's cleanup block
+                    *unwind = self.cleanup_block;
+                }
+            }
+            TerminatorKind::Call { ref mut destination, ref mut cleanup, .. } => {
+                if let Some((_, ref mut tgt)) = *destination {
+                    *tgt = self.update_target(*tgt);
+                }
+                if let Some(tgt) = *cleanup {
+                    *cleanup = Some(self.update_target(tgt));
+                } else if !self.in_cleanup_block {
+                    // Unless this call is in a cleanup block, add an unwind edge to
+                    // the orignal call's cleanup block
+                    *cleanup = self.cleanup_block;
+                }
+            }
+            TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
+                *target = self.update_target(*target);
+                if let Some(tgt) = *cleanup {
+                    *cleanup = Some(self.update_target(tgt));
+                } else if !self.in_cleanup_block {
+                    // Unless this assert is in a cleanup block, add an unwind edge to
+                    // the orignal call's cleanup block
+                    *cleanup = self.cleanup_block;
+                }
+            }
+            TerminatorKind::Return => {
+                *kind = TerminatorKind::Goto { target: self.return_block };
+            }
+            TerminatorKind::Resume => {
+                if let Some(tgt) = self.cleanup_block {
+                    *kind = TerminatorKind::Goto { target: tgt }
+                }
+            }
+            TerminatorKind::Unreachable => { }
+        }
+    }
+
+    fn visit_visibility_scope(&mut self, scope: &mut VisibilityScope) {
+        *scope = self.scope_map[*scope];
+    }
+
+    fn visit_literal(&mut self, literal: &mut Literal<'tcx>, loc: Location) {
+        if let Literal::Promoted { ref mut index } = *literal {
+            if let Some(p) = self.promoted_map.get(*index).cloned() {
+                *index = p;
+            }
+        } else {
+            self.super_literal(literal, loc);
+        }
+    }
+}
index ae255f70fb78892ac21ca8e0e813427692053639..cbd054a72499b9adbdf5c044b7aa48f08a77f3b5 100644 (file)
@@ -20,3 +20,4 @@
 pub mod deaggregator;
 pub mod instcombine;
 pub mod copy_prop;
+pub mod inline;
index e93a412dc744fcb6ddb4f8ef9a16d957ec4733b6..a762507f35e7ecccdaf994db4667df34048b5266 100644 (file)
@@ -79,7 +79,7 @@ pub struct CfgSimplifier<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> {
-    fn new(mir: &'a mut Mir<'tcx>) -> Self {
+    pub fn new(mir: &'a mut Mir<'tcx>) -> Self {
         let mut pred_count = IndexVec::from_elem(0u32, mir.basic_blocks());
 
         // we can't use mir.predecessors() here because that counts
@@ -102,7 +102,7 @@ fn new(mir: &'a mut Mir<'tcx>) -> Self {
         }
     }
 
-    fn simplify(mut self) {
+    pub fn simplify(mut self) {
         loop {
             let mut changed = false;
 
@@ -137,6 +137,8 @@ fn simplify(mut self) {
 
             if !changed { break }
         }
+
+        self.strip_nops()
     }
 
     // Collapse a goto chain starting from `start`
@@ -231,9 +233,19 @@ fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>) -> bool {
         terminator.kind = TerminatorKind::Goto { target: first_succ };
         true
     }
+
+    fn strip_nops(&mut self) {
+        for blk in self.basic_blocks.iter_mut() {
+            blk.statements.retain(|stmt| if let StatementKind::Nop = stmt.kind {
+                false
+            } else {
+                true
+            })
+        }
+    }
 }
 
-fn remove_dead_blocks(mir: &mut Mir) {
+pub fn remove_dead_blocks(mir: &mut Mir) {
     let mut seen = BitVector::new(mir.basic_blocks().len());
     for (bb, _) in traversal::preorder(mir) {
         seen.insert(bb.index());
index 65a60732fc8074e423790ba73597b0e387316d64..749146fe49672a766c755e2fd02b180fbadf57cc 100644 (file)
@@ -375,9 +375,4 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'v ast::TypeBinding) {
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
         self.record("Attribute", Id::None, attr);
     }
-
-    fn visit_macro_def(&mut self, macro_def: &'v ast::MacroDef) {
-        self.record("MacroDef", Id::None, macro_def);
-        ast_visit::walk_macro_def(self, macro_def)
-    }
 }
index 3700d0295e9639dd50a7a08a85a3263a0d3c92f8..cdde56f5f634be75a2d0917a5a1885bf59606e2d 100644 (file)
@@ -13,8 +13,6 @@
 use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
 use rustc::session::Session;
 
-use rustc::mir::transform::MirMapPass;
-
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT, IdentTT};
 use syntax::ext::base::MacroExpanderFn;
 use syntax::symbol::Symbol;
@@ -53,9 +51,6 @@ pub struct Registry<'a> {
     #[doc(hidden)]
     pub late_lint_passes: Vec<LateLintPassObject>,
 
-    #[doc(hidden)]
-    pub mir_passes: Vec<Box<for<'pcx> MirMapPass<'pcx>>>,
-
     #[doc(hidden)]
     pub lint_groups: HashMap<&'static str, Vec<LintId>>,
 
@@ -81,7 +76,6 @@ pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
             lint_groups: HashMap::new(),
             llvm_passes: vec![],
             attributes: vec![],
-            mir_passes: Vec::new(),
             whitelisted_custom_derives: Vec::new(),
         }
     }
@@ -157,11 +151,6 @@ pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>
         self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
     }
 
-    /// Register a MIR pass
-    pub fn register_mir_pass(&mut self, pass: Box<for<'pcx> MirMapPass<'pcx>>) {
-        self.mir_passes.push(pass);
-    }
-
     /// Register an LLVM pass.
     ///
     /// Registration with LLVM itself is handled through static C++ objects with
index da08d1b7c78e2d1edf302f74bf26fb05a4e820ae..03c61067d64c20d44b2a7aebf412519f68739b8e 100644 (file)
@@ -37,7 +37,6 @@
 use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::Undetermined;
-use syntax::ext::expand::mark_tts;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::parse::token;
@@ -373,7 +372,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 self.define(parent, ident, TypeNS, (module, vis, sp, expansion));
                 self.current_module = module;
             }
-            ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
+            ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(),
         }
     }
 
@@ -493,6 +492,16 @@ fn get_extern_crate_root(&mut self, cnum: CrateNum) -> Module<'a> {
         })
     }
 
+    pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
+        let def_id = self.macro_defs[&expansion];
+        if let Some(id) = self.definitions.as_local_node_id(def_id) {
+            self.local_macro_def_scopes[&id]
+        } else {
+            let module_def_id = ty::DefIdTree::parent(&*self, def_id).unwrap();
+            self.get_extern_crate_root(module_def_id.krate)
+        }
+    }
+
     pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
         let def_id = match def {
             Def::Macro(def_id, ..) => def_id,
@@ -502,22 +511,12 @@ pub fn get_macro(&mut self, def: Def) -> Rc<SyntaxExtension> {
             return ext.clone();
         }
 
-        let mut macro_rules = match self.session.cstore.load_macro(def_id, &self.session) {
-            LoadedMacro::MacroRules(macro_rules) => macro_rules,
+        let macro_def = match self.session.cstore.load_macro(def_id, &self.session) {
+            LoadedMacro::MacroDef(macro_def) => macro_def,
             LoadedMacro::ProcMacro(ext) => return ext,
         };
 
-        let mark = Mark::fresh();
-        let invocation = self.arenas.alloc_invocation_data(InvocationData {
-            module: Cell::new(self.get_extern_crate_root(def_id.krate)),
-            def_index: CRATE_DEF_INDEX,
-            const_expr: false,
-            legacy_scope: Cell::new(LegacyScope::Empty),
-            expansion: Cell::new(LegacyScope::Empty),
-        });
-        self.invocations.insert(mark, invocation);
-        macro_rules.body = mark_tts(macro_rules.stream(), mark).into();
-        let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, &macro_rules));
+        let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, &macro_def));
         self.macro_map.insert(def_id, ext.clone());
         ext
     }
@@ -707,12 +706,12 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
 
     fn visit_item(&mut self, item: &'a Item) {
         let macro_use = match item.node {
-            ItemKind::Mac(ref mac) => {
-                if mac.node.path.segments.is_empty() {
-                    self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
-                } else {
-                    self.resolver.define_macro(item, &mut self.legacy_scope);
-                }
+            ItemKind::MacroDef(..) => {
+                self.resolver.define_macro(item, &mut self.legacy_scope);
+                return
+            }
+            ItemKind::Mac(..) => {
+                self.legacy_scope = LegacyScope::Expansion(self.visit_invoc(item.id));
                 return
             }
             ItemKind::Mod(..) => self.resolver.contains_macro_use(&item.attrs),
index d51ec268ec21788a19d972452343b4449af0c13d..104cc78597a4a501f89286355d633d99fc06fbfa 100644 (file)
@@ -407,7 +407,7 @@ enum PathSource<'a> {
     // Trait paths in bounds or impls.
     Trait,
     // Expression paths `path`, with optional parent context.
-    Expr(Option<&'a ExprKind>),
+    Expr(Option<&'a Expr>),
     // Paths in path patterns `Path`.
     Pat,
     // Paths in struct expressions and patterns `Path { .. }`.
@@ -464,7 +464,7 @@ fn descr_expected(self) -> &'static str {
                 ValueNS => "method or associated constant",
                 MacroNS => bug!("associated macro"),
             },
-            PathSource::Expr(parent) => match parent {
+            PathSource::Expr(parent) => match parent.map(|p| &p.node) {
                 // "function" here means "anything callable" rather than `Def::Fn`,
                 // this is not precise but usually more helpful than just "value".
                 Some(&ExprKind::Call(..)) => "function",
@@ -779,8 +779,8 @@ enum RibKind<'a> {
     // We passed through a module.
     ModuleRibKind(Module<'a>),
 
-    // We passed through a `macro_rules!` statement with the given expansion
-    MacroDefinition(Mark),
+    // We passed through a `macro_rules!` statement
+    MacroDefinition(DefId),
 
     // All bindings in this rib are type parameters that can't be used
     // from the default of a type parameter because they're not declared
@@ -997,14 +997,18 @@ fn def(&self) -> Def {
         }
     }
 
-    fn get_macro(&self, resolver: &mut Resolver<'a>) -> Rc<SyntaxExtension> {
+    fn def_ignoring_ambiguity(&self) -> Def {
         match self.kind {
-            NameBindingKind::Import { binding, .. } => binding.get_macro(resolver),
-            NameBindingKind::Ambiguity { b1, .. } => b1.get_macro(resolver),
-            _ => resolver.get_macro(self.def()),
+            NameBindingKind::Import { binding, .. } => binding.def_ignoring_ambiguity(),
+            NameBindingKind::Ambiguity { b1, .. } => b1.def_ignoring_ambiguity(),
+            _ => self.def(),
         }
     }
 
+    fn get_macro(&self, resolver: &mut Resolver<'a>) -> Rc<SyntaxExtension> {
+        resolver.get_macro(self.def_ignoring_ambiguity())
+    }
+
     // We sometimes need to treat variants as `pub` for backwards compatibility
     fn pseudo_vis(&self) -> ty::Visibility {
         if self.is_variant() { ty::Visibility::Public } else { self.vis }
@@ -1092,10 +1096,6 @@ pub struct Resolver<'a> {
 
     pub definitions: Definitions,
 
-    // Maps the node id of a statement to the expansions of the `macro_rules!`s
-    // immediately above the statement (if appropriate).
-    macros_at_scope: FxHashMap<NodeId, Vec<Mark>>,
-
     graph_root: Module<'a>,
 
     prelude: Option<Module<'a>>,
@@ -1171,12 +1171,13 @@ pub struct Resolver<'a> {
     dummy_binding: &'a NameBinding<'a>,
     use_extern_macros: bool, // true if `#![feature(use_extern_macros)]`
 
-    pub exported_macros: Vec<ast::MacroDef>,
     crate_loader: &'a mut CrateLoader,
     macro_names: FxHashSet<Name>,
     builtin_macros: FxHashMap<Name, &'a NameBinding<'a>>,
     lexical_macro_resolutions: Vec<(Name, &'a Cell<LegacyScope<'a>>)>,
     macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
+    macro_defs: FxHashMap<Mark, DefId>,
+    local_macro_def_scopes: FxHashMap<NodeId, Module<'a>>,
     macro_exports: Vec<Export>,
     pub whitelisted_legacy_custom_derives: Vec<Name>,
     pub found_unresolved_macro: bool,
@@ -1305,11 +1306,13 @@ pub fn new(session: &'a Session,
 
         let features = session.features.borrow();
 
+        let mut macro_defs = FxHashMap();
+        macro_defs.insert(Mark::root(), root_def_id);
+
         Resolver {
             session: session,
 
             definitions: definitions,
-            macros_at_scope: FxHashMap(),
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
@@ -1365,7 +1368,6 @@ pub fn new(session: &'a Session,
             // `#![feature(proc_macro)]` implies `#[feature(extern_macros)]`
             use_extern_macros: features.use_extern_macros || features.proc_macro,
 
-            exported_macros: Vec::new(),
             crate_loader: crate_loader,
             macro_names: FxHashSet(),
             builtin_macros: FxHashMap(),
@@ -1373,6 +1375,8 @@ pub fn new(session: &'a Session,
             macro_map: FxHashMap(),
             macro_exports: Vec::new(),
             invocations: invocations,
+            macro_defs: macro_defs,
+            local_macro_def_scopes: FxHashMap(),
             name_already_seen: FxHashMap(),
             whitelisted_legacy_custom_derives: Vec::new(),
             proc_macro_enabled: features.proc_macro,
@@ -1510,12 +1514,12 @@ fn resolve_ident_in_lexical_scope(&mut self,
                 }
             }
 
-            if let MacroDefinition(mac) = self.ribs[ns][i].kind {
+            if let MacroDefinition(def) = self.ribs[ns][i].kind {
                 // If an invocation of this macro created `ident`, give up on `ident`
                 // and switch to `ident`'s source from the macro definition.
-                let (source_ctxt, source_macro) = ident.ctxt.source();
-                if source_macro == mac {
-                    ident.ctxt = source_ctxt;
+                let ctxt_data = ident.ctxt.data();
+                if def == self.macro_defs[&ctxt_data.outer_mark] {
+                    ident.ctxt = ctxt_data.prev_ctxt;
                 }
             }
         }
@@ -1523,11 +1527,12 @@ fn resolve_ident_in_lexical_scope(&mut self,
         None
     }
 
-    fn resolve_crate_var(&mut self, mut crate_var_ctxt: SyntaxContext) -> Module<'a> {
-        while crate_var_ctxt.source().0 != SyntaxContext::empty() {
-            crate_var_ctxt = crate_var_ctxt.source().0;
+    fn resolve_crate_var(&mut self, crate_var_ctxt: SyntaxContext) -> Module<'a> {
+        let mut ctxt_data = crate_var_ctxt.data();
+        while ctxt_data.prev_ctxt != SyntaxContext::empty() {
+            ctxt_data = ctxt_data.prev_ctxt.data();
         }
-        let module = self.invocations[&crate_var_ctxt.source().1].module.get();
+        let module = self.macro_def_scope(ctxt_data.outer_mark);
         if module.is_local() { self.graph_root } else { module }
     }
 
@@ -1579,12 +1584,12 @@ fn search_label(&self, mut ident: Ident) -> Option<Def> {
                 NormalRibKind => {
                     // Continue
                 }
-                MacroDefinition(mac) => {
+                MacroDefinition(def) => {
                     // If an invocation of this macro created `ident`, give up on `ident`
                     // and switch to `ident`'s source from the macro definition.
-                    let (source_ctxt, source_macro) = ident.ctxt.source();
-                    if source_macro == mac {
-                        ident.ctxt = source_ctxt;
+                    let ctxt_data = ident.ctxt.data();
+                    if def == self.macro_defs[&ctxt_data.outer_mark] {
+                        ident.ctxt = ctxt_data.prev_ctxt;
                     }
                 }
                 _ => {
@@ -1696,7 +1701,7 @@ fn resolve_item(&mut self, item: &Item) {
                 }
             }
 
-            ItemKind::ExternCrate(_) => {
+            ItemKind::ExternCrate(_) | ItemKind::MacroDef(..) => {
                 // do nothing, these are just around to be encoded
             }
 
@@ -2031,11 +2036,12 @@ fn resolve_block(&mut self, block: &Block) {
 
         // Descend into the block.
         for stmt in &block.stmts {
-            if let Some(marks) = self.macros_at_scope.remove(&stmt.id) {
-                num_macro_definition_ribs += marks.len() as u32;
-                for mark in marks {
-                    self.ribs[ValueNS].push(Rib::new(MacroDefinition(mark)));
-                    self.label_ribs.push(Rib::new(MacroDefinition(mark)));
+            if let ast::StmtKind::Item(ref item) = stmt.node {
+                if let ast::ItemKind::MacroDef(..) = item.node {
+                    num_macro_definition_ribs += 1;
+                    let def = self.definitions.local_def_id(item.id);
+                    self.ribs[ValueNS].push(Rib::new(MacroDefinition(def)));
+                    self.label_ribs.push(Rib::new(MacroDefinition(def)));
                 }
             }
 
@@ -2194,7 +2200,8 @@ fn smart_resolve_path(&mut self,
                           source: PathSource)
                           -> PathResolution {
         let segments = &path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
-        self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
+        let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
+        self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
     }
 
     fn smart_resolve_path_fragment(&mut self,
@@ -2202,6 +2209,7 @@ fn smart_resolve_path_fragment(&mut self,
                                    qself: Option<&QSelf>,
                                    path: &[Ident],
                                    span: Span,
+                                   ident_span: Span,
                                    source: PathSource)
                                    -> PathResolution {
         let ns = source.namespace();
@@ -2213,9 +2221,9 @@ fn smart_resolve_path_fragment(&mut self,
             let expected = source.descr_expected();
             let path_str = names_to_string(path);
             let code = source.error_code(def.is_some());
-            let (base_msg, fallback_label) = if let Some(def) = def {
+            let (base_msg, fallback_label, base_span) = if let Some(def) = def {
                 (format!("expected {}, found {} `{}`", expected, def.kind_name(), path_str),
-                 format!("not a {}", expected))
+                 format!("not a {}", expected), span)
             } else {
                 let item_str = path[path.len() - 1];
                 let (mod_prefix, mod_str) = if path.len() == 1 {
@@ -2231,9 +2239,9 @@ fn smart_resolve_path_fragment(&mut self,
                     (mod_prefix, format!("`{}`", names_to_string(mod_path)))
                 };
                 (format!("cannot find {} `{}` in {}{}", expected, item_str, mod_prefix, mod_str),
-                 format!("not found in {}", mod_str))
+                 format!("not found in {}", mod_str), ident_span)
             };
-            let mut err = this.session.struct_span_err_with_code(span, &base_msg, code);
+            let mut err = this.session.struct_span_err_with_code(base_span, &base_msg, code);
 
             // Emit special messages for unresolved `Self` and `self`.
             if is_self_type(path, ns) {
@@ -2291,15 +2299,15 @@ fn smart_resolve_path_fragment(&mut self,
                         err.span_label(span, &format!("type aliases cannot be used for traits"));
                         return err;
                     }
-                    (Def::Mod(..), PathSource::Expr(Some(parent))) => match *parent {
+                    (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
                         ExprKind::Field(_, ident) => {
-                            err.span_label(span, &format!("did you mean `{}::{}`?",
-                                                           path_str, ident.node));
+                            err.span_label(parent.span, &format!("did you mean `{}::{}`?",
+                                                                 path_str, ident.node));
                             return err;
                         }
                         ExprKind::MethodCall(ident, ..) => {
-                            err.span_label(span, &format!("did you mean `{}::{}(...)`?",
-                                                           path_str, ident.node));
+                            err.span_label(parent.span, &format!("did you mean `{}::{}(...)`?",
+                                                                 path_str, ident.node));
                             return err;
                         }
                         _ => {}
@@ -2324,12 +2332,12 @@ fn smart_resolve_path_fragment(&mut self,
 
             // Try Levenshtein if nothing else worked.
             if let Some(candidate) = this.lookup_typo_candidate(path, ns, is_expected) {
-                err.span_label(span, &format!("did you mean `{}`?", candidate));
+                err.span_label(ident_span, &format!("did you mean `{}`?", candidate));
                 return err;
             }
 
             // Fallback label.
-            err.span_label(span, &fallback_label);
+            err.span_label(base_span, &fallback_label);
             err
         };
         let report_errors = |this: &mut Self, def: Option<Def>| {
@@ -2449,7 +2457,7 @@ fn resolve_qpath(&mut self,
             // Make sure `A::B` in `<T as A>::B::C` is a trait item.
             let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
             let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
-                                                       span, PathSource::TraitItem(ns));
+                                                       span, span, PathSource::TraitItem(ns));
             return Some(PathResolution::with_unresolved_segments(
                 res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
             ));
@@ -2807,7 +2815,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
                                        path: &[Ident],
                                        ns: Namespace,
                                        filter_fn: FilterFn)
-                                       -> Option<String>
+                                       -> Option<Symbol>
         where FilterFn: Fn(Def) -> bool
     {
         let add_module_candidates = |module: Module, names: &mut Vec<Name>| {
@@ -2821,7 +2829,7 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
         };
 
         let mut names = Vec::new();
-        let prefix_str = if path.len() == 1 {
+        if path.len() == 1 {
             // Search in lexical scope.
             // Walk backwards up the ribs in scope and collect candidates.
             for rib in self.ribs[ns].iter().rev() {
@@ -2855,21 +2863,19 @@ fn lookup_typo_candidate<FilterFn>(&mut self,
                     names.push(*name);
                 }
             }
-            String::new()
         } else {
             // Search in module.
             let mod_path = &path[..path.len() - 1];
             if let PathResult::Module(module) = self.resolve_path(mod_path, Some(TypeNS), None) {
                 add_module_candidates(module, &mut names);
             }
-            names_to_string(mod_path) + "::"
-        };
+        }
 
         let name = path[path.len() - 1].name;
         // Make sure error reporting is deterministic.
         names.sort_by_key(|name| name.as_str());
         match find_best_match_for_name(names.iter(), &name.as_str(), None) {
-            Some(found) if found != name => Some(format!("{}{}", prefix_str, found)),
+            Some(found) if found != name => Some(found),
             _ => None,
         }
     }
@@ -2892,7 +2898,7 @@ fn resolve_labeled_block(&mut self, label: Option<SpannedIdent>, id: NodeId, blo
         self.with_resolved_label(label, id, |this| this.visit_block(block));
     }
 
-    fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
+    fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
         // First, record candidate traits for this expression if it could
         // result in the invocation of a method call.
 
@@ -2973,11 +2979,11 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
 
             // Equivalent to `visit::walk_expr` + passing some context to children.
             ExprKind::Field(ref subexpression, _) => {
-                self.resolve_expr(subexpression, Some(&expr.node));
+                self.resolve_expr(subexpression, Some(expr));
             }
             ExprKind::MethodCall(_, ref types, ref arguments) => {
                 let mut arguments = arguments.iter();
-                self.resolve_expr(arguments.next().unwrap(), Some(&expr.node));
+                self.resolve_expr(arguments.next().unwrap(), Some(expr));
                 for argument in arguments {
                     self.resolve_expr(argument, None);
                 }
@@ -2993,7 +2999,7 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&ExprKind>) {
                 });
             }
             ExprKind::Call(ref callee, ref arguments) => {
-                self.resolve_expr(callee, Some(&expr.node));
+                self.resolve_expr(callee, Some(expr));
                 for argument in arguments {
                     self.resolve_expr(argument, None);
                 }
@@ -3124,11 +3130,10 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                 if ident.name == lookup_name && ns == namespace {
                     if filter_fn(name_binding.def()) {
                         // create the path
-                        let span = name_binding.span;
                         let mut segms = path_segments.clone();
-                        segms.push(ident.into());
+                        segms.push(ast::PathSegment::from_ident(ident, name_binding.span));
                         let path = Path {
-                            span: span,
+                            span: name_binding.span,
                             segments: segms,
                         };
                         // the entity is accessible in the following cases:
@@ -3148,7 +3153,7 @@ fn lookup_import_candidates<FilterFn>(&mut self,
                 if let Some(module) = name_binding.module() {
                     // form the path
                     let mut path_segments = path_segments.clone();
-                    path_segments.push(ident.into());
+                    path_segments.push(ast::PathSegment::from_ident(ident, name_binding.span));
 
                     if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
                         // add the module to the lookup
index 720d616e007d21ea5f6fc1d974756ea744bbca4e..dbdf3a0b21e691119a593de08a0e566ba1c0cd55 100644 (file)
 use rustc::hir::def::{Def, Export};
 use rustc::hir::map::{self, DefCollector};
 use rustc::ty;
-use std::cell::Cell;
-use std::rc::Rc;
 use syntax::ast::{self, Name, Ident};
-use syntax::attr;
+use syntax::attr::{self, HasAttrs};
 use syntax::errors::DiagnosticBuilder;
-use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
-use syntax::ext::base::{Resolver as SyntaxResolver, SyntaxExtension};
-use syntax::ext::base::MacroKind;
-use syntax::ext::expand::{Expansion, mark_tts};
+use syntax::ext::base::{self, Annotatable, Determinacy, MultiModifier, MultiDecorator};
+use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
+use syntax::ext::expand::{Expansion, ExpansionKind, Invocation, InvocationKind, find_attr_invoc};
 use syntax::ext::hygiene::Mark;
+use syntax::ext::placeholders::placeholder;
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{self, emit_feature_err, GateIssue};
 use syntax::fold::{self, Folder};
 use syntax::ptr::P;
 use syntax::symbol::{Symbol, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
-use syntax::visit::Visitor;
 use syntax_pos::{Span, DUMMY_SP};
 
+use std::cell::Cell;
+use std::mem;
+use std::rc::Rc;
+
 #[derive(Clone)]
 pub struct InvocationData<'a> {
     pub module: Cell<Module<'a>>,
@@ -73,7 +74,7 @@ pub enum LegacyScope<'a> {
 pub struct LegacyBinding<'a> {
     pub parent: Cell<LegacyScope<'a>>,
     pub name: ast::Name,
-    ext: Rc<SyntaxExtension>,
+    def_id: DefId,
     pub span: Span,
 }
 
@@ -110,8 +111,11 @@ fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
                     path.segments[0].identifier.name = keywords::CrateRoot.name();
                     let module = self.0.resolve_crate_var(ident.ctxt);
                     if !module.is_local() {
+                        let span = path.segments[0].span;
                         path.segments.insert(1, match module.kind {
-                            ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name).into(),
+                            ModuleKind::Def(_, name) => ast::PathSegment::from_ident(
+                                ast::Ident::with_empty_ctxt(name), span
+                            ),
                             _ => unreachable!(),
                         })
                     }
@@ -151,7 +155,7 @@ fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark
         invocation.expansion.set(visitor.legacy_scope);
     }
 
-    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
+    fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         let def_id = DefId {
             krate: BUILTIN_MACROS_CRATE,
             index: DefIndex::new(self.macro_map.len()),
@@ -167,10 +171,6 @@ fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>) {
         self.builtin_macros.insert(ident.name, binding);
     }
 
-    fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>) {
-        self.macros_at_scope.insert(id, macros);
-    }
-
     fn resolve_imports(&mut self) {
         ImportResolver { resolver: self }.resolve_imports()
     }
@@ -240,8 +240,83 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
         None
     }
 
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
-                     force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
+    fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
+                     -> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
+        let def = match invoc.kind {
+            InvocationKind::Attr { attr: None, .. } => return Ok(None),
+            _ => match self.resolve_invoc_to_def(invoc, scope, force) {
+                Ok(def) => def,
+                Err(determinacy) => return Err(determinacy),
+            },
+        };
+        self.macro_defs.insert(invoc.expansion_data.mark, def.def_id());
+        Ok(Some(self.get_macro(def)))
+    }
+
+    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
+                     -> Result<Rc<SyntaxExtension>, Determinacy> {
+        self.resolve_macro_to_def(scope, path, kind, force).map(|def| self.get_macro(def))
+    }
+}
+
+impl<'a> Resolver<'a> {
+    fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
+                            -> Result<Def, Determinacy> {
+        let (attr, traits, item) = match invoc.kind {
+            InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
+            InvocationKind::Bang { ref mac, .. } => {
+                return self.resolve_macro_to_def(scope, &mac.node.path, MacroKind::Bang, force);
+            }
+            InvocationKind::Derive { name, span, .. } => {
+                let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
+                return self.resolve_macro_to_def(scope, &path, MacroKind::Derive, force);
+            }
+        };
+
+        let (attr_name, path) = {
+            let attr = attr.as_ref().unwrap();
+            (attr.name(), ast::Path::from_ident(attr.span, Ident::with_empty_ctxt(attr.name())))
+        };
+
+        let mut determined = true;
+        match self.resolve_macro_to_def(scope, &path, MacroKind::Attr, force) {
+            Ok(def) => return Ok(def),
+            Err(Determinacy::Undetermined) => determined = false,
+            Err(Determinacy::Determined) if force => return Err(Determinacy::Determined),
+            Err(Determinacy::Determined) => {}
+        }
+
+        for &(name, span) in traits {
+            let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
+            match self.resolve_macro(scope, &path, MacroKind::Derive, force) {
+                Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
+                    if inert_attrs.contains(&attr_name) {
+                        // FIXME(jseyfried) Avoid `mem::replace` here.
+                        let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
+                            .make_items().pop().unwrap();
+                        let dummy_item = Annotatable::Item(dummy_item);
+                        *item = mem::replace(item, dummy_item).map_attrs(|mut attrs| {
+                            let inert_attr = attr.take().unwrap();
+                            attr::mark_known(&inert_attr);
+                            if self.proc_macro_enabled {
+                                *attr = find_attr_invoc(&mut attrs);
+                            }
+                            attrs.push(inert_attr);
+                            attrs
+                        });
+                    }
+                    return Err(Determinacy::Undetermined);
+                },
+                Err(Determinacy::Undetermined) => determined = false,
+                Err(Determinacy::Determined) => {}
+            }
+        }
+
+        Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined })
+    }
+
+    fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
+                            -> Result<Def, Determinacy> {
         let ast::Path { ref segments, span } = *path;
         if segments.iter().any(|segment| segment.parameters.is_some()) {
             let kind =
@@ -264,10 +339,10 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
                 return Err(Determinacy::Determined);
             }
 
-            let ext = match self.resolve_path(&path, Some(MacroNS), None) {
+            let def = match self.resolve_path(&path, Some(MacroNS), None) {
                 PathResult::NonModule(path_res) => match path_res.base_def() {
                     Def::Err => Err(Determinacy::Determined),
-                    def @ _ => Ok(self.get_macro(def)),
+                    def @ _ => Ok(def),
                 },
                 PathResult::Module(..) => unreachable!(),
                 PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
@@ -278,15 +353,15 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
             };
             self.current_module.macro_resolutions.borrow_mut()
                 .push((path.into_boxed_slice(), span));
-            return ext;
+            return def;
         }
 
         let name = path[0].name;
         let result = match self.resolve_legacy_scope(&invocation.legacy_scope, name, false) {
-            Some(MacroBinding::Legacy(binding)) => Ok(binding.ext.clone()),
-            Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)),
+            Some(MacroBinding::Legacy(binding)) => Ok(Def::Macro(binding.def_id, MacroKind::Bang)),
+            Some(MacroBinding::Modern(binding)) => Ok(binding.def_ignoring_ambiguity()),
             None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
-                Ok(binding) => Ok(binding.get_macro(self)),
+                Ok(binding) => Ok(binding.def_ignoring_ambiguity()),
                 Err(Determinacy::Undetermined) if !force =>
                     return Err(Determinacy::Undetermined),
                 Err(_) => {
@@ -301,9 +376,7 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
 
         result
     }
-}
 
-impl<'a> Resolver<'a> {
     // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
     pub fn resolve_lexical_macro_path_segment(&mut self,
                                               ident: Ident,
@@ -499,7 +572,6 @@ fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
             };
             let ident = Ident::from_str(name);
             self.lookup_typo_candidate(&vec![ident], MacroNS, is_macro)
-                .as_ref().map(|s| Symbol::intern(s))
         });
 
         if let Some(suggestion) = suggestion {
@@ -544,45 +616,23 @@ fn collect_def_ids(&mut self, invocation: &'a InvocationData<'a>, expansion: &Ex
     }
 
     pub fn define_macro(&mut self, item: &ast::Item, legacy_scope: &mut LegacyScope<'a>) {
-        let tts = match item.node {
-            ast::ItemKind::Mac(ref mac) => mac.node.stream(),
-            _ => unreachable!(),
-        };
-
-        if item.ident.name == "macro_rules" {
+        self.local_macro_def_scopes.insert(item.id, self.current_module);
+        let ident = item.ident;
+        if ident.name == "macro_rules" {
             self.session.span_err(item.span, "user-defined macros may not be named `macro_rules`");
         }
 
-        let mark = Mark::from_placeholder_id(item.id);
-        let invocation = self.invocations[&mark];
-        invocation.module.set(self.current_module);
-
-        let mut def = ast::MacroDef {
-            ident: item.ident,
-            attrs: item.attrs.clone(),
-            id: ast::DUMMY_NODE_ID,
-            span: item.span,
-            body: mark_tts(tts, mark).into(),
-        };
-
+        let def_id = self.definitions.local_def_id(item.id);
+        let ext = Rc::new(macro_rules::compile(&self.session.parse_sess, item));
+        self.macro_map.insert(def_id, ext);
         *legacy_scope = LegacyScope::Binding(self.arenas.alloc_legacy_binding(LegacyBinding {
-            parent: Cell::new(*legacy_scope),
-            name: def.ident.name,
-            ext: Rc::new(macro_rules::compile(&self.session.parse_sess, &def)),
-            span: def.span,
+            parent: Cell::new(*legacy_scope), name: ident.name, def_id: def_id, span: item.span,
         }));
-        self.macro_names.insert(def.ident.name);
+        self.macro_names.insert(ident.name);
 
-        if attr::contains_name(&def.attrs, "macro_export") {
-            def.id = self.next_node_id();
-            DefCollector::new(&mut self.definitions).with_parent(CRATE_DEF_INDEX, |collector| {
-                collector.visit_macro_def(&def)
-            });
-            self.macro_exports.push(Export {
-                name: def.ident.name,
-                def: Def::Macro(self.definitions.local_def_id(def.id), MacroKind::Bang),
-            });
-            self.exported_macros.push(def);
+        if attr::contains_name(&item.attrs, "macro_export") {
+            let def = Def::Macro(def_id, MacroKind::Bang);
+            self.macro_exports.push(Export { name: ident.name, def: def });
         }
     }
 
index 0a6281bf8c54ccaf4357f956fc97844fe136a41d..6caf81380e40dad51f8c33c1d90a51c7dd5f7065 100644 (file)
@@ -15,7 +15,7 @@
 
 use rustc::hir;
 use rustc::hir::def_id::{CrateNum, DefId};
-use syntax::ast::{self, NodeId};
+use syntax::ast::{self, Attribute, NodeId};
 use syntax_pos::Span;
 
 pub struct CrateData {
@@ -136,6 +136,7 @@ pub struct EnumData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for extern crates.
@@ -171,6 +172,7 @@ pub struct FunctionData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data about a function call.
@@ -256,6 +258,7 @@ pub struct MethodData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for modules.
@@ -271,6 +274,7 @@ pub struct ModData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for a reference to a module.
@@ -295,6 +299,7 @@ pub struct StructData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -309,6 +314,7 @@ pub struct StructVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -323,6 +329,7 @@ pub struct TraitData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -337,6 +344,7 @@ pub struct TupleVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for a typedef.
@@ -351,6 +359,7 @@ pub struct TypeDefData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 /// Data for a reference to a type or trait.
@@ -396,6 +405,7 @@ pub struct VariableData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
index 3c275e0996dac0c3877c693f5bad6a7763cf0274..61956e5cd9d66e4abfd1e411e7b30d1a7ccfedf8 100644 (file)
@@ -327,6 +327,9 @@ fn process_def_kind(&mut self,
                     scope: scope
                 }.lower(self.tcx));
             }
+            // With macros 2.0, we can legitimately get a ref to a macro, but
+            // we don't handle it properly for now (FIXME).
+            Def::Macro(..) => {}
             Def::Local(..) |
             Def::Upvar(..) |
             Def::SelfTy(..) |
@@ -336,7 +339,6 @@ fn process_def_kind(&mut self,
             Def::AssociatedTy(..) |
             Def::AssociatedConst(..) |
             Def::PrimTy(_) |
-            Def::Macro(..) |
             Def::Err => {
                span_bug!(span,
                          "process_def_kind for unexpected item: {:?}",
@@ -373,6 +375,7 @@ fn process_formals(&mut self, formals: &'l [ast::Arg], qualname: &str) {
                         visibility: Visibility::Inherited,
                         docs: String::new(),
                         sig: None,
+                        attributes: vec![],
                     }.lower(self.tcx));
                 }
             }
@@ -448,6 +451,7 @@ fn process_method(&mut self,
                     visibility: vis,
                     docs: docs_for_attrs(attrs),
                     sig: method_data.sig,
+                    attributes: attrs.to_vec(),
                 }.lower(self.tcx));
             }
 
@@ -519,6 +523,7 @@ fn process_generic_params(&mut self,
                     parent: None,
                     docs: String::new(),
                     sig: None,
+                    attributes: vec![],
                 }.lower(self.tcx));
             }
         }
@@ -592,6 +597,7 @@ fn process_assoc_const(&mut self,
                 visibility: vis,
                 docs: docs_for_attrs(attrs),
                 sig: None,
+                attributes: attrs.to_vec(),
             }.lower(self.tcx));
         }
 
@@ -636,6 +642,7 @@ fn process_struct(&mut self,
                 visibility: From::from(&item.vis),
                 docs: docs_for_attrs(&item.attrs),
                 sig: self.save_ctxt.sig_base(item),
+                attributes: item.attrs.clone(),
             }.lower(self.tcx));
         }
 
@@ -701,6 +708,7 @@ fn process_enum(&mut self,
                             parent: Some(make_def_id(item.id, &self.tcx.hir)),
                             docs: docs_for_attrs(&variant.node.attrs),
                             sig: sig,
+                            attributes: variant.node.attrs.clone(),
                         }.lower(self.tcx));
                     }
                 }
@@ -727,6 +735,7 @@ fn process_enum(&mut self,
                             parent: Some(make_def_id(item.id, &self.tcx.hir)),
                             docs: docs_for_attrs(&variant.node.attrs),
                             sig: sig,
+                            attributes: variant.node.attrs.clone(),
                         }.lower(self.tcx));
                     }
                 }
@@ -798,6 +807,7 @@ fn process_trait(&mut self,
                 visibility: From::from(&item.vis),
                 docs: docs_for_attrs(&item.attrs),
                 sig: self.save_ctxt.sig_base(item),
+                attributes: item.attrs.clone(),
             }.lower(self.tcx));
         }
 
@@ -1064,6 +1074,7 @@ fn process_var_decl(&mut self, p: &'l ast::Pat, value: String) {
                     visibility: Visibility::Inherited,
                     docs: String::new(),
                     sig: None,
+                    attributes: vec![],
                 }.lower(self.tcx));
             }
         }
@@ -1305,6 +1316,7 @@ fn visit_item(&mut self, item: &'l ast::Item) {
                         parent: None,
                         docs: docs_for_attrs(&item.attrs),
                         sig: Some(self.save_ctxt.sig_base(item)),
+                        attributes: item.attrs.clone(),
                     }.lower(self.tcx));
                 }
 
@@ -1527,6 +1539,7 @@ fn visit_arm(&mut self, arm: &'l ast::Arm) {
                             visibility: Visibility::Inherited,
                             docs: String::new(),
                             sig: None,
+                            attributes: vec![],
                         }.lower(self.tcx));
                     }
                 }
index fccb56e88b3de801a55eb08a7e77f6f175b072e2..41658dc5b1b48b043b9faf344768803a1db2b52b 100644 (file)
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex};
 use rustc::hir::map::Map;
 use rustc::ty::TyCtxt;
-use syntax::ast::NodeId;
+use syntax::ast::{self, NodeId};
 use syntax::codemap::CodeMap;
+use syntax::print::pprust;
+use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 use data::{self, Visibility, SigElement};
@@ -64,6 +66,39 @@ pub fn from_span(span: Span, cm: &CodeMap) -> SpanData {
     }
 }
 
+/// Represent an arbitrary attribute on a code element
+#[derive(Clone, Debug, RustcEncodable)]
+pub struct Attribute {
+    value: String,
+    span: SpanData,
+}
+
+impl Lower for Vec<ast::Attribute> {
+    type Target = Vec<Attribute>;
+
+    fn lower(self, tcx: TyCtxt) -> Vec<Attribute> {
+        let doc = Symbol::intern("doc");
+        self.into_iter()
+        // Only retain real attributes. Doc comments are lowered separately.
+        .filter(|attr| attr.name() != doc)
+        .map(|mut attr| {
+            // Remove the surrounding '#[..]' or '#![..]' of the pretty printed
+            // attribute. First normalize all inner attribute (#![..]) to outer
+            // ones (#[..]), then remove the two leading and the one trailing character.
+            attr.style = ast::AttrStyle::Outer;
+            let value = pprust::attribute_to_string(&attr);
+            // This str slicing works correctly, because the leading and trailing characters
+            // are in the ASCII range and thus exactly one byte each.
+            let value = value[2..value.len()-1].to_string();
+
+            Attribute {
+                value: value,
+                span: SpanData::from_span(attr.span, tcx.sess.codemap()),
+            }
+        }).collect()
+    }
+}
+
 #[derive(Debug, RustcEncodable)]
 pub struct CratePreludeData {
     pub crate_name: String,
@@ -98,6 +133,7 @@ pub struct EnumData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::EnumData {
@@ -115,6 +151,7 @@ fn lower(self, tcx: TyCtxt) -> EnumData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -179,6 +216,7 @@ pub struct FunctionData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::FunctionData {
@@ -197,6 +235,7 @@ fn lower(self, tcx: TyCtxt) -> FunctionData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -346,6 +385,7 @@ pub struct MethodData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::MethodData {
@@ -364,6 +404,7 @@ fn lower(self, tcx: TyCtxt) -> MethodData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -381,6 +422,7 @@ pub struct ModData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::ModData {
@@ -398,6 +440,7 @@ fn lower(self, tcx: TyCtxt) -> ModData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -437,6 +480,7 @@ pub struct StructData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::StructData {
@@ -455,6 +499,7 @@ fn lower(self, tcx: TyCtxt) -> StructData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -471,6 +516,7 @@ pub struct StructVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::StructVariantData {
@@ -488,6 +534,7 @@ fn lower(self, tcx: TyCtxt) -> StructVariantData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -504,6 +551,7 @@ pub struct TraitData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::TraitData {
@@ -521,6 +569,7 @@ fn lower(self, tcx: TyCtxt) -> TraitData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -537,6 +586,7 @@ pub struct TupleVariantData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Signature,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::TupleVariantData {
@@ -554,6 +604,7 @@ fn lower(self, tcx: TyCtxt) -> TupleVariantData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.lower(tcx),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -570,6 +621,7 @@ pub struct TypeDefData {
     pub parent: Option<DefId>,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::TypeDefData {
@@ -586,6 +638,7 @@ fn lower(self, tcx: TyCtxt) -> TypeDefData {
             parent: self.parent,
             docs: self.docs,
             sig: self.sig.map(|s| s.lower(tcx)),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
@@ -675,6 +728,7 @@ pub struct VariableData {
     pub visibility: Visibility,
     pub docs: String,
     pub sig: Option<Signature>,
+    pub attributes: Vec<Attribute>,
 }
 
 impl Lower for data::VariableData {
@@ -694,6 +748,7 @@ fn lower(self, tcx: TyCtxt) -> VariableData {
             visibility: self.visibility,
             docs: self.docs,
             sig: self.sig.map(|s| s.lower(tcx)),
+            attributes: self.attributes.lower(tcx),
         }
     }
 }
index 09752994290c9c3490ec0ec4f1a4397c98740992..1b72489f83c67da2d611710b757001966994c3f5 100644 (file)
@@ -87,6 +87,7 @@ fn mod_data(&mut self, data: ModData) {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         };
         if def.span.file_name != def.value {
             // If the module is an out-of-line defintion, then we'll make the
@@ -232,6 +233,7 @@ struct Def {
     decl_id: Option<Id>,
     docs: String,
     sig: Option<JsonSignature>,
+    attributes: Vec<Attribute>,
 }
 
 #[derive(Debug, RustcEncodable)]
@@ -274,6 +276,7 @@ fn from(data: EnumData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -291,6 +294,7 @@ fn from(data: TupleVariantData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -307,6 +311,7 @@ fn from(data: StructVariantData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -323,6 +328,7 @@ fn from(data: StructData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -339,6 +345,7 @@ fn from(data: TraitData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -355,6 +362,7 @@ fn from(data: FunctionData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -371,6 +379,7 @@ fn from(data: MethodData) -> Def {
             decl_id: data.decl_id.map(|id| From::from(id)),
             docs: data.docs,
             sig: Some(From::from(data.sig)),
+            attributes: data.attributes,
         }
     }
 }
@@ -387,6 +396,7 @@ fn from(data: MacroData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: None,
+            attributes: vec![],
         }
     }
 }
@@ -403,6 +413,7 @@ fn from(data: TypeDefData) -> Def {
             decl_id: None,
             docs: String::new(),
             sig: data.sig.map(|s| From::from(s)),
+            attributes: data.attributes,
         }
     }
 }
@@ -424,6 +435,7 @@ fn from(data: VariableData) -> Def {
             decl_id: None,
             docs: data.docs,
             sig: None,
+            attributes: data.attributes,
         }
     }
 }
index b1e435dcc751c40b1bdff58ed027eb1f212f1a84..111c8370be2b1ca2582c113537cf006cd8cc6c59 100644 (file)
@@ -136,6 +136,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     parent: None,
                     docs: docs_for_attrs(&item.attrs),
                     sig: self.sig_base(item),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Static(ref typ, mt, ref expr) => {
@@ -164,6 +165,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: Some(self.sig_base(item)),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Const(ref typ, ref expr) => {
@@ -183,6 +185,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: Some(self.sig_base(item)),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Mod(ref m) => {
@@ -205,6 +208,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: self.sig_base(item),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Enum(ref def, _) => {
@@ -228,6 +232,7 @@ pub fn get_item_data(&self, item: &ast::Item) -> Option<Data> {
                     visibility: From::from(&item.vis),
                     docs: docs_for_attrs(&item.attrs),
                     sig: self.sig_base(item),
+                    attributes: item.attrs.clone(),
                 }))
             }
             ast::ItemKind::Impl(.., ref trait_ref, ref typ, _) => {
@@ -315,6 +320,7 @@ pub fn get_field_data(&self,
                 visibility: From::from(&field.vis),
                 docs: docs_for_attrs(&field.attrs),
                 sig: Some(sig),
+                attributes: field.attrs.clone(),
             })
         } else {
             None
@@ -327,7 +333,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
                            name: ast::Name, span: Span) -> Option<FunctionData> {
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
-        let (qualname, parent_scope, decl_id, vis, docs) =
+        let (qualname, parent_scope, decl_id, vis, docs, attributes) =
           match self.tcx.impl_of_method(self.tcx.hir.local_def_id(id)) {
             Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
                 Some(Node::NodeItem(item)) => {
@@ -349,7 +355,8 @@ pub fn get_method_data(&self, id: ast::NodeId,
 
                             (result, trait_id, decl_id,
                              From::from(&item.vis),
-                             docs_for_attrs(&item.attrs))
+                             docs_for_attrs(&item.attrs),
+                             item.attrs.to_vec())
                         }
                         _ => {
                             span_bug!(span,
@@ -374,7 +381,8 @@ pub fn get_method_data(&self, id: ast::NodeId,
                             (format!("::{}", self.tcx.item_path_str(def_id)),
                              Some(def_id), None,
                              From::from(&item.vis),
-                             docs_for_attrs(&item.attrs))
+                             docs_for_attrs(&item.attrs),
+                             item.attrs.to_vec())
                         }
                         r => {
                             span_bug!(span,
@@ -387,7 +395,10 @@ pub fn get_method_data(&self, id: ast::NodeId,
                     }
                 }
                 None => {
-                    span_bug!(span, "Could not find container for method {}", id);
+                    debug!("Could not find container for method {} at {:?}", id, span);
+                    // This is not necessarily a bug, if there was a compilation error, the tables
+                    // we need might not exist.
+                    return None;
                 }
             },
         };
@@ -423,6 +434,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
             parent: parent_scope,
             docs: docs,
             sig: sig,
+            attributes: attributes,
         })
     }
 
index b58f96033bf5b5dc2404c31657ac89dda25ea00e..a1703b1c155eb0535410d5002c3221c070721b40 100644 (file)
@@ -752,8 +752,54 @@ fn link_natively(sess: &Session,
     sess.abort_if_errors();
 
     // Invoke the system linker
+    //
+    // Note that there's a terribly awful hack that really shouldn't be present
+    // in any compiler. Here an environment variable is supported to
+    // automatically retry the linker invocation if the linker looks like it
+    // segfaulted.
+    //
+    // Gee that seems odd, normally segfaults are things we want to know about!
+    // Unfortunately though in rust-lang/rust#38878 we're experiencing the
+    // linker segfaulting on Travis quite a bit which is causing quite a bit of
+    // pain to land PRs when they spuriously fail due to a segfault.
+    //
+    // The issue #38878 has some more debugging information on it as well, but
+    // this unfortunately looks like it's just a race condition in OSX's linker
+    // with some thread pool working in the background. It seems that no one
+    // currently knows a fix for this so in the meantime we're left with this...
     info!("{:?}", &cmd);
-    let prog = time(sess.time_passes(), "running linker", || cmd.output());
+    let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
+    let mut prog;
+    let mut i = 0;
+    loop {
+        i += 1;
+        prog = time(sess.time_passes(), "running linker", || cmd.output());
+        if !retry_on_segfault || i > 3 {
+            break
+        }
+        let output = match prog {
+            Ok(ref output) => output,
+            Err(_) => break,
+        };
+        if output.status.success() {
+            break
+        }
+        let mut out = output.stderr.clone();
+        out.extend(&output.stdout);
+        let out = String::from_utf8_lossy(&out);
+        let msg = "clang: error: unable to execute command: \
+                   Segmentation fault: 11";
+        if !out.contains(msg) {
+            break
+        }
+
+        sess.struct_warn("looks like the linker segfaulted when we tried to \
+                          call it, automatically retrying again")
+            .note(&format!("{:?}", cmd))
+            .note(&out)
+            .emit();
+    }
+
     match prog {
         Ok(prog) => {
             fn escape_string(s: &[u8]) -> String {
index 36f6fa764390929a6647ca0880e217e817d8c302..1b43491e73c8f420e6efafcb5c308e46483ad2fa 100644 (file)
@@ -41,7 +41,7 @@
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::dep_graph::{DepNode, WorkProduct};
+use rustc::dep_graph::{AssertDepGraphSafe, DepNode, WorkProduct};
 use rustc::hir::map as hir_map;
 use rustc::util::common::time;
 use session::config::{self, NoDebugInfo};
@@ -1211,21 +1211,40 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Instantiate translation items without filling out definitions yet...
     for ccx in crate_context_list.iter_need_trans() {
-        let cgu = ccx.codegen_unit();
-        let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
-
-        tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+        let dep_node = ccx.codegen_unit().work_product_dep_node();
+        tcx.dep_graph.with_task(dep_node,
+                                ccx,
+                                AssertDepGraphSafe(symbol_map.clone()),
+                                trans_decl_task);
+
+        fn trans_decl_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
+                                     symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>) {
+            // FIXME(#40304): Instead of this, the symbol-map should be an
+            // on-demand thing that we compute.
+            let AssertDepGraphSafe(symbol_map) = symbol_map;
+            let cgu = ccx.codegen_unit();
+            let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
             for (trans_item, linkage) in trans_items {
                 trans_item.predefine(&ccx, linkage);
             }
-        });
+        }
     }
 
     // ... and now that we have everything pre-defined, fill out those definitions.
     for ccx in crate_context_list.iter_need_trans() {
-        let cgu = ccx.codegen_unit();
-        let trans_items = cgu.items_in_deterministic_order(tcx, &symbol_map);
-        tcx.dep_graph.with_task(cgu.work_product_dep_node(), || {
+        let dep_node = ccx.codegen_unit().work_product_dep_node();
+        tcx.dep_graph.with_task(dep_node,
+                                ccx,
+                                AssertDepGraphSafe(symbol_map.clone()),
+                                trans_def_task);
+
+        fn trans_def_task<'a, 'tcx>(ccx: CrateContext<'a, 'tcx>,
+                                    symbol_map: AssertDepGraphSafe<Rc<SymbolMap<'tcx>>>) {
+            // FIXME(#40304): Instead of this, the symbol-map should be an
+            // on-demand thing that we compute.
+            let AssertDepGraphSafe(symbol_map) = symbol_map;
+            let cgu = ccx.codegen_unit();
+            let trans_items = cgu.items_in_deterministic_order(ccx.tcx(), &symbol_map);
             for (trans_item, _) in trans_items {
                 trans_item.define(&ccx);
             }
@@ -1247,7 +1266,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             if ccx.sess().opts.debuginfo != NoDebugInfo {
                 debuginfo::finalize(&ccx);
             }
-        });
+        }
     }
 
     symbol_names_test::report_symbol_names(&shared_ccx);
index d5f7549ece07b21134587e71f1c9fd10a55084be..52851ea995d4b7c42edd769695931a5fc707a064 100644 (file)
@@ -10,7 +10,8 @@
 
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef};
-use rustc::dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig, WorkProduct};
+use rustc::dep_graph::{DepGraph, DepGraphSafe, DepNode, DepTrackingMap,
+                       DepTrackingMapConfig, WorkProduct};
 use middle::cstore::LinkMeta;
 use rustc::hir;
 use rustc::hir::def::ExportMap;
@@ -274,6 +275,9 @@ pub struct CrateContext<'a, 'tcx: 'a> {
     index: usize,
 }
 
+impl<'a, 'tcx> DepGraphSafe for CrateContext<'a, 'tcx> {
+}
+
 pub struct CrateContextIterator<'a, 'tcx: 'a> {
     shared: &'a SharedCrateContext<'a, 'tcx>,
     local_ccxs: &'a [LocalCrateContext<'tcx>],
index 34d8c6500b9263d325bb3251cff8202a9904caf4..9d40419d338b8a50b2a2f5322b897dd61314885b 100644 (file)
@@ -833,8 +833,21 @@ fn make_return_dest(&mut self, bcx: &Builder<'a, 'tcx>,
             self.trans_lvalue(bcx, dest)
         };
         if fn_ret_ty.is_indirect() {
-            llargs.push(dest.llval);
-            ReturnDest::Nothing
+            match dest.alignment {
+                Alignment::AbiAligned => {
+                    llargs.push(dest.llval);
+                    ReturnDest::Nothing
+                },
+                Alignment::Packed => {
+                    // Currently, MIR code generation does not create calls
+                    // that store directly to fields of packed structs (in
+                    // fact, the calls it creates write only to temps),
+                    //
+                    // If someone changes that, please update this code path
+                    // to create a temporary.
+                    span_bug!(self.mir.span, "can't directly store to unaligned value");
+                }
+            }
         } else {
             ReturnDest::Store(dest.llval)
         }
index cb77fcbbff85dbea7f015394b73f77cc494d202f..3f29545ecf45a16c2bf8c59607503ce69a903322 100644 (file)
@@ -268,10 +268,17 @@ pub fn store_operand(&mut self,
                 bcx.store(base::from_immediate(bcx, s), lldest, align);
             }
             OperandValue::Pair(a, b) => {
+                let f_align = match *bcx.ccx.layout_of(operand.ty) {
+                    Layout::Univariant { ref variant, .. } if variant.packed => {
+                        Some(1)
+                    }
+                    _ => align
+                };
+
                 let a = base::from_immediate(bcx, a);
                 let b = base::from_immediate(bcx, b);
-                bcx.store(a, bcx.struct_gep(lldest, 0), align);
-                bcx.store(b, bcx.struct_gep(lldest, 1), align);
+                bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
+                bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
             }
         }
     }
index ca0ab8f1e8c7742b4310816e7a1a6efdc6125430..1aab4853a4f641f6efd096c191365258b75d46c9 100644 (file)
@@ -12,6 +12,7 @@
 
 use super::FnCtxt;
 
+use rustc::infer::InferOk;
 use rustc::traits;
 use rustc::ty::{self, Ty, TraitRef};
 use rustc::ty::{ToPredicate, TypeFoldable};
@@ -149,6 +150,14 @@ pub fn maybe_ambiguous_final_ty(&self) -> Ty<'tcx> {
 
     pub fn finalize<'b, I>(self, pref: LvaluePreference, exprs: I)
         where I: IntoIterator<Item = &'b hir::Expr>
+    {
+        let fcx = self.fcx;
+        fcx.register_infer_ok_obligations(self.finalize_as_infer_ok(pref, exprs));
+    }
+
+    pub fn finalize_as_infer_ok<'b, I>(self, pref: LvaluePreference, exprs: I)
+                                       -> InferOk<'tcx, ()>
+        where I: IntoIterator<Item = &'b hir::Expr>
     {
         let methods: Vec<_> = self.steps
             .iter()
@@ -176,8 +185,9 @@ pub fn finalize<'b, I>(self, pref: LvaluePreference, exprs: I)
             }
         }
 
-        for obligation in self.obligations {
-            self.fcx.register_predicate(obligation);
+        InferOk {
+            value: (),
+            obligations: self.obligations
         }
     }
 }
index 53759cc115d1cb69039a9473cdb2fc04c5b1446b..c43291557f7fa4034959ac0f2fb1eb06a89c03ac 100644 (file)
@@ -64,7 +64,8 @@
 
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::infer::{Coercion, InferOk, TypeTrace};
+use rustc::infer::{Coercion, InferResult, InferOk, TypeTrace};
+use rustc::infer::type_variable::TypeVariableOrigin;
 use rustc::traits::{self, ObligationCause, ObligationCauseCode};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow};
 use rustc::ty::{self, LvaluePreference, TypeAndMut,
@@ -75,9 +76,7 @@
 use rustc::ty::subst::Subst;
 use syntax::abi;
 use syntax::feature_gate;
-use util::common::indent;
 
-use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::ops::Deref;
 
@@ -85,7 +84,6 @@ struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     cause: ObligationCause<'tcx>,
     use_lub: bool,
-    unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
 }
 
 impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> {
@@ -95,7 +93,7 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, Adjust<'tcx>)>;
+type CoerceResult<'tcx> = InferResult<'tcx, Adjustment<'tcx>>;
 
 fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
                        to_mutbl: hir::Mutability)
@@ -108,44 +106,53 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
     }
 }
 
+fn identity<'tcx>() -> Adjust<'tcx> {
+    Adjust::DerefRef {
+        autoderefs: 0,
+        autoref: None,
+        unsize: false,
+    }
+}
+
+fn success<'tcx>(kind: Adjust<'tcx>,
+                 target: Ty<'tcx>,
+                 obligations: traits::PredicateObligations<'tcx>)
+                 -> CoerceResult<'tcx> {
+    Ok(InferOk {
+        value: Adjustment {
+            kind,
+            target
+        },
+        obligations
+    })
+}
+
 impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
     fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self {
         Coerce {
             fcx: fcx,
             cause: cause,
             use_lub: false,
-            unsizing_obligations: RefCell::new(vec![]),
         }
     }
 
-    fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+    fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
         self.commit_if_ok(|_| {
             let trace = TypeTrace::types(&self.cause, false, a, b);
             if self.use_lub {
                 self.lub(false, trace, &a, &b)
-                    .map(|ok| self.register_infer_ok_obligations(ok))
             } else {
                 self.sub(false, trace, &a, &b)
-                    .map(|InferOk { value, obligations }| {
-                        self.fcx.register_predicates(obligations);
-                        value
-                    })
             }
         })
     }
 
-    /// Unify two types (using sub or lub) and produce a noop coercion.
-    fn unify_and_identity(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
-        self.unify(&a, &b).and_then(|ty| self.identity(ty))
-    }
-
-    /// Synthesize an identity adjustment.
-    fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> {
-        Ok((ty, Adjust::DerefRef {
-            autoderefs: 0,
-            autoref: None,
-            unsize: false,
-        }))
+    /// Unify two types (using sub or lub) and produce a specific coercion.
+    fn unify_and(&self, a: Ty<'tcx>, b: Ty<'tcx>, kind: Adjust<'tcx>)
+                 -> CoerceResult<'tcx> {
+        self.unify(&a, &b).and_then(|InferOk { value: ty, obligations }| {
+            success(kind, ty, obligations)
+        })
     }
 
     fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx>
@@ -158,11 +165,11 @@ fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<
 
         // Just ignore error types.
         if a.references_error() || b.references_error() {
-            return self.identity(b);
+            return success(identity(), b, vec![]);
         }
 
         if a.is_never() {
-            return Ok((b, Adjust::NeverToAny));
+            return success(Adjust::NeverToAny, b, vec![]);
         }
 
         // Consider coercing the subtype to a DST
@@ -208,7 +215,7 @@ fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<
             }
             _ => {
                 // Otherwise, just use unification rules.
-                self.unify_and_identity(a, b)
+                self.unify_and(a, b, identity())
             }
         }
     }
@@ -240,7 +247,7 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
                 coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?;
                 (r_a, mt_a)
             }
-            _ => return self.unify_and_identity(a, b),
+            _ => return self.unify_and(a, b, identity()),
         };
 
         let span = self.cause.span;
@@ -248,7 +255,7 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
         let mut first_error = None;
         let mut r_borrow_var = None;
         let mut autoderef = self.autoderef(span, a);
-        let mut success = None;
+        let mut found = None;
 
         for (referent_ty, autoderefs) in autoderef.by_ref() {
             if autoderefs == 0 {
@@ -346,8 +353,8 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
                                                   mutbl: mt_b.mutbl, // [1] above
                                               });
             match self.unify(derefd_ty_a, b) {
-                Ok(ty) => {
-                    success = Some((ty, autoderefs));
+                Ok(ok) => {
+                    found = Some((ok, autoderefs));
                     break;
                 }
                 Err(err) => {
@@ -363,7 +370,7 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
         // (e.g., in example above, the failure from relating `Vec<T>`
         // to the target type), since that should be the least
         // confusing.
-        let (ty, autoderefs) = match success {
+        let (InferOk { value: ty, mut obligations }, autoderefs) = match found {
             Some(d) => d,
             None => {
                 let err = first_error.expect("coerce_borrowed_pointer had no error");
@@ -372,12 +379,6 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
             }
         };
 
-        // This commits the obligations to the fulfillcx. After this succeeds,
-        // this snapshot can't be rolled back.
-        autoderef.finalize(LvaluePreference::from_mutbl(mt_b.mutbl), exprs());
-
-        // Now apply the autoref. We have to extract the region out of
-        // the final ref type we got.
         if ty == a && mt_a.mutbl == hir::MutImmutable && autoderefs == 1 {
             // As a special case, if we would produce `&'a *x`, that's
             // a total no-op. We end up with the type `&'a T` just as
@@ -391,8 +392,11 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
             // `self.x`, but we auto-coerce it to `foo(&mut *self.x)`,
             // which is a borrow.
             assert_eq!(mt_b.mutbl, hir::MutImmutable); // can only coerce &T -> &U
-            return self.identity(ty);
+            return success(identity(), ty, obligations);
         }
+
+        // Now apply the autoref. We have to extract the region out of
+        // the final ref type we got.
         let r_borrow = match ty.sty {
             ty::TyRef(r_borrow, _) => r_borrow,
             _ => span_bug!(span, "expected a ref type, got {:?}", ty),
@@ -402,11 +406,15 @@ fn coerce_borrowed_pointer<'a, E, I>(&self,
                ty,
                autoderefs,
                autoref);
-        Ok((ty, Adjust::DerefRef {
+
+        let pref = LvaluePreference::from_mutbl(mt_b.mutbl);
+        obligations.extend(autoderef.finalize_as_infer_ok(pref, exprs()).obligations);
+
+        success(Adjust::DerefRef {
             autoderefs: autoderefs,
             autoref: autoref,
             unsize: false,
-        }))
+        }, ty, obligations)
     }
 
 
@@ -445,18 +453,32 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
             }
             _ => (source, None),
         };
-        let source = source.adjust_for_autoref(self.tcx, reborrow);
+        let coerce_source = source.adjust_for_autoref(self.tcx, reborrow);
+
+        let adjust = Adjust::DerefRef {
+            autoderefs: if reborrow.is_some() { 1 } else { 0 },
+            autoref: reborrow,
+            unsize: true,
+        };
+
+        // Setup either a subtyping or a LUB relationship between
+        // the `CoerceUnsized` target type and the expected type.
+        // We only have the latter, so we use an inference variable
+        // for the former and let type inference do the rest.
+        let origin = TypeVariableOrigin::MiscVariable(self.cause.span);
+        let coerce_target = self.next_ty_var(origin);
+        let mut coercion = self.unify_and(coerce_target, target, adjust)?;
 
         let mut selcx = traits::SelectionContext::new(self);
 
         // Use a FIFO queue for this custom fulfillment procedure.
         let mut queue = VecDeque::new();
-        let mut leftover_predicates = vec![];
 
         // Create an obligation for `Source: CoerceUnsized<Target>`.
         let cause = ObligationCause::misc(self.cause.span, self.body_id);
         queue.push_back(self.tcx
-            .predicate_for_trait_def(cause, coerce_unsized_did, 0, source, &[target]));
+            .predicate_for_trait_def(cause, coerce_unsized_did, 0,
+                                     coerce_source, &[coerce_target]));
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -467,7 +489,7 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
             let trait_ref = match obligation.predicate {
                 ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => tr.clone(),
                 _ => {
-                    leftover_predicates.push(obligation);
+                    coercion.obligations.push(obligation);
                     continue;
                 }
             };
@@ -495,33 +517,26 @@ fn coerce_unsized(&self, source: Ty<'tcx>, target: Ty<'tcx>) -> CoerceResult<'tc
             }
         }
 
-        *self.unsizing_obligations.borrow_mut() = leftover_predicates;
-
-        let adjustment = Adjust::DerefRef {
-            autoderefs: if reborrow.is_some() { 1 } else { 0 },
-            autoref: reborrow,
-            unsize: true,
-        };
-        debug!("Success, coerced with {:?}", adjustment);
-        Ok((target, adjustment))
+        Ok(coercion)
     }
 
     fn coerce_from_safe_fn(&self,
                            a: Ty<'tcx>,
                            fn_ty_a: ty::PolyFnSig<'tcx>,
-                           b: Ty<'tcx>)
+                           b: Ty<'tcx>,
+                           to_unsafe: Adjust<'tcx>,
+                           normal: Adjust<'tcx>)
                            -> CoerceResult<'tcx> {
         if let ty::TyFnPtr(fn_ty_b) = b.sty {
             match (fn_ty_a.unsafety(), fn_ty_b.unsafety()) {
                 (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => {
                     let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a);
-                    return self.unify_and_identity(unsafe_a, b)
-                        .map(|(ty, _)| (ty, Adjust::UnsafeFnPointer));
+                    return self.unify_and(unsafe_a, b, to_unsafe);
                 }
                 _ => {}
             }
         }
-        self.unify_and_identity(a, b)
+        self.unify_and(a, b, normal)
     }
 
     fn coerce_from_fn_pointer(&self,
@@ -536,7 +551,8 @@ fn coerce_from_fn_pointer(&self,
         let b = self.shallow_resolve(b);
         debug!("coerce_from_fn_pointer(a={:?}, b={:?})", a, b);
 
-        self.coerce_from_safe_fn(a, fn_ty_a, b)
+        self.coerce_from_safe_fn(a, fn_ty_a, b,
+            Adjust::UnsafeFnPointer, identity())
     }
 
     fn coerce_from_fn_item(&self,
@@ -554,10 +570,10 @@ fn coerce_from_fn_item(&self,
         match b.sty {
             ty::TyFnPtr(_) => {
                 let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a);
-                self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b)
-                    .map(|(ty, _)| (ty, Adjust::ReifyFnPointer))
+                self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b,
+                    Adjust::ReifyFnPointer, Adjust::ReifyFnPointer)
             }
-            _ => self.unify_and_identity(a, b),
+            _ => self.unify_and(a, b, identity()),
         }
     }
 
@@ -582,7 +598,7 @@ fn coerce_closure_to_fn(&self,
                                                    self.cause.span,
                                                    feature_gate::GateIssue::Language,
                                                    feature_gate::CLOSURE_TO_FN_COERCION);
-                    return self.unify_and_identity(a, b);
+                    return self.unify_and(a, b, identity());
                 }
                 // We coerce the closure, which has fn type
                 //     `extern "rust-call" fn((arg0,arg1,...)) -> _`
@@ -607,10 +623,9 @@ fn coerce_closure_to_fn(&self,
                 let pointer_ty = self.tcx.mk_fn_ptr(converted_sig);
                 debug!("coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})",
                        a, b, pointer_ty);
-                self.unify_and_identity(pointer_ty, b)
-                    .map(|(ty, _)| (ty, Adjust::ClosureFnPointer))
+                self.unify_and(pointer_ty, b, Adjust::ClosureFnPointer)
             }
-            _ => self.unify_and_identity(a, b),
+            _ => self.unify_and(a, b, identity()),
         }
     }
 
@@ -625,7 +640,7 @@ fn coerce_unsafe_ptr(&self,
             ty::TyRef(_, mt) => (true, mt),
             ty::TyRawPtr(mt) => (false, mt),
             _ => {
-                return self.unify_and_identity(a, b);
+                return self.unify_and(a, b, identity());
             }
         };
 
@@ -634,50 +649,22 @@ fn coerce_unsafe_ptr(&self,
             mutbl: mutbl_b,
             ty: mt_a.ty,
         });
-        let (ty, noop) = self.unify_and_identity(a_unsafe, b)?;
         coerce_mutbls(mt_a.mutbl, mutbl_b)?;
-
         // Although references and unsafe ptrs have the same
         // representation, we still register an Adjust::DerefRef so that
         // regionck knows that the region for `a` must be valid here.
-        Ok((ty,
-            if is_ref {
-                Adjust::DerefRef {
-                    autoderefs: 1,
-                    autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
-                    unsize: false,
-                }
-            } else if mt_a.mutbl != mutbl_b {
-                Adjust::MutToConstPointer
-            } else {
-                noop
-            }))
-    }
-}
-
-fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
-                                   exprs: &E,
-                                   a: Ty<'tcx>,
-                                   b: Ty<'tcx>)
-                                   -> RelateResult<'tcx, Adjustment<'tcx>>
-    where E: Fn() -> I,
-          I: IntoIterator<Item = &'b hir::Expr>
-{
-
-    let (ty, adjust) = indent(|| coerce.coerce(exprs, a, b))?;
-
-    let fcx = coerce.fcx;
-    if let Adjust::DerefRef { unsize: true, .. } = adjust {
-        let mut obligations = coerce.unsizing_obligations.borrow_mut();
-        for obligation in obligations.drain(..) {
-            fcx.register_predicate(obligation);
-        }
+        self.unify_and(a_unsafe, b, if is_ref {
+            Adjust::DerefRef {
+                autoderefs: 1,
+                autoref: Some(AutoBorrow::RawPtr(mutbl_b)),
+                unsize: false,
+            }
+        } else if mt_a.mutbl != mutbl_b {
+            Adjust::MutToConstPointer
+        } else {
+            identity()
+        })
     }
-
-    Ok(Adjustment {
-        kind: adjust,
-        target: ty
-    })
 }
 
 impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
@@ -694,9 +681,10 @@ pub fn try_coerce(&self,
         debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target);
 
         let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable);
-        let mut coerce = Coerce::new(self, cause);
+        let coerce = Coerce::new(self, cause);
         self.commit_if_ok(|_| {
-            let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?;
+            let ok = coerce.coerce(&|| Some(expr), source, target)?;
+            let adjustment = self.register_infer_ok_obligations(ok);
             if !adjustment.is_identity() {
                 debug!("Success, coerced with {:?}", adjustment);
                 match self.tables.borrow().adjustments.get(&expr.id) {
@@ -773,9 +761,10 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
         // but only if the new expression has no coercion already applied to it.
         let mut first_error = None;
         if !self.tables.borrow().adjustments.contains_key(&new.id) {
-            let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty));
+            let result = self.commit_if_ok(|_| coerce.coerce(&|| Some(new), new_ty, prev_ty));
             match result {
-                Ok(adjustment) => {
+                Ok(ok) => {
+                    let adjustment = self.register_infer_ok_obligations(ok);
                     if !adjustment.is_identity() {
                         self.write_adjustment(new.id, adjustment);
                     }
@@ -816,7 +805,7 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
             }
         }
 
-        match self.commit_if_ok(|_| apply(&mut coerce, &exprs, prev_ty, new_ty)) {
+        match self.commit_if_ok(|_| coerce.coerce(&exprs, prev_ty, new_ty)) {
             Err(_) => {
                 // Avoid giving strange errors on failed attempts.
                 if let Some(e) = first_error {
@@ -828,7 +817,8 @@ pub fn try_find_coercion_lub<'b, E, I>(&self,
                     })
                 }
             }
-            Ok(adjustment) => {
+            Ok(ok) => {
+                let adjustment = self.register_infer_ok_obligations(ok);
                 if !adjustment.is_identity() {
                     let mut tables = self.tables.borrow_mut();
                     for expr in exprs() {
index 2b9ccf6d3e246c666e0eabf9c9d812638324313f..5a582a523ea1c910a6c52102b4104b2ec352ccfc 100644 (file)
@@ -539,13 +539,15 @@ pub fn check_item_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult
 }
 
 pub fn check_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> CompileResult {
-    tcx.sess.track_errors(|| {
-        tcx.dep_graph.with_task(DepNode::TypeckBodiesKrate, || {
-            tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
-                tcx.item_tables(body_owner_def_id);
-            });
+    return tcx.sess.track_errors(|| {
+        tcx.dep_graph.with_task(DepNode::TypeckBodiesKrate, tcx, (), check_item_bodies_task);
+    });
+
+    fn check_item_bodies_task<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (): ()) {
+        tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
+            tcx.item_tables(body_owner_def_id);
         });
-    })
+    }
 }
 
 pub fn provide(providers: &mut Providers) {
index db7cf3c000ba4cae91f45e0567edf4b9b4423365..2417745571910b3c848b213ff12d57f696b358d4 100644 (file)
@@ -165,15 +165,10 @@ impl<'a, 'tcx> CollectItemTypesVisitor<'a, 'tcx> {
     /// 4. This is added by the code in `visit_expr` when we write to `item_types`.
     /// 5. This is added by the code in `convert_item` when we write to `item_types`;
     ///    note that this write occurs inside the `CollectItemSig` task.
-    /// 6. Added by explicit `read` below
-    fn with_collect_item_sig<OP>(&self, id: ast::NodeId, op: OP)
-        where OP: FnOnce()
-    {
+    /// 6. Added by reads from within `op`.
+    fn with_collect_item_sig(&self, id: ast::NodeId, op: fn(TyCtxt<'a, 'tcx, 'tcx>, ast::NodeId)) {
         let def_id = self.tcx.hir.local_def_id(id);
-        self.tcx.dep_graph.with_task(DepNode::CollectItemSig(def_id), || {
-            self.tcx.hir.read(id);
-            op();
-        });
+        self.tcx.dep_graph.with_task(DepNode::CollectItemSig(def_id), self.tcx, id, op);
     }
 }
 
@@ -183,7 +178,7 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_item(&mut self, item: &'tcx hir::Item) {
-        self.with_collect_item_sig(item.id, || convert_item(self.tcx, item));
+        self.with_collect_item_sig(item.id, convert_item);
         intravisit::walk_item(self, item);
     }
 
@@ -216,16 +211,12 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
     }
 
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) {
-        self.with_collect_item_sig(trait_item.id, || {
-            convert_trait_item(self.tcx, trait_item)
-        });
+        self.with_collect_item_sig(trait_item.id, convert_trait_item);
         intravisit::walk_trait_item(self, trait_item);
     }
 
     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
-        self.with_collect_item_sig(impl_item.id, || {
-            convert_impl_item(self.tcx, impl_item)
-        });
+        self.with_collect_item_sig(impl_item.id, convert_impl_item);
         intravisit::walk_impl_item(self, impl_item);
     }
 }
@@ -493,9 +484,10 @@ fn ensure_no_ty_param_bounds(tcx: TyCtxt,
     }
 }
 
-fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) {
+fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_id: ast::NodeId) {
+    let it = tcx.hir.expect_item(item_id);
     debug!("convert: item {} with id {}", it.name, it.id);
-    let def_id = tcx.hir.local_def_id(it.id);
+    let def_id = tcx.hir.local_def_id(item_id);
     match it.node {
         // These don't define types.
         hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => {
@@ -560,7 +552,8 @@ fn convert_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::Item) {
     }
 }
 
-fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item: &hir::TraitItem) {
+fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item_id: ast::NodeId) {
+    let trait_item = tcx.hir.expect_trait_item(trait_item_id);
     let def_id = tcx.hir.local_def_id(trait_item.id);
     tcx.item_generics(def_id);
 
@@ -577,8 +570,8 @@ fn convert_trait_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_item: &hir::T
     tcx.item_predicates(def_id);
 }
 
-fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item: &hir::ImplItem) {
-    let def_id = tcx.hir.local_def_id(impl_item.id);
+fn convert_impl_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl_item_id: ast::NodeId) {
+    let def_id = tcx.hir.local_def_id(impl_item_id);
     tcx.item_generics(def_id);
     tcx.item_type(def_id);
     tcx.item_predicates(def_id);
index 23507dc889b710be084cb53985f9575d7ba87dc3..fc5507d4d5559cde8ddc306560265c9bf8fe92d9 100644 (file)
@@ -442,7 +442,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec<String>)> {
 /// Used when rendering a `ResolvedPath` structure. This invokes the `path`
 /// rendering function with the necessary arguments for linking to a local path.
 fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
-                 print_all: bool, use_absolute: bool) -> fmt::Result {
+                 print_all: bool, use_absolute: bool, is_not_debug: bool) -> fmt::Result {
     let last = path.segments.last().unwrap();
     let rel_root = match &*path.segments[0].name {
         "self" => Some("./".to_string()),
@@ -459,10 +459,14 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
                     } else {
                         root.push_str(&seg.name);
                         root.push_str("/");
-                        write!(w, "<a class=\"mod\"
-                                       href=\"{}index.html\">{}</a>::",
-                                 root,
-                                 seg.name)?;
+                        if is_not_debug {
+                            write!(w, "<a class=\"mod\"
+                                           href=\"{}index.html\">{}</a>::",
+                                     root,
+                                     seg.name)?;
+                        } else {
+                            write!(w, "{}::", seg.name)?;
+                        }
                     }
                 }
             }
@@ -474,19 +478,37 @@ fn resolved_path(w: &mut fmt::Formatter, did: DefId, path: &clean::Path,
         }
     }
     if w.alternate() {
-        write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
+        if is_not_debug {
+            write!(w, "{:#}{:#}", HRef::new(did, &last.name), last.params)?;
+        } else {
+            write!(w, "{:?}{:?}", HRef::new(did, &last.name), last.params)?;
+        }
     } else {
-        let path = if use_absolute {
-            match href(did) {
-                Some((_, _, fqp)) => format!("{}::{}",
-                                             fqp[..fqp.len()-1].join("::"),
-                                             HRef::new(did, fqp.last().unwrap())),
-                None => format!("{}", HRef::new(did, &last.name)),
-            }
+        if is_not_debug {
+            let path = if use_absolute {
+                match href(did) {
+                    Some((_, _, fqp)) => format!("{}::{}",
+                                                 fqp[..fqp.len()-1].join("::"),
+                                                 HRef::new(did, fqp.last().unwrap())),
+                    None => format!("{}", HRef::new(did, &last.name)),
+                }
+            } else {
+                format!("{}", HRef::new(did, &last.name))
+            };
+            write!(w, "{}{}", path, last.params)?;
         } else {
-            format!("{}", HRef::new(did, &last.name))
-        };
-        write!(w, "{}{}", path, last.params)?;
+            let path = if use_absolute {
+                match href(did) {
+                    Some((_, _, fqp)) => format!("{:?}::{:?}",
+                                                 fqp[..fqp.len()-1].join("::"),
+                                                 HRef::new(did, fqp.last().unwrap())),
+                    None => format!("{:?}", HRef::new(did, &last.name)),
+                }
+            } else {
+                format!("{:?}", HRef::new(did, &last.name))
+            };
+            write!(w, "{}{:?}", path, last.params)?;
+        }
     }
     Ok(())
 }
@@ -570,6 +592,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl<'a> fmt::Debug for HRef<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.text)
+    }
+}
+
 fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool,
             is_not_debug: bool) -> fmt::Result {
     match *t {
@@ -578,7 +606,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool,
         }
         clean::ResolvedPath{ did, ref typarams, ref path, is_generic } => {
             // Paths like T::Output and Self::Output should be rendered with all segments
-            resolved_path(f, did, path, is_generic, use_absolute)?;
+            resolved_path(f, did, path, is_generic, use_absolute, is_not_debug)?;
             tybounds(f, typarams)
         }
         clean::Infer => write!(f, "_"),
@@ -767,7 +795,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool,
                 write!(f, "{}::", self_type)?;
             }
             let path = clean::Path::singleton(name.clone());
-            resolved_path(f, did, &path, true, use_absolute)?;
+            resolved_path(f, did, &path, true, use_absolute, is_not_debug)?;
 
             // FIXME: `typarams` are not rendered, and this seems bad?
             drop(typarams);
@@ -1051,7 +1079,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl fmt::Display for clean::ImportSource {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self.did {
-            Some(did) => resolved_path(f, did, &self.path, true, false),
+            Some(did) => resolved_path(f, did, &self.path, true, false, true),
             _ => {
                 for (i, seg) in self.path.segments.iter().enumerate() {
                     if i > 0 {
index 44f71d8952985b0098e482d561dad83d960969da..c571bcb08e4b7fc3c0c3e2d9758c2998c73029fa 100644 (file)
@@ -763,7 +763,7 @@ fn collect(path: &Path, krate: &str,
             // going on). If they're in different crates then the crate defining
             // the trait will be interested in our implementation.
             if imp.def_id.krate == did.krate { continue }
-            write!(implementors, r#""{}","#, imp.impl_).unwrap();
+            write!(implementors, "{},", as_json(&imp.impl_.to_string())).unwrap();
         }
         implementors.push_str("];");
 
index 6bd9cf6620b0e4f40fe5214e303c620eba115a75..4047f6045bcc5fae61b401cf6e8b182edb714228 100644 (file)
@@ -377,13 +377,13 @@ h4 > code, h3 > code, .invisible > code {
 .content .method .where,
 .content .fn .where,
 .content .where.fmt-newline {
-    display: block;
+       display: block;
 }
 /* Bit of whitespace to indent it */
 .content .method .where::before,
 .content .fn .where::before,
 .content .where.fmt-newline::before {
-    content: '  ';
+       content: '  ';
 }
 
 .content .methods > div { margin-left: 40px; }
@@ -506,17 +506,15 @@ body.blur > :not(#help) {
 }
 #help > div {
        flex: 0 0 auto;
-       background: #e9e9e9;
        box-shadow: 0 0 6px rgba(0,0,0,.2);
        width: 550px;
        height: 330px;
-       border: 1px solid #bfbfbf;
+       border: 1px solid;
 }
 #help dt {
        float: left;
        border-radius: 4px;
-       border: 1px solid #bfbfbf;
-       background: #fff;
+       border: 1px solid;
        width: 23px;
        text-align: center;
        clear: left;
@@ -567,7 +565,6 @@ body.blur > :not(#help) {
 .since {
        font-weight: normal;
        font-size: initial;
-       color: grey;
        position: absolute;
        right: 0;
        top: 0;
@@ -589,24 +586,12 @@ td.summary-column {
        padding-right: 0px;
 }
 
-.line-numbers :target { background-color: transparent; }
-
-/* Code highlighting */
-pre.rust .kw { color: #8959A8; }
-pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
-pre.rust .number, pre.rust .string { color: #718C00; }
-pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
-pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
-pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
-pre.rust .lifetime { color: #B76514; }
 pre.rust .question-mark {
-       color: #ff9011;
        font-weight: bold;
 }
 
 pre.rust { position: relative; }
 a.test-arrow {
-       background-color: rgba(78, 139, 202, 0.2);
        display: inline-block;
        position: absolute;
        padding: 5px 10px 5px 10px;
@@ -616,7 +601,6 @@ a.test-arrow {
        right: 5px;
 }
 a.test-arrow:hover{
-       background-color: #4e8bca;
        text-decoration: none;
 }
 
@@ -660,10 +644,6 @@ a.test-arrow:hover{
        text-align: center;
 }
 
-.toggle-label {
-       color: #999;
-}
-
 .ghost {
        display: none;
 }
@@ -719,8 +699,7 @@ span.since {
 }
 
 :target > code {
-   background: #FDFFD3;
-   opacity: 1;
+       opacity: 1;
 }
 
 /* Media Queries */
@@ -793,4 +772,4 @@ span.since {
        nav.sub, .content .out-of-band, .collapse-toggle {
                display: none;
        }
-}
+}
\ No newline at end of file
index f1e81900d1eecc356db4c2efca25fd89a6fe220a..40561597e93e09be91c1eb555ab9e7b9319ad834 100644 (file)
 /* General structure and fonts */
 
 body {
-    background-color: white;
-    color: black;
+       background-color: white;
+       color: black;
 }
 
 h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
-    color: black;
+       color: black;
 }
 h1.fqn {
-    border-bottom-color: #D5D5D5;
+       border-bottom-color: #D5D5D5;
 }
 h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
-    border-bottom-color: #DDDDDD;
+       border-bottom-color: #DDDDDD;
 }
 .in-band {
-    background-color: white;
+       background-color: white;
 }
 
 .docblock code, .docblock-short code {
-    background-color: #F5F5F5;
+       background-color: #F5F5F5;
 }
 pre {
-    background-color: #F5F5F5;
+       background-color: #F5F5F5;
+}
+
+.sidebar {
+       background-color: #F1F1F1;
+}
+
+.sidebar .current {
+       background-color: #fff;
 }
 
 .sidebar {
@@ -46,24 +54,24 @@ pre {
 }
 
 .sidebar .location {
-    border-color: #000;
-    background-color: #fff;
-    color: #333;
+       border-color: #000;
+       background-color: #fff;
+       color: #333;
 }
 
 .block a:hover {
-    background: #F5F5F5;
+       background: #F5F5F5;
 }
 
 .line-numbers span { color: #c67e2d; }
 .line-numbers .line-highlighted {
-    background-color: #f6fdb0 !important;
+       background-color: #f6fdb0 !important;
 }
 
 :target { background: #FDFFD3; }
 .content .highlighted {
-    color: #000 !important;
-    background-color: #ccc;
+       color: #000 !important;
+       background-color: #ccc;
 }
 .content .highlighted a, .content .highlighted span { color: #000 !important; }
 .content .highlighted.trait { background-color: #fece7e; }
@@ -76,21 +84,21 @@ pre {
 .content .highlighted.type { background-color: #c6afb3; }
 
 .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
-    border-bottom-color: #DDD;
+       border-bottom-color: #DDD;
 }
 
 .docblock table {
-    border-color: #ddd;
+       border-color: #ddd;
 }
 
 .docblock table td {
-    border-top-color: #ddd;
-    border-bottom-color: #ddd;
+       border-top-color: #ddd;
+       border-bottom-color: #ddd;
 }
 
 .docblock table th {
-    border-top-color: #ddd;
-    border-bottom-color: #ddd;
+       border-top-color: #ddd;
+       border-bottom-color: #ddd;
 }
 
 .content span.primitive, .content a.primitive, .block a.current.primitive { color: #39a7bf; }
@@ -105,34 +113,78 @@ pre.rust .comment { color: #8E908C; }
 pre.rust .doccomment { color: #4D4D4C; }
 
 nav {
-    border-bottom-color: #e0e0e0;
+       border-bottom-color: #e0e0e0;
 }
 nav.main .current {
-    border-top-color: #000;
-    border-bottom-color: #000;
+       border-top-color: #000;
+       border-bottom-color: #000;
 }
 nav.main .separator {
-    border: 1px solid #000;
+       border: 1px solid #000;
 }
 a {
-    color: #000;
+       color: #000;
 }
 
 .docblock a, .docblock-short a, .stability a {
-    color: #3873AD;
+       color: #3873AD;
 }
 
 a.test-arrow {
-    color: #f5f5f5;
+       color: #f5f5f5;
 }
 
 .content span.trait, .content a.trait, .block a.current.trait { color: #7c5af3; }
 
 .search-input {
-    color: #555;
-    box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
-    background-color: white;
+       color: #555;
+       box-shadow: 0 0 0 1px #e0e0e0, 0 0 0 2px transparent;
+       background-color: white;
 }
 
 .stab.unstable { background: #FFF5D6; border-color: #FFC600; }
 .stab.deprecated { background: #F3DFFF; border-color: #7F0087; }
+
+#help > div {
+       background: #e9e9e9;
+       border-color: #bfbfbf;;
+}
+
+#help dt {
+       border-color: #bfbfbf;
+       background: #fff;
+}
+
+.since {
+       color: grey;
+}
+
+.line-numbers :target { background-color: transparent; }
+
+/* Code highlighting */
+pre.rust .kw { color: #8959A8; }
+pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }
+pre.rust .number, pre.rust .string { color: #718C00; }
+pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val,
+pre.rust .attribute, pre.rust .attribute .ident { color: #C82829; }
+pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; }
+pre.rust .lifetime { color: #B76514; }
+pre.rust .question-mark {
+       color: #ff9011;
+}
+
+a.test-arrow {
+       background-color: rgba(78, 139, 202, 0.2);
+}
+
+a.test-arrow:hover{
+       background-color: #4e8bca;
+}
+
+.toggle-label {
+       color: #999;
+}
+
+:target > code {
+       background: #FDFFD3;
+}
\ No newline at end of file
index 42928427233d780723a0996911e96dabfe6446e3..b80de3cc505464450aa0a00483fe73ca5dd67495 100644 (file)
@@ -16,6 +16,7 @@
 use syntax::abi;
 use syntax::ast;
 use syntax::attr;
+use syntax::tokenstream::TokenStream;
 use syntax_pos::Span;
 
 use rustc::hir::map as hir_map;
@@ -205,14 +206,17 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
                     }
                     let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate);
                     let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) {
-                        LoadedMacro::MacroRules(macro_rules) => macro_rules,
+                        LoadedMacro::MacroDef(macro_def) => macro_def,
                         // FIXME(jseyfried): document proc macro reexports
                         LoadedMacro::ProcMacro(..) => continue,
                     };
 
-                    // FIXME(jseyfried) merge with `self.visit_macro()`
-                    let tts = def.stream().trees().collect::<Vec<_>>();
-                    let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect();
+                    let matchers = if let ast::ItemKind::MacroDef(ref tokens) = def.node {
+                        let tts: Vec<_> = TokenStream::from(tokens.clone()).into_trees().collect();
+                        tts.chunks(4).map(|arm| arm[0].span()).collect()
+                    } else {
+                        unreachable!()
+                    };
                     om.macros.push(Macro {
                         def_id: def_id,
                         attrs: def.attrs.clone().into(),
index f9b0ec479d70115768328111f24537acbb979453..3ca8b41347a268c3ac3f65529ee09bf00506dd6c 100644 (file)
@@ -19,8 +19,9 @@
 use hash::{Hash, Hasher, BuildHasher, SipHasher13};
 use iter::{FromIterator, FusedIterator};
 use mem::{self, replace};
-use ops::{Deref, Index};
+use ops::{Deref, Index, InPlace, Place, Placer};
 use rand::{self, Rng};
+use ptr;
 
 use super::table::{self, Bucket, EmptyBucket, FullBucket, FullBucketMut, RawTable, SafeHash};
 use super::table::BucketState::{Empty, Full};
@@ -483,7 +484,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
                                 mut hash: SafeHash,
                                 mut key: K,
                                 mut val: V)
-                                -> &'a mut V {
+                                -> FullBucketMut<'a, K, V> {
     let start_index = bucket.index();
     let size = bucket.table().size();
     // Save the *starting point*.
@@ -515,7 +516,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(bucket: FullBucketMut<'a, K, V>,
                     // bucket, which is a FullBucket on top of a
                     // FullBucketMut, into just one FullBucketMut. The "table"
                     // refers to the inner FullBucketMut in this context.
-                    return bucket.into_table().into_mut_refs().1;
+                    return bucket.into_table();
                 }
                 Full(bucket) => bucket,
             };
@@ -1818,6 +1819,80 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+/// A place for insertion to a `Entry`.
+///
+/// See [`HashMap::entry`](struct.HashMap.html#method.entry) for details.
+#[must_use = "places do nothing unless written to with `<-` syntax"]
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol is subject to change",
+           issue = "30172")]
+pub struct EntryPlace<'a, K: 'a, V: 'a> {
+    bucket: FullBucketMut<'a, K, V>,
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for EntryPlace<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("EntryPlace")
+            .field("key", self.bucket.read().0)
+            .field("value", self.bucket.read().1)
+            .finish()
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "struct name and placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, K, V> Drop for EntryPlace<'a, K, V> {
+    fn drop(&mut self) {
+        // Inplacement insertion failed. Only key need to drop.
+        // The value is failed to insert into map.
+        unsafe { self.bucket.remove_key() };
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, K, V> Placer<V> for Entry<'a, K, V> {
+    type Place = EntryPlace<'a, K, V>;
+
+    fn make_place(self) -> EntryPlace<'a, K, V> {
+        let b = match self {
+            Occupied(mut o) => {
+                unsafe { ptr::drop_in_place(o.elem.read_mut().1); }
+                o.elem
+            }
+            Vacant(v) => {
+                unsafe { v.insert_key() }
+            }
+        };
+        EntryPlace { bucket: b }
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, K, V> Place<V> for EntryPlace<'a, K, V> {
+    fn pointer(&mut self) -> *mut V {
+        self.bucket.read_mut().1
+    }
+}
+
+#[unstable(feature = "collection_placement",
+           reason = "placement protocol is subject to change",
+           issue = "30172")]
+impl<'a, K, V> InPlace<V> for EntryPlace<'a, K, V> {
+    type Owner = ();
+
+    unsafe fn finalize(self) {
+        mem::forget(self);
+    }
+}
+
 impl<'a, K, V> Entry<'a, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
@@ -2108,7 +2183,7 @@ pub fn into_key(self) -> K {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
-        match self.elem {
+        let b = match self.elem {
             NeqElem(mut bucket, disp) => {
                 if disp >= DISPLACEMENT_THRESHOLD {
                     bucket.table_mut().set_tag(true);
@@ -2119,7 +2194,28 @@ pub fn insert(self, value: V) -> &'a mut V {
                 if disp >= DISPLACEMENT_THRESHOLD {
                     bucket.table_mut().set_tag(true);
                 }
-                bucket.put(self.hash, self.key, value).into_mut_refs().1
+                bucket.put(self.hash, self.key, value)
+            },
+        };
+        b.into_mut_refs().1
+    }
+
+    // Only used for InPlacement insert. Avoid unnecessary value copy.
+    // The value remains uninitialized.
+    unsafe fn insert_key(self) -> FullBucketMut<'a, K, V> {
+        match self.elem {
+            NeqElem(mut bucket, disp) => {
+                if disp >= DISPLACEMENT_THRESHOLD {
+                    bucket.table_mut().set_tag(true);
+                }
+                let uninit = mem::uninitialized();
+                robin_hood(bucket, disp, self.hash, self.key, uninit)
+            },
+            NoElem(mut bucket, disp) => {
+                if disp >= DISPLACEMENT_THRESHOLD {
+                    bucket.table_mut().set_tag(true);
+                }
+                bucket.put_key(self.hash, self.key)
             },
         }
     }
@@ -2392,6 +2488,7 @@ mod test_map {
     use super::RandomState;
     use cell::RefCell;
     use rand::{thread_rng, Rng};
+    use panic;
 
     #[test]
     fn test_zero_capacities() {
@@ -3265,4 +3362,57 @@ fn test_adaptive() {
         }
         panic!("Adaptive early resize failed");
     }
+
+    #[test]
+    fn test_placement_in() {
+        let mut map = HashMap::new();
+        map.extend((0..10).map(|i| (i, i)));
+
+        map.entry(100) <- 100;
+        assert_eq!(map[&100], 100);
+
+        map.entry(0) <- 10;
+        assert_eq!(map[&0], 10);
+
+        assert_eq!(map.len(), 11);
+    }
+
+    #[test]
+    fn test_placement_panic() {
+        let mut map = HashMap::new();
+        map.extend((0..10).map(|i| (i, i)));
+
+        fn mkpanic() -> usize { panic!() }
+
+        // modify existing key
+        // when panic happens, previous key is removed.
+        let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(0) <- mkpanic(); }));
+        assert_eq!(map.len(), 9);
+        assert!(!map.contains_key(&0));
+
+        // add new key
+        let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { map.entry(100) <- mkpanic(); }));
+        assert_eq!(map.len(), 9);
+        assert!(!map.contains_key(&100));
+    }
+
+    #[test]
+    fn test_placement_drop() {
+        // correctly drop
+        struct TestV<'a>(&'a mut bool);
+        impl<'a> Drop for TestV<'a> {
+            fn drop(&mut self) {
+                if !*self.0 { panic!("value double drop!"); } // no double drop
+                *self.0 = false;
+            }
+        }
+
+        fn makepanic<'a>() -> TestV<'a> { panic!() }
+
+        let mut can_drop = true;
+        let mut hm = HashMap::new();
+        hm.insert(0, TestV(&mut can_drop));
+        let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { hm.entry(0) <- makepanic(); }));
+        assert_eq!(hm.len(), 0);
+    }
 }
index 0e225b2964f63752246b7a30d6fc26096b425e98..2c8bb433e8aef1ba1fd65a5d3948802be26293e8 100644 (file)
@@ -506,6 +506,22 @@ pub fn put(mut self, hash: SafeHash, key: K, value: V) -> FullBucket<K, V, M> {
             table: self.table,
         }
     }
+
+    /// Puts given key, remain value uninitialized.
+    /// It is only used for inplacement insertion.
+    pub unsafe fn put_key(mut self, hash: SafeHash, key: K) -> FullBucket<K, V, M> {
+        *self.raw.hash = hash.inspect();
+        let pair_mut = self.raw.pair as *mut (K, V);
+        ptr::write(&mut (*pair_mut).0, key);
+
+        self.table.borrow_table_mut().size += 1;
+
+        FullBucket {
+            raw: self.raw,
+            idx: self.idx,
+            table: self.table,
+        }
+    }
 }
 
 impl<K, V, M: Deref<Target = RawTable<K, V>>> FullBucket<K, V, M> {
@@ -581,6 +597,17 @@ pub fn take(mut self) -> (EmptyBucket<K, V, &'t mut RawTable<K, V>>, K, V) {
             v)
         }
     }
+
+    /// Remove this bucket's `key` from the hashtable.
+    /// Only used for inplacement insertion.
+    /// NOTE: `Value` is uninitialized when this function is called, don't try to drop the `Value`.
+    pub unsafe fn remove_key(&mut self) {
+        self.table.size -= 1;
+
+        *self.raw.hash = EMPTY_BUCKET;
+        let pair_mut = self.raw.pair as *mut (K, V);
+        ptr::drop_in_place(&mut (*pair_mut).0); // only drop key
+    }
 }
 
 // This use of `Put` is misleading and restrictive, but safe and sufficient for our use cases
index a3f4154ba4af7a4f0d5c9e380ab0958eab209e33..2d14bb66bf4f976e6016832f1ff17050d008fe9c 100644 (file)
@@ -154,7 +154,28 @@ pub struct CStr {
 /// byte was found too early in the slice provided or one wasn't found at all.
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
-pub struct FromBytesWithNulError { _a: () }
+pub struct FromBytesWithNulError {
+    kind: FromBytesWithNulErrorKind,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+enum FromBytesWithNulErrorKind {
+    InteriorNul(usize),
+    NotNulTerminated,
+}
+
+impl FromBytesWithNulError {
+    fn interior_nul(pos: usize) -> FromBytesWithNulError {
+        FromBytesWithNulError {
+            kind: FromBytesWithNulErrorKind::InteriorNul(pos),
+        }
+    }
+    fn not_nul_terminated() -> FromBytesWithNulError {
+        FromBytesWithNulError {
+            kind: FromBytesWithNulErrorKind::NotNulTerminated,
+        }
+    }
+}
 
 /// An error returned from `CString::into_string` to indicate that a UTF-8 error
 /// was encountered during the conversion.
@@ -472,14 +493,23 @@ fn from(_: NulError) -> io::Error {
 #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
 impl Error for FromBytesWithNulError {
     fn description(&self) -> &str {
-        "data provided is not null terminated or contains an interior nul byte"
+        match self.kind {
+            FromBytesWithNulErrorKind::InteriorNul(..) =>
+                "data provided contains an interior nul byte",
+            FromBytesWithNulErrorKind::NotNulTerminated =>
+                "data provided is not nul terminated",
+        }
     }
 }
 
 #[stable(feature = "frombyteswithnulerror_impls", since = "1.17.0")]
 impl fmt::Display for FromBytesWithNulError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.description().fmt(f)
+        f.write_str(self.description())?;
+        if let FromBytesWithNulErrorKind::InteriorNul(pos) = self.kind {
+            write!(f, " at byte pos {}", pos)?;
+        }
+        Ok(())
     }
 }
 
@@ -573,10 +603,14 @@ pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
     #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
     pub fn from_bytes_with_nul(bytes: &[u8])
                                -> Result<&CStr, FromBytesWithNulError> {
-        if bytes.is_empty() || memchr::memchr(0, &bytes) != Some(bytes.len() - 1) {
-            Err(FromBytesWithNulError { _a: () })
+        let nul_pos = memchr::memchr(0, bytes);
+        if let Some(nul_pos) = nul_pos {
+            if nul_pos + 1 != bytes.len() {
+                return Err(FromBytesWithNulError::interior_nul(nul_pos));
+            }
+            Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) })
         } else {
-            Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) })
+            Err(FromBytesWithNulError::not_nul_terminated())
         }
     }
 
index c9c207d8b8eb4fcaec1259ed61a5b10e1ce0506a..2765fd83ed554027cb213cb07f484540ca91f085 100644 (file)
@@ -205,6 +205,12 @@ pub fn reserve_exact(&mut self, additional: usize) {
         self.inner.reserve_exact(additional)
     }
 
+    /// Shrinks the capacity of the `OsString` to match its length.
+    #[unstable(feature = "osstring_shrink_to_fit", issue = "40421")]
+    pub fn shrink_to_fit(&mut self) {
+        self.inner.shrink_to_fit()
+    }
+
     /// Converts this `OsString` into a boxed `OsStr`.
     #[unstable(feature = "into_boxed_os_str", issue = "40380")]
     pub fn into_boxed_os_str(self) -> Box<OsStr> {
index 070690773b6c4792a05dc525ce790c9d1cdc72ce..7fa5ad255609cc236a48c8f5248aac4a49412388 100644 (file)
 #![feature(panic_unwind)]
 #![feature(peek)]
 #![feature(placement_in_syntax)]
+#![feature(placement_new_protocol)]
 #![feature(prelude_import)]
 #![feature(pub_restricted)]
 #![feature(rand)]
index 90b8289524e2659d4479eba7920dc7a3d12c940f..c2bba07f68ce0be0e346aa0763759cd97da51198 100644 (file)
@@ -83,6 +83,11 @@ pub fn reserve_exact(&mut self, additional: usize) {
         self.inner.reserve_exact(additional)
     }
 
+    #[inline]
+    pub fn shrink_to_fit(&mut self) {
+        self.inner.shrink_to_fit()
+    }
+
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
index 225924168a5b20cd45037e673e87e194777d0155..f5b942d3343dc23e5ba221a9b498855e2c71448d 100644 (file)
@@ -83,6 +83,11 @@ pub fn reserve_exact(&mut self, additional: usize) {
         self.inner.reserve_exact(additional)
     }
 
+    #[inline]
+    pub fn shrink_to_fit(&mut self) {
+        self.inner.shrink_to_fit()
+    }
+
     pub fn as_slice(&self) -> &Slice {
         unsafe { mem::transmute(&*self.inner) }
     }
index 810b67b785b5cf8a67b8133be8794f63153b0deb..f401e7b35c8d8d6c78c360733f8e6d99f724d8f1 100644 (file)
@@ -89,6 +89,10 @@ pub fn reserve_exact(&mut self, additional: usize) {
         self.inner.reserve_exact(additional)
     }
 
+    pub fn shrink_to_fit(&mut self) {
+        self.inner.shrink_to_fit()
+    }
+
     #[inline]
     pub fn into_box(self) -> Box<Slice> {
         unsafe { mem::transmute(self.inner.into_box()) }
index 1ea5cca44c7e40154f383bce344187a8b703a94e..14c0e8699bc060b2cbbf9255e4fbff86701ce1b7 100644 (file)
@@ -105,9 +105,6 @@ pub fn resolve_symname<F>(frame: Frame,
               msg: *const libc::c_char,
               errnum: libc::c_int);
 enum backtrace_state {}
-#[link(name = "backtrace", kind = "static")]
-#[cfg(all(not(test), not(cargobuild)))]
-extern {}
 
 extern {
     fn backtrace_create_state(filename: *const libc::c_char,
index 28cab10e8f9cc1b455ed4c93bde897277c16c29a..79aaf34ce2e0f5d68d18ea134f7cefa4275b20f2 100644 (file)
@@ -236,6 +236,11 @@ pub fn reserve_exact(&mut self, additional: usize) {
         self.bytes.reserve_exact(additional)
     }
 
+    #[inline]
+    pub fn shrink_to_fit(&mut self) {
+        self.bytes.shrink_to_fit()
+    }
+
     /// Returns the number of bytes that this string buffer can hold without reallocating.
     #[inline]
     pub fn capacity(&self) -> usize {
index 9cc754cbf4d1912590251b479d80716f69f35f68..a456fa512254c788050c584b0e8c67ebe9b4056d 100644 (file)
@@ -134,7 +134,7 @@ impl Path {
     pub fn from_ident(s: Span, identifier: Ident) -> Path {
         Path {
             span: s,
-            segments: vec![identifier.into()],
+            segments: vec![PathSegment::from_ident(identifier, s)],
         }
     }
 
@@ -159,6 +159,8 @@ pub fn is_global(&self) -> bool {
 pub struct PathSegment {
     /// The identifier portion of this path segment.
     pub identifier: Ident,
+    /// Span of the segment identifier.
+    pub span: Span,
 
     /// Type/lifetime parameters attached to this path. They come in
     /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
@@ -170,16 +172,14 @@ pub struct PathSegment {
     pub parameters: Option<P<PathParameters>>,
 }
 
-impl From<Ident> for PathSegment {
-    fn from(id: Ident) -> Self {
-        PathSegment { identifier: id, parameters: None }
-    }
-}
-
 impl PathSegment {
+    pub fn from_ident(ident: Ident, span: Span) -> Self {
+        PathSegment { identifier: ident, span: span, parameters: None }
+    }
     pub fn crate_root() -> Self {
         PathSegment {
             identifier: keywords::CrateRoot.ident(),
+            span: DUMMY_SP,
             parameters: None,
         }
     }
@@ -414,7 +414,6 @@ pub struct Crate {
     pub module: Mod,
     pub attrs: Vec<Attribute>,
     pub span: Span,
-    pub exported_macros: Vec<MacroDef>,
 }
 
 /// A spanned compile-time attribute list item.
@@ -936,6 +935,8 @@ pub enum ExprKind {
     Closure(CaptureBy, P<FnDecl>, P<Expr>, Span),
     /// A block (`{ ... }`)
     Block(P<Block>),
+    /// A catch block (`catch { ... }`)
+    Catch(P<Block>),
 
     /// An assignment (`a = foo()`)
     Assign(P<Expr>, P<Expr>),
@@ -1855,10 +1856,13 @@ pub enum ItemKind {
              Option<TraitRef>, // (optional) trait this impl implements
              P<Ty>, // self
              Vec<ImplItem>),
-    /// A macro invocation (which includes macro definition).
+    /// A macro invocation.
     ///
     /// E.g. `macro_rules! foo { .. }` or `foo!(..)`
     Mac(Mac),
+
+    /// A macro definition.
+    MacroDef(ThinTokenStream),
 }
 
 impl ItemKind {
@@ -1877,6 +1881,7 @@ pub fn descriptive_variant(&self) -> &str {
             ItemKind::Union(..) => "union",
             ItemKind::Trait(..) => "trait",
             ItemKind::Mac(..) |
+            ItemKind::MacroDef(..) |
             ItemKind::Impl(..) |
             ItemKind::DefaultImpl(..) => "item"
         }
@@ -1912,24 +1917,6 @@ pub fn descriptive_variant(&self) -> &str {
     }
 }
 
-/// A macro definition, in this crate or imported from another.
-///
-/// Not parsed directly, but created on macro import or `macro_rules!` expansion.
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct MacroDef {
-    pub ident: Ident,
-    pub attrs: Vec<Attribute>,
-    pub id: NodeId,
-    pub span: Span,
-    pub body: ThinTokenStream,
-}
-
-impl MacroDef {
-    pub fn stream(&self) -> TokenStream {
-        self.body.clone().into()
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use serialize;
index e242cf2777fe59dd00fbed82820a06848bb39c82..dc7e7673eb03cb1c1d6282852131824c94d99cb0 100644 (file)
@@ -15,7 +15,7 @@
 use codemap::{self, CodeMap, ExpnInfo, Spanned, respan};
 use syntax_pos::{Span, ExpnId, NO_EXPANSION};
 use errors::{DiagnosticBuilder, FatalError};
-use ext::expand::{self, Expansion};
+use ext::expand::{self, Expansion, Invocation};
 use ext::hygiene::Mark;
 use fold::{self, Folder};
 use parse::{self, parser, DirectoryOwnership};
@@ -552,14 +552,15 @@ pub trait Resolver {
     fn is_whitelisted_legacy_custom_derive(&self, name: Name) -> bool;
 
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion, derives: &[Mark]);
-    fn add_ext(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
-    fn add_expansions_at_stmt(&mut self, id: ast::NodeId, macros: Vec<Mark>);
+    fn add_builtin(&mut self, ident: ast::Ident, ext: Rc<SyntaxExtension>);
 
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
     fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
-                     force: bool) -> Result<Rc<SyntaxExtension>, Determinacy>;
+    fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
+                     -> Result<Option<Rc<SyntaxExtension>>, Determinacy>;
+    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
+                     -> Result<Rc<SyntaxExtension>, Determinacy>;
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -577,11 +578,14 @@ fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
     fn is_whitelisted_legacy_custom_derive(&self, _name: Name) -> bool { false }
 
     fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion, _derives: &[Mark]) {}
-    fn add_ext(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
-    fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
+    fn add_builtin(&mut self, _ident: ast::Ident, _ext: Rc<SyntaxExtension>) {}
 
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
+    fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool)
+                     -> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
+        Err(Determinacy::Determined)
+    }
     fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
                      _force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
index f8d4eff80b2d19f7eeb95fb62bdcc8be080688ee..e0fb46ff5eb095a01c659ab0a6e124c30f82c577 100644 (file)
@@ -38,11 +38,11 @@ fn path_all(&self, sp: Span,
 
     fn qpath(&self, self_type: P<ast::Ty>,
              trait_path: ast::Path,
-             ident: ast::Ident)
+             ident: ast::SpannedIdent)
              -> (ast::QSelf, ast::Path);
     fn qpath_all(&self, self_type: P<ast::Ty>,
                 trait_path: ast::Path,
-                ident: ast::Ident,
+                ident: ast::SpannedIdent,
                 lifetimes: Vec<ast::Lifetime>,
                 types: Vec<P<ast::Ty>>,
                 bindings: Vec<ast::TypeBinding>)
@@ -323,7 +323,7 @@ fn path_all(&self,
             segments.push(ast::PathSegment::crate_root());
         }
 
-        segments.extend(idents.into_iter().map(Into::into));
+        segments.extend(idents.into_iter().map(|i| ast::PathSegment::from_ident(i, sp)));
         let parameters = if lifetimes.is_empty() && types.is_empty() && bindings.is_empty() {
             None
         } else {
@@ -333,7 +333,11 @@ fn path_all(&self,
                 bindings: bindings,
             })))
         };
-        segments.push(ast::PathSegment { identifier: last_identifier, parameters: parameters });
+        segments.push(ast::PathSegment {
+            identifier: last_identifier,
+            span: sp,
+            parameters: parameters
+        });
         ast::Path {
             span: sp,
             segments: segments,
@@ -346,7 +350,7 @@ fn path_all(&self,
     fn qpath(&self,
              self_type: P<ast::Ty>,
              trait_path: ast::Path,
-             ident: ast::Ident)
+             ident: ast::SpannedIdent)
              -> (ast::QSelf, ast::Path) {
         self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
     }
@@ -357,7 +361,7 @@ fn qpath(&self,
     fn qpath_all(&self,
                  self_type: P<ast::Ty>,
                  trait_path: ast::Path,
-                 ident: ast::Ident,
+                 ident: ast::SpannedIdent,
                  lifetimes: Vec<ast::Lifetime>,
                  types: Vec<P<ast::Ty>>,
                  bindings: Vec<ast::TypeBinding>)
@@ -369,7 +373,8 @@ fn qpath_all(&self,
             bindings: bindings,
         };
         path.segments.push(ast::PathSegment {
-            identifier: ident,
+            identifier: ident.node,
+            span: ident.span,
             parameters: Some(P(ast::PathParameters::AngleBracketed(parameters))),
         });
 
index f1662284a88206657283952e9c444e4c5ea39397..10168f010a077c9b94f2ec1d8e130fc108426252 100644 (file)
@@ -154,7 +154,7 @@ fn expect_from_annotatables<I: IntoIterator<Item = Annotatable>>(self, items: I)
 pub struct Invocation {
     pub kind: InvocationKind,
     expansion_kind: ExpansionKind,
-    expansion_data: ExpansionData,
+    pub expansion_data: ExpansionData,
 }
 
 pub enum InvocationKind {
@@ -251,7 +251,7 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
 
             let scope =
                 if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark };
-            let ext = match self.resolve_invoc(&mut invoc, scope, force) {
+            let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) {
                 Ok(ext) => Some(ext),
                 Err(Determinacy::Determined) => None,
                 Err(Determinacy::Undetermined) => {
@@ -364,64 +364,6 @@ fn collect_invocations(&mut self, expansion: Expansion, derives: &[Mark])
         result
     }
 
-    fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
-                     -> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
-        let (attr, traits, item) = match invoc.kind {
-            InvocationKind::Bang { ref mac, .. } => {
-                return self.cx.resolver.resolve_macro(scope, &mac.node.path,
-                                                      MacroKind::Bang, force).map(Some);
-            }
-            InvocationKind::Attr { attr: None, .. } => return Ok(None),
-            InvocationKind::Derive { name, span, .. } => {
-                let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-                return self.cx.resolver.resolve_macro(scope, &path,
-                                                      MacroKind::Derive, force).map(Some)
-            }
-            InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
-        };
-
-        let (attr_name, path) = {
-            let attr = attr.as_ref().unwrap();
-            (attr.name(), ast::Path::from_ident(attr.span, Ident::with_empty_ctxt(attr.name())))
-        };
-
-        let mut determined = true;
-        match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Attr, force) {
-            Ok(ext) => return Ok(Some(ext)),
-            Err(Determinacy::Undetermined) => determined = false,
-            Err(Determinacy::Determined) if force => return Err(Determinacy::Determined),
-            _ => {}
-        }
-
-        for &(name, span) in traits {
-            let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-            match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Derive, force) {
-                Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
-                    if inert_attrs.contains(&attr_name) {
-                        // FIXME(jseyfried) Avoid `mem::replace` here.
-                        let dummy_item = placeholder(ExpansionKind::Items, ast::DUMMY_NODE_ID)
-                            .make_items().pop().unwrap();
-                        *item = mem::replace(item, Annotatable::Item(dummy_item))
-                            .map_attrs(|mut attrs| {
-                                let inert_attr = attr.take().unwrap();
-                                attr::mark_known(&inert_attr);
-                                if self.cx.ecfg.proc_macro_enabled() {
-                                    *attr = find_attr_invoc(&mut attrs);
-                                }
-                                attrs.push(inert_attr);
-                                attrs
-                            });
-                    }
-                    return Err(Determinacy::Undetermined);
-                },
-                Err(Determinacy::Undetermined) => determined = false,
-                Err(Determinacy::Determined) => {}
-            }
-        }
-
-        Err(if determined { Determinacy::Determined } else { Determinacy::Undetermined })
-    }
-
     fn expand_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) -> Expansion {
         match invoc.kind {
             InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext),
@@ -464,8 +406,20 @@ fn expand_attr_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
                 let attr_toks = stream_for_attr_args(&attr, &self.cx.parse_sess);
                 let item_toks = stream_for_item(&item, &self.cx.parse_sess);
 
+                let span = Span {
+                    expn_id: self.cx.codemap().record_expansion(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            format: MacroAttribute(name),
+                            span: None,
+                            allow_internal_unstable: false,
+                        },
+                    }),
+                    ..attr.span
+                };
+
                 let tok_result = mac.expand(self.cx, attr.span, attr_toks, item_toks);
-                self.parse_expansion(tok_result, kind, name, attr.span)
+                self.parse_expansion(tok_result, kind, name, span)
             }
             SyntaxExtension::ProcMacroDerive(..) | SyntaxExtension::BuiltinDerive(..) => {
                 self.cx.span_err(attr.span, &format!("`{}` is a derive mode", name));
@@ -490,7 +444,8 @@ fn expand_bang_invoc(&mut self, invoc: Invocation, ext: Rc<SyntaxExtension>) ->
 
         let extname = path.segments.last().unwrap().identifier.name;
         let ident = ident.unwrap_or(keywords::Invalid.ident());
-        let marked_tts = mark_tts(mac.node.stream(), mark);
+        let marked_tts =
+            noop_fold_tts(mac.node.stream(), &mut Marker { mark: mark, expn_id: None });
         let opt_expanded = match *ext {
             NormalTT(ref expandfun, exp_span, allow_internal_unstable) => {
                 if ident.name != keywords::Invalid.name() {
@@ -802,7 +757,7 @@ fn check_attributes(&mut self, attrs: &[ast::Attribute]) {
     }
 }
 
-fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
+pub fn find_attr_invoc(attrs: &mut Vec<ast::Attribute>) -> Option<ast::Attribute> {
     for i in 0 .. attrs.len() {
         if !attr::is_known(&attrs[i]) && !is_builtin_attr(&attrs[i]) {
              return Some(attrs.remove(i));
@@ -948,17 +903,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
         match item.node {
             ast::ItemKind::Mac(..) => {
                 self.check_attributes(&item.attrs);
-                let is_macro_def = if let ItemKind::Mac(ref mac) = item.node {
-                    mac.node.path.segments[0].identifier.name == "macro_rules"
-                } else {
-                    unreachable!()
-                };
-
-                item.and_then(|mut item| match item.node {
-                    ItemKind::Mac(_) if is_macro_def => {
-                        item.id = Mark::fresh().as_placeholder_id();
-                        SmallVector::one(P(item))
-                    }
+                item.and_then(|item| match item.node {
                     ItemKind::Mac(mac) => {
                         self.collect(ExpansionKind::Items, InvocationKind::Bang {
                             mac: mac,
@@ -1078,7 +1023,10 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod
     }
 
     fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
-        noop_fold_item_kind(self.cfg.configure_item_kind(item), self)
+        match item {
+            ast::ItemKind::MacroDef(..) => item,
+            _ => noop_fold_item_kind(self.cfg.configure_item_kind(item), self),
+        }
     }
 
     fn new_id(&mut self, id: ast::NodeId) -> ast::NodeId {
@@ -1159,8 +1107,3 @@ fn new_span(&mut self, mut span: Span) -> Span {
         span
     }
 }
-
-// apply a given mark to the given token trees. Used prior to expansion of a macro.
-pub fn mark_tts(tts: TokenStream, m: Mark) -> TokenStream {
-    noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None})
-}
index 2af5c2ea9995ef61f20ba390f2efffd5bf043065..57f5ab73d37062fbbb4079dae08a649e273e0f0c 100644 (file)
@@ -31,7 +31,7 @@ pub struct SyntaxContextData {
 }
 
 /// A mark is a unique id associated with a macro expansion.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Default, RustcEncodable, RustcDecodable)]
 pub struct Mark(u32);
 
 impl Mark {
@@ -118,13 +118,6 @@ pub fn apply_mark(self, mark: Mark) -> SyntaxContext {
             })
         })
     }
-
-    /// If `ident` is macro expanded, return the source ident from the macro definition
-    /// and the mark of the expansion that created the macro definition.
-    pub fn source(self) -> (Self /* source context */, Mark /* source macro */) {
-         let macro_def_ctxt = self.data().prev_ctxt.data();
-         (macro_def_ctxt.prev_ctxt, macro_def_ctxt.outer_mark)
-    }
 }
 
 impl fmt::Debug for SyntaxContext {
index e2fb1946e90dbdd05b1299e1a6d6c33dae3a2882..f60b1d17a5e2f0c3c74058602712b3d172b35148 100644 (file)
@@ -21,7 +21,6 @@
 use util::small_vector::SmallVector;
 
 use std::collections::HashMap;
-use std::mem;
 
 pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
     fn mac_placeholder() -> ast::Mac {
@@ -174,20 +173,11 @@ fn fold_ty(&mut self, ty: P<ast::Ty>) -> P<ast::Ty> {
 
     fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
         noop_fold_block(block, self).map(|mut block| {
-            let mut macros = Vec::new();
             let mut remaining_stmts = block.stmts.len();
 
             block.stmts = block.stmts.move_flat_map(|mut stmt| {
                 remaining_stmts -= 1;
 
-                // `macro_rules!` macro definition
-                if let ast::StmtKind::Item(ref item) = stmt.node {
-                    if let ast::ItemKind::Mac(_) = item.node {
-                        macros.push(Mark::from_placeholder_id(item.id));
-                        return None;
-                    }
-                }
-
                 match stmt.node {
                     // Avoid wasting a node id on a trailing expression statement,
                     // which shares a HIR node with the expression itself.
@@ -201,11 +191,6 @@ fn fold_block(&mut self, block: P<ast::Block>) -> P<ast::Block> {
                     _ => {}
                 }
 
-                if self.monotonic && !macros.is_empty() {
-                    let macros = mem::replace(&mut macros, Vec::new());
-                    self.cx.resolver.add_expansions_at_stmt(stmt.id, macros);
-                }
-
                 Some(stmt)
             });
 
index 1d386c1a3ac930f494630fcefc44039feb0be40b..7aa1230f9aeea9a9eb664be80fed382307e9039a 100644 (file)
@@ -153,7 +153,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
 // Holy self-referential!
 
 /// Converts a `macro_rules!` invocation into a syntax extension.
-pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
+pub fn compile(sess: &ParseSess, def: &ast::Item) -> SyntaxExtension {
     let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs"));
     let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs"));
 
@@ -183,7 +183,11 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension {
     ];
 
     // Parse the macro_rules! invocation
-    let argument_map = match parse(sess, def.body.clone().into(), &argument_gram, None) {
+    let body = match def.node {
+        ast::ItemKind::MacroDef(ref body) => body.clone().into(),
+        _ => unreachable!(),
+    };
+    let argument_map = match parse(sess, body, &argument_gram, None) {
         Success(m) => m,
         Failure(sp, tok) => {
             let s = parse_failure_msg(tok);
index e7bf16eae9ee660bd6bbf06f70bccb096a683116..15913d56d162f0cba362d22881b496c066a6fcd0 100644 (file)
@@ -339,6 +339,9 @@ pub fn new() -> Features {
 
     // `extern "x86-interrupt" fn()`
     (active, abi_x86_interrupt, "1.17.0", Some(40180)),
+
+    // Allows the `catch {...}` expression
+    (active, catch_expr, "1.17.0", Some(31436)),
 );
 
 declare_features! (
@@ -1287,6 +1290,9 @@ fn visit_expr(&mut self, e: &'a ast::Expr) {
                     }
                 }
             }
+            ast::ExprKind::Catch(_) => {
+                gate_feature_post!(&self, catch_expr, e.span, "`catch` expression is experimental");
+            }
             _ => {}
         }
         visit::walk_expr(self, e);
index 4242b0f8b9803d17df7b06e2c18b55987a1ce671..9f11d0173d6d5168c6602b8d85dc58f5642325f0 100644 (file)
@@ -434,8 +434,9 @@ pub fn noop_fold_usize<T: Folder>(i: usize, _: &mut T) -> usize {
 
 pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) -> Path {
     Path {
-        segments: segments.move_map(|PathSegment {identifier, parameters}| PathSegment {
+        segments: segments.move_map(|PathSegment {identifier, span, parameters}| PathSegment {
             identifier: fld.fold_ident(identifier),
+            span: fld.new_span(span),
             parameters: parameters.map(|ps| ps.map(|ps| fld.fold_path_parameters(ps))),
         }),
         span: fld.new_span(span)
@@ -899,6 +900,7 @@ pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
             items.move_flat_map(|item| folder.fold_trait_item(item)),
         ),
         ItemKind::Mac(m) => ItemKind::Mac(folder.fold_mac(m)),
+        ItemKind::MacroDef(tts) => ItemKind::MacroDef(folder.fold_tts(tts.into()).into()),
     }
 }
 
@@ -959,7 +961,7 @@ pub fn noop_fold_mod<T: Folder>(Mod {inner, items}: Mod, folder: &mut T) -> Mod
     }
 }
 
-pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, mut exported_macros, span}: Crate,
+pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
                                   folder: &mut T) -> Crate {
     let mut items = folder.fold_item(P(ast::Item {
         ident: keywords::Invalid.ident(),
@@ -987,14 +989,9 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, mut exported_macros, spa
         }, vec![], span)
     };
 
-    for def in &mut exported_macros {
-        def.id = folder.new_id(def.id);
-    }
-
     Crate {
         module: module,
         attrs: attrs,
-        exported_macros: exported_macros,
         span: span,
     }
 }
@@ -1272,6 +1269,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                 };
             }
             ExprKind::Try(ex) => ExprKind::Try(folder.fold_expr(ex)),
+            ExprKind::Catch(body) => ExprKind::Catch(folder.fold_block(body)),
         },
         id: folder.new_id(id),
         span: folder.new_span(span),
@@ -1387,6 +1385,6 @@ macro_rules! assert_pred {
             matches_codepattern,
             "matches_codepattern",
             pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
-            "zz!zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
+            "macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
     }
 }
index c00d2952b3b425bcc87e6ac78be0bf9719c53a2c..88535f91379f72330ed449f407519d05b9edeb8a 100644 (file)
@@ -617,13 +617,17 @@ fn sp(a: u32, b: u32) -> Span {
         Span {lo: BytePos(a), hi: BytePos(b), expn_id: NO_EXPANSION}
     }
 
+    fn str2seg(s: &str, lo: u32, hi: u32) -> ast::PathSegment {
+        ast::PathSegment::from_ident(Ident::from_str(s), sp(lo, hi))
+    }
+
     #[test] fn path_exprs_1() {
         assert!(string_to_expr("a".to_string()) ==
                    P(ast::Expr{
                     id: ast::DUMMY_NODE_ID,
                     node: ast::ExprKind::Path(None, ast::Path {
                         span: sp(0, 1),
-                        segments: vec![Ident::from_str("a").into()],
+                        segments: vec![str2seg("a", 0, 1)],
                     }),
                     span: sp(0, 1),
                     attrs: ThinVec::new(),
@@ -637,8 +641,8 @@ fn sp(a: u32, b: u32) -> Span {
                     node: ast::ExprKind::Path(None, ast::Path {
                         span: sp(0, 6),
                         segments: vec![ast::PathSegment::crate_root(),
-                                       Ident::from_str("a").into(),
-                                       Ident::from_str("b").into()]
+                                       str2seg("a", 2, 3),
+                                       str2seg("b", 5, 6)]
                     }),
                     span: sp(0, 6),
                     attrs: ThinVec::new(),
@@ -744,7 +748,7 @@ fn string_to_tts_1() {
                         id: ast::DUMMY_NODE_ID,
                         node:ast::ExprKind::Path(None, ast::Path{
                             span: sp(7, 8),
-                            segments: vec![Ident::from_str("d").into()],
+                            segments: vec![str2seg("d", 7, 8)],
                         }),
                         span:sp(7,8),
                         attrs: ThinVec::new(),
@@ -761,7 +765,7 @@ fn string_to_tts_1() {
                            id: ast::DUMMY_NODE_ID,
                            node: ast::ExprKind::Path(None, ast::Path {
                                span:sp(0,1),
-                               segments: vec![Ident::from_str("b").into()],
+                               segments: vec![str2seg("b", 0, 1)],
                             }),
                            span: sp(0,1),
                            attrs: ThinVec::new()})),
@@ -802,7 +806,7 @@ fn parser_done(p: Parser){
                                     ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
                                                   node: ast::TyKind::Path(None, ast::Path{
                                         span:sp(10,13),
-                                        segments: vec![Ident::from_str("i32").into()],
+                                        segments: vec![str2seg("i32", 10, 13)],
                                         }),
                                         span:sp(10,13)
                                     }),
@@ -844,7 +848,7 @@ fn parser_done(p: Parser){
                                                 node: ast::ExprKind::Path(None,
                                                       ast::Path{
                                                         span:sp(17,18),
-                                                        segments: vec![Ident::from_str("b").into()],
+                                                        segments: vec![str2seg("b", 17, 18)],
                                                       }),
                                                 span: sp(17,18),
                                                 attrs: ThinVec::new()})),
index 6c566dab1d6060df69321913816289568062f3f7..8f66c1a2b8cf630eada9a2627ac6360b1d2dd72b 100644 (file)
@@ -27,7 +27,7 @@
 use ast::MacStmtStyle;
 use ast::Mac_;
 use ast::{MutTy, Mutability};
-use ast::{Pat, PatKind};
+use ast::{Pat, PatKind, PathSegment};
 use ast::{PolyTraitRef, QSelf};
 use ast::{Stmt, StmtKind};
 use ast::{VariantData, StructField};
@@ -1048,7 +1048,7 @@ pub fn bump_with(&mut self,
         self.expected_tokens.clear();
     }
 
-    pub fn look_ahead<R, F>(&mut self, dist: usize, f: F) -> R where
+    pub fn look_ahead<R, F>(&self, dist: usize, f: F) -> R where
         F: FnOnce(&token::Token) -> R,
     {
         if dist == 0 {
@@ -1811,7 +1811,7 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
         };
 
         if is_global {
-            segments.insert(0, ast::PathSegment::crate_root());
+            segments.insert(0, PathSegment::crate_root());
         }
 
         // Assemble the span.
@@ -1829,11 +1829,12 @@ pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> {
     /// - `a::b<T,U>::c<V,W>`
     /// - `a::b<T,U>::c(V) -> W`
     /// - `a::b<T,U>::c(V)`
-    pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
+    pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<PathSegment>> {
         let mut segments = Vec::new();
         loop {
             // First, parse an identifier.
             let identifier = self.parse_path_segment_ident()?;
+            let ident_span = self.prev_span;
 
             if self.check(&token::ModSep) && self.look_ahead(1, |t| *t == token::Lt) {
                 self.bump();
@@ -1881,7 +1882,11 @@ pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::Pat
             };
 
             // Assemble and push the result.
-            segments.push(ast::PathSegment { identifier: identifier, parameters: parameters });
+            segments.push(PathSegment {
+                identifier: identifier,
+                span: ident_span,
+                parameters: parameters
+            });
 
             // Continue only if we see a `::`
             if !self.eat(&token::ModSep) {
@@ -1892,15 +1897,16 @@ pub fn parse_path_segments_without_colons(&mut self) -> PResult<'a, Vec<ast::Pat
 
     /// Examples:
     /// - `a::b::<T,U>::c`
-    pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSegment>> {
+    pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<PathSegment>> {
         let mut segments = Vec::new();
         loop {
             // First, parse an identifier.
             let identifier = self.parse_path_segment_ident()?;
+            let ident_span = self.prev_span;
 
             // If we do not see a `::`, stop.
             if !self.eat(&token::ModSep) {
-                segments.push(identifier.into());
+                segments.push(PathSegment::from_ident(identifier, ident_span));
                 return Ok(segments);
             }
 
@@ -1909,8 +1915,9 @@ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSe
                 // Consumed `a::b::<`, go look for types
                 let (lifetimes, types, bindings) = self.parse_generic_args()?;
                 self.expect_gt()?;
-                segments.push(ast::PathSegment {
+                segments.push(PathSegment {
                     identifier: identifier,
+                    span: ident_span,
                     parameters: ast::AngleBracketedParameterData {
                         lifetimes: lifetimes,
                         types: types,
@@ -1924,7 +1931,7 @@ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSe
                 }
             } else {
                 // Consumed `a::`, go look for `b`
-                segments.push(identifier.into());
+                segments.push(PathSegment::from_ident(identifier, ident_span));
             }
         }
     }
@@ -1932,14 +1939,14 @@ pub fn parse_path_segments_with_colons(&mut self) -> PResult<'a, Vec<ast::PathSe
     /// Examples:
     /// - `a::b::c`
     pub fn parse_path_segments_without_types(&mut self)
-                                             -> PResult<'a, Vec<ast::PathSegment>> {
+                                             -> PResult<'a, Vec<PathSegment>> {
         let mut segments = Vec::new();
         loop {
             // First, parse an identifier.
             let identifier = self.parse_path_segment_ident()?;
 
             // Assemble and push the result.
-            segments.push(identifier.into());
+            segments.push(PathSegment::from_ident(identifier, self.prev_span));
 
             // If we do not see a `::` or see `::{`/`::*`, stop.
             if !self.check(&token::ModSep) || self.is_import_coupler() {
@@ -2273,6 +2280,12 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P<Expr>> {
                         BlockCheckMode::Unsafe(ast::UserProvided),
                         attrs);
                 }
+                if self.is_catch_expr() {
+                    assert!(self.eat_keyword(keywords::Do));
+                    assert!(self.eat_keyword(keywords::Catch));
+                    let lo = self.prev_span.lo;
+                    return self.parse_catch_expr(lo, attrs);
+                }
                 if self.eat_keyword(keywords::Return) {
                     if self.token.can_begin_expr() {
                         let e = self.parse_expr()?;
@@ -3092,6 +3105,16 @@ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
         Ok(self.mk_expr(span_lo, hi, ExprKind::Loop(body, opt_ident), attrs))
     }
 
+    /// Parse a `do catch {...}` expression (`do catch` token already eaten)
+    pub fn parse_catch_expr(&mut self, span_lo: BytePos, mut attrs: ThinVec<Attribute>)
+        -> PResult<'a, P<Expr>>
+    {
+        let (iattrs, body) = self.parse_inner_attrs_and_block()?;
+        attrs.extend(iattrs);
+        let hi = body.span.hi;
+        Ok(self.mk_expr(span_lo, hi, ExprKind::Catch(body), attrs))
+    }
+
     // `match` token already eaten
     fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         let match_span = self.prev_span;
@@ -3699,11 +3722,50 @@ fn parse_stmt_(&mut self, macro_legacy_warnings: bool) -> Option<Stmt> {
         })
     }
 
-    fn is_union_item(&mut self) -> bool {
+    fn is_catch_expr(&mut self) -> bool {
+        self.token.is_keyword(keywords::Do) &&
+        self.look_ahead(1, |t| t.is_keyword(keywords::Catch)) &&
+        self.look_ahead(2, |t| *t == token::OpenDelim(token::Brace)) &&
+
+        // prevent `while catch {} {}`, `if catch {} {} else {}`, etc.
+        !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL)
+    }
+
+    fn is_union_item(&self) -> bool {
         self.token.is_keyword(keywords::Union) &&
         self.look_ahead(1, |t| t.is_ident() && !t.is_any_keyword())
     }
 
+    fn eat_macro_def(&mut self, attrs: &[Attribute], vis: &Visibility)
+                     -> PResult<'a, Option<P<Item>>> {
+        let lo = self.span.lo;
+        match self.token {
+            token::Ident(ident) if ident.name == "macro_rules" => {
+                if self.look_ahead(1, |t| *t == token::Not) {
+                    let prev_span = self.prev_span;
+                    self.complain_if_pub_macro(vis, prev_span);
+                    self.bump();
+                    self.bump();
+                }
+            }
+            _ => return Ok(None),
+        };
+
+        let id = self.parse_ident()?;
+        let (delim, tts) = self.expect_delimited_token_tree()?;
+        if delim != token::Brace {
+            if !self.eat(&token::Semi) {
+                let msg = "macros that expand to items must either be surrounded with braces \
+                           or followed by a semicolon";
+                self.span_err(self.prev_span, msg);
+            }
+        }
+
+        let hi = self.prev_span.hi;
+        let kind = ItemKind::MacroDef(tts);
+        Ok(Some(self.mk_item(lo, hi, id, kind, Visibility::Inherited, attrs.to_owned())))
+    }
+
     fn parse_stmt_without_recovery(&mut self,
                                    macro_legacy_warnings: bool)
                                    -> PResult<'a, Option<Stmt>> {
@@ -3718,6 +3780,12 @@ fn parse_stmt_without_recovery(&mut self,
                 node: StmtKind::Local(self.parse_local(attrs.into())?),
                 span: mk_sp(lo, self.prev_span.hi),
             }
+        } else if let Some(macro_def) = self.eat_macro_def(&attrs, &Visibility::Inherited)? {
+            Stmt {
+                id: ast::DUMMY_NODE_ID,
+                node: StmtKind::Item(macro_def),
+                span: mk_sp(lo, self.prev_span.hi),
+            }
         // Starts like a simple path, but not a union item.
         } else if self.token.is_path_start() &&
                   !self.token.is_qpath_start() &&
@@ -4605,7 +4673,7 @@ pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> {
 
         let mut attrs = self.parse_outer_attributes()?;
         let lo = self.span.lo;
-        let vis = self.parse_visibility(true)?;
+        let vis = self.parse_visibility()?;
         let defaultness = self.parse_defaultness()?;
         let (name, node) = if self.eat_keyword(keywords::Type) {
             let name = self.parse_ident()?;
@@ -4839,6 +4907,7 @@ fn parse_poly_trait_ref(&mut self) -> PResult<'a, PolyTraitRef> {
     /// Parse struct Foo { ... }
     fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
         let class_name = self.parse_ident()?;
+
         let mut generics = self.parse_generics()?;
 
         // There is a special case worth noting here, as reported in issue #17904.
@@ -4888,6 +4957,7 @@ fn parse_item_struct(&mut self) -> PResult<'a, ItemInfo> {
     /// Parse union Foo { ... }
     fn parse_item_union(&mut self) -> PResult<'a, ItemInfo> {
         let class_name = self.parse_ident()?;
+
         let mut generics = self.parse_generics()?;
 
         let vdata = if self.token.is_keyword(keywords::Where) {
@@ -4936,7 +5006,7 @@ pub fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
             |p| {
                 let attrs = p.parse_outer_attributes()?;
                 let lo = p.span.lo;
-                let mut vis = p.parse_visibility(false)?;
+                let mut vis = p.parse_visibility()?;
                 let ty_is_interpolated =
                     p.token.is_interpolated() || p.look_ahead(1, |t| t.is_interpolated());
                 let mut ty = p.parse_ty()?;
@@ -4993,38 +5063,46 @@ pub fn parse_single_struct_field(&mut self,
     fn parse_struct_decl_field(&mut self) -> PResult<'a, StructField> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span.lo;
-        let vis = self.parse_visibility(true)?;
+        let vis = self.parse_visibility()?;
         self.parse_single_struct_field(lo, vis, attrs)
     }
 
-    // If `allow_path` is false, just parse the `pub` in `pub(path)` (but still parse `pub(crate)`)
-    fn parse_visibility(&mut self, allow_path: bool) -> PResult<'a, Visibility> {
-        let pub_crate = |this: &mut Self| {
-            let span = this.prev_span;
-            this.expect(&token::CloseDelim(token::Paren))?;
-            Ok(Visibility::Crate(span))
-        };
-
+    // Parse `pub`, `pub(crate)` and `pub(in path)` plus shortcuts
+    // `pub(self)` for `pub(in self)` and `pub(super)` for `pub(in super)`.
+    fn parse_visibility(&mut self) -> PResult<'a, Visibility> {
         if !self.eat_keyword(keywords::Pub) {
-            Ok(Visibility::Inherited)
-        } else if !allow_path {
-            // Look ahead to avoid eating the `(` in `pub(path)` while still parsing `pub(crate)`
-            if self.token == token::OpenDelim(token::Paren) &&
-               self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) {
-                self.bump(); self.bump();
-                pub_crate(self)
-            } else {
-                Ok(Visibility::Public)
-            }
-        } else if !self.eat(&token::OpenDelim(token::Paren)) {
-            Ok(Visibility::Public)
-        } else if self.eat_keyword(keywords::Crate) {
-            pub_crate(self)
-        } else {
-            let path = self.parse_path(PathStyle::Mod)?.default_to_global();
-            self.expect(&token::CloseDelim(token::Paren))?;
-            Ok(Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID })
-        }
+            return Ok(Visibility::Inherited)
+        }
+
+        if self.check(&token::OpenDelim(token::Paren)) {
+            if self.look_ahead(1, |t| t.is_keyword(keywords::Crate)) {
+                // `pub(crate)`
+                self.bump(); // `(`
+                self.bump(); // `crate`
+                let vis = Visibility::Crate(self.prev_span);
+                self.expect(&token::CloseDelim(token::Paren))?; // `)`
+                return Ok(vis)
+            } else if self.look_ahead(1, |t| t.is_keyword(keywords::In)) {
+                // `pub(in path)`
+                self.bump(); // `(`
+                self.bump(); // `in`
+                let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path`
+                let vis = Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID };
+                self.expect(&token::CloseDelim(token::Paren))?; // `)`
+                return Ok(vis)
+            } else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
+                      self.look_ahead(1, |t| t.is_keyword(keywords::Super) ||
+                                             t.is_keyword(keywords::SelfValue)) {
+                // `pub(self)` or `pub(super)`
+                self.bump(); // `(`
+                let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self`
+                let vis = Visibility::Restricted { path: P(path), id: ast::DUMMY_NODE_ID };
+                self.expect(&token::CloseDelim(token::Paren))?; // `)`
+                return Ok(vis)
+            }
+        }
+
+        Ok(Visibility::Public)
     }
 
     /// Parse defaultness: DEFAULT or nothing
@@ -5499,7 +5577,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
 
         let lo = self.span.lo;
 
-        let visibility = self.parse_visibility(true)?;
+        let visibility = self.parse_visibility()?;
 
         if self.eat_keyword(keywords::Use) {
             // USE ITEM
@@ -5767,6 +5845,10 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
                                     maybe_append(attrs, extra_attrs));
             return Ok(Some(item));
         }
+        if let Some(macro_def) = self.eat_macro_def(&attrs, &visibility)? {
+            return Ok(Some(macro_def));
+        }
+
         self.parse_macro_use_or_failure(attrs,macros_allowed,attributes_allowed,lo,visibility)
     }
 
@@ -5774,7 +5856,7 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
     fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span.lo;
-        let visibility = self.parse_visibility(true)?;
+        let visibility = self.parse_visibility()?;
 
         if self.check_keyword(keywords::Static) {
             // FOREIGN STATIC ITEM
@@ -5902,7 +5984,7 @@ fn parse_view_path(&mut self) -> PResult<'a, P<ViewPath>> {
             // `{foo, bar}`, `::{foo, bar}`, `*`, or `::*`.
             self.eat(&token::ModSep);
             let prefix = ast::Path {
-                segments: vec![ast::PathSegment::crate_root()],
+                segments: vec![PathSegment::crate_root()],
                 span: mk_sp(lo, self.span.hi),
             };
             let view_path_kind = if self.eat(&token::BinOp(token::Star)) {
@@ -5948,7 +6030,6 @@ pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> {
             attrs: self.parse_inner_attributes()?,
             module: self.parse_mod_items(&token::Eof, lo)?,
             span: mk_sp(lo, self.span.lo),
-            exported_macros: Vec::new(),
         })
     }
 
index 5b65aac92b81c2d28ad6efe19d6ba38e1d0c59bc..25601f2420e8a7d680d4f21c2861200f3e55ce3e 100644 (file)
@@ -86,6 +86,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
     !ident_token.is_any_keyword() ||
     ident_token.is_path_segment_keyword() ||
     [
+        keywords::Do.name(),
         keywords::Box.name(),
         keywords::Break.name(),
         keywords::Continue.name(),
index 53ef8e8dfa49c3c225a8abfacd59827f6c1da906..83753f398a3765cd7e3df0424a89cf97c7fae479 100644 (file)
@@ -1318,7 +1318,6 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.bclose(item.span)?;
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
-                self.print_visibility(&item.vis)?;
                 self.print_path(&node.path, false, 0, false)?;
                 word(&mut self.s, "! ")?;
                 self.print_ident(item.ident)?;
@@ -1329,6 +1328,16 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 word(&mut self.s, ";")?;
                 self.end()?;
             }
+            ast::ItemKind::MacroDef(ref tts) => {
+                word(&mut self.s, "macro_rules! ")?;
+                self.print_ident(item.ident)?;
+                self.cbox(INDENT_UNIT)?;
+                self.popen()?;
+                self.print_tts(tts.clone().into())?;
+                self.pclose()?;
+                word(&mut self.s, ";")?;
+                self.end()?;
+            }
         }
         self.ann.post(self, NodeItem(item))
     }
@@ -2270,6 +2279,11 @@ fn print_expr_outer_attr_style(&mut self,
                 self.print_expr(e)?;
                 word(&mut self.s, "?")?
             }
+            ast::ExprKind::Catch(ref blk) => {
+                self.head("do catch")?;
+                space(&mut self.s)?;
+                self.print_block_with_attrs(&blk, attrs)?
+            }
         }
         self.ann.post(self, NodeExpr(expr))?;
         self.end()
index 4a2dfaf61247cb1648e5ea6ce0a3ffb049556421..2192d203cdc23cce08e67e73d352d4e35640d5b4 100644 (file)
@@ -82,7 +82,7 @@ pub fn maybe_inject_crates_ref(sess: &ParseSess,
         vis: ast::Visibility::Inherited,
         node: ast::ItemKind::Use(P(codemap::dummy_spanned(ast::ViewPathGlob(ast::Path {
             segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
-                ast::Ident::from_str(name).into()
+                ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
             }).collect(),
             span: span,
         })))),
index c278171aa109a81120433777fafd9a4504dedb53..6642c60d256b3c4e40e0cc437ddb60993544e1f6 100644 (file)
@@ -221,9 +221,10 @@ fn fresh() -> Self {
     (53, Default,        "default")
     (54, StaticLifetime, "'static")
     (55, Union,          "union")
+    (56, Catch,          "catch")
 
     // A virtual keyword that resolves to the crate root when used in a lexical scope.
-    (56, CrateRoot, "{{root}}")
+    (57, CrateRoot, "{{root}}")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
index dd2756cd2b22c95aa42b715c59a095488ab4bf41..e052d2cda3a42469b000be576f82b416a08bb20c 100644 (file)
@@ -580,7 +580,7 @@ fn nospan<T>(t: T) -> codemap::Spanned<T> {
 fn path_node(ids: Vec<Ident>) -> ast::Path {
     ast::Path {
         span: DUMMY_SP,
-        segments: ids.into_iter().map(Into::into).collect(),
+        segments: ids.into_iter().map(|id| ast::PathSegment::from_ident(id, DUMMY_SP)).collect(),
     }
 }
 
index b90802d1e7eb8f908b5a5de1ac6957789712c7db..9d9957a0f45341c06746f44d886b842b1caa0c28 100644 (file)
@@ -148,9 +148,4 @@ fn visit_assoc_type_binding(&mut self, type_binding: &TypeBinding) {
     fn visit_attribute(&mut self, _attr: &Attribute) {
         self.count += 1;
     }
-    fn visit_macro_def(&mut self, macro_def: &MacroDef) {
-        self.count += 1;
-        walk_macro_def(self, macro_def)
-    }
-
 }
index 013632141dee69b27baf174a1abfe5a62b9fb973..a5333f3bb6a6e46c1f3af1c8e1d30194c194d897 100644 (file)
@@ -125,9 +125,6 @@ fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
         walk_assoc_type_binding(self, type_binding)
     }
     fn visit_attribute(&mut self, _attr: &'ast Attribute) {}
-    fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
-        walk_macro_def(self, macro_def)
-    }
     fn visit_vis(&mut self, vis: &'ast Visibility) {
         walk_vis(self, vis)
     }
@@ -176,12 +173,6 @@ pub fn walk_ident<'a, V: Visitor<'a>>(visitor: &mut V, span: Span, ident: Ident)
 pub fn walk_crate<'a, V: Visitor<'a>>(visitor: &mut V, krate: &'a Crate) {
     visitor.visit_mod(&krate.module, krate.span, CRATE_NODE_ID);
     walk_list!(visitor, visit_attribute, &krate.attrs);
-    walk_list!(visitor, visit_macro_def, &krate.exported_macros);
-}
-
-pub fn walk_macro_def<'a, V: Visitor<'a>>(visitor: &mut V, macro_def: &'a MacroDef) {
-    visitor.visit_ident(macro_def.span, macro_def.ident);
-    walk_list!(visitor, visit_attribute, &macro_def.attrs);
 }
 
 pub fn walk_mod<'a, V: Visitor<'a>>(visitor: &mut V, module: &'a Mod) {
@@ -295,6 +286,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             walk_list!(visitor, visit_trait_item, methods);
         }
         ItemKind::Mac(ref mac) => visitor.visit_mac(mac),
+        ItemKind::MacroDef(..) => {},
     }
     walk_list!(visitor, visit_attribute, &item.attrs);
 }
@@ -787,6 +779,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
         ExprKind::Try(ref subexpression) => {
             visitor.visit_expr(subexpression)
         }
+        ExprKind::Catch(ref body) => {
+            visitor.visit_block(body)
+        }
     }
 
     visitor.visit_expr_post(expression)
index 1fc1bdff593c2766fa16ab94bad998451f82e0ee..dc4b8eb24cd0a570ce18531a84024bd2e90ebff9 100644 (file)
@@ -61,7 +61,7 @@ impl Result {
         fn path(&self) -> ast::Path {
             ast::Path {
                 span: self.span,
-                segments: vec![self.ident.into()],
+                segments: vec![ast::PathSegment::from_ident(self.ident, self.span)],
             }
         }
     }
index 3bceb02f3d6c5af6a2e2cff0a5cb9c452ce275c5..b51591bf89d5e2275724a87d7a41c6d82dcb72c6 100644 (file)
@@ -99,7 +99,7 @@ pub fn is_builtin_trait(name: ast::Name) -> bool {
 
         pub fn register_builtin_derives(resolver: &mut Resolver) {
             $(
-                resolver.add_ext(
+                resolver.add_builtin(
                     ast::Ident::with_empty_ctxt(Symbol::intern($name)),
                     Rc::new(SyntaxExtension::BuiltinDerive($func))
                 );
index f92cde4019f67b06e9147c6264badd7e4e41cfac..1e9b112b6df564263738be5f058d2e4c1a54bed6 100644 (file)
@@ -59,7 +59,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
     deriving::register_builtin_derives(resolver);
 
     let mut register = |name, ext| {
-        resolver.add_ext(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
+        resolver.add_builtin(ast::Ident::with_empty_ctxt(name), Rc::new(ext));
     };
 
     macro_rules! register {
index 9c96ad547e1ae33254dc8034826b68748db50bc9..5adaf470f2374be020e1e2b0330ad3d87cd99762 100644 (file)
@@ -90,12 +90,7 @@ pub fn modify(sess: &ParseSess,
 
     krate.module.items.push(mk_registrar(&mut cx, &derives, &attr_macros, &bang_macros));
 
-    if krate.exported_macros.len() > 0 {
-        handler.err("cannot export macro_rules! macros from a `proc-macro` \
-                     crate type currently");
-    }
-
-    return krate
+    krate
 }
 
 fn is_proc_macro_attr(attr: &ast::Attribute) -> bool {
@@ -251,6 +246,15 @@ fn collect_bang_proc_macro(&mut self, item: &'a ast::Item, attr: &'a ast::Attrib
 
 impl<'a> Visitor<'a> for CollectProcMacros<'a> {
     fn visit_item(&mut self, item: &'a ast::Item) {
+        if let ast::ItemKind::MacroDef(..) = item.node {
+            if self.is_proc_macro_crate &&
+               item.attrs.iter().any(|attr| attr.name() == "macro_export") {
+                let msg =
+                    "cannot export macro_rules! macros from a `proc-macro` crate type currently";
+                self.handler.span_err(item.span, msg);
+            }
+        }
+
         // First up, make sure we're checking a bare function. If we're not then
         // we're just not interested in this item.
         //
index 50ab09fb43f038e4f824eea6cb278f560d3e8621..859fb269364623b17e092efaba3f94e70ce97c5e 160000 (submodule)
--- a/src/llvm
+++ b/src/llvm
@@ -1 +1 @@
-Subproject commit 50ab09fb43f038e4f824eea6cb278f560d3e8621
+Subproject commit 859fb269364623b17e092efaba3f94e70ce97c5e
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
deleted file mode 100644 (file)
index 57f37ea..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
-# The actual contents of this file do not matter, but to trigger a change on the
-# build bots then the contents should be changed so git updates the mtime.
-2017-03-02
diff --git a/src/rustllvm/llvm-rebuild-trigger b/src/rustllvm/llvm-rebuild-trigger
new file mode 100644 (file)
index 0000000..aeabf4a
--- /dev/null
@@ -0,0 +1,4 @@
+# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
+# The actual contents of this file do not matter, but to trigger a change on the
+# build bots then the contents should be changed so git updates the mtime.
+2017-03-04
index db2cd3b41656d3026d310bb08051d4073209475a..99e6e38a3bf0bd97654846d3f5c6e151d1d2b822 100644 (file)
@@ -27,3 +27,36 @@ pub fn write_pkd(pkd: &mut Packed) -> u32 {
     pkd.data = 42;
     result
 }
+
+pub struct Array([i32; 8]);
+#[repr(packed)]
+pub struct BigPacked {
+    dealign: u8,
+    data: Array
+}
+
+// CHECK-LABEL: @call_pkd
+#[no_mangle]
+pub fn call_pkd(f: fn() -> Array) -> BigPacked {
+// CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
+// CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* %{{.*}}, i8* %{{.*}}, i{{[0-9]+}} 32, i32 1, i1 false)
+    // check that calls whose destination is a field of a packed struct
+    // go through an alloca rather than calling the function with an
+    // unaligned destination.
+    BigPacked { dealign: 0, data: f() }
+}
+
+#[repr(packed)]
+#[derive(Copy, Clone)]
+pub struct PackedPair(u8, u32);
+
+// CHECK-LABEL: @pkd_pair
+#[no_mangle]
+pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) {
+    // CHECK: [[V1:%[a-z0-9]+]] = load i8, i8* %{{.*}}, align 1
+    // CHECK: [[V2:%[a-z0-9]+]] = load i32, i32* %{{.*}}, align 1
+    // CHECK: store i8 [[V1]], i8* {{.*}}, align 1
+    // CHECK: store i32 [[V2]], i32* {{.*}}, align 1
+    *pair2 = *pair1;
+}
index 9dc4cf1252ec33234f4c613b7c2447d541a46ef2..6f458da9b527ba861e1f330e77acb4e9771a2e7b 100644 (file)
@@ -55,7 +55,7 @@ pub struct Record {
         #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
         pub(crate) b_crate: i32,
         #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
-        pub(m) c_mod: i32,
+        pub(in m) c_mod: i32,
         #[stable(feature = "unit_test", since = "0.0.0")] // SILLY
         d_priv: i32
     }
@@ -71,7 +71,7 @@ pub struct Tuple(
         pub i32,
 
         pub(crate) i32,
-        pub(m) i32,
+        pub(in m) i32,
         i32);
 
     impl Record {
@@ -124,7 +124,7 @@ pub fn stable(&self) -> i32 { self.d_priv }
         #[unstable(feature = "unstable_undeclared", issue = "38412")] // SILLY
         pub(crate) fn pub_crate(&self) -> i32 { self.d_priv }
         #[unstable(feature = "unstable_declared", issue = "38412")] // SILLY
-        pub(m) fn pub_mod(&self) -> i32 { self.d_priv }
+        pub(in m) fn pub_mod(&self) -> i32 { self.d_priv }
         #[stable(feature = "unit_test", since = "0.0.0")] // SILLY
         fn private(&self) -> i32 { self.d_priv }
     }
@@ -138,7 +138,7 @@ pub fn unstable_declared(&self) -> i32 { self.0 }
         pub fn stable(&self) -> i32 { self.0 }
 
         pub(crate) fn pub_crate(&self) -> i32 { self.0 }
-        pub(m) fn pub_mod(&self) -> i32 { self.0 }
+        pub(in m) fn pub_mod(&self) -> i32 { self.0 }
         fn private(&self) -> i32 { self.0 }
     }
 }
diff --git a/src/test/compile-fail/catch-in-match.rs b/src/test/compile-fail/catch-in-match.rs
new file mode 100644 (file)
index 0000000..9f9968e
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(catch_expr)]
+
+fn main() {
+    match do catch { false } { _ => {} } //~ ERROR expected expression, found reserved keyword `do`
+}
diff --git a/src/test/compile-fail/catch-in-while.rs b/src/test/compile-fail/catch-in-while.rs
new file mode 100644 (file)
index 0000000..cb8613e
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(catch_expr)]
+
+fn main() {
+    while do catch { false } {} //~ ERROR expected expression, found reserved keyword `do`
+}
diff --git a/src/test/compile-fail/feature-gate-catch_expr.rs b/src/test/compile-fail/feature-gate-catch_expr.rs
new file mode 100644 (file)
index 0000000..5568a5c
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+    let catch_result = do catch { //~ ERROR `catch` expression is experimental
+        let x = 5;
+        x
+    };
+    assert_eq!(catch_result, 5);
+}
diff --git a/src/test/compile-fail/issue-40288-2.rs b/src/test/compile-fail/issue-40288-2.rs
new file mode 100644 (file)
index 0000000..c1e8cb8
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn prove_static<T: 'static + ?Sized>(_: &'static T) {}
+
+fn lifetime_transmute_slice<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
+    let mut out = [x];
+    //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
+    {
+        let slice: &mut [_] = &mut out;
+        slice[0] = y;
+    }
+    out[0]
+}
+
+struct Struct<T, U: ?Sized> {
+    head: T,
+    _tail: U
+}
+
+fn lifetime_transmute_struct<'a, T: ?Sized>(x: &'a T, y: &T) -> &'a T {
+    let mut out = Struct { head: x, _tail: [()] };
+    //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
+    {
+        let dst: &mut Struct<_, [()]> = &mut out;
+        dst.head = y;
+    }
+    out.head
+}
+
+fn main() {
+    prove_static(lifetime_transmute_slice("", &String::from("foo")));
+    prove_static(lifetime_transmute_struct("", &String::from("bar")));
+}
diff --git a/src/test/compile-fail/issue-40288.rs b/src/test/compile-fail/issue-40288.rs
new file mode 100644 (file)
index 0000000..b5418e8
--- /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.
+
+fn save_ref<'a>(refr: &'a i32, to: &mut [&'a i32]) {
+    for val in &mut *to {
+        *val = refr;
+    }
+}
+
+fn main() {
+    let ref init = 0i32;
+    let ref mut refr = 1i32;
+
+    let mut out = [init];
+
+    save_ref(&*refr, &mut out);
+
+    // This shouldn't be allowed as `refr` is borrowed
+    *refr = 3; //~ ERROR cannot assign to `*refr` because it is borrowed
+
+    // Prints 3?!
+    println!("{:?}", out[0]);
+}
diff --git a/src/test/compile-fail/lint-unused-unsafe.rs b/src/test/compile-fail/lint-unused-unsafe.rs
deleted file mode 100644 (file)
index 5c8e73e..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Exercise the unused_unsafe attribute in some positive and negative cases
-
-#![allow(dead_code)]
-#![deny(unused_unsafe)]
-
-
-mod foo {
-    extern {
-        pub fn bar();
-    }
-}
-
-fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() }
-unsafe fn unsf() {}
-
-fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
-fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
-unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
-fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
-unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
-fn bad6() {
-    unsafe {                             // don't put the warning here
-        unsafe {                         //~ ERROR: unnecessary `unsafe` block
-            unsf()
-        }
-    }
-}
-unsafe fn bad7() {
-    unsafe {                             //~ ERROR: unnecessary `unsafe` block
-        unsafe {                         //~ ERROR: unnecessary `unsafe` block
-            unsf()
-        }
-    }
-}
-
-unsafe fn good0() { unsf() }
-fn good1() { unsafe { unsf() } }
-fn good2() {
-    /* bug uncovered when implementing warning about unused unsafe blocks. Be
-       sure that when purity is inherited that the source of the unsafe-ness
-       is tracked correctly */
-    unsafe {
-        unsafe fn what() -> Vec<String> { panic!() }
-
-        callback(|| {
-            what();
-        });
-    }
-}
-
-unsafe fn good3() { foo::bar() }
-fn good4() { unsafe { foo::bar() } }
-
-#[allow(unused_unsafe)] fn allowed() { unsafe {} }
-
-fn main() {}
index fb75b9aa1dd941ac83d9537b1f714f4c5743ad6d..e37b6a2bb9c99aa0993c5c3525edc5c322efc696 100644 (file)
@@ -79,7 +79,7 @@ fn load3<'a,'b>(ss: &'a SomeTrait) -> &'b SomeTrait {
     // which fails to type check.
 
     ss
-        //~^ ERROR lifetime bound not satisfied
+        //~^ ERROR cannot infer
         //~| ERROR cannot infer
 }
 
index dd94dfe1e0823463701bafc0f68dba06963dc831..c0dd5200f6cb4e97be5e24eddf6f1d699f27052a 100644 (file)
@@ -25,7 +25,7 @@ fn load(ss: &mut SomeStruct) -> Box<SomeTrait> {
     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
     // is illegal.
 
-    ss.r //~ ERROR lifetime bound not satisfied
+    ss.r //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
@@ -38,7 +38,7 @@ fn store(ss: &mut SomeStruct, b: Box<SomeTrait>) {
 fn store1<'b>(ss: &mut SomeStruct, b: Box<SomeTrait+'b>) {
     // Here we override the lifetimes explicitly, and so naturally we get an error.
 
-    ss.r = b; //~ ERROR lifetime bound not satisfied
+    ss.r = b; //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() {
index 4e2a69cb79e1945aa9e9a6fe076aace0c8140866..2d4b5545544c68556c2408360abf6be5c39326e8 100644 (file)
@@ -16,10 +16,10 @@ mod foo {
     mod bar {
         #[derive(Default)]
         pub struct S {
-            pub(foo) x: i32,
+            pub(in foo) x: i32,
         }
         impl S {
-            pub(foo) fn f(&self) -> i32 { 0 }
+            pub(in foo) fn f(&self) -> i32 { 0 }
         }
 
         pub struct S2 {
index e254e005656c10267149a8cadc2be0bed39a69af..53786d45c73ee36a2773d314348cd5558788236e 100644 (file)
@@ -15,7 +15,7 @@
 mod foo {
     pub mod bar {
         pub struct S {
-            pub(foo) x: i32,
+            pub(in foo) x: i32,
         }
     }
 
index 01e2c6cd7e8288b40a99fc27d9e42bbb9802e6cf..d55ee8221cd733f96c4b672b9610951c04f95088 100644 (file)
@@ -57,6 +57,6 @@ fn main() {
 }
 
 mod pathological {
-    pub(bad::path) mod m1 {} //~ ERROR failed to resolve. Maybe a missing `extern crate bad;`?
-    pub(foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules
+    pub(in bad::path) mod m1 {} //~ ERROR failed to resolve. Maybe a missing `extern crate bad;`?
+    pub(in foo) mod m2 {} //~ ERROR visibilities can only be restricted to ancestor modules
 }
index da7086cf554c3860788b0b004f1bdc4f81e6d6e6..cd0edc8fe7c4414775f91973b52877f5da9ee38f 100644 (file)
 #![feature(pub_restricted)]
 
 macro_rules! m {
-    ($p: path) => (pub($p) struct Z;)
+    ($p: path) => (pub(in $p) struct Z;)
 }
 
 struct S<T>(T);
 m!{ S<u8> } //~ ERROR type or lifetime parameters in visibility path
 //~^ ERROR expected module, found struct `S`
 
-mod foo {
-    struct S(pub(foo<T>) ()); //~ ERROR type or lifetime parameters in visibility path
-    //~^ ERROR cannot find type `T` in this scope
-}
-
 fn main() {}
index c5cf43e355d5aae777bef840103e56e29cf40c33..ad6c5a31bbbd3fbc4076af08cde2723acd0992ad 100644 (file)
@@ -27,7 +27,7 @@ fn make_object_good2<'a,'b,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'b> {
 
 fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box<SomeTrait+'c> {
     // A outlives 'a AND 'b...but not 'c.
-    box v as Box<SomeTrait+'a> //~ ERROR lifetime bound not satisfied
+    box v as Box<SomeTrait+'a> //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() {
index fb726e31af586a5ba81e434d086ccf8d3f7af9d1..17fd55b031b61463513dc077928a330bb5ffe6ac 100644 (file)
@@ -16,7 +16,7 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box<FnMut()->(isize) + 'a> {
 
 fn static_proc(x: &isize) -> Box<FnMut()->(isize) + 'static> {
     // This is illegal, because the region bound on `proc` is 'static.
-    Box::new(move|| { *x }) //~ ERROR does not fulfill the required lifetime
+    Box::new(move|| { *x }) //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() { }
index b4e527972e4765b6339e457ed769e6ab1e844301..e8ada6a1755719205422e74f43591b9bf8ea138f 100644 (file)
@@ -22,8 +22,8 @@ fn foo2<'a:'b,'b>(x: &'b mut (Dummy+'a)) -> &'b mut (Dummy+'b) {
 
 fn foo3<'a,'b>(x: &'a mut Dummy) -> &'b mut Dummy {
     // Without knowing 'a:'b, we can't coerce
-    x //~ ERROR lifetime bound not satisfied
-     //~^ ERROR cannot infer
+    x //~ ERROR cannot infer an appropriate lifetime
+     //~^ ERROR cannot infer an appropriate lifetime
 }
 
 struct Wrapper<T>(T);
index 6b5cd4dce265ac8461a88ecb1ba227861dc25efc..20878a91ede9907d88c2f178a7f8b9672261e14b 100644 (file)
 enum E {}
 trait Tr {}
 
-pub(E) struct S; //~ ERROR expected module, found enum `E`
-pub(Tr) struct Z; //~ ERROR expected module, found trait `Tr`
-pub(std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules
-pub(nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root
-pub(too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root
+pub(in E) struct S; //~ ERROR expected module, found enum `E`
+pub(in Tr) struct Z; //~ ERROR expected module, found trait `Tr`
+pub(in std::vec) struct F; //~ ERROR visibilities can only be restricted to ancestor modules
+pub(in nonexistent) struct G; //~ ERROR cannot find module `nonexistent` in the crate root
+pub(in too_soon) struct H; //~ ERROR cannot find module `too_soon` in the crate root
 
 // Visibilities are resolved eagerly without waiting for modules becoming fully populated.
 // Visibilities can only use ancestor modules legally which are always available in time,
index 1795ac95358d7c6c29c2bde494f0212b16ad6076..d3bf92e85f411a5207e03786dc844487d7417dcf 100644 (file)
@@ -21,7 +21,7 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
                                 -> Box<Get<&'min i32>>
     where 'max : 'min
 {
-    v //~ ERROR mismatched types
+    v //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
@@ -29,7 +29,7 @@ fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
     where 'max : 'min
 {
     // Previously OK:
-    v //~ ERROR mismatched types
+    v //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() { }
index ad059a467f570bb2d4b9e5ef872d907ff1f8522c..0e94e35df2839895fdc389f970eeb6396db708e0 100644 (file)
@@ -22,14 +22,14 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
     where 'max : 'min
 {
     // Previously OK, now an error as traits are invariant.
-    v //~ ERROR mismatched types
+    v //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
                                    -> Box<Get<&'max i32>>
     where 'max : 'min
 {
-    v //~ ERROR mismatched types
+    v //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() { }
index 9edb510b826a12df92df2fe2ea40966ca9ac98fa..aa3e06c015d503829e89c839c2beb07e52a40e4e 100644 (file)
@@ -18,14 +18,14 @@ fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
                                 -> Box<Get<&'min i32>>
     where 'max : 'min
 {
-    v //~ ERROR mismatched types
+    v //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
                                    -> Box<Get<&'max i32>>
     where 'max : 'min
 {
-    v //~ ERROR mismatched types
+    v //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() { }
index 2452c18f54347d6d639ae8cd06890016aaf79033..900b0829530f3c41923cb30a1feecac01b1251d2 100644 (file)
 
 // === GDB TESTS ===================================================================================
 
-// gdb-command:print 'c_style_enum::SINGLE_VARIANT'
+// gdbg-command:print 'c_style_enum::SINGLE_VARIANT'
+// gdbr-command:print c_style_enum::SINGLE_VARIANT
 // gdbg-check:$1 = TheOnlyVariant
 // gdbr-check:$1 = c_style_enum::SingleVariant::TheOnlyVariant
 
-// gdb-command:print 'c_style_enum::AUTO_ONE'
+// gdbg-command:print 'c_style_enum::AUTO_ONE'
+// gdbr-command:print c_style_enum::AUTO_ONE
 // gdbg-check:$2 = One
 // gdbr-check:$2 = c_style_enum::AutoDiscriminant::One
 
-// gdb-command:print 'c_style_enum::AUTO_TWO'
+// gdbg-command:print 'c_style_enum::AUTO_TWO'
+// gdbr-command:print c_style_enum::AUTO_TWO
 // gdbg-check:$3 = One
 // gdbr-check:$3 = c_style_enum::AutoDiscriminant::One
 
-// gdb-command:print 'c_style_enum::AUTO_THREE'
+// gdbg-command:print 'c_style_enum::AUTO_THREE'
+// gdbr-command:print c_style_enum::AUTO_THREE
 // gdbg-check:$4 = One
 // gdbr-check:$4 = c_style_enum::AutoDiscriminant::One
 
-// gdb-command:print 'c_style_enum::MANUAL_ONE'
+// gdbg-command:print 'c_style_enum::MANUAL_ONE'
+// gdbr-command:print c_style_enum::MANUAL_ONE
 // gdbg-check:$5 = OneHundred
 // gdbr-check:$5 = c_style_enum::ManualDiscriminant::OneHundred
 
-// gdb-command:print 'c_style_enum::MANUAL_TWO'
+// gdbg-command:print 'c_style_enum::MANUAL_TWO'
+// gdbr-command:print c_style_enum::MANUAL_TWO
 // gdbg-check:$6 = OneHundred
 // gdbr-check:$6 = c_style_enum::ManualDiscriminant::OneHundred
 
-// gdb-command:print 'c_style_enum::MANUAL_THREE'
+// gdbg-command:print 'c_style_enum::MANUAL_THREE'
+// gdbr-command:print c_style_enum::MANUAL_THREE
 // gdbg-check:$7 = OneHundred
 // gdbr-check:$7 = c_style_enum::ManualDiscriminant::OneHundred
 
index 3d21def3953b802fdffcf0d951060b53558448bc..e8c3597b8c8dd68fdbd194f10c79831b82032f54 100644 (file)
 
 // Make sure functions have proper names
 // gdb-command:info functions
-// gdb-check:[...]void[...]main([...]);
-// gdb-check:[...]void[...]some_function([...]);
-// gdb-check:[...]void[...]some_other_function([...]);
-// gdb-check:[...]void[...]zzz([...]);
+// gdbg-check:[...]void[...]main([...]);
+// gdbr-check:fn limited_debuginfo::main();
+// gdbg-check:[...]void[...]some_function([...]);
+// gdbr-check:fn limited_debuginfo::some_function();
+// gdbg-check:[...]void[...]some_other_function([...]);
+// gdbr-check:fn limited_debuginfo::some_other_function();
+// gdbg-check:[...]void[...]zzz([...]);
+// gdbr-check:fn limited_debuginfo::zzz();
 
 // gdb-command:run
 
index 4956313ad2214d2c0eb3c18232d2fac878906848..ae05bafe5adaa70c07967a202d8f929bf1771f3e 100644 (file)
@@ -14,9 +14,6 @@
 
 // === GDB TESTS ===================================================================================
 
-// there's no frame yet for gdb to reliably detect the language, set it explicitly
-// gdbr-command:set language rust
-
 // gdbg-command:print 'simple_struct::NO_PADDING_16'
 // gdbr-command:print simple_struct::NO_PADDING_16
 // gdbg-check:$1 = {x = 1000, y = -1001}
index 354a2c26cb36db21932bf0761eaace5cc161a478..b3c270411509592141fac499eb96864fb3d0c665 100644 (file)
@@ -14,9 +14,6 @@
 
 // === GDB TESTS ===================================================================================
 
-// there's no frame yet for gdb to reliably detect the language, set it explicitly
-// gdbr-command:set language rust
-
 // gdbg-command:print/d 'simple_tuple::NO_PADDING_8'
 // gdbr-command:print simple_tuple::NO_PADDING_8
 // gdbg-check:$1 = {__0 = -50, __1 = 50}
index 1d452907cf59acad2c58c4fedb74da2b66e302cb..fbbffe8953b38959a550565ba3fcd80128315e47 100644 (file)
@@ -35,7 +35,6 @@ fn main() {
 //     }
 //
 //     bb2: {
-//         StorageLive(_6);
 //         _0 = ();
 //         StorageDead(_4);
 //         StorageDead(_1);
diff --git a/src/test/run-make/dep-info-doesnt-run-much/Makefile b/src/test/run-make/dep-info-doesnt-run-much/Makefile
new file mode 100644 (file)
index 0000000..2fd8463
--- /dev/null
@@ -0,0 +1,4 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) foo.rs --emit dep-info
diff --git a/src/test/run-make/dep-info-doesnt-run-much/foo.rs b/src/test/run-make/dep-info-doesnt-run-much/foo.rs
new file mode 100644 (file)
index 0000000..3591182
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// We're only emitting dep info, so we shouldn't be running static analysis to
+// figure out that this program is erroneous.
+fn main() {
+    let a: u8 = "a";
+}
index c0f55893a3abe4370e0a779081591bd56a3cdc71..9e81636e36703c4372203d87202027456c7496db 100644 (file)
@@ -8,14 +8,36 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::fmt;
+
 #[repr(packed)]
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone)]
 struct Foo {
     a: i8,
     b: i16,
     c: i8
 }
 
+impl PartialEq for Foo {
+    fn eq(&self, other: &Foo) -> bool {
+        self.a == other.a && self.b == other.b && self.c == other.c
+    }
+}
+
+impl fmt::Debug for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let a = self.a;
+        let b = self.b;
+        let c = self.c;
+
+        f.debug_struct("Foo")
+            .field("a", &a)
+            .field("b", &b)
+            .field("c", &c)
+            .finish()
+    }
+}
+
 #[link(name = "test", kind = "static")]
 extern {
     fn foo(f: Foo) -> Foo;
index 0717af98b30b43c87600cdecba73241d1056b4a4..3d2dd380e488e76abadd2afed8c68435b56f4909 100644 (file)
@@ -12,6 +12,7 @@
 #![feature(no_core)]
 #![no_core]
 
+macro_rules! foo /* 60#0 */(( $ x : ident ) => { y + $ x });
 
 fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }
 
diff --git a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs
deleted file mode 100644 (file)
index 3bc4a40..0000000
+++ /dev/null
@@ -1,55 +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.
-
-// force-host
-
-#![feature(plugin_registrar, rustc_private)]
-#![feature(box_syntax)]
-
-#[macro_use] extern crate rustc;
-extern crate rustc_plugin;
-extern crate rustc_const_math;
-extern crate syntax;
-
-use rustc::mir::transform::{self, MirPass, MirSource};
-use rustc::mir::{Mir, Literal, Location};
-use rustc::mir::visit::MutVisitor;
-use rustc::ty::TyCtxt;
-use rustc::middle::const_val::ConstVal;
-use rustc_const_math::ConstInt;
-use rustc_plugin::Registry;
-
-struct Pass;
-
-impl transform::Pass for Pass {}
-
-impl<'tcx> MirPass<'tcx> for Pass {
-    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>,
-                    _: MirSource, mir: &mut Mir<'tcx>) {
-        Visitor.visit_mir(mir)
-    }
-}
-
-struct Visitor;
-
-impl<'tcx> MutVisitor<'tcx> for Visitor {
-    fn visit_literal(&mut self, literal: &mut Literal<'tcx>, _: Location) {
-        if let Literal::Value { ref mut value } = *literal {
-            if let ConstVal::Integral(ConstInt::I32(ref mut i @ 11)) = *value {
-                *i = 42;
-            }
-        }
-    }
-}
-
-#[plugin_registrar]
-pub fn plugin_registrar(reg: &mut Registry) {
-    reg.register_mir_pass(box Pass);
-}
diff --git a/src/test/run-pass-fulldeps/mir-pass.rs b/src/test/run-pass-fulldeps/mir-pass.rs
deleted file mode 100644 (file)
index 8ac4bf9..0000000
+++ /dev/null
@@ -1,23 +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:dummy_mir_pass.rs
-// ignore-stage1
-
-#![feature(plugin)]
-#![plugin(dummy_mir_pass)]
-
-fn math() -> i32 {
-    11
-}
-
-pub fn main() {
-    assert_eq!(math(), 42);
-}
diff --git a/src/test/run-pass/catch-expr.rs b/src/test/run-pass/catch-expr.rs
new file mode 100644 (file)
index 0000000..a9b28a5
--- /dev/null
@@ -0,0 +1,32 @@
+// 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(catch_expr)]
+
+struct catch {}
+
+pub fn main() {
+    let catch_result = do catch {
+        let x = 5;
+        x
+    };
+    assert_eq!(catch_result, 5);
+
+    let mut catch = true;
+    while catch { catch = false; }
+    assert_eq!(catch, false);
+
+    catch = if catch { false } else { true };
+    assert_eq!(catch, true);
+
+    match catch {
+        _ => {}
+    };
+}
diff --git a/src/test/run-pass/coerce-unsize-subtype.rs b/src/test/run-pass/coerce-unsize-subtype.rs
new file mode 100644 (file)
index 0000000..b19708f
--- /dev/null
@@ -0,0 +1,48 @@
+// 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.
+
+// pretty-expanded FIXME #23616
+
+use std::rc::Rc;
+
+fn lub_short<'a, T>(_: &[&'a T], _: &[&'a T]) {}
+
+// The two arguments are a subtype of their LUB, after coercion.
+fn long_and_short<'a, T>(xs: &[&'static T; 1], ys: &[&'a T; 1]) {
+    lub_short(xs, ys);
+}
+
+// The argument coerces to a subtype of the return type.
+fn long_to_short<'a, 'b, T>(xs: &'b [&'static T; 1]) -> &'b [&'a T] {
+    xs
+}
+
+// Rc<T> is covariant over T just like &T.
+fn long_to_short_rc<'a, T>(xs: Rc<[&'static T; 1]>) -> Rc<[&'a T]> {
+    xs
+}
+
+// LUB-coercion (if-else/match/array) coerces `xs: &'b [&'static T: N]`
+// to a subtype of the LUB of `xs` and `ys` (i.e. `&'b [&'a T]`),
+// regardless of the order they appear (in if-else/match/array).
+fn long_and_short_lub1<'a, 'b, T>(xs: &'b [&'static T; 1], ys: &'b [&'a T]) {
+    let _order1 = [xs, ys];
+    let _order2 = [ys, xs];
+}
+
+// LUB-coercion should also have the exact same effect when `&'b [&'a T; N]`
+// needs to be coerced, i.e. the resulting type is not &'b [&'static T], but
+// rather the `&'b [&'a T]` LUB.
+fn long_and_short_lub2<'a, 'b, T>(xs: &'b [&'static T], ys: &'b [&'a T; 1]) {
+    let _order1 = [xs, ys];
+    let _order2 = [ys, xs];
+}
+
+fn main() {}
index 4b32b881be73868eed9442a63fb2805c5ac5fa32..57407b8422371be2152d5d30207e1c78a17f6c8d 100644 (file)
@@ -8,15 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::fmt;
 use std::mem;
 
 #[repr(packed)]
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone)]
 struct Foo {
     bar: u8,
     baz: u64
 }
 
+impl PartialEq for Foo {
+    fn eq(&self, other: &Foo) -> bool {
+        self.bar == other.bar && self.baz == other.baz
+    }
+}
+
+impl fmt::Debug for Foo {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let bar = self.bar;
+        let baz = self.baz;
+
+        f.debug_struct("Foo")
+            .field("bar", &bar)
+            .field("baz", &baz)
+            .finish()
+    }
+}
+
 pub fn main() {
     let foos = [Foo { bar: 1, baz: 2 }; 10];
 
diff --git a/src/test/ui/codemap_tests/issue-38812-2.rs b/src/test/ui/codemap_tests/issue-38812-2.rs
deleted file mode 100644 (file)
index c476657..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let (x,) = (vec![],);
-}
diff --git a/src/test/ui/codemap_tests/issue-38812-2.stderr b/src/test/ui/codemap_tests/issue-38812-2.stderr
deleted file mode 100644 (file)
index 156a6bd..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/issue-38812-2.rs:12:17
-   |
-12 |     let (x,) = (vec![],);
-   |         ----    ^^^^^^ cannot infer type for `T`
-   |         |
-   |         consider giving a type to pattern
-   |
-   = note: this error originates in a macro outside of the current crate
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/codemap_tests/issue-38812.rs b/src/test/ui/codemap_tests/issue-38812.rs
deleted file mode 100644 (file)
index a9943f7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
-    let x = vec![];
-}
diff --git a/src/test/ui/codemap_tests/issue-38812.stderr b/src/test/ui/codemap_tests/issue-38812.stderr
deleted file mode 100644 (file)
index 6365e76..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/issue-38812.rs:12:13
-   |
-12 |     let x = vec![];
-   |         -   ^^^^^^ cannot infer type for `T`
-   |         |
-   |         consider giving `x` a type
-   |
-   = note: this error originates in a macro outside of the current crate
-
-error: aborting due to previous error
-
index f190f5dd0534d09999ccf95cd30d36e04df1bb75..383224b2f92737ac886c22f726abb5d18173bb52 100644 (file)
@@ -14,7 +14,7 @@ pub mod m {
     pub struct S(u8);
 
     pub mod n {
-        pub(m) struct Z(pub(m::n) u8);
+        pub(in m) struct Z(pub(in m::n) u8);
     }
 }
 
index d541aa599a48b2bdbbf24c1b8336c707c52ab246..dd04c5ce356c626224f5eda92cbc93e69edc4d5c 100644 (file)
@@ -1,26 +1,26 @@
 error[E0425]: cannot find value `A` in module `namespaced_enums`
-  --> $DIR/enums-are-namespaced-xc.rs:15:13
+  --> $DIR/enums-are-namespaced-xc.rs:15:31
    |
 15 |     let _ = namespaced_enums::A;
-   |             ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
+   |                               ^ not found in `namespaced_enums`
    |
    = help: possible candidate is found in another module, you can import it into scope:
              `use namespaced_enums::Foo::A;`
 
 error[E0425]: cannot find function `B` in module `namespaced_enums`
-  --> $DIR/enums-are-namespaced-xc.rs:18:13
+  --> $DIR/enums-are-namespaced-xc.rs:18:31
    |
 18 |     let _ = namespaced_enums::B(10);
-   |             ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
+   |                               ^ not found in `namespaced_enums`
    |
    = help: possible candidate is found in another module, you can import it into scope:
              `use namespaced_enums::Foo::B;`
 
 error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums`
-  --> $DIR/enums-are-namespaced-xc.rs:21:13
+  --> $DIR/enums-are-namespaced-xc.rs:21:31
    |
 21 |     let _ = namespaced_enums::C { a: 10 };
-   |             ^^^^^^^^^^^^^^^^^^^ not found in `namespaced_enums`
+   |                               ^ not found in `namespaced_enums`
    |
    = help: possible candidate is found in another module, you can import it into scope:
              `use namespaced_enums::Foo::C;`
index c7c42bcf239405088ebea527aaae1baa55e460cb..4dff2620319e4607dcee7cf5fe92c79bd922a8ab 100644 (file)
@@ -14,7 +14,7 @@ error[E0412]: cannot find type `Opiton` in this scope
   --> $DIR/levenshtein.rs:20:10
    |
 20 | type B = Opiton<u8>; // Misspelled type name from the prelude.
-   |          ^^^^^^^^^^ did you mean `Option`?
+   |          ^^^^^^ did you mean `Option`?
 
 error[E0412]: cannot find type `Baz` in this scope
   --> $DIR/levenshtein.rs:23:14
@@ -35,16 +35,16 @@ error[E0425]: cannot find function `foobar` in this scope
    |     ^^^^^^ did you mean `foo_bar`?
 
 error[E0412]: cannot find type `first` in module `m`
-  --> $DIR/levenshtein.rs:32:12
+  --> $DIR/levenshtein.rs:32:15
    |
 32 |     let b: m::first = m::second; // Misspelled item in module.
-   |            ^^^^^^^^ did you mean `m::First`?
+   |               ^^^^^ did you mean `First`?
 
 error[E0425]: cannot find value `second` in module `m`
-  --> $DIR/levenshtein.rs:32:23
+  --> $DIR/levenshtein.rs:32:26
    |
 32 |     let b: m::first = m::second; // Misspelled item in module.
-   |                       ^^^^^^^^^ did you mean `m::Second`?
+   |                          ^^^^^^ did you mean `Second`?
 
 error: aborting due to 8 previous errors
 
index 3d0c76c740ad6cc27abc93cd75a4c5917059bc0a..68bd74719f55cdadcac6d7384040706f467e1e9e 100644 (file)
@@ -18,7 +18,7 @@ mod m {
     pub struct S(u8);
 
     pub mod n {
-        pub(m) struct Z(pub(m::n) u8);
+        pub(in m) struct Z(pub(in m::n) u8);
     }
 
     use m::n::Z; // OK, only the type is imported
index 57c0ecc813505d39b31a9ffc956a1a970ef44274..85fb1777dea233abf7e71dd53e577a29a7ba84b5 100644 (file)
@@ -2,55 +2,73 @@ error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
    |
 27 |     a.I
-   |     ^ did you mean `a::I`?
+   |     ^--
+   |     |
+   |     did you mean `a::I`?
 
 error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:33:5
    |
 33 |     a.g()
-   |     ^ did you mean `a::g(...)`?
+   |     ^----
+   |     |
+   |     did you mean `a::g(...)`?
 
 error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:39:5
    |
 39 |     a.b.J
-   |     ^ did you mean `a::b`?
+   |     ^--
+   |     |
+   |     did you mean `a::b`?
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
    |
 45 |     a::b.J
-   |     ^^^^ did you mean `a::b::J`?
+   |     ^^^^--
+   |     |
+   |     did you mean `a::b::J`?
 
 error[E0423]: expected value, found module `a`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:51:5
    |
 51 |     a.b.f();
-   |     ^ did you mean `a::b`?
+   |     ^--
+   |     |
+   |     did you mean `a::b`?
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:55:12
    |
 55 |     v.push(a::b);
-   |            ^^^^ did you mean `a::I`?
+   |            ^^^-
+   |               |
+   |               did you mean `I`?
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:61:5
    |
 61 |     a::b.f()
-   |     ^^^^ did you mean `a::b::f(...)`?
+   |     ^^^^----
+   |     |
+   |     did you mean `a::b::f(...)`?
 
 error[E0423]: expected value, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:67:5
    |
 67 |     a::b
-   |     ^^^^ did you mean `a::I`?
+   |     ^^^-
+   |        |
+   |        did you mean `I`?
 
 error[E0423]: expected function, found module `a::b`
   --> $DIR/suggest-path-instead-of-mod-dot-item.rs:73:5
    |
 73 |     a::b()
-   |     ^^^^ did you mean `a::I`?
+   |     ^^^-
+   |        |
+   |        did you mean `I`?
 
 error: main function not found
 
index f0d363f7335f72c19d650efcfbdc3b38b1d78a7c..015dbfc3dc775fe509d4ac8e7bef1b8748332212 100644 (file)
@@ -2,7 +2,7 @@ error[E0405]: cannot find trait `Nonexist` in this scope
   --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:11:8
    |
 11 | fn f<F:Nonexist(isize) -> isize>(x: F) {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope
+   |        ^^^^^^^^ not found in this scope
 
 error[E0404]: expected trait, found type alias `Typedef`
   --> $DIR/unboxed-closure-sugar-nonexistent-trait.rs:17:8
diff --git a/src/test/ui/span/issue-40157.rs b/src/test/ui/span/issue-40157.rs
new file mode 100644 (file)
index 0000000..8f3a7ae
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main () {
+    {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
+}
diff --git a/src/test/ui/span/issue-40157.stderr b/src/test/ui/span/issue-40157.stderr
new file mode 100644 (file)
index 0000000..ad1c149
--- /dev/null
@@ -0,0 +1,14 @@
+error: `foo` does not live long enough
+  --> $DIR/issue-40157.rs:12:64
+   |
+12 |     {println!("{:?}", match { let foo = vec![1, 2]; foo.get(1) } { x => x });}
+   |      ----------------------------------------------------------^-------------
+   |      |                                              |          |
+   |      |                                              |          `foo` dropped here while still borrowed
+   |      |                                              borrow occurs here
+   |      borrowed value needs to live until here
+   |
+   = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs
new file mode 100644 (file)
index 0000000..5c8e73e
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Exercise the unused_unsafe attribute in some positive and negative cases
+
+#![allow(dead_code)]
+#![deny(unused_unsafe)]
+
+
+mod foo {
+    extern {
+        pub fn bar();
+    }
+}
+
+fn callback<T, F>(_f: F) -> T where F: FnOnce() -> T { panic!() }
+unsafe fn unsf() {}
+
+fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
+fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+fn bad6() {
+    unsafe {                             // don't put the warning here
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+unsafe fn bad7() {
+    unsafe {                             //~ ERROR: unnecessary `unsafe` block
+        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+            unsf()
+        }
+    }
+}
+
+unsafe fn good0() { unsf() }
+fn good1() { unsafe { unsf() } }
+fn good2() {
+    /* bug uncovered when implementing warning about unused unsafe blocks. Be
+       sure that when purity is inherited that the source of the unsafe-ness
+       is tracked correctly */
+    unsafe {
+        unsafe fn what() -> Vec<String> { panic!() }
+
+        callback(|| {
+            what();
+        });
+    }
+}
+
+unsafe fn good3() { foo::bar() }
+fn good4() { unsafe { foo::bar() } }
+
+#[allow(unused_unsafe)] fn allowed() { unsafe {} }
+
+fn main() {}
diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.stderr
new file mode 100644 (file)
index 0000000..0df3fa4
--- /dev/null
@@ -0,0 +1,116 @@
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:26:13
+   |
+26 | fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
+   |             ^^^^^^^^^ unnecessary `unsafe` block
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-unsafe.rs:14:9
+   |
+14 | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:27:13
+   |
+27 | fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
+   |             ^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:28:20
+   |
+28 | unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+   |                    ^^^^^^^^^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:28:1
+   |
+28 | unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:29:13
+   |
+29 | fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:30:20
+   |
+30 | unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+   |                    ^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:30:1
+   |
+30 | unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:33:9
+   |
+33 |           unsafe {                         //~ ERROR: unnecessary `unsafe` block
+   |  _________^ starting here...
+34 | |             unsf()
+35 | |         }
+   | |_________^ ...ending here: unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:32:5
+   |
+32 |       unsafe {                             // don't put the warning here
+   |  _____^ starting here...
+33 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+34 | |             unsf()
+35 | |         }
+36 | |     }
+   | |_____^ ...ending here
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:39:5
+   |
+39 |       unsafe {                             //~ ERROR: unnecessary `unsafe` block
+   |  _____^ starting here...
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+41 | |             unsf()
+42 | |         }
+43 | |     }
+   | |_____^ ...ending here: unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:38:1
+   |
+38 |   unsafe fn bad7() {
+   |  _^ starting here...
+39 | |     unsafe {                             //~ ERROR: unnecessary `unsafe` block
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+41 | |             unsf()
+42 | |         }
+43 | |     }
+44 | | }
+   | |_^ ...ending here
+
+error: unnecessary `unsafe` block
+  --> $DIR/lint-unused-unsafe.rs:40:9
+   |
+40 |           unsafe {                         //~ ERROR: unnecessary `unsafe` block
+   |  _________^ starting here...
+41 | |             unsf()
+42 | |         }
+   | |_________^ ...ending here: unnecessary `unsafe` block
+   |
+note: because it's nested under this `unsafe` fn
+  --> $DIR/lint-unused-unsafe.rs:38:1
+   |
+38 |   unsafe fn bad7() {
+   |  _^ starting here...
+39 | |     unsafe {                             //~ ERROR: unnecessary `unsafe` block
+40 | |         unsafe {                         //~ ERROR: unnecessary `unsafe` block
+41 | |             unsf()
+42 | |         }
+43 | |     }
+44 | | }
+   | |_^ ...ending here
+
+error: aborting due to 8 previous errors
+
diff --git a/src/test/ui/span/suggestion-non-ascii.rs b/src/test/ui/span/suggestion-non-ascii.rs
new file mode 100644 (file)
index 0000000..67dbe1d
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+fn main() {
+    let tup = (1,);
+    println!("☃{}", tup[0]);
+}
+
diff --git a/src/test/ui/span/suggestion-non-ascii.stderr b/src/test/ui/span/suggestion-non-ascii.stderr
new file mode 100644 (file)
index 0000000..385c211
--- /dev/null
@@ -0,0 +1,11 @@
+error: cannot index a value of type `({integer},)`
+  --> $DIR/suggestion-non-ascii.rs:14:21
+   |
+14 |     println!("☃{}", tup[0]);
+   |                     ^^^^^^
+   |
+help: to access tuple elements, use tuple indexing syntax as shown
+   |     println!("☃{}", tup.0);
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-check/issue-38812-2.rs b/src/test/ui/type-check/issue-38812-2.rs
new file mode 100644 (file)
index 0000000..c476657
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let (x,) = (vec![],);
+}
diff --git a/src/test/ui/type-check/issue-38812-2.stderr b/src/test/ui/type-check/issue-38812-2.stderr
new file mode 100644 (file)
index 0000000..156a6bd
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-38812-2.rs:12:17
+   |
+12 |     let (x,) = (vec![],);
+   |         ----    ^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving a type to pattern
+   |
+   = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-check/issue-38812.rs b/src/test/ui/type-check/issue-38812.rs
new file mode 100644 (file)
index 0000000..a9943f7
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let x = vec![];
+}
diff --git a/src/test/ui/type-check/issue-38812.stderr b/src/test/ui/type-check/issue-38812.stderr
new file mode 100644 (file)
index 0000000..6365e76
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-38812.rs:12:13
+   |
+12 |     let x = vec![];
+   |         -   ^^^^^^ cannot infer type for `T`
+   |         |
+   |         consider giving `x` a type
+   |
+   = note: this error originates in a macro outside of the current crate
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-check/issue-40294.rs b/src/test/ui/type-check/issue-40294.rs
new file mode 100644 (file)
index 0000000..d30a425
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo: Sized {
+    fn foo(self);
+}
+
+fn foo<'a,'b,T>(x: &'a T, y: &'b T)
+    where &'a T : Foo,
+          &'b T : Foo
+{
+    x.foo();
+    y.foo();
+}
+
+fn main() { }
diff --git a/src/test/ui/type-check/issue-40294.stderr b/src/test/ui/type-check/issue-40294.stderr
new file mode 100644 (file)
index 0000000..5c388c9
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-40294.rs:15:1
+   |
+15 |   fn foo<'a,'b,T>(x: &'a T, y: &'b T)
+   |  _^ starting here...
+16 | |     where &'a T : Foo,
+17 | |           &'b T : Foo
+18 | | {
+19 | |     x.foo();
+20 | |     y.foo();
+21 | | }
+   | |_^ ...ending here: cannot infer type for `&'a T`
+
+error: aborting due to previous error
+
index ceefcc9e0ec46b80c0c07ea491f967ee96c15104..c2ec42195fcb7e16a76601780e46a10334e1ac60 100644 (file)
@@ -45,6 +45,7 @@
 
 static TARGETS: &'static [&'static str] = &[
     "aarch64-apple-ios",
+    "aarch64-unknown-fuchsia",
     "aarch64-linux-android",
     "aarch64-unknown-linux-gnu",
     "arm-linux-androideabi",
@@ -86,6 +87,7 @@
     "x86_64-pc-windows-msvc",
     "x86_64-rumprun-netbsd",
     "x86_64-unknown-freebsd",
+    "x86_64-unknown-fuchsia",
     "x86_64-unknown-linux-gnu",
     "x86_64-unknown-linux-musl",
     "x86_64-unknown-netbsd",
@@ -183,15 +185,19 @@ fn build(&mut self) {
         let mut manifest = BTreeMap::new();
         manifest.insert("manifest-version".to_string(),
                         toml::Value::String(manifest_version));
-        manifest.insert("date".to_string(), toml::Value::String(date));
+        manifest.insert("date".to_string(), toml::Value::String(date.clone()));
         manifest.insert("pkg".to_string(), toml::encode(&pkg));
         let manifest = toml::Value::Table(manifest).to_string();
 
         let filename = format!("channel-rust-{}.toml", self.rust_release);
         self.write_manifest(&manifest, &filename);
 
+        let filename = format!("channel-rust-{}-date.txt", self.rust_release);
+        self.write_date_stamp(&date, &filename);
+
         if self.rust_release != "beta" && self.rust_release != "nightly" {
             self.write_manifest(&manifest, "channel-rust-stable.toml");
+            self.write_date_stamp(&date, "channel-rust-stable-date.txt");
         }
     }
 
@@ -218,7 +224,7 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("rust-docs", &mut manifest.pkg, TARGETS);
         self.package("rust-src", &mut manifest.pkg, &["*"]);
 
-        if self.channel == "nightly" {
+        if self.rust_release == "nightly" {
             self.package("rust-analysis", &mut manifest.pkg, TARGETS);
         }
 
@@ -271,7 +277,7 @@ fn build_manifest(&mut self) -> Manifest {
                         target: target.to_string(),
                     });
                 }
-                if self.channel == "nightly" {
+                if self.rust_release == "nightly" {
                     extensions.push(Component {
                         pkg: "rust-analysis".to_string(),
                         target: target.to_string(),
@@ -411,4 +417,11 @@ fn write_manifest(&self, manifest: &str, name: &str) {
         self.hash(&dst);
         self.sign(&dst);
     }
+
+    fn write_date_stamp(&self, date: &str, name: &str) {
+        let dst = self.output.join(name);
+        t!(t!(File::create(&dst)).write_all(date.as_bytes()));
+        self.hash(&dst);
+        self.sign(&dst);
+    }
 }
diff --git a/src/tools/cargo b/src/tools/cargo
deleted file mode 160000 (submodule)
index d17b61a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit d17b61aa5a2ca790f268a043bffdb0ffb04f0ec7
index 40318141e04fa57716c45c673ab798eb33357789..d5b95c08306b27afc372d866f5bda97b814e7368 100644 (file)
@@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
 clap = "2.19.3"
 
 [dependencies.mdbook]
-version = "0.0.17"
+version = "0.0.18"
 default-features = false