diff options
674 files changed, 11848 insertions, 7829 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9c54dfd3388..c424ca7ab00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -415,4 +415,4 @@ are: [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/ [ro]: http://www.rustaceans.org/ [rctd]: ./src/test/COMPILER_TESTS.md -[cheatsheet]: https://buildbot.rust-lang.org/homu/ +[cheatsheet]: https://buildbot2.rust-lang.org/homu/ diff --git a/README.md b/README.md index b6ff6df0aec..78a9f509bbc 100644 --- a/README.md +++ b/README.md @@ -135,7 +135,7 @@ Windows build triples are: - `i686-pc-windows-msvc` - `x86_64-pc-windows-msvc` -The build triple can be specified by either specifying `--build=ABI` when +The build triple can be specified by either specifying `--build=<triple>` when invoking `x.py` commands, or by copying the `config.toml` file (as described in Building From Source), and modifying the `build` option under the `[build]` section. diff --git a/RELEASES.md b/RELEASES.md index 7bf0bcab640..c3a7367a2ee 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -92,7 +92,7 @@ Stabilized APIs Cargo ----- - [Cargo API token location moved from `~/.cargo/config` to - `~/cargo/credentials`.][cargo/3978] + `~/.cargo/credentials`.][cargo/3978] - [Cargo will now build `main.rs` binaries that are in sub-directories of `src/bin`.][cargo/4214] ie. Having `src/bin/server/main.rs` and `src/bin/client/main.rs` generates `target/debug/server` and `target/debug/client` @@ -172,7 +172,6 @@ Compatibility Notes [`slice::sort_unstable`]: https://doc.rust-lang.org/std/primitive.slice.html#method.sort_unstable [`ste::from_boxed_utf8_unchecked`]: https://doc.rust-lang.org/std/str/fn.from_boxed_utf8_unchecked.html [`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut -[`str::as_bytes_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.as_bytes_mut [`str::from_utf8_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_mut.html [`str::from_utf8_unchecked_mut`]: https://doc.rust-lang.org/std/str/fn.from_utf8_unchecked_mut.html [`str::get_mut`]: https://doc.rust-lang.org/std/primitive.str.html#method.get_mut @@ -898,6 +897,9 @@ Compatibility Notes * [Ctrl-Z returns from `Stdin.read()` when reading from the console on Windows][38274] * [Clean up semantics of `self` in an import list][38313] +* Reimplemented lifetime elision. This change was almost entirely compatible + with existing code, but it did close a number of small bugs and loopholes, + as well as being more accepting in some other [cases][41105]. [37057]: https://github.com/rust-lang/rust/pull/37057 [37761]: https://github.com/rust-lang/rust/pull/37761 @@ -932,6 +934,7 @@ Compatibility Notes [39048]: https://github.com/rust-lang/rust/pull/39048 [39282]: https://github.com/rust-lang/rust/pull/39282 [39379]: https://github.com/rust-lang/rust/pull/39379 +[41105]: https://github.com/rust-lang/rust/issues/41105 [`<*const T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset [`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset [`Duration::checked_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_add diff --git a/appveyor.yml b/appveyor.yml index aaede7236a9..f548d6694c8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ environment: RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler SCRIPT: python x.py test - MSYS_BITS: 32 - RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i586-pc-windows-msvc + RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --target=i686-pc-windows-msvc SCRIPT: python x.py test --host i686-pc-windows-msvc --target i686-pc-windows-msvc # MSVC aux tests @@ -145,7 +145,8 @@ install: # - set PATH=%PATH%;%CD% -- this already happens above for sccache # Install InnoSetup to get `iscc` used to produce installers - - appveyor-retry choco install -y InnoSetup + - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-08-22-is.exe + - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH% # Help debug some handle issues on AppVeyor diff --git a/config.toml.example b/config.toml.example index 48d27fa58ca..3f5101ebf34 100644 --- a/config.toml.example +++ b/config.toml.example @@ -73,6 +73,10 @@ # controlled by rustbuild's -j parameter. #link-jobs = 0 +# When invoking `llvm-config` this configures whether the `--shared` argument is +# passed to prefer linking to shared libraries. +#link-shared = false + # ============================================================================= # General build configuration options # ============================================================================= @@ -166,6 +170,15 @@ # to +10 on Unix platforms, and by using a "low priority" job object on Windows. #low-priority = false +# Arguments passed to the `./configure` script, used during distcheck. You +# probably won't fill this in but rather it's filled in by the `./configure` +# script. +#configure-args = [] + +# Indicates that a local rebuild is ocurring instead of a full bootstrap, +# essentially skipping stage0 as the local compiler is recompiling itself again. +#local-rebuild = false + # ============================================================================= # General install configuration options # ============================================================================= @@ -195,6 +208,13 @@ # ============================================================================= [rust] +# Indicates that the build should be optimized for debugging Rust. Note that +# this is typically not what you want as it takes an incredibly large amount of +# time to have a debug-mode rustc compile any code (notably libstd). If this +# value is set to `true` it will affect a number of configuration options below +# as well, if unconfigured. +#debug = false + # Whether or not to optimize the compiler and standard library # Note: the slowness of the non optimized compiler compiling itself usually # outweighs the time gains in not doing optimizations, therefore a @@ -249,6 +269,10 @@ # desired in distributions, for example. #rpath = true +# Suppresses extraneous output from tests to ensure the output of the test +# harness is relatively clean. +#quiet-tests = false + # Flag indicating whether tests are compiled with optimizations (the -O flag) or # with debuginfo (the -g flag) #optimize-tests = true @@ -264,6 +288,9 @@ # will default to true if channel = "dev", but will default to false otherwise. #ignore-git = true +# When creating source tarballs whether or not to create a source tarball. +#dist-src = false + # ============================================================================= # Options for specific targets # @@ -295,12 +322,22 @@ # build native code. #android-ndk = "/path/to/ndk" +# Force static or dynamic linkage of the standard library for this target. If +# this target is a host for rustc, this will also affect the linkage of the +# compiler itself. This is useful for building rustc on targets that normally +# only use static libraries. If unset, the target's default linkage is used. +#crt-static = false + # The root location of the MUSL installation directory. The library directory # will also need to contain libunwind.a for an unwinding implementation. Note # that this option only makes sense for MUSL targets that produce statically # linked binaries #musl-root = "..." +# Used in testing for configuring where the QEMU images are located, you +# probably don't want to use this. +#qemu-rootfs = "..." + # ============================================================================= # Distribution options # diff --git a/configure b/configure index 664b473b2c9..eeb8d081d34 100755 --- a/configure +++ b/configure @@ -1,779 +1,17 @@ #!/bin/sh -# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/bash is. -if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then - POSIX_SHELL="true" - export POSIX_SHELL - exec /usr/bin/env bash $0 "$@" -fi -unset POSIX_SHELL # clear it so if we invoke other scripts, they run as bash as well +script="$(dirname $0)"/src/bootstrap/configure.py -msg() { - echo "configure: $*" -} - -step_msg() { - msg - msg "$1" - msg -} - -warn() { - echo "configure: WARNING: $1" -} - -err() { - echo "configure: error: $1" - exit 1 -} - -run() { - msg "$@" - "$@" -} - -need_ok() { - if [ $? -ne 0 ] - then - err "$1" - fi -} - -need_cmd() { - if command -v $1 >/dev/null 2>&1 - then msg "found program '$1'" - else err "program '$1' is missing, please install it" - fi -} - -make_dir() { - if [ ! -d $1 ] - then - run mkdir -p $1 - fi -} - -copy_if_changed() { - if cmp -s $1 $2 - then - msg "leaving $2 unchanged" - else - run cp -f $1 $2 - chmod u-w $2 # make copied artifact read-only - fi -} - -move_if_changed() { - if cmp -s $1 $2 - then - msg "leaving $2 unchanged" - else - run mv -f $1 $2 - chmod u-w $2 # make moved artifact read-only - fi -} - -putvar() { - local T - eval T=\$$1 - eval TLEN=\${#$1} - if [ $TLEN -gt 35 ] - then - printf "configure: %-20s := %.35s ...\n" $1 "$T" - else - printf "configure: %-20s := %s %s\n" $1 "$T" "$2" - fi - printf "%-20s := %s\n" $1 "$T" >>config.tmp -} - -putpathvar() { - local T - eval T=\$$1 - eval TLEN=\${#$1} - if [ $TLEN -gt 35 ] - then - printf "configure: %-20s := %.35s ...\n" $1 "$T" - else - printf "configure: %-20s := %s %s\n" $1 "$T" "$2" - fi - if [ -z "$T" ] - then - printf "%-20s := \n" $1 >>config.tmp - else - printf "%-20s := \"%s\"\n" $1 "$T" >>config.tmp - fi -} - -probe() { - local V=$1 +try() { + cmd=$1 shift - local P - local T - for P - do - T=$(command -v $P 2>&1) - if [ $? -eq 0 ] - then - VER0=$($P --version 2>/dev/null \ - | grep -o '[vV]\?[0-9][0-9.][a-z0-9.-]*' | head -1 ) - if [ $? -eq 0 -a "x${VER0}" != "x" ] - then - VER="($VER0)" - else - VER="" - fi - break - else - VER="" - T="" - fi - done - eval $V=\$T - putpathvar $V "$VER" -} - -probe_need() { - probe $* - local V=$1 - shift - eval VV=\$$V - if [ -z "$VV" ] - then - err "$V needed, but unable to find any of: $*" - fi -} - -validate_opt () { - for arg in $CFG_CONFIGURE_ARGS - do - isArgValid=0 - for option in $BOOL_OPTIONS - do - if test --disable-$option = $arg - then - isArgValid=1 - fi - if test --enable-$option = $arg - then - isArgValid=1 - fi - done - for option in $VAL_OPTIONS - do - if echo "$arg" | grep -q -- "--$option=" - then - isArgValid=1 - fi - done - if [ "$arg" = "--help" ] - then - echo - echo "No more help available for Configure options," - echo "check the Wiki or join our IRC channel" - break - else - if test $isArgValid -eq 0 - then - err "Option '$arg' is not recognized" - fi - fi - done -} - -# `valopt OPTION_NAME DEFAULT DOC` extracts a string-valued option -# from command line, using provided default value for the option if -# not present, and saves it to the generated config.mk. -# -# `valopt_nosave` is much the same, except that it does not save the -# result to config.mk (instead the script should use `putvar` itself -# later on to save it). `valopt_core` is the core upon which the -# other two are built. - -valopt_core() { - VAL_OPTIONS="$VAL_OPTIONS $2" - - local SAVE=$1 - local OP=$2 - local DEFAULT=$3 - shift - shift - shift - local DOC="$*" - if [ $HELP -eq 0 ] - then - local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') - local V="CFG_${UOP}" - local V_PROVIDED="${V}_PROVIDED" - eval $V="$DEFAULT" - for arg in $CFG_CONFIGURE_ARGS - do - if echo "$arg" | grep -q -- "--$OP=" - then - val=$(echo "$arg" | cut -f2 -d=) - eval $V=$val - eval $V_PROVIDED=1 - fi - done - if [ "$SAVE" = "save" ] - then - putvar $V - fi - else - if [ -z "$DEFAULT" ] - then - DEFAULT="<none>" - fi - OP="${OP}=[${DEFAULT}]" - printf " --%-30s %s\n" "$OP" "$DOC" - fi -} - -valopt_nosave() { - valopt_core nosave "$@" -} - -valopt() { - valopt_core save "$@" -} - -# `opt OPTION_NAME DEFAULT DOC` extracts a boolean-valued option from -# command line, using the provided default value (0/1) for the option -# if not present, and saves it to the generated config.mk. -# -# `opt_nosave` is much the same, except that it does not save the -# result to config.mk (instead the script should use `putvar` itself -# later on to save it). `opt_core` is the core upon which the other -# two are built. - -opt_core() { - BOOL_OPTIONS="$BOOL_OPTIONS $2" - - local SAVE=$1 - local OP=$2 - local DEFAULT=$3 - shift - shift - shift - local DOC="$*" - local FLAG="" - - if [ $DEFAULT -eq 0 ] - then - FLAG="enable" - DEFAULT_FLAG="disable" - else - FLAG="disable" - DEFAULT_FLAG="enable" - DOC="don't $DOC" - fi - - if [ $HELP -eq 0 ] - then - for arg in $CFG_CONFIGURE_ARGS - do - if [ "$arg" = "--${FLAG}-${OP}" ] - then - OP=$(echo $OP | tr 'a-z-' 'A-Z_') - FLAG=$(echo $FLAG | tr 'a-z' 'A-Z') - local V="CFG_${FLAG}_${OP}" - local V_PROVIDED="CFG_${FLAG}_${OP}_PROVIDED" - eval $V=1 - eval $V_PROVIDED=1 - if [ "$SAVE" = "save" ] - then - putvar $V - fi - elif [ "$arg" = "--${DEFAULT_FLAG}-${OP}" ] - then - OP=$(echo $OP | tr 'a-z-' 'A-Z_') - DEFAULT_FLAG=$(echo $DEFAULT_FLAG | tr 'a-z' 'A-Z') - local V_PROVIDED="CFG_${DEFAULT_FLAG}_${OP}_PROVIDED" - eval $V_PROVIDED=1 - fi - done - else - if [ -n "$META" ] - then - OP="$OP=<$META>" - fi - printf " --%-30s %s\n" "$FLAG-$OP" "$DOC" - fi -} - -opt_nosave() { - opt_core nosave "$@" -} - -opt() { - opt_core save "$@" -} - -envopt() { - local NAME=$1 - local V="CFG_${NAME}" - eval VV=\$$V - - # If configure didn't set a value already, then check environment. - # - # (It is recommended that the configure script always check the - # environment before setting any values to envopt variables; see - # e.g. how CFG_CC is handled, where it first checks `-z "$CC"`, - # and issues msg if it ends up employing that provided value.) - if [ -z "$VV" ] - then - eval $V=\$$NAME - eval VV=\$$V - fi - - # If script or environment provided a value, save it. - if [ -n "$VV" ] - then - putvar $V - fi -} - -enable_if_not_disabled() { - local OP=$1 - local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_') - local ENAB_V="CFG_ENABLE_$UOP" - local EXPLICITLY_DISABLED="CFG_DISABLE_${UOP}_PROVIDED" - eval VV=\$$EXPLICITLY_DISABLED - if [ -z "$VV" ]; then - eval $ENAB_V=1 + T=$($cmd --version 2>/dev/null) + if [ $? -eq 0 ]; then + exec $cmd "$script" "$@" fi } -to_gnu_triple() { - case $1 in - i686-pc-windows-gnu) echo i686-w64-mingw32 ;; - x86_64-pc-windows-gnu) echo x86_64-w64-mingw32 ;; - *) echo $1 ;; - esac -} - -# Prints the absolute path of a directory to stdout -abs_path() { - local _path="$1" - # Unset CDPATH because it causes havok: it makes the destination unpredictable - # and triggers 'cd' to print the path to stdout. Route `cd`'s output to /dev/null - # for good measure. - (unset CDPATH && cd "$_path" > /dev/null && pwd) -} - -HELP=0 -for arg; do - case "$arg" in - --help) HELP=1;; - esac -done - -msg "looking for configure programs" -need_cmd cmp -need_cmd mkdir -need_cmd printf -need_cmd cut -need_cmd head -need_cmd grep -need_cmd xargs -need_cmd cp -need_cmd find -need_cmd uname -need_cmd date -need_cmd tr -need_cmd sed -need_cmd file -need_cmd make - -CFG_SRC_DIR="$(abs_path $(dirname $0))/" -CFG_SRC_DIR_RELATIVE="$(dirname $0)/" -CFG_BUILD_DIR="$(pwd)/" -CFG_SELF="$0" -CFG_CONFIGURE_ARGS="$@" - - -case "${CFG_SRC_DIR}" in - *\ * ) - err "The path to the rust source directory contains spaces, which is not supported" - ;; - *) - ;; -esac - - -OPTIONS="" -if [ "$HELP" -eq 1 ] -then - echo - echo "Usage: $CFG_SELF [options]" - echo - echo "Options:" - echo -else - msg "recreating config.tmp" - echo '' >config.tmp - - step_msg "processing $CFG_SELF args" -fi - -BOOL_OPTIONS="" -VAL_OPTIONS="" - -opt debug 0 "debug mode; disables optimization unless \`--enable-optimize\` given" -opt valgrind 0 "run tests with valgrind (memcheck by default)" -opt helgrind 0 "run tests with helgrind instead of memcheck" -opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind" -opt docs 1 "build standard library documentation" -opt compiler-docs 0 "build compiler documentation" -opt optimize-tests 1 "build tests with optimizations" -opt debuginfo-tests 0 "build tests with debugger metadata" -opt quiet-tests 0 "enable quieter output when running tests" -opt libcpp 1 "build llvm with libc++ instead of libstdc++ when using clang" -opt llvm-assertions 0 "build LLVM with assertions" -opt debug-assertions 0 "build with debugging assertions" -opt fast-make 0 "use .gitmodules as timestamp for submodule deps" -opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" -opt sccache 0 "invoke gcc/clang via sccache to reuse object files between builds" -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 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 -opt dist-host-only 0 "only install bins for the host architecture" -opt inject-std-version 1 "inject the current compiler version of libstd into programs" -opt llvm-version-check 1 "check if the LLVM version is supported, build anyway" -opt codegen-tests 1 "run the src/test/codegen tests" -opt option-checking 1 "complain about unrecognized options in this configure script" -opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)" -opt locked-deps 0 "force Cargo.lock to be up to date" -opt vendor 0 "enable usage of vendored Rust crates" -opt sanitizers 0 "build the sanitizer runtimes (asan, lsan, msan, tsan)" -opt dist-src 1 "when building tarballs enables building a source tarball" -opt cargo-openssl-static 0 "static openssl in cargo" -opt profiler 0 "build the profiler runtime" - -# Optimization and debugging options. These may be overridden by the release channel, etc. -opt_nosave optimize 1 "build optimized rust code" -opt_nosave optimize-cxx 1 "build optimized C++ code" -opt_nosave optimize-llvm 1 "build optimized LLVM" -opt_nosave llvm-assertions 0 "build LLVM with assertions" -opt_nosave debug-assertions 0 "build with debugging assertions" -opt_nosave llvm-release-debuginfo 0 "build LLVM with debugger metadata" -opt_nosave debuginfo 0 "build with debugger metadata" -opt_nosave debuginfo-lines 0 "build with line number debugger metadata" -opt_nosave debuginfo-only-std 0 "build only libstd with debugging information" -opt_nosave debug-jemalloc 0 "build jemalloc with --enable-debug --enable-fill" - -valopt localstatedir "/var/lib" "local state directory" -valopt sysconfdir "/etc" "install system configuration files" - -valopt datadir "${CFG_PREFIX}/share" "install data" -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 "" "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" -valopt armv7-linux-androideabi-ndk "" "armv7-linux-androideabi NDK standalone path" -valopt aarch64-linux-android-ndk "" "aarch64-linux-android NDK standalone path" -valopt x86_64-linux-android-ndk "" "x86_64-linux-android NDK standalone path" -valopt nacl-cross-path "" "NaCl SDK path (Pepper Canary is recommended). Must be absolute!" -valopt musl-root "/usr/local" "MUSL root installation directory (deprecated)" -valopt musl-root-x86_64 "" "x86_64-unknown-linux-musl install directory" -valopt musl-root-i686 "" "i686-unknown-linux-musl install directory" -valopt musl-root-arm "" "arm-unknown-linux-musleabi install directory" -valopt musl-root-armhf "" "arm-unknown-linux-musleabihf install directory" -valopt musl-root-armv7 "" "armv7-unknown-linux-musleabihf install directory" -valopt extra-filename "" "Additional data that is hashed and passed to the -C extra-filename flag" -valopt qemu-armhf-rootfs "" "rootfs in qemu testing, you probably don't want to use this" -valopt qemu-aarch64-rootfs "" "rootfs in qemu testing, you probably don't want to use this" -valopt experimental-targets "" "experimental LLVM targets to build" - -if [ -e ${CFG_SRC_DIR}.git ] -then - valopt release-channel "dev" "the name of the release channel to build" -else - # If we have no git directory then we are probably a tarball distribution - # and should default to stable channel - Issue 28322 - probe CFG_GIT git - msg "git: no git directory. Changing default release channel to stable" - valopt release-channel "stable" "the name of the release channel to build" -fi - -# Used on systems where "cc" and "ar" are unavailable -valopt default-linker "cc" "the default linker" -valopt default-ar "ar" "the default ar" - -# Many of these are saved below during the "writing configuration" step -# (others are conditionally saved). -opt_nosave manage-submodules 1 "let the build manage the git submodules" -opt_nosave clang 0 "prefer clang to gcc for building the runtime" -opt_nosave jemalloc 1 "build liballoc with jemalloc" -opt full-bootstrap 0 "build three compilers instead of two" -opt extended 0 "build an extended rust tool set" - -valopt_nosave prefix "/usr/local" "set installation prefix" -valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary" -valopt_nosave host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples" -valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples" -valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH" -valopt_nosave docdir "${CFG_PREFIX}/share/doc/rust" "install documentation in PATH" -valopt_nosave bindir "${CFG_PREFIX}/bin" "install binaries" - -# On Windows this determines root of the subtree for target libraries. -# Host runtime libs always go to 'bin'. -valopt libdir "${CFG_PREFIX}/lib" "install libraries" - -case "$CFG_LIBDIR" in - "$CFG_PREFIX"/*) CAT_INC=2;; - "$CFG_PREFIX"*) CAT_INC=1;; - *) - err "libdir must begin with the prefix. Use --prefix to set it accordingly.";; -esac - -CFG_LIBDIR_RELATIVE=`echo ${CFG_LIBDIR} | cut -c$((${#CFG_PREFIX}+${CAT_INC}))-` - -if [ $HELP -eq 1 ] -then - echo - exit 0 -fi - -# Validate Options -if [ -z "$CFG_DISABLE_OPTION_CHECKING" ] -then - step_msg "validating $CFG_SELF args" - validate_opt -fi - -# Validate the release channel, and configure options -case "$CFG_RELEASE_CHANNEL" in - nightly ) - msg "overriding settings for $CFG_RELEASE_CHANNEL" - enable_if_not_disabled llvm-assertions - # FIXME(stage0) re-enable this on the next stage0 now that #35566 is - # fixed - case "$CFG_BUILD" in - *-pc-windows-gnu) - ;; - *) - enable_if_not_disabled debuginfo-lines - enable_if_not_disabled debuginfo-only-std - ;; - esac - - ;; - beta | stable) - msg "overriding settings for $CFG_RELEASE_CHANNEL" - case "$CFG_BUILD" in - *-pc-windows-gnu) - ;; - *) - enable_if_not_disabled debuginfo-lines - enable_if_not_disabled debuginfo-only-std - ;; - esac - ;; - dev) - ;; - *) - err "release channel must be 'dev', 'nightly', 'beta' or 'stable'" - ;; -esac - -# Adjust perf and debug options for debug mode -if [ -n "$CFG_ENABLE_DEBUG" ]; then - msg "debug mode enabled, setting performance options" - if [ -z "$CFG_ENABLE_OPTIMIZE_PROVIDED" ]; then - msg "optimization not explicitly enabled, disabling optimization" - CFG_DISABLE_OPTIMIZE=1 - CFG_DISABLE_OPTIMIZE_CXX=1 - fi - - # Set following variables to 1 unless setting already provided - enable_if_not_disabled debug-assertions - enable_if_not_disabled debug-jemalloc - enable_if_not_disabled debuginfo - enable_if_not_disabled llvm-assertions -fi - -# OK, now write the debugging options -if [ -n "$CFG_DISABLE_OPTIMIZE" ]; then putvar CFG_DISABLE_OPTIMIZE; fi -if [ -n "$CFG_DISABLE_OPTIMIZE_CXX" ]; then putvar CFG_DISABLE_OPTIMIZE_CXX; fi -if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then putvar CFG_DISABLE_OPTIMIZE_LLVM; fi -if [ -n "$CFG_ENABLE_LLVM_ASSERTIONS" ]; then putvar CFG_ENABLE_LLVM_ASSERTIONS; fi -if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTIONS; fi -if [ -n "$CFG_ENABLE_LLVM_RELEASE_DEBUGINFO" ]; then putvar CFG_ENABLE_LLVM_RELEASE_DEBUGINFO; fi -if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi -if [ -n "$CFG_ENABLE_DEBUGINFO_LINES" ]; then putvar CFG_ENABLE_DEBUGINFO_LINES; fi -if [ -n "$CFG_ENABLE_DEBUGINFO_ONLY_STD" ]; then putvar CFG_ENABLE_DEBUGINFO_ONLY_STD; fi -if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi - -step_msg "looking for build programs" - -probe_need CFG_CURL curl -if [ -z "$CFG_PYTHON_PROVIDED" ]; then - probe_need CFG_PYTHON python2.7 python2 python -fi - -python_version=$($CFG_PYTHON -V 2>&1) -if [ $(echo $python_version | grep -c '^Python 2\.7') -ne 1 ]; then - err "Found $python_version, but Python 2.7 is required" -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" ] -then - # If the user has explicitly asked for valgrind tests, then fail - if [ -n "$CFG_ENABLE_VALGRIND" ] && [ -n "$CFG_ENABLE_VALGRIND_PROVIDED" ] - then - err "No valgrind present, but valgrind tests explicitly requested" - else - CFG_DISABLE_VALGRIND_RPASS=1 - putvar CFG_DISABLE_VALGRIND_RPASS - fi -fi - -# 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 - # Frequently the llvm submodule directory is broken by the build - # being killed - llvm_lock="${CFG_SRC_DIR}/.git/modules/src/llvm/index.lock" - if [ -e "$llvm_lock" ]; then - step_msg "removing $llvm_lock" - rm -f "$llvm_lock" - fi -fi - -BIN_SUF= -if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ] -then - BIN_SUF=.exe -fi - -# --enable-local-rebuild implies --enable-local-rust too -if [ -n "$CFG_ENABLE_LOCAL_REBUILD" ] -then - if [ -z "$CFG_ENABLE_LOCAL_RUST" ] - then - CFG_ENABLE_LOCAL_RUST=1 - putvar CFG_ENABLE_LOCAL_RUST - fi -fi - -if [ -n "$CFG_ENABLE_LOCAL_RUST" ] -then - system_rustc=$(which rustc) - if [ -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} ] - then - : # everything already configured - elif [ -n "$system_rustc" ] - then - # we assume that rustc is in a /bin directory - CFG_LOCAL_RUST_ROOT=${system_rustc%/bin/rustc} - else - err "no local rust to use" - fi - - CMD="${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF}" - LRV=`LD_LIBRARY_PATH=${CFG_LOCAL_RUST_ROOT}/lib $CMD --version` - if [ $? -ne 0 ] - then - step_msg "failure while running $CMD --version" - exit 1 - fi - step_msg "using rustc at: ${CFG_LOCAL_RUST_ROOT} with version: $LRV" - putvar CFG_LOCAL_RUST_ROOT -fi - -# Same with jemalloc. save the setting here. -if [ -n "$CFG_DISABLE_JEMALLOC" ] -then - putvar CFG_DISABLE_JEMALLOC -fi - -# All safeguards based on $CFG_ENABLE_CLANG should occur before this -# point in the script; after this point, script logic should inspect -# $CFG_USING_CLANG rather than $CFG_ENABLE_CLANG. - -# Set CFG_{CC,CXX,CPP,CFLAGS,CXXFLAGS,LDFLAGS} -envopt CC -envopt CXX -envopt CPP -envopt CFLAGS -envopt CXXFLAGS -envopt LDFLAGS - -# a little post-processing of various config values -CFG_PREFIX=${CFG_PREFIX%/} -CFG_MANDIR=${CFG_MANDIR%/} -CFG_DOCDIR=${CFG_DOCDIR%/} -CFG_BINDIR=${CFG_BINDIR%/} -CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')" -CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')" - -# copy build-triples to host-triples so that builds are a subset of hosts -V_TEMP="" -for i in $CFG_BUILD $CFG_HOST; -do - echo "$V_TEMP" | grep -qF $i || V_TEMP="$V_TEMP${V_TEMP:+ }$i" -done -CFG_HOST=$V_TEMP - -# copy host-triples to target-triples so that hosts are a subset of targets -V_TEMP="" -for i in $CFG_HOST $CFG_TARGET; -do - echo "$V_TEMP" | grep -qF $i || V_TEMP="$V_TEMP${V_TEMP:+ }$i" -done -CFG_TARGET=$V_TEMP - -step_msg "writing configuration" - -putvar CFG_SRC_DIR -putvar CFG_SRC_DIR_RELATIVE -putvar CFG_BUILD_DIR -putvar CFG_OSTYPE -putvar CFG_CPUTYPE -putvar CFG_CONFIGURE_ARGS -putvar CFG_PREFIX -putvar CFG_HOST -putvar CFG_TARGET -putvar CFG_LIBDIR_RELATIVE -putvar CFG_DISABLE_MANAGE_SUBMODULES -putvar CFG_AARCH64_LINUX_ANDROID_NDK -putvar CFG_ARM_LINUX_ANDROIDEABI_NDK -putvar CFG_ARMV7_LINUX_ANDROIDEABI_NDK -putvar CFG_I686_LINUX_ANDROID_NDK -putvar CFG_X86_64_LINUX_ANDROID_NDK -putvar CFG_NACL_CROSS_PATH -putvar CFG_MANDIR -putvar CFG_DOCDIR -putvar CFG_BINDIR -putvar CFG_USING_LIBCPP - -msg -copy_if_changed ${CFG_SRC_DIR}src/bootstrap/mk/Makefile.in ./Makefile -move_if_changed config.tmp config.mk -rm -f config.tmp -touch config.stamp - -if [ -z "$CFG_ENABLE_DEBUG" ]; then - step_msg "configured in release mode. for development consider --enable-debug" -else - step_msg "complete" -fi - -if [ "$CFG_SRC_DIR" = `pwd` ]; then - X_PY=x.py -else - X_PY=${CFG_SRC_DIR_RELATIVE}x.py -fi - -msg "run \`python ${X_PY} --help\`" -msg +try python2.7 "$@" +try python27 "$@" +try python2 "$@" +exec python $script "$@" diff --git a/src/Cargo.lock b/src/Cargo.lock index c175198c227..123c884585c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -94,7 +94,7 @@ dependencies = [ "dbghelp-sys 0.2.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.29 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -142,10 +142,10 @@ dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -161,9 +161,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "build-manifest" version = "0.1.0" dependencies = [ - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -176,7 +176,7 @@ dependencies = [ [[package]] name = "cargo" version = "0.22.0" -source = "git+https://github.com/rust-lang/cargo#88aa6423a164774d09abc78a24e74e8e665f651b" +source = "git+https://github.com/rust-lang/cargo#bcf3997b1fa177afc5b6c632a6fbbf6cc75df427" replace = "cargo 0.22.0" [[package]] @@ -187,6 +187,7 @@ dependencies = [ "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargotest 0.1.0", + "core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "crates-io 0.11.0", "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -210,19 +211,20 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (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.13 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -231,22 +233,16 @@ dependencies = [ name = "cargotest" version = "0.1.0" dependencies = [ - "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "cargo 0.22.0", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.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.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -260,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.25.1" +version = "2.26.0" 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)", @@ -268,8 +264,8 @@ dependencies = [ "bitflags 0.9.1 (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.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -324,13 +320,30 @@ dependencies = [ ] [[package]] +name = "core-foundation" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "crates-io" version = "0.11.0" dependencies = [ "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -348,8 +361,8 @@ dependencies = [ "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 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)", ] @@ -361,7 +374,7 @@ dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -397,8 +410,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -473,6 +486,10 @@ name = "find_all_refs_no_cfg_test" version = "0.1.0" [[package]] +name = "find_impls" +version = "0.1.0" + +[[package]] name = "flate2" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -529,7 +546,7 @@ dependencies = [ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -588,7 +605,7 @@ dependencies = [ "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -643,10 +660,22 @@ dependencies = [ ] [[package]] +name = "infer_bin" +version = "0.1.0" + +[[package]] +name = "infer_custom_bin" +version = "0.1.0" + +[[package]] +name = "infer_lib" +version = "0.1.0" + +[[package]] name = "installer" version = "0.0.0" dependencies = [ - "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -673,13 +702,13 @@ dependencies = [ [[package]] name = "jsonrpc-core" -version = "7.0.1" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -698,8 +727,8 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -733,7 +762,7 @@ dependencies = [ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -745,7 +774,7 @@ dependencies = [ "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -771,7 +800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lzma-sys" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -789,16 +818,16 @@ name = "mdbook" version = "0.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -832,7 +861,7 @@ version = "0.2.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)", - "net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.31 (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)", ] @@ -843,7 +872,7 @@ version = "0.1.0" [[package]] name = "net2" -version = "0.2.30" +version = "0.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -859,7 +888,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -879,7 +908,7 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -928,20 +957,24 @@ dependencies = [ ] [[package]] +name = "omit_init_build" +version = "0.1.0" + +[[package]] name = "open" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.9.15" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.9.1 (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.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -951,12 +984,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.15" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1051,14 +1085,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "racer" -version = "2.0.9" +version = "2.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1140,20 +1172,20 @@ version = "0.1.0" dependencies = [ "cargo 0.22.0 (git+https://github.com/rust-lang/cargo)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1177,8 +1209,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1187,8 +1219,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1196,7 +1228,7 @@ name = "rls-vfs" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1204,7 +1236,7 @@ dependencies = [ name = "rustbook" version = "0.1.0" dependencies = [ - "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1231,7 +1263,7 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1295,7 +1327,6 @@ dependencies = [ "graphviz 0.0.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_mir 0.0.0", "syntax 0.0.0", @@ -1432,7 +1463,6 @@ dependencies = [ "proc_macro 0.0.0", "rustc 0.0.0", "rustc_back 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "serialize 0.0.0", @@ -1452,6 +1482,7 @@ dependencies = [ "rustc_const_eval 0.0.0", "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", + "rustc_errors 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -1543,7 +1574,7 @@ dependencies = [ "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_back 0.0.0", "rustc_bitflags 0.0.0", @@ -1572,6 +1603,7 @@ dependencies = [ name = "rustc_tsan" version = "0.0.0" dependencies = [ + "alloc 0.0.0", "alloc_system 0.0.0", "build_helper 0.1.0", "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1615,7 +1647,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1625,13 +1657,13 @@ dependencies = [ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1660,7 +1692,7 @@ version = "0.7.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)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1670,12 +1702,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1697,7 +1729,7 @@ name = "serde_ignored" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1708,7 +1740,7 @@ 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.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1722,7 +1754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "socket2" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1826,7 +1858,6 @@ name = "syntax_ext" version = "0.0.0" dependencies = [ "fmt_macros 0.0.0", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_errors 0.0.0", "syntax 0.0.0", @@ -1936,7 +1967,7 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1983,10 +2014,10 @@ dependencies = [ [[package]] name = "toml" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2009,7 +2040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-segmentation" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2057,7 +2088,7 @@ name = "url_serde" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2146,7 +2177,7 @@ name = "xz2" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2169,8 +2200,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32" "checksum cargo 0.22.0 (git+https://github.com/rust-lang/cargo)" = "<none>" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1aabf260a8f3fefa8871f16b531038c98dd9eab1cfa2c575e78c459abfa3a0" +"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0" "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f" +"checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7" +"checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387" "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97" "checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c" "checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de" @@ -2204,7 +2237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5" "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133" -"checksum jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da622868a84d3f4fd897f6408ba6714aabf663302802358564b384157c1a5bfa" +"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" @@ -2213,26 +2246,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75" "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" -"checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8" +"checksum lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "66b2e318eb97ab84f05725471f90c52a09c964053a5899a13fd0165acc26d00b" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "94101fd932816f97eb9a5116f6c1a11511a1fed7db21c5ccd823b2dc11abf566" +"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" "checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd" -"checksum num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "eb24db7f1904e67a5dfe5f7f62b82f5c963e0f777b23f98cde9c5094fc4fa179" +"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6" "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" "checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790" "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" "checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842" -"checksum openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f776f1d8af832fd2c637ee182c801e8f7ea8895718a2be9914cca001f6e2c40a" +"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5" "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf" -"checksum openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "ad95f8160d1c150c4f44d4c4959732e048ac046c37f597fe362f8bf57561ffb4" +"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8" @@ -2242,7 +2275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd" +"checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0" "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.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" @@ -2252,21 +2285,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff" -"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa1ffc66e1e1786355f22e8a958a57bd67fbf9564f522f87f31de9586715f8f6" +"checksum rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6eea0d0590ae793fc4d281df56e01dc7531575c8ed9a72fadf5fdc7305a0d32f" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57" "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "433d7d9f8530d5a939ad5e0e72a6243d2e42a24804f70bf592c679363dcacb2f" -"checksum serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7b707cf0d4cab852084f573058def08879bb467fda89d99052485e7d00edd624" +"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" +"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" "checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46" "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8" -"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371" +"checksum socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4daf80fcf54186fac4fe049e0b39d36a5cfde69a11a06413e61e77f553cccf9a" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" @@ -2281,16 +2314,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca" -"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167" +"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4" -"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" +"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" -"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" +"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" diff --git a/src/Cargo.toml b/src/Cargo.toml index 4b84272df98..ffec3eb0755 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -32,6 +32,11 @@ members = [ "tools/rls/test_data/multiple_bins", "tools/rls/test_data/bin_lib", "tools/rls/test_data/reformat_with_range", + "tools/rls/test_data/find_impls", + "tools/rls/test_data/infer_bin", + "tools/rls/test_data/infer_custom_bin", + "tools/rls/test_data/infer_lib", + "tools/rls/test_data/omit_init_build", ] # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 65c1088f547..e543b8c070b 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -73,16 +73,18 @@ The script accepts commands, flags, and arguments to determine what to do: ## Configuring rustbuild -There are currently two primary methods for configuring the rustbuild build -system. First, the `./configure` options serialized in `config.mk` will be -parsed and read. That is, if any `./configure` options are passed, they'll be -handled naturally. +There are currently two methods for configuring the rustbuild build system. + +First, rustbuild offers a TOML-based configuration system with a `config.toml` +file. An example of this configuration can be found at `config.toml.example`, +and the configuration file can also be passed as `--config path/to/config.toml` +if the build system is being invoked manually (via the python script). -Next, rustbuild offers a TOML-based configuration system with a `config.toml` -file in the same location as `config.mk`. An example of this configuration can -be found at `config.toml.example`, and the configuration file -can also be passed as `--config path/to/config.toml` if the build system is -being invoked manually (via the python script). +Next, the `./configure` options serialized in `config.mk` will be +parsed and read. That is, if any `./configure` options are passed, they'll be +handled naturally. `./configure` should almost never be used for local +installations, and is primarily useful for CI. Prefer to customize behavior +using `config.toml`. Finally, rustbuild makes use of the [gcc-rs crate] which has [its own method][env-vars] of configuring C compilers and C flags via environment @@ -310,17 +312,18 @@ After that, each module in rustbuild should have enough documentation to keep you up and running. Some general areas that you may be interested in modifying are: -* Adding a new build tool? Take a look at `bootstrap/step.rs` for examples of +* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of other tools. * Adding a new compiler crate? Look no further! Adding crates can be done by adding a new directory with `Cargo.toml` followed by configuring all `Cargo.toml` files accordingly. -* Adding a new dependency from crates.io? We're still working on that, so hold - off on that for now. -* Adding a new configuration option? Take a look at `bootstrap/config.rs` or - perhaps `bootstrap/flags.rs` and then modify the build elsewhere to read that - option. +* Adding a new dependency from crates.io? This should just work inside the + compiler artifacts stage (everything other than libtest and libstd). +* Adding a new configuration option? You'll want to modify `bootstrap/flags.rs` + for command line flags and then `bootstrap/config.rs` to copy the flags to the + `Config` struct. * Adding a sanity check? Take a look at `bootstrap/sanity.rs`. -If you have any questions feel free to reach out on `#rust-internals` on IRC or -open an issue in the bug tracker! +If you have any questions feel free to reach out on `#rust-infra` on IRC or ask on +internals.rust-lang.org. When you encounter bugs, please file issues on the +rust-lang/rust issue tracker. diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index f6ed4ee91b3..0baca9e58f4 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -237,9 +237,13 @@ fn main() { } } - if target.contains("pc-windows-msvc") { - cmd.arg("-Z").arg("unstable-options"); - cmd.arg("-C").arg("target-feature=+crt-static"); + if let Ok(s) = env::var("RUSTC_CRT_STATIC") { + if s == "true" { + cmd.arg("-C").arg("target-feature=+crt-static"); + } + if s == "false" { + cmd.arg("-C").arg("target-feature=-crt-static"); + } } // Force all crates compiled by this compiler to (a) be unstable and (b) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 9369a55ccb9..4c1bd7bdca9 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -167,6 +167,141 @@ def format_build_time(duration): return str(datetime.timedelta(seconds=int(duration))) +def default_build_triple(): + """Build triple as in LLVM""" + default_encoding = sys.getdefaultencoding() + try: + ostype = subprocess.check_output( + ['uname', '-s']).strip().decode(default_encoding) + cputype = subprocess.check_output( + ['uname', '-m']).strip().decode(default_encoding) + except (subprocess.CalledProcessError, OSError): + if sys.platform == 'win32': + return 'x86_64-pc-windows-msvc' + err = "uname not found" + sys.exit(err) + + # 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. + ostype_mapper = { + 'Bitrig': 'unknown-bitrig', + 'Darwin': 'apple-darwin', + 'DragonFly': 'unknown-dragonfly', + 'FreeBSD': 'unknown-freebsd', + 'Haiku': 'unknown-haiku', + 'NetBSD': 'unknown-netbsd', + 'OpenBSD': 'unknown-openbsd' + } + + # Consider the direct transformation first and then the special cases + if ostype in ostype_mapper: + ostype = ostype_mapper[ostype] + elif ostype == 'Linux': + os_from_sp = subprocess.check_output( + ['uname', '-o']).strip().decode(default_encoding) + if os_from_sp == 'Android': + ostype = 'linux-android' + else: + ostype = 'unknown-linux-gnu' + elif ostype == 'SunOS': + ostype = 'sun-solaris' + # On Solaris, uname -m will return a machine classification instead + # of a cpu type, so uname -p is recommended instead. However, the + # output from that option is too generic for our purposes (it will + # always emit 'i386' on x86/amd64 systems). As such, isainfo -k + # must be used instead. + try: + cputype = subprocess.check_output( + ['isainfo', '-k']).strip().decode(default_encoding) + except (subprocess.CalledProcessError, OSError): + err = "isainfo not found" + sys.exit(err) + elif ostype.startswith('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. + ostype = 'pc-windows-gnu' + cputype = 'i686' + if os.environ.get('MSYSTEM') == 'MINGW64': + cputype = 'x86_64' + elif ostype.startswith('MSYS'): + ostype = 'pc-windows-gnu' + elif ostype.startswith('CYGWIN_NT'): + cputype = 'i686' + if ostype.endswith('WOW64'): + cputype = 'x86_64' + ostype = 'pc-windows-gnu' + else: + err = "unknown OS type: {}".format(ostype) + sys.exit(err) + + cputype_mapper = { + 'BePC': 'i686', + 'aarch64': 'aarch64', + 'amd64': 'x86_64', + 'arm64': 'aarch64', + 'i386': 'i686', + 'i486': 'i686', + 'i686': 'i686', + 'i786': 'i686', + 'powerpc': 'powerpc', + 'powerpc64': 'powerpc64', + 'powerpc64le': 'powerpc64le', + 'ppc': 'powerpc', + 'ppc64': 'powerpc64', + 'ppc64le': 'powerpc64le', + 's390x': 's390x', + 'x64': 'x86_64', + 'x86': 'i686', + 'x86-64': 'x86_64', + 'x86_64': 'x86_64' + } + + # Consider the direct transformation first and then the special cases + if cputype in cputype_mapper: + cputype = cputype_mapper[cputype] + elif cputype in {'xscale', 'arm'}: + cputype = 'arm' + if ostype == 'linux-android': + ostype = 'linux-androideabi' + elif cputype == 'armv6l': + cputype = 'arm' + if ostype == 'linux-android': + ostype = 'linux-androideabi' + else: + ostype += 'eabihf' + elif cputype in {'armv7l', 'armv8l'}: + cputype = 'armv7' + if ostype == 'linux-android': + ostype = 'linux-androideabi' + else: + ostype += 'eabihf' + elif cputype == 'mips': + if sys.byteorder == 'big': + cputype = 'mips' + elif sys.byteorder == 'little': + cputype = 'mipsel' + else: + raise ValueError("unknown byteorder: {}".format(sys.byteorder)) + elif cputype == 'mips64': + if sys.byteorder == 'big': + cputype = 'mips64' + elif sys.byteorder == 'little': + cputype = 'mips64el' + else: + raise ValueError('unknown byteorder: {}'.format(sys.byteorder)) + # only the n64 ABI is supported, indicate it + ostype += 'abi64' + elif cputype == 'sparcv9': + pass + else: + err = "unknown cpu type: {}".format(cputype) + sys.exit(err) + + return "{}-{}".format(cputype, ostype) + class RustBuild(object): """Provide all the methods required to build Rust""" def __init__(self): @@ -177,7 +312,6 @@ class RustBuild(object): self.build = '' self.build_dir = os.path.join(os.getcwd(), "build") self.clean = False - self.config_mk = '' self.config_toml = '' self.printed = False self.rust_root = os.path.abspath(os.path.join(__file__, '../../..')) @@ -374,26 +508,6 @@ class RustBuild(object): return self.get_string(value) or value.strip() return None - def get_mk(self, key): - """Returns the value of the given key in config.mk, otherwise returns None - - >>> rb = RustBuild() - >>> rb.config_mk = 'key := value\\n' - >>> rb.get_mk('key') - 'value' - - If the key does not exists, the result is None: - - >>> rb.get_mk('does_not_exists') == None - True - """ - for line in iter(self.config_mk.splitlines()): - if line.startswith(key + ' '): - var = line[line.find(':=') + 2:].strip() - if var != '': - return var - return None - def cargo(self): """Return config path for cargo""" return self.program_config('cargo') @@ -407,7 +521,6 @@ class RustBuild(object): >>> rb = RustBuild() >>> rb.config_toml = 'rustc = "rustc"\\n' - >>> rb.config_mk = 'CFG_LOCAL_RUST_ROOT := /tmp/rust\\n' >>> rb.program_config('rustc') 'rustc' >>> cargo_path = rb.program_config('cargo') @@ -415,7 +528,6 @@ class RustBuild(object): ... "bin", "cargo") True >>> rb.config_toml = '' - >>> rb.config_mk = '' >>> cargo_path = rb.program_config('cargo') >>> cargo_path.rstrip(".exe") == os.path.join(rb.bin_root(), ... "bin", "cargo") @@ -424,10 +536,6 @@ class RustBuild(object): config = self.get_toml(program) if config: return config - config = self.get_mk('CFG_LOCAL_RUST_ROOT') - if config: - return os.path.join(config, "bin", "{}{}".format( - program, self.exe_suffix())) return os.path.join(self.bin_root(), "bin", "{}{}".format( program, self.exe_suffix())) @@ -439,10 +547,14 @@ class RustBuild(object): 'devel' """ start = line.find('"') - if start == -1: - return None - end = start + 1 + line[start + 1:].find('"') - return line[start + 1:end] + if start != -1: + end = start + 1 + line[start + 1:].find('"') + return line[start + 1:end] + start = line.find('\'') + if start != -1: + end = start + 1 + line[start + 1:].find('\'') + return line[start + 1:end] + return None @staticmethod def exe_suffix(): @@ -521,154 +633,12 @@ class RustBuild(object): config = self.get_toml('build') if config: return config - config = self.get_mk('CFG_BUILD') - if config: - return config - try: - ostype = subprocess.check_output( - ['uname', '-s']).strip().decode(default_encoding) - cputype = subprocess.check_output( - ['uname', '-m']).strip().decode(default_encoding) - except (subprocess.CalledProcessError, OSError): - if sys.platform == 'win32': - return 'x86_64-pc-windows-msvc' - err = "uname not found" - if self.verbose: - raise Exception(err) - sys.exit(err) - - # 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. - ostype_mapper = { - 'Bitrig': 'unknown-bitrig', - 'Darwin': 'apple-darwin', - 'DragonFly': 'unknown-dragonfly', - 'FreeBSD': 'unknown-freebsd', - 'Haiku': 'unknown-haiku', - 'NetBSD': 'unknown-netbsd', - 'OpenBSD': 'unknown-openbsd' - } - - # Consider the direct transformation first and then the special cases - if ostype in ostype_mapper: - ostype = ostype_mapper[ostype] - elif ostype == 'Linux': - os_from_sp = subprocess.check_output( - ['uname', '-o']).strip().decode(default_encoding) - if os_from_sp == 'Android': - ostype = 'linux-android' - else: - ostype = 'unknown-linux-gnu' - elif ostype == 'SunOS': - ostype = 'sun-solaris' - # On Solaris, uname -m will return a machine classification instead - # of a cpu type, so uname -p is recommended instead. However, the - # output from that option is too generic for our purposes (it will - # always emit 'i386' on x86/amd64 systems). As such, isainfo -k - # must be used instead. - try: - cputype = subprocess.check_output( - ['isainfo', '-k']).strip().decode(default_encoding) - except (subprocess.CalledProcessError, OSError): - err = "isainfo not found" - if self.verbose: - raise Exception(err) - sys.exit(err) - elif ostype.startswith('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. - ostype = 'pc-windows-gnu' - cputype = 'i686' - if os.environ.get('MSYSTEM') == 'MINGW64': - cputype = 'x86_64' - elif ostype.startswith('MSYS'): - ostype = 'pc-windows-gnu' - elif ostype.startswith('CYGWIN_NT'): - cputype = 'i686' - if ostype.endswith('WOW64'): - cputype = 'x86_64' - ostype = 'pc-windows-gnu' - else: - err = "unknown OS type: {}".format(ostype) - if self.verbose: - raise ValueError(err) - sys.exit(err) - - cputype_mapper = { - 'BePC': 'i686', - 'aarch64': 'aarch64', - 'amd64': 'x86_64', - 'arm64': 'aarch64', - 'i386': 'i686', - 'i486': 'i686', - 'i686': 'i686', - 'i786': 'i686', - 'powerpc': 'powerpc', - 'powerpc64': 'powerpc64', - 'powerpc64le': 'powerpc64le', - 'ppc': 'powerpc', - 'ppc64': 'powerpc64', - 'ppc64le': 'powerpc64le', - 's390x': 's390x', - 'x64': 'x86_64', - 'x86': 'i686', - 'x86-64': 'x86_64', - 'x86_64': 'x86_64' - } - - # Consider the direct transformation first and then the special cases - if cputype in cputype_mapper: - cputype = cputype_mapper[cputype] - elif cputype in {'xscale', 'arm'}: - cputype = 'arm' - if ostype == 'linux-android': - ostype = 'linux-androideabi' - elif cputype == 'armv6l': - cputype = 'arm' - if ostype == 'linux-android': - ostype = 'linux-androideabi' - else: - ostype += 'eabihf' - elif cputype in {'armv7l', 'armv8l'}: - cputype = 'armv7' - if ostype == 'linux-android': - ostype = 'linux-androideabi' - else: - ostype += 'eabihf' - elif cputype == 'mips': - if sys.byteorder == 'big': - cputype = 'mips' - elif sys.byteorder == 'little': - cputype = 'mipsel' - else: - raise ValueError("unknown byteorder: {}".format(sys.byteorder)) - elif cputype == 'mips64': - if sys.byteorder == 'big': - cputype = 'mips64' - elif sys.byteorder == 'little': - cputype = 'mips64el' - else: - raise ValueError('unknown byteorder: {}'.format(sys.byteorder)) - # only the n64 ABI is supported, indicate it - ostype += 'abi64' - elif cputype == 'sparcv9': - pass - else: - err = "unknown cpu type: {}".format(cputype) - if self.verbose: - raise ValueError(err) - sys.exit(err) - - return "{}-{}".format(cputype, ostype) + return default_build_triple() def update_submodules(self): """Update submodules""" if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \ - self.get_toml('submodules') == "false" or \ - self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1": + self.get_toml('submodules') == "false": return print('Updating submodules') default_encoding = sys.getdefaultencoding() @@ -680,11 +650,9 @@ class RustBuild(object): ).decode(default_encoding).splitlines()] submodules = [module for module in submodules if not ((module.endswith("llvm") and - (self.get_toml('llvm-config') or - self.get_mk('CFG_LLVM_ROOT'))) or + self.get_toml('llvm-config')) or (module.endswith("jemalloc") and - (self.get_toml('jemalloc') or - self.get_mk('CFG_JEMALLOC_ROOT'))))] + self.get_toml('jemalloc')))] run(["git", "submodule", "update", "--init", "--recursive"] + submodules, cwd=self.rust_root, verbose=self.verbose) @@ -721,21 +689,15 @@ def bootstrap(): build.config_toml = config.read() except: pass - try: - build.config_mk = open('config.mk').read() - except: - pass if '\nverbose = 2' in build.config_toml: build.verbose = 2 elif '\nverbose = 1' in build.config_toml: build.verbose = 1 - build.use_vendored_sources = '\nvendor = true' in build.config_toml or \ - 'CFG_ENABLE_VENDOR' in build.config_mk + build.use_vendored_sources = '\nvendor = true' in build.config_toml - build.use_locked_deps = '\nlocked-deps = true' in build.config_toml or \ - 'CFG_ENABLE_LOCKED_DEPS' in build.config_mk + build.use_locked_deps = '\nlocked-deps = true' in build.config_toml if 'SUDO_USER' in os.environ and not build.use_vendored_sources: if os.environ.get('USER') != os.environ['SUDO_USER']: diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 91dddc7b5bc..298f6a004a2 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -193,7 +193,7 @@ pub struct ShouldRun<'a> { impl<'a> ShouldRun<'a> { fn new(builder: &'a Builder) -> ShouldRun<'a> { ShouldRun { - builder: builder, + builder, paths: BTreeSet::new(), is_really_default: true, // by default no additional conditions } @@ -257,7 +257,7 @@ impl<'a> Builder<'a> { Kind::Bench => describe!(check::Crate, check::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::Rustc, doc::ErrorIndex, doc::Nomicon, - doc::Reference, doc::Rustdoc), + doc::Reference, doc::Rustdoc, doc::CargoBook), Kind::Dist => describe!(dist::Docs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Extended, dist::HashSign), @@ -278,9 +278,9 @@ impl<'a> Builder<'a> { }; let builder = Builder { - build: build, + build, top_stage: build.config.stage.unwrap_or(2), - kind: kind, + kind, cache: Cache::new(), stack: RefCell::new(Vec::new()), }; @@ -309,9 +309,9 @@ impl<'a> Builder<'a> { }; let builder = Builder { - build: build, + build, top_stage: build.config.stage.unwrap_or(2), - kind: kind, + kind, cache: Cache::new(), stack: RefCell::new(Vec::new()), }; @@ -503,6 +503,10 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_METADATA_SUFFIX", "rustc"); } + if let Some(x) = self.crt_static(target) { + cargo.env("RUSTC_CRT_STATIC", x.to_string()); + } + // Enable usage of unstable features cargo.env("RUSTC_BOOTSTRAP", "1"); self.add_rust_test_threads(&mut cargo); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1823dd4ebc0..92fb2105b7c 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -872,7 +872,7 @@ impl Step for CrateLibrustc { builder.ensure(CrateLibrustc { compiler, target: run.target, - test_kind: test_kind, + test_kind, krate: name, }); }; @@ -934,8 +934,8 @@ impl Step for Crate { builder.ensure(Crate { compiler, target: run.target, - mode: mode, - test_kind: test_kind, + mode, + test_kind, krate: name, }); }; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 33c3638a894..335e1690a2e 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -74,13 +74,21 @@ impl Step for Std { let from = builder.compiler(1, build.build); builder.ensure(Std { compiler: from, - target: target, + target, }); println!("Uplifting stage1 std ({} -> {})", from.host, target); + + // Even if we're not building std this stage, the new sysroot must + // still contain the musl startup objects. + if target.contains("musl") && !target.contains("mips") { + let libdir = builder.sysroot_libdir(compiler, target); + copy_musl_third_party_objects(build, target, &libdir); + } + builder.ensure(StdLink { compiler: from, target_compiler: compiler, - target: target, + target, }); return; } @@ -89,6 +97,11 @@ impl Step for Std { println!("Building stage{} std artifacts ({} -> {})", compiler.stage, &compiler.host, target); + if target.contains("musl") && !target.contains("mips") { + let libdir = builder.sysroot_libdir(compiler, target); + copy_musl_third_party_objects(build, target, &libdir); + } + let out_dir = build.cargo_out(compiler, Mode::Libstd, target); build.clear_if_dirty(&out_dir, &builder.rustc(compiler)); let mut cargo = builder.cargo(compiler, Mode::Libstd, target, "build"); @@ -100,11 +113,25 @@ impl Step for Std { builder.ensure(StdLink { compiler: builder.compiler(compiler.stage, build.build), target_compiler: compiler, - target: target, + target, }); } } +/// Copies the crt(1,i,n).o startup objects +/// +/// Since musl supports fully static linking, we can cross link for it even +/// with a glibc-targeting toolchain, given we have the appropriate startup +/// files. As those shipped with glibc won't work, copy the ones provided by +/// musl so we have them on linux-gnu hosts. +fn copy_musl_third_party_objects(build: &Build, + target: Interned<String>, + into: &Path) { + for &obj in &["crt1.o", "crti.o", "crtn.o"] { + copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); + } +} + /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. pub fn std_cargo(build: &Build, @@ -189,10 +216,6 @@ impl Step for StdLink { let libdir = builder.sysroot_libdir(target_compiler, target); add_to_sysroot(&libdir, &libstd_stamp(build, compiler, target)); - if target.contains("musl") && !target.contains("mips") { - copy_musl_third_party_objects(build, target, &libdir); - } - if build.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { // The sanitizers are only built in stage1 or above, so the dylibs will // be missing in stage0 and causes panic. See the `std()` function above @@ -202,21 +225,12 @@ impl Step for StdLink { builder.ensure(tool::CleanTools { compiler: target_compiler, - target: target, + target, mode: Mode::Libstd, }); } } -/// Copies the crt(1,i,n).o startup objects -/// -/// Only required for musl targets that statically link to libc -fn copy_musl_third_party_objects(build: &Build, target: Interned<String>, into: &Path) { - for &obj in &["crt1.o", "crti.o", "crtn.o"] { - copy(&build.musl_root(target).unwrap().join("lib").join(obj), &into.join(obj)); - } -} - fn copy_apple_sanitizer_dylibs(native_dir: &Path, platform: &str, into: &Path) { for &sanitizer in &["asan", "tsan"] { let filename = format!("libclang_rt.{}_{}_dynamic.dylib", sanitizer, platform); @@ -326,13 +340,13 @@ impl Step for Test { if build.force_use_stage1(compiler, target) { builder.ensure(Test { compiler: builder.compiler(1, build.build), - target: target, + target, }); println!("Uplifting stage1 test ({} -> {})", &build.build, target); builder.ensure(TestLink { compiler: builder.compiler(1, build.build), target_compiler: compiler, - target: target, + target, }); return; } @@ -351,7 +365,7 @@ impl Step for Test { builder.ensure(TestLink { compiler: builder.compiler(compiler.stage, build.build), target_compiler: compiler, - target: target, + target, }); } } @@ -398,7 +412,7 @@ impl Step for TestLink { &libtest_stamp(build, compiler, target)); builder.ensure(tool::CleanTools { compiler: target_compiler, - target: target, + target, mode: Mode::Libtest, }); } @@ -445,7 +459,7 @@ impl Step for Rustc { if build.force_use_stage1(compiler, target) { builder.ensure(Rustc { compiler: builder.compiler(1, build.build), - target: target, + target, }); println!("Uplifting stage1 rustc ({} -> {})", &build.build, target); builder.ensure(RustcLink { @@ -581,7 +595,7 @@ impl Step for RustcLink { &librustc_stamp(build, compiler, target)); builder.ensure(tool::CleanTools { compiler: target_compiler, - target: target, + target, mode: Mode::Librustc, }); } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5975c88c560..2c25f374e12 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -10,12 +10,12 @@ //! Serialized configuration of a build. //! -//! This module implements parsing `config.mk` and `config.toml` configuration -//! files to tweak how the build runs. +//! This module implements parsing `config.toml` configuration files to tweak +//! how the build runs. use std::collections::HashMap; use std::env; -use std::fs::{self, File}; +use std::fs::File; use std::io::prelude::*; use std::path::PathBuf; use std::process; @@ -23,7 +23,7 @@ use std::cmp; use num_cpus; use toml; -use util::{exe, push_exe_path}; +use util::exe; use cache::{INTERNER, Interned}; use flags::Flags; pub use flags::Subcommand; @@ -124,14 +124,12 @@ pub struct Config { pub nodejs: Option<PathBuf>, pub gdb: Option<PathBuf>, pub python: Option<PathBuf>, - pub configure_args: Vec<String>, pub openssl_static: bool, - + pub configure_args: Vec<String>, // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, - } /// Per-target configuration stored in the global configuration structure. @@ -143,6 +141,7 @@ pub struct Target { pub cc: Option<PathBuf>, pub cxx: Option<PathBuf>, pub ndk: Option<PathBuf>, + pub crt_static: Option<bool>, pub musl_root: Option<PathBuf>, pub qemu_rootfs: Option<PathBuf>, } @@ -189,6 +188,8 @@ struct Build { sanitizers: Option<bool>, profiler: Option<bool>, openssl_static: Option<bool>, + configure_args: Option<Vec<String>>, + local_rebuild: Option<bool>, } /// TOML representation of various global install decisions. @@ -218,6 +219,7 @@ struct Llvm { targets: Option<String>, experimental_targets: Option<String>, link_jobs: Option<u32>, + link_shared: Option<bool>, } #[derive(Deserialize, Default, Clone)] @@ -264,6 +266,9 @@ struct Rust { debuginfo_tests: Option<bool>, codegen_tests: Option<bool>, ignore_git: Option<bool>, + debug: Option<bool>, + dist_src: Option<bool>, + quiet_tests: Option<bool>, } /// TOML representation of how each build target is configured. @@ -275,6 +280,7 @@ struct TomlTarget { cc: Option<String>, cxx: Option<String>, android_ndk: Option<String>, + crt_static: Option<bool>, musl_root: Option<String>, qemu_rootfs: Option<String>, } @@ -372,6 +378,8 @@ impl Config { set(&mut config.sanitizers, build.sanitizers); set(&mut config.profiler, build.profiler); set(&mut config.openssl_static, build.openssl_static); + set(&mut config.configure_args, build.configure_args); + set(&mut config.local_rebuild, build.local_rebuild); config.verbose = cmp::max(config.verbose, flags.verbose); if let Some(ref install) = toml.install { @@ -383,6 +391,17 @@ impl Config { config.mandir = install.mandir.clone().map(PathBuf::from); } + // Store off these values as options because if they're not provided + // we'll infer default values for them later + let mut llvm_assertions = None; + let mut debuginfo_lines = None; + let mut debuginfo_only_std = None; + let mut debug = None; + let mut debug_jemalloc = None; + let mut debuginfo = None; + let mut debug_assertions = None; + let mut optimize = None; + if let Some(ref llvm) = toml.llvm { match llvm.ccache { Some(StringOrBool::String(ref s)) => { @@ -395,36 +414,35 @@ impl Config { } set(&mut config.ninja, llvm.ninja); set(&mut config.llvm_enabled, llvm.enabled); - set(&mut config.llvm_assertions, llvm.assertions); + llvm_assertions = llvm.assertions; set(&mut config.llvm_optimize, llvm.optimize); 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_link_shared, llvm.link_shared); config.llvm_targets = llvm.targets.clone(); config.llvm_experimental_targets = llvm.experimental_targets.clone(); config.llvm_link_jobs = llvm.link_jobs; } if let Some(ref rust) = toml.rust { - set(&mut config.rust_debug_assertions, rust.debug_assertions); - set(&mut config.rust_debuginfo, rust.debuginfo); - set(&mut config.rust_debuginfo_lines, rust.debuginfo_lines); - set(&mut config.rust_debuginfo_only_std, rust.debuginfo_only_std); - set(&mut config.rust_optimize, rust.optimize); + debug = rust.debug; + debug_assertions = rust.debug_assertions; + debuginfo = rust.debuginfo; + debuginfo_lines = rust.debuginfo_lines; + debuginfo_only_std = rust.debuginfo_only_std; + optimize = rust.optimize; + debug_jemalloc = rust.debug_jemalloc; set(&mut config.rust_optimize_tests, rust.optimize_tests); set(&mut config.rust_debuginfo_tests, rust.debuginfo_tests); set(&mut config.codegen_tests, rust.codegen_tests); set(&mut config.rust_rpath, rust.rpath); - set(&mut config.debug_jemalloc, rust.debug_jemalloc); set(&mut config.use_jemalloc, rust.use_jemalloc); set(&mut config.backtrace, rust.backtrace); set(&mut config.channel, rust.channel.clone()); - - // on the dev channel, ignore_git should be true by default - // on other channels it should be false by default - config.ignore_git = config.channel == "dev"; set(&mut config.ignore_git, rust.ignore_git); - + set(&mut config.rust_dist_src, rust.dist_src); + set(&mut config.quiet_tests, rust.quiet_tests); config.rustc_default_linker = rust.default_linker.clone(); config.rustc_default_ar = rust.default_ar.clone(); config.musl_root = rust.musl_root.clone().map(PathBuf::from); @@ -451,6 +469,7 @@ impl Config { } target.cxx = cfg.cxx.clone().map(PathBuf::from); target.cc = cfg.cc.clone().map(PathBuf::from); + target.crt_static = cfg.crt_static.clone(); target.musl_root = cfg.musl_root.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); @@ -478,224 +497,26 @@ impl Config { None => stage0_root.join(exe("cargo", &config.build)), }; - // compat with `./configure` while we're still using that - if fs::metadata("config.mk").is_ok() { - config.update_with_config_mk(); - } - - config - } + // Now that we've reached the end of our configuration, infer the + // default values for all options that we haven't otherwise stored yet. - /// "Temporary" routine to parse `config.mk` into this configuration. - /// - /// While we still have `./configure` this implements the ability to decode - /// that configuration into this. This isn't exactly a full-blown makefile - /// parser, but hey it gets the job done! - fn update_with_config_mk(&mut self) { - let mut config = String::new(); - File::open("config.mk").unwrap().read_to_string(&mut config).unwrap(); - for line in config.lines() { - let mut parts = line.splitn(2, ":=").map(|s| s.trim()); - let key = parts.next().unwrap(); - let value = match parts.next() { - Some(n) if n.starts_with('\"') => &n[1..n.len() - 1], - Some(n) => n, - None => continue - }; - - macro_rules! check { - ($(($name:expr, $val:expr),)*) => { - if value == "1" { - $( - if key == concat!("CFG_ENABLE_", $name) { - $val = true; - continue - } - if key == concat!("CFG_DISABLE_", $name) { - $val = false; - continue - } - )* - } - } - } + let default = config.channel == "nightly"; + config.llvm_assertions = llvm_assertions.unwrap_or(default); - check! { - ("MANAGE_SUBMODULES", self.submodules), - ("COMPILER_DOCS", self.compiler_docs), - ("DOCS", self.docs), - ("LLVM_ASSERTIONS", self.llvm_assertions), - ("LLVM_RELEASE_DEBUGINFO", self.llvm_release_debuginfo), - ("OPTIMIZE_LLVM", self.llvm_optimize), - ("LLVM_VERSION_CHECK", self.llvm_version_check), - ("LLVM_STATIC_STDCPP", self.llvm_static_stdcpp), - ("LLVM_LINK_SHARED", self.llvm_link_shared), - ("OPTIMIZE", self.rust_optimize), - ("DEBUG_ASSERTIONS", self.rust_debug_assertions), - ("DEBUGINFO", self.rust_debuginfo), - ("DEBUGINFO_LINES", self.rust_debuginfo_lines), - ("DEBUGINFO_ONLY_STD", self.rust_debuginfo_only_std), - ("JEMALLOC", self.use_jemalloc), - ("DEBUG_JEMALLOC", self.debug_jemalloc), - ("RPATH", self.rust_rpath), - ("OPTIMIZE_TESTS", self.rust_optimize_tests), - ("DEBUGINFO_TESTS", self.rust_debuginfo_tests), - ("QUIET_TESTS", self.quiet_tests), - ("LOCAL_REBUILD", self.local_rebuild), - ("NINJA", self.ninja), - ("CODEGEN_TESTS", self.codegen_tests), - ("LOCKED_DEPS", self.locked_deps), - ("VENDOR", self.vendor), - ("FULL_BOOTSTRAP", self.full_bootstrap), - ("EXTENDED", self.extended), - ("SANITIZERS", self.sanitizers), - ("PROFILER", self.profiler), - ("DIST_SRC", self.rust_dist_src), - ("CARGO_OPENSSL_STATIC", self.openssl_static), - } + let default = match &config.channel[..] { + "stable" | "beta" | "nightly" => true, + _ => false, + }; + config.rust_debuginfo_lines = debuginfo_lines.unwrap_or(default); + config.rust_debuginfo_only_std = debuginfo_only_std.unwrap_or(default); - match key { - "CFG_BUILD" if value.len() > 0 => self.build = INTERNER.intern_str(value), - "CFG_HOST" if value.len() > 0 => { - self.hosts.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); + let default = debug == Some(true); + config.debug_jemalloc = debug_jemalloc.unwrap_or(default); + config.rust_debuginfo = debuginfo.unwrap_or(default); + config.rust_debug_assertions = debug_assertions.unwrap_or(default); + config.rust_optimize = optimize.unwrap_or(!default); - } - "CFG_TARGET" if value.len() > 0 => { - self.targets.extend(value.split(" ").map(|s| INTERNER.intern_str(s))); - } - "CFG_EXPERIMENTAL_TARGETS" if value.len() > 0 => { - self.llvm_experimental_targets = Some(value.to_string()); - } - "CFG_MUSL_ROOT" if value.len() > 0 => { - self.musl_root = Some(parse_configure_path(value)); - } - "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => { - let target = INTERNER.intern_str("x86_64-unknown-linux-musl"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.musl_root = Some(parse_configure_path(value)); - } - "CFG_MUSL_ROOT_I686" if value.len() > 0 => { - let target = INTERNER.intern_str("i686-unknown-linux-musl"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.musl_root = Some(parse_configure_path(value)); - } - "CFG_MUSL_ROOT_ARM" if value.len() > 0 => { - let target = INTERNER.intern_str("arm-unknown-linux-musleabi"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.musl_root = Some(parse_configure_path(value)); - } - "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => { - let target = INTERNER.intern_str("arm-unknown-linux-musleabihf"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.musl_root = Some(parse_configure_path(value)); - } - "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => { - let target = INTERNER.intern_str("armv7-unknown-linux-musleabihf"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.musl_root = Some(parse_configure_path(value)); - } - "CFG_DEFAULT_AR" if value.len() > 0 => { - self.rustc_default_ar = Some(value.to_string()); - } - "CFG_DEFAULT_LINKER" if value.len() > 0 => { - self.rustc_default_linker = Some(value.to_string()); - } - "CFG_GDB" if value.len() > 0 => { - self.gdb = Some(parse_configure_path(value)); - } - "CFG_RELEASE_CHANNEL" => { - self.channel = value.to_string(); - } - "CFG_PREFIX" => { - self.prefix = Some(PathBuf::from(value)); - } - "CFG_SYSCONFDIR" => { - self.sysconfdir = Some(PathBuf::from(value)); - } - "CFG_DOCDIR" => { - self.docdir = Some(PathBuf::from(value)); - } - "CFG_BINDIR" => { - self.bindir = Some(PathBuf::from(value)); - } - "CFG_LIBDIR" => { - self.libdir = Some(PathBuf::from(value)); - } - "CFG_LIBDIR_RELATIVE" => { - self.libdir_relative = Some(PathBuf::from(value)); - } - "CFG_MANDIR" => { - self.mandir = Some(PathBuf::from(value)); - } - "CFG_LLVM_ROOT" if value.len() > 0 => { - let target = self.target_config.entry(self.build.clone()) - .or_insert(Target::default()); - let root = parse_configure_path(value); - target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); - } - "CFG_JEMALLOC_ROOT" if value.len() > 0 => { - let target = self.target_config.entry(self.build.clone()) - .or_insert(Target::default()); - target.jemalloc = Some(parse_configure_path(value).join("libjemalloc_pic.a")); - } - "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { - let target = INTERNER.intern_str("arm-linux-androideabi"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.ndk = Some(parse_configure_path(value)); - } - "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { - let target = INTERNER.intern_str("armv7-linux-androideabi"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.ndk = Some(parse_configure_path(value)); - } - "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = INTERNER.intern_str("i686-linux-android"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.ndk = Some(parse_configure_path(value)); - } - "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = INTERNER.intern_str("aarch64-linux-android"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.ndk = Some(parse_configure_path(value)); - } - "CFG_X86_64_LINUX_ANDROID_NDK" if value.len() > 0 => { - let target = INTERNER.intern_str("x86_64-linux-android"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.ndk = Some(parse_configure_path(value)); - } - "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { - let path = parse_configure_path(value); - self.initial_rustc = push_exe_path(path.clone(), &["bin", "rustc"]); - self.initial_cargo = push_exe_path(path, &["bin", "cargo"]); - } - "CFG_PYTHON" if value.len() > 0 => { - let path = parse_configure_path(value); - self.python = Some(path); - } - "CFG_ENABLE_CCACHE" if value == "1" => { - self.ccache = Some(exe("ccache", &self.build)); - } - "CFG_ENABLE_SCCACHE" if value == "1" => { - self.ccache = Some(exe("sccache", &self.build)); - } - "CFG_CONFIGURE_ARGS" if value.len() > 0 => { - self.configure_args = value.split_whitespace() - .map(|s| s.to_string()) - .collect(); - } - "CFG_QEMU_ARMHF_ROOTFS" if value.len() > 0 => { - let target = INTERNER.intern_str("arm-unknown-linux-gnueabihf"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.qemu_rootfs = Some(parse_configure_path(value)); - } - "CFG_QEMU_AARCH64_ROOTFS" if value.len() > 0 => { - let target = INTERNER.intern_str("aarch64-unknown-linux-gnu"); - let target = self.target_config.entry(target).or_insert(Target::default()); - target.qemu_rootfs = Some(parse_configure_path(value)); - } - _ => {} - } - } + config } pub fn verbose(&self) -> bool { @@ -707,30 +528,6 @@ impl Config { } } -#[cfg(not(windows))] -fn parse_configure_path(path: &str) -> PathBuf { - path.into() -} - -#[cfg(windows)] -fn parse_configure_path(path: &str) -> PathBuf { - // on windows, configure produces unix style paths e.g. /c/some/path but we - // only want real windows paths - - use std::process::Command; - use build_helper; - - // '/' is invalid in windows paths, so we can detect unix paths by the presence of it - if !path.contains('/') { - return path.into(); - } - - let win_path = build_helper::output(Command::new("cygpath").arg("-w").arg(path)); - let win_path = win_path.trim(); - - win_path.into() -} - fn set<T>(field: &mut T, val: Option<T>) { if let Some(v) = val { *field = v; diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py new file mode 100755 index 00000000000..0e11635c3a0 --- /dev/null +++ b/src/bootstrap/configure.py @@ -0,0 +1,408 @@ +#!/usr/bin/env python +# 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. + +# ignore-tidy-linelength + +import sys +import os +rust_dir = os.path.dirname(os.path.abspath(__file__)) +rust_dir = os.path.dirname(rust_dir) +rust_dir = os.path.dirname(rust_dir) +sys.path.append(os.path.join(rust_dir, "src", "bootstrap")) +import bootstrap + +class Option: + def __init__(self, name, rustbuild, desc, value): + self.name = name + self.rustbuild = rustbuild + self.desc = desc + self.value = value + +options = [] + +def o(*args): + options.append(Option(*args, value=False)) + +def v(*args): + options.append(Option(*args, value=True)) + +o("debug", "rust.debug", "debug mode; disables optimization unless `--enable-optimize` given") +o("docs", "build.docs", "build standard library documentation") +o("compiler-docs", "build.compiler-docs", "build compiler documentation") +o("optimize-tests", "rust.optimize-tests", "build tests with optimizations") +o("debuginfo-tests", "rust.debuginfo-tests", "build tests with debugger metadata") +o("quiet-tests", "rust.quiet-tests", "enable quieter output when running tests") +o("ccache", "llvm.ccache", "invoke gcc/clang via ccache to reuse object files between builds") +o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds") +o("local-rust", None, "use an installed rustc rather than downloading a snapshot") +v("local-rust-root", None, "set prefix for local rust binary") +o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version") +o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM") +o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)") +o("rpath", "rust.rpath", "build rpaths into rustc itself") +o("llvm-version-check", "llvm.version-check", "check if the LLVM version is supported, build anyway") +o("codegen-tests", "rust.codegen-tests", "run the src/test/codegen tests") +o("option-checking", None, "complain about unrecognized options in this configure script") +o("ninja", "llvm.ninja", "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)") +o("locked-deps", "build.locked-deps", "force Cargo.lock to be up to date") +o("vendor", "build.vendor", "enable usage of vendored Rust crates") +o("sanitizers", "build.sanitizers", "build the sanitizer runtimes (asan, lsan, msan, tsan)") +o("dist-src", "rust.dist-src", "when building tarballs enables building a source tarball") +o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo") +o("profiler", "build.profiler", "build the profiler runtime") + +# Optimization and debugging options. These may be overridden by the release +# channel, etc. +o("optimize", "rust.optimize", "build optimized rust code") +o("optimize-llvm", "llvm.optimize", "build optimized LLVM") +o("llvm-assertions", "llvm.assertions", "build LLVM with assertions") +o("debug-assertions", "rust.debug-assertions", "build with debugging assertions") +o("llvm-release-debuginfo", "llvm.release-debuginfo", "build LLVM with debugger metadata") +o("debuginfo", "rust.debuginfo", "build with debugger metadata") +o("debuginfo-lines", "rust.debuginfo-lines", "build with line number debugger metadata") +o("debuginfo-only-std", "rust.debuginfo-only-std", "build only libstd with debugging information") +o("debug-jemalloc", "rust.debug-jemalloc", "build jemalloc with --enable-debug --enable-fill") + +v("prefix", "install.prefix", "set installation prefix") +v("localstatedir", "install.localstatedir", "local state directory") +v("datadir", "install.datadir", "install data") +v("sysconfdir", "install.sysconfdir", "install system configuration files") +v("infodir", "install.infodir", "install additional info") +v("libdir", "install.libdir", "install libraries") +v("mandir", "install.mandir", "install man pages in PATH") +v("docdir", "install.docdir", "install documentation in PATH") +v("bindir", "install.bindir", "install binaries") + +v("llvm-root", None, "set LLVM root") +v("python", "build.python", "set path to python") +v("jemalloc-root", None, "set directory where libjemalloc_pic.a is located") +v("android-cross-path", "target.arm-linux-androideabi.android-ndk", + "Android NDK standalone path (deprecated)") +v("i686-linux-android-ndk", "target.i686-linux-android.android-ndk", + "i686-linux-android NDK standalone path") +v("arm-linux-androideabi-ndk", "target.arm-linux-androideabi.android-ndk", + "arm-linux-androideabi NDK standalone path") +v("armv7-linux-androideabi-ndk", "target.armv7-linux-androideabi.android-ndk", + "armv7-linux-androideabi NDK standalone path") +v("aarch64-linux-android-ndk", "target.aarch64-linux-android.android-ndk", + "aarch64-linux-android NDK standalone path") +v("x86_64-linux-android-ndk", "target.x86_64-linux-android.android-ndk", + "x86_64-linux-android NDK standalone path") +v("musl-root", "target.x86_64-unknown-linux-musl.musl-root", + "MUSL root installation directory (deprecated)") +v("musl-root-x86_64", "target.x86_64-unknown-linux-musl.musl-root", + "x86_64-unknown-linux-musl install directory") +v("musl-root-i686", "target.i686-unknown-linux-musl.musl-root", + "i686-unknown-linux-musl install directory") +v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root", + "arm-unknown-linux-musleabi install directory") +v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", + "arm-unknown-linux-musleabihf install directory") +v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root", + "armv7-unknown-linux-musleabihf install directory") +v("qemu-armhf-rootfs", "target.arm-unknown-linux-gnueabihf.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this") +v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this") +v("experimental-targets", "llvm.experimental-targets", + "experimental LLVM targets to build") +v("release-channel", "rust.channel", "the name of the release channel to build") + +# Used on systems where "cc" and "ar" are unavailable +v("default-linker", "rust.default-linker", "the default linker") +v("default-ar", "rust.default-ar", "the default ar") + +# Many of these are saved below during the "writing configuration" step +# (others are conditionally saved). +o("manage-submodules", "build.submodules", "let the build manage the git submodules") +o("jemalloc", "rust.use-jemalloc", "build liballoc with jemalloc") +o("full-bootstrap", "build.full-bootstrap", "build three compilers instead of two") +o("extended", "build.extended", "build an extended rust tool set") + +v("build", "build.build", "GNUs ./configure syntax LLVM build triple") +v("host", None, "GNUs ./configure syntax LLVM host triples") +v("target", None, "GNUs ./configure syntax LLVM target triples") + +v("set", None, "set arbitrary key/value pairs in TOML configuration") + +def p(msg): + print("configure: " + msg) + +def err(msg): + print("configure: error: " + msg) + sys.exit(1) + +if '--help' in sys.argv or '-h' in sys.argv: + print('Usage: ./configure [options]') + print('') + print('Options') + for option in options: + if 'android' in option.name: + # no one needs to know about these obscure options + continue + if option.value: + print('\t{:30} {}'.format('--{}=VAL'.format(option.name), option.desc)) + else: + print('\t{:30} {}'.format('--enable-{}'.format(option.name), option.desc)) + print('') + print('This configure script is a thin configuration shim over the true') + print('configuration system, `config.toml`. You can explore the comments') + print('in `config.toml.example` next to this configure script to see') + print('more information about what each option is. Additionally you can') + print('pass `--set` as an argument to set arbitrary key/value pairs') + print('in the TOML configuration if desired') + print('') + print('Also note that all options which take `--enable` can similarly') + print('be passed with `--disable-foo` to forcibly disable the option') + sys.exit(0) + +# Parse all command line arguments into one of these three lists, handling +# boolean and value-based options separately +unknown_args = [] +need_value_args = [] +known_args = {} + +p("processing command line") +i = 1 +while i < len(sys.argv): + arg = sys.argv[i] + i += 1 + if not arg.startswith('--'): + unknown_args.append(arg) + continue + + found = False + for option in options: + value = None + if option.value: + keyval = arg[2:].split('=', 1) + key = keyval[0] + if option.name != key: + continue + + if len(keyval) > 1: + value = keyval[1] + elif i < len(sys.argv): + value = sys.argv[i] + i += 1 + else: + need_value_args.append(arg) + continue + else: + if arg[2:] == 'enable-' + option.name: + value = True + elif arg[2:] == 'disable-' + option.name: + value = False + else: + continue + + found = True + if not option.name in known_args: + known_args[option.name] = [] + known_args[option.name].append((option, value)) + break + + if not found: + unknown_args.append(arg) +p("") + +if 'option-checking' not in known_args or known_args['option-checking'][1]: + if len(unknown_args) > 0: + err("Option '" + unknown_args[0] + "' is not recognized") + if len(need_value_args) > 0: + err("Option '{0}' needs a value ({0}=val)".format(need_value_args[0])) + +# Parse all known arguments into a configuration structure that reflects the +# TOML we're going to write out +config = {} + +def build(): + if 'build' in known_args: + return known_args['build'][0][1] + return bootstrap.default_build_triple() + +def set(key, value): + s = "{:20} := {}".format(key, value) + if len(s) < 70: + p(s) + else: + p(s[:70] + " ...") + + arr = config + parts = key.split('.') + for i, part in enumerate(parts): + if i == len(parts) - 1: + arr[part] = value + else: + if not part in arr: + arr[part] = {} + arr = arr[part] + +for key in known_args: + # The `set` option is special and an be passed a bunch of times + if key == 'set': + for option, value in known_args[key]: + keyval = value.split('=', 1) + set(keyval[0], True if len(keyval) == 1 else keyval[1]) + continue + + # Ensure each option is only passed once + arr = known_args[key] + if len(arr) > 1: + err("Option '{}' provided more than once".format(key)) + option, value = arr[0] + + # If we have a clear avenue to set our value in rustbuild, do so + if option.rustbuild is not None: + set(option.rustbuild, value) + continue + + # Otherwise we're a "special" option and need some extra handling, so do + # that here. + if option.name == 'sccache': + set('llvm.ccache', 'sccache') + elif option.name == 'local-rust': + for path in os.environ['PATH'].split(os.pathsep): + if os.path.exists(path + '/rustc'): + set('build.rustc', path + '/rustc') + break + for path in os.environ['PATH'].split(os.pathsep): + if os.path.exists(path + '/cargo'): + set('build.cargo', path + '/cargo') + break + elif option.name == 'local-rust-root': + set('build.rustc', value + '/bin/rustc') + set('build.cargo', value + '/bin/cargo') + elif option.name == 'llvm-root': + set('target.{}.llvm-config'.format(build()), value + '/bin/llvm-config') + elif option.name == 'jemalloc-root': + set('target.{}.jemalloc'.format(build()), value + '/libjemalloc_pic.a') + elif option.name == 'host': + set('build.host', value.split(',')) + elif option.name == 'target': + set('build.target', value.split(',')) + elif option.name == 'option-checking': + # this was handled above + pass + else: + raise RuntimeError("unhandled option {}".format(option.name)) + +set('build.configure-args', sys.argv[1:]) + +# "Parse" the `config.toml.example` file into the various sections, and we'll +# use this as a template of a `config.toml` to write out which preserves +# all the various comments and whatnot. +# +# Note that the `target` section is handled separately as we'll duplicate it +# per configure dtarget, so there's a bit of special handling for that here. +sections = {} +cur_section = None +sections[None] = [] +section_order = [None] +targets = {} + +for line in open(rust_dir + '/config.toml.example').read().split("\n"): + if line.startswith('['): + cur_section = line[1:-1] + if cur_section.startswith('target'): + cur_section = 'target' + elif '.' in cur_section: + raise RuntimeError("don't know how to deal with section: {}".format(cur_section)) + sections[cur_section] = [line] + section_order.append(cur_section) + else: + sections[cur_section].append(line) + +# Fill out the `targets` array by giving all configured targets a copy of the +# `target` section we just loaded from the example config +configured_targets = [build()] +if 'build' in config: + if 'host' in config['build']: + configured_targets += config['build']['host'] + if 'target' in config['build']: + configured_targets += config['build']['target'] +if 'target' in config: + for target in config['target']: + configured_targets.append(target) +for target in configured_targets: + targets[target] = sections['target'][:] + targets[target][0] = targets[target][0].replace("x86_64-unknown-linux-gnu", target) + +# Here we walk through the constructed configuration we have from the parsed +# command line arguemnts. We then apply each piece of configuration by +# basically just doing a `sed` to change the various configuration line to what +# we've got configure. +def to_toml(value): + if isinstance(value, bool): + if value: + return "true" + else: + return "false" + elif isinstance(value, list): + return '[' + ', '.join(map(to_toml, value)) + ']' + elif isinstance(value, str): + return "'" + value + "'" + else: + raise 'no toml' + +def configure_section(lines, config): + for key in config: + value = config[key] + found = False + for i, line in enumerate(lines): + if not line.startswith('#' + key + ' = '): + continue + found = True + lines[i] = "{} = {}".format(key, to_toml(value)) + break + if not found: + raise RuntimeError("failed to find config line for {}".format(key)) + +for section_key in config: + section_config = config[section_key] + if not section_key in sections: + raise RuntimeError("config key {} not in sections".format(key)) + + if section_key == 'target': + for target in section_config: + configure_section(targets[target], section_config[target]) + else: + configure_section(sections[section_key], section_config) + +# Now that we've built up our `config.toml`, write it all out in the same +# order that we read it in. +p("") +p("writing `config.toml` in current directory") +with open('config.toml', 'w') as f: + for section in section_order: + if section == 'target': + for target in targets: + for line in targets[target]: + f.write(line + "\n") + else: + for line in sections[section]: + f.write(line + "\n") + +with open('Makefile', 'w') as f: + contents = os.path.join(rust_dir, 'src', 'bootstrap', 'mk', 'Makefile.in') + contents = open(contents).read() + contents = contents.replace("$(CFG_SRC_DIR)", rust_dir + '/') + contents = contents.replace("$(CFG_PYTHON)", sys.executable) + f.write(contents) + +# Finally, clean up with a bit of a help message +relpath = os.path.dirname(__file__) +if relpath == '': + relpath = '.' + +p("") +p("run `python {}/x.py --help`".format(relpath)) +p("") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bfcfb5f9a37..153ffe509f3 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -822,6 +822,7 @@ impl Step for PlainSourceTarball { "RELEASES.md", "configure", "x.py", + "config.toml.example", ]; let src_dirs = [ "man", diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 05c7d689f2c..86f5346bea1 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -213,13 +213,13 @@ impl Step for TheBook { let name = self.name; // build book first edition builder.ensure(Rustbook { - target: target, + target, name: INTERNER.intern_string(format!("{}/first-edition", name)), }); // build book second edition builder.ensure(Rustbook { - target: target, + target, name: INTERNER.intern_string(format!("{}/second-edition", name)), }); @@ -240,6 +240,51 @@ impl Step for TheBook { } } +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub struct CargoBook { + target: Interned<String>, +} + +impl Step for CargoBook { + type Output = (); + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun) -> ShouldRun { + let builder = run.builder; + run.path("src/doc/cargo").default_condition(builder.build.config.docs) + } + + fn make_run(run: RunConfig) { + run.builder.ensure(CargoBook { + target: run.target, + }); + } + + /// Create a placeholder for the cargo documentation so that doc.rust-lang.org/cargo will + /// redirect to doc.crates.io. We want to publish doc.rust-lang.org/cargo in the paper + /// version of the book, but we don't want to rush the process of switching cargo's docs + /// over to mdbook and deploying them. When the cargo book is ready, this implementation + /// should build the mdbook instead of this redirect page. + fn run(self, builder: &Builder) { + let build = builder.build; + let out = build.doc_out(self.target); + + let cargo_dir = out.join("cargo"); + t!(fs::create_dir_all(&cargo_dir)); + + let index = cargo_dir.join("index.html"); + let redirect_html = r#" + <html> + <head> + <meta http-equiv="refresh" content="0; URL='http://doc.crates.io'" /> + </head> + </html>"#; + + println!("Creating cargo book redirect page"); + t!(t!(File::create(&index)).write_all(redirect_html.as_bytes())); + } +} + fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String>, markdown: &str) { let build = builder.build; let out = build.doc_out(target); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a9cefb65f49..a84d43d3dee 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -274,14 +274,14 @@ Arguments: } "test" => { Subcommand::Test { - paths: paths, + paths, test_args: matches.opt_strs("test-args"), fail_fast: !matches.opt_present("no-fail-fast"), } } "bench" => { Subcommand::Bench { - paths: paths, + paths, test_args: matches.opt_strs("test-args"), } } @@ -297,12 +297,12 @@ Arguments: } "dist" => { Subcommand::Dist { - paths: paths, + paths, } } "install" => { Subcommand::Install { - paths: paths, + paths, } } _ => { @@ -324,7 +324,7 @@ Arguments: Flags { verbose: matches.opt_count("verbose"), - stage: stage, + stage, on_fail: matches.opt_str("on-fail"), keep_stage: matches.opt_str("keep-stage").map(|j| j.parse().unwrap()), build: matches.opt_str("build").map(|s| INTERNER.intern_string(s)), @@ -333,9 +333,9 @@ Arguments: target: split(matches.opt_strs("target")) .into_iter().map(|x| INTERNER.intern_string(x)).collect::<Vec<_>>(), config: cfg_file, - src: src, + src, jobs: matches.opt_str("jobs").map(|j| j.parse().unwrap()), - cmd: cmd, + cmd, incremental: matches.opt_present("incremental"), } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 1452a38f6ed..55358f2ffcb 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -314,19 +314,19 @@ impl Build { hosts: config.hosts.clone(), targets: config.targets.clone(), - config: config, - src: src, - out: out, + config, + src, + out, - rust_info: rust_info, - cargo_info: cargo_info, - rls_info: rls_info, + rust_info, + cargo_info, + rls_info, cc: HashMap::new(), cxx: HashMap::new(), crates: HashMap::new(), lldb_version: None, lldb_python_dir: None, - is_sudo: is_sudo, + is_sudo, ci_env: CiEnv::current(), delayed_failures: Cell::new(0), } @@ -444,7 +444,7 @@ impl Build { } /// Returns the root output directory for all Cargo output in a given stage, - /// running a particular compiler, wehther or not we're building the + /// running a particular compiler, whether or not we're building the /// standard library, and targeting the specified architecture. fn cargo_out(&self, compiler: Compiler, @@ -656,6 +656,16 @@ impl Build { base } + /// Returns if this target should statically link the C runtime, if specified + fn crt_static(&self, target: Interned<String>) -> Option<bool> { + if target.contains("pc-windows-msvc") { + Some(true) + } else { + self.config.target_config.get(&target) + .and_then(|t| t.crt_static) + } + } + /// Returns the "musl root" for this `target`, if defined fn musl_root(&self, target: Interned<String>) -> Option<&Path> { self.config.target_config.get(&target) diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs index ad555be877a..5f1df1d26e2 100644 --- a/src/bootstrap/metadata.rs +++ b/src/bootstrap/metadata.rs @@ -75,10 +75,10 @@ fn build_krate(build: &mut Build, krate: &str) { doc_step: format!("doc-crate-{}", name), test_step: format!("test-crate-{}", name), bench_step: format!("bench-crate-{}", name), - name: name, + name, version: package.version, deps: Vec::new(), - path: path, + path, }); } } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 9410927824c..67495b891f8 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -8,8 +8,6 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. -include config.mk - ifdef VERBOSE Q := BOOTSTRAP_ARGS := -v diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 59efbd5c4d2..0a307e72bf6 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -11,7 +11,7 @@ //! Compilation of native dependencies like LLVM. //! //! Native projects like LLVM unfortunately aren't suited just yet for -//! compilation in build scripts that Cargo has. This is because thie +//! compilation in build scripts that Cargo has. This is because the //! compilation takes a *very* long time but also because we don't want to //! compile LLVM 3 times as part of a normal bootstrap (we want it cached). //! diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 436a13500f2..54208d8bb57 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -93,10 +93,27 @@ pub fn check(build: &mut Build) { } // Ninja is currently only used for LLVM itself. - // Some Linux distros rename `ninja` to `ninja-build`. - // CMake can work with either binary name. - if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() { - cmd_finder.must_have("ninja"); + if building_llvm { + if build.config.ninja { + // Some Linux distros rename `ninja` to `ninja-build`. + // CMake can work with either binary name. + if cmd_finder.maybe_have("ninja-build").is_none() { + cmd_finder.must_have("ninja"); + } + } + + // If ninja isn't enabled but we're building for MSVC then we try + // doubly hard to enable it. It was realized in #43767 that the msbuild + // CMake generator for MSVC doesn't respect configuration options like + // disabling LLVM assertions, which can often be quite important! + // + // In these cases we automatically enable Ninja if we find it in the + // environment. + if !build.config.ninja && build.config.build.contains("msvc") { + if cmd_finder.maybe_have("ninja").is_some() { + build.config.ninja = true; + } + } } build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p)) @@ -151,8 +168,15 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } - // Make sure musl-root is valid if specified + // Make sure musl-root is valid if target.contains("musl") && !target.contains("mips") { + // If this is a native target (host is also musl) and no musl-root is given, + // fall back to the system toolchain in /usr before giving up + if build.musl_root(*target).is_none() && build.config.build == *target { + let target = build.config.target_config.entry(target.clone()) + .or_insert(Default::default()); + target.musl_root = Some("/usr".into()); + } match build.musl_root(*target) { Some(root) => { if fs::metadata(root.join("lib/libc.a")).is_err() { diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile index 6cdaf6acfef..49d07d28d3c 100644 --- a/src/ci/docker/arm-android/Dockerfile +++ b/src/ci/docker/arm-android/Dockerfile @@ -3,9 +3,6 @@ FROM ubuntu:16.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm 9 @@ -38,4 +35,4 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh COPY scripts/android-start-emulator.sh /scripts/ -ENTRYPOINT ["/usr/bin/dumb-init", "--", "/scripts/android-start-emulator.sh"] +ENTRYPOINT ["/scripts/android-start-emulator.sh"] diff --git a/src/ci/docker/armhf-gnu/Dockerfile b/src/ci/docker/armhf-gnu/Dockerfile index 14785b706fb..191f8e3a289 100644 --- a/src/ci/docker/armhf-gnu/Dockerfile +++ b/src/ci/docker/armhf-gnu/Dockerfile @@ -73,14 +73,9 @@ RUN arm-linux-gnueabihf-gcc addentropy.c -o rootfs/addentropy -static # TODO: What is this?! RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/current/images/device-tree/vexpress-v2p-ca15-tc1.dtb -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS \ --target=arm-unknown-linux-gnueabihf \ --qemu-armhf-rootfs=/tmp/rootfs diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 1c39e8523da..28caf1fb57a 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -13,9 +13,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh @@ -35,5 +32,3 @@ ENV SCRIPT python2.7 ../x.py test --target $TARGETS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile index 70dfbb53da2..a83bbe9c60e 100644 --- a/src/ci/docker/cross/Dockerfile +++ b/src/ci/docker/cross/Dockerfile @@ -21,9 +21,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - WORKDIR /tmp COPY cross/build-rumprun.sh /tmp/ @@ -38,6 +35,9 @@ RUN ./install-mips-musl.sh COPY cross/install-mipsel-musl.sh /tmp/ RUN ./install-mipsel-musl.sh +COPY cross/install-x86_64-redox.sh /tmp/ +RUN ./install-x86_64-redox.sh + ENV TARGETS=asmjs-unknown-emscripten ENV TARGETS=$TARGETS,wasm32-unknown-emscripten ENV TARGETS=$TARGETS,x86_64-rumprun-netbsd @@ -47,10 +47,12 @@ ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu +ENV TARGETS=$TARGETS,x86_64-unknown-redox ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \ - CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc + CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ + CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc # Suppress some warnings in the openwrt toolchains we downloaded ENV STAGING_DIR=/tmp @@ -66,5 +68,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS # sccache COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/scripts/dumb-init.sh b/src/ci/docker/cross/install-x86_64-redox.sh index 42ecec6ba08..8e052c4acd2 100644..100755 --- a/src/ci/docker/scripts/dumb-init.sh +++ b/src/ci/docker/cross/install-x86_64-redox.sh @@ -1,3 +1,4 @@ +#!/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. @@ -8,8 +9,15 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. +# ignore-tidy-linelength + set -ex -curl -fOL 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 +apt-get update +apt-get install -y --no-install-recommends software-properties-common apt-transport-https + +apt-key adv --batch --yes --keyserver keyserver.ubuntu.com --recv-keys AA12E97F0881517F +add-apt-repository -y 'deb https://static.redox-os.org/toolchain/apt /' + +apt-get update +apt-get install -y x86-64-unknown-redox-gcc diff --git a/src/ci/docker/disabled/aarch64-gnu/Dockerfile b/src/ci/docker/disabled/aarch64-gnu/Dockerfile index e468b1abdfb..9a0e4531223 100644 --- a/src/ci/docker/disabled/aarch64-gnu/Dockerfile +++ b/src/ci/docker/disabled/aarch64-gnu/Dockerfile @@ -70,14 +70,9 @@ RUN chmod +x rootfs/etc/init.d/rcS COPY scripts/qemu-bare-bones-addentropy.c /tmp/addentropy.c RUN aarch64-linux-gnu-gcc addentropy.c -o rootfs/addentropy -static -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS \ --target=aarch64-unknown-linux-gnu \ --qemu-aarch64-rootfs=/tmp/rootfs diff --git a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile index 1c9e036f093..20d823a3d73 100644 --- a/src/ci/docker/disabled/dist-aarch64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-aarch64-android/Dockerfile @@ -3,9 +3,6 @@ FROM ubuntu:16.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip arm64 21 @@ -28,5 +25,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-armv7-android/Dockerfile b/src/ci/docker/disabled/dist-armv7-android/Dockerfile index 326e00548b1..3435d641a13 100644 --- a/src/ci/docker/disabled/dist-armv7-android/Dockerfile +++ b/src/ci/docker/disabled/dist-armv7-android/Dockerfile @@ -3,9 +3,6 @@ FROM ubuntu:16.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r13b-linux-x86_64.zip && \ @@ -46,5 +43,3 @@ ENV SCRIPT \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-i686-android/Dockerfile b/src/ci/docker/disabled/dist-i686-android/Dockerfile index d01648e2b9d..4bb7053760f 100644 --- a/src/ci/docker/disabled/dist-i686-android/Dockerfile +++ b/src/ci/docker/disabled/dist-i686-android/Dockerfile @@ -3,9 +3,6 @@ FROM ubuntu:16.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_ndk android-ndk-r13b-linux-x86_64.zip && \ @@ -46,5 +43,3 @@ ENV SCRIPT \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile index 2622b4b3fac..525b218417b 100644 --- a/src/ci/docker/disabled/dist-x86_64-android/Dockerfile +++ b/src/ci/docker/disabled/dist-x86_64-android/Dockerfile @@ -3,9 +3,6 @@ FROM ubuntu:16.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ download_and_make_toolchain android-ndk-r13b-linux-x86_64.zip x86_64 21 @@ -28,5 +25,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $HOSTS --host $HOSTS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile new file mode 100644 index 00000000000..ed19939545f --- /dev/null +++ b/src/ci/docker/disabled/dist-x86_64-redox/Dockerfile @@ -0,0 +1,22 @@ +FROM ubuntu:16.04 + +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/crosstool-ng.sh /scripts/ +RUN sh /scripts/crosstool-ng.sh + +WORKDIR /tmp +COPY cross/install-x86_64-redox.sh /tmp/ +RUN ./install-x86_64-redox.sh + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV \ + AR_x86_64_unknown_redox=x86_64-unknown-redox-ar \ + CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ + CXX_x86_64_unknown_redox=x86_64-unknown-redox-g++ + +ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-redox --enable-extended +ENV SCRIPT python2.7 ../x.py dist --target x86_64-unknown-redox diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile index 4e337883165..6323369421b 100644 --- a/src/ci/docker/disabled/wasm32-exp/Dockerfile +++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile @@ -15,10 +15,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ jq \ bzip2 -# dumb-init -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - # emscripten COPY scripts/emscripten-wasm.sh /scripts/ COPY disabled/wasm32-exp/node.sh /usr/local/bin/node @@ -37,6 +33,3 @@ ENV TARGETS=wasm32-experimental-emscripten ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly ENV SCRIPT python2.7 ../x.py test --target $TARGETS - -# init -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile index bf9bf77e649..7f6f8ae0882 100644 --- a/src/ci/docker/disabled/wasm32/Dockerfile +++ b/src/ci/docker/disabled/wasm32/Dockerfile @@ -13,9 +13,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - # emscripten COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh @@ -36,5 +33,3 @@ ENV TARGETS=wasm32-unknown-emscripten ENV RUST_CONFIGURE_ARGS --target=$TARGETS ENV SCRIPT python2.7 ../x.py test --target $TARGETS - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index cc3b6b8c692..841d3012125 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-android/Dockerfile b/src/ci/docker/dist-android/Dockerfile index f3beddfae0a..a36f7fc1ac5 100644 --- a/src/ci/docker/dist-android/Dockerfile +++ b/src/ci/docker/dist-android/Dockerfile @@ -3,9 +3,6 @@ FROM ubuntu:16.04 COPY scripts/android-base-apt-get.sh /scripts/ RUN sh /scripts/android-base-apt-get.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - # ndk COPY scripts/android-ndk.sh /scripts/ RUN . /scripts/android-ndk.sh && \ @@ -36,5 +33,3 @@ ENV SCRIPT python2.7 ../x.py dist --target $TARGETS COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index 590d6eb98b3..ecd5090ea05 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-armhf-linux/Dockerfile b/src/ci/docker/dist-armhf-linux/Dockerfile index b3dedc4b7f0..5bbd17bd414 100644 --- a/src/ci/docker/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/dist-armhf-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index 82536b68bbe..ea9034d7178 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-fuchsia/Dockerfile b/src/ci/docker/dist-fuchsia/Dockerfile index 24ad12a4900..e18cb453baf 100644 --- a/src/ci/docker/dist-fuchsia/Dockerfile +++ b/src/ci/docker/dist-fuchsia/Dockerfile @@ -24,11 +24,6 @@ WORKDIR /tmp COPY dist-fuchsia/shared.sh dist-fuchsia/build-toolchain.sh dist-fuchsia/compiler-rt-dso-handle.patch /tmp/ RUN /tmp/build-toolchain.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile index 036dce2a735..efde3ff5296 100644 --- a/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i686-musl/Dockerfile @@ -20,11 +20,6 @@ WORKDIR /build/ COPY dist-i586-gnu-i686-musl/musl-libunwind-patch.patch dist-i586-gnu-i686-musl/build-musl.sh /build/ RUN sh /build/build-musl.sh && rm -rf /build -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-i686-freebsd/Dockerfile b/src/ci/docker/dist-i686-freebsd/Dockerfile index c40881332a1..b82d227b3ef 100644 --- a/src/ci/docker/dist-i686-freebsd/Dockerfile +++ b/src/ci/docker/dist-i686-freebsd/Dockerfile @@ -19,11 +19,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY dist-i686-freebsd/build-toolchain.sh /tmp/ RUN /tmp/build-toolchain.sh i686 -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-i686-linux/Dockerfile b/src/ci/docker/dist-i686-linux/Dockerfile index beb53783bac..a5d776af19d 100644 --- a/src/ci/docker/dist-i686-linux/Dockerfile +++ b/src/ci/docker/dist-i686-linux/Dockerfile @@ -76,11 +76,6 @@ RUN ./build-cmake.sh COPY dist-i686-linux/build-headers.sh /tmp/ RUN ./build-headers.sh -RUN curl -Lo /rustroot/dumb-init \ - https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \ - chmod +x /rustroot/dumb-init -ENTRYPOINT ["/rustroot/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-mips-linux/Dockerfile b/src/ci/docker/dist-mips-linux/Dockerfile index 81997e0508a..94a3cf8a382 100644 --- a/src/ci/docker/dist-mips-linux/Dockerfile +++ b/src/ci/docker/dist-mips-linux/Dockerfile @@ -17,14 +17,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV HOSTS=mips-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended diff --git a/src/ci/docker/dist-mips64-linux/Dockerfile b/src/ci/docker/dist-mips64-linux/Dockerfile index 646cb4d256a..0b0dfff1fe3 100644 --- a/src/ci/docker/dist-mips64-linux/Dockerfile +++ b/src/ci/docker/dist-mips64-linux/Dockerfile @@ -16,14 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV HOSTS=mips64-unknown-linux-gnuabi64 ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended diff --git a/src/ci/docker/dist-mips64el-linux/Dockerfile b/src/ci/docker/dist-mips64el-linux/Dockerfile index 1abb04fd8b2..1810b1cdc5a 100644 --- a/src/ci/docker/dist-mips64el-linux/Dockerfile +++ b/src/ci/docker/dist-mips64el-linux/Dockerfile @@ -17,14 +17,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV HOSTS=mips64el-unknown-linux-gnuabi64 ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended diff --git a/src/ci/docker/dist-mipsel-linux/Dockerfile b/src/ci/docker/dist-mipsel-linux/Dockerfile index a78e39e7d71..f5be0748475 100644 --- a/src/ci/docker/dist-mipsel-linux/Dockerfile +++ b/src/ci/docker/dist-mipsel-linux/Dockerfile @@ -16,14 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV HOSTS=mipsel-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended diff --git a/src/ci/docker/dist-powerpc-linux/Dockerfile b/src/ci/docker/dist-powerpc-linux/Dockerfile index ed9f883cc83..14ce3654fce 100644 --- a/src/ci/docker/dist-powerpc-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-powerpc64-linux/Dockerfile b/src/ci/docker/dist-powerpc64-linux/Dockerfile index 523211498fb..1f6e83e2f49 100644 --- a/src/ci/docker/dist-powerpc64-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64-linux/Dockerfile @@ -3,10 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 diff --git a/src/ci/docker/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/dist-powerpc64le-linux/Dockerfile index 06b262c515a..d4677e18060 100644 --- a/src/ci/docker/dist-powerpc64le-linux/Dockerfile +++ b/src/ci/docker/dist-powerpc64le-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-s390x-linux/Dockerfile b/src/ci/docker/dist-s390x-linux/Dockerfile index 84769af12b5..39478e92f7c 100644 --- a/src/ci/docker/dist-s390x-linux/Dockerfile +++ b/src/ci/docker/dist-s390x-linux/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/dist-x86_64-freebsd/Dockerfile index b62b46701a7..b7c00df4db2 100644 --- a/src/ci/docker/dist-x86_64-freebsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-freebsd/Dockerfile @@ -19,11 +19,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY dist-x86_64-freebsd/build-toolchain.sh /tmp/ RUN /tmp/build-toolchain.sh x86_64 -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-x86_64-linux/Dockerfile b/src/ci/docker/dist-x86_64-linux/Dockerfile index d0ab47ad3dc..a954fd86a24 100644 --- a/src/ci/docker/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/dist-x86_64-linux/Dockerfile @@ -76,11 +76,6 @@ RUN ./build-cmake.sh COPY dist-x86_64-linux/build-headers.sh /tmp/ RUN ./build-headers.sh -RUN curl -Lo /rustroot/dumb-init \ - https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 && \ - chmod +x /rustroot/dumb-init -ENTRYPOINT ["/rustroot/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-x86_64-musl/Dockerfile b/src/ci/docker/dist-x86_64-musl/Dockerfile index eebc283e966..91ed6bfe1f6 100644 --- a/src/ci/docker/dist-x86_64-musl/Dockerfile +++ b/src/ci/docker/dist-x86_64-musl/Dockerfile @@ -20,11 +20,6 @@ WORKDIR /build/ COPY dist-x86_64-musl/build-musl.sh /build/ RUN sh /build/build-musl.sh && rm -rf /build -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-x86_64-netbsd/Dockerfile b/src/ci/docker/dist-x86_64-netbsd/Dockerfile index 0c140500266..4fd2503c31b 100644 --- a/src/ci/docker/dist-x86_64-netbsd/Dockerfile +++ b/src/ci/docker/dist-x86_64-netbsd/Dockerfile @@ -3,11 +3,6 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - # Ubuntu 16.04 (this container) ships with make 4, but something in the # toolchains we build below chokes on that, so go back to make 3 COPY scripts/make3.sh /scripts/ diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile index 56ff9922ae3..5a83bd318c4 100644 --- a/src/ci/docker/i686-gnu-nopt/Dockerfile +++ b/src/ci/docker/i686-gnu-nopt/Dockerfile @@ -14,13 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests ENV RUST_CHECK_TARGET check diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile index 1c1333cd7c8..daa24e0e818 100644 --- a/src/ci/docker/i686-gnu/Dockerfile +++ b/src/ci/docker/i686-gnu/Dockerfile @@ -14,13 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu ENV SCRIPT python2.7 ../x.py test diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index d3f339bc15f..5eba81ff60a 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -89,6 +89,7 @@ exec docker \ --env TRAVIS_BRANCH \ --volume "$HOME/.cargo:/cargo" \ --volume "$HOME/rustsrc:$HOME/rustsrc" \ + --init \ --rm \ rust-ci \ /checkout/src/ci/run.sh diff --git a/src/ci/docker/x86_64-gnu-aux/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile index a449526efcc..35a387221c6 100644 --- a/src/ci/docker/x86_64-gnu-aux/Dockerfile +++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile @@ -14,13 +14,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUST_CHECK_TARGET check-aux diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index 8111118ad3d..95d41028595 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -13,14 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-debug \ diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile index c3fe8ea51cb..786f59eb9f7 100644 --- a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile +++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile @@ -15,14 +15,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ libssl-dev \ pkg-config -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV SCRIPT python2.7 ../x.py test distcheck ENV DIST_SRC 1 diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile index 377e0869557..70390c2ac1d 100644 --- a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile +++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile @@ -13,14 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-full-bootstrap diff --git a/src/ci/docker/x86_64-gnu-incremental/Dockerfile b/src/ci/docker/x86_64-gnu-incremental/Dockerfile index a21a99e965e..d323677698c 100644 --- a/src/ci/docker/x86_64-gnu-incremental/Dockerfile +++ b/src/ci/docker/x86_64-gnu-incremental/Dockerfile @@ -13,14 +13,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu ENV RUSTFLAGS -Zincremental=/tmp/rust-incr-cache ENV RUST_CHECK_TARGET check diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile index 1a9f1d2d737..e832a2445ba 100644 --- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile @@ -16,14 +16,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ zlib1g-dev \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-3.7 diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile index e008b21f66f..d2b0dd13dc2 100644 --- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile +++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile @@ -13,13 +13,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests ENV RUST_CHECK_TARGET check diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile index 3a6760b4762..7570bca5906 100644 --- a/src/ci/docker/x86_64-gnu/Dockerfile +++ b/src/ci/docker/x86_64-gnu/Dockerfile @@ -13,13 +13,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ xz-utils -COPY scripts/dumb-init.sh /scripts/ -RUN sh /scripts/dumb-init.sh - COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENTRYPOINT ["/usr/bin/dumb-init", "--"] - ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --enable-sanitizers --enable-profiler ENV SCRIPT python2.7 ../x.py test diff --git a/src/doc/book b/src/doc/book -Subproject 6f1a03dae6bcea44976918186f2d554186b3499 +Subproject d09c9e8144ed32170b7596abb145ade8b097aca diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject f570bcb681771d691aa4fdb8dfcfad1939844bf +Subproject a4322ccb289a43cc238d4536982f184a3eec9ba diff --git a/src/doc/reference b/src/doc/reference -Subproject 1abfbaa70313fdf527cf799ffd9b9a096a62105 +Subproject 266d429a48468371d2d90669f6a30dd659bb4bd diff --git a/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md b/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md deleted file mode 100644 index 2583d350ebe..00000000000 --- a/src/doc/unstable-book/src/language-features/rvalue-static-promotion.md +++ /dev/null @@ -1,23 +0,0 @@ -# `rvalue_static_promotion` - -The tracking issue for this feature is: [#38865] - -[#38865]: https://github.com/rust-lang/rust/issues/38865 - ------------------------- - -The `rvalue_static_promotion` feature allows directly creating `'static` references to -constant `rvalue`s, which in particular allowing for more concise code in the common case -in which a `'static` reference is all that's needed. - - -## Examples - -```rust -#![feature(rvalue_static_promotion)] - -fn main() { - let DEFAULT_VALUE: &'static u32 = &42; - assert_eq!(*DEFAULT_VALUE, 42); -} -``` diff --git a/src/doc/unstable-book/src/library-features/string-retain.md b/src/doc/unstable-book/src/library-features/string-retain.md new file mode 100644 index 00000000000..049444aa49b --- /dev/null +++ b/src/doc/unstable-book/src/library-features/string-retain.md @@ -0,0 +1,23 @@ +# `string_retain` + +The tracking issue for this feature is: [#43874] + +[#43874]: https://github.com/rust-lang/rust/issues/43874 + +------------------------ + +Retains only the characters specified by the predicate. + +In other words, remove all characters `c` such that `f(c)` returns `false`. +This method operates in place and preserves the order of the retained +characters. + +```rust +#![feature(string_retain)] + +let mut s = String::from("f_o_ob_ar"); + +s.retain(|c| c != '_'); + +assert_eq!(s, "foobar"); +``` diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py index a5449b748dd..7e8fde20346 100644 --- a/src/etc/htmldocck.py +++ b/src/etc/htmldocck.py @@ -29,7 +29,7 @@ showing the expected renderings. In order to avoid one-off dependencies for this task, this script uses a reasonably working HTML parser and the existing XPath implementation -from Python 2's standard library. Hopefully we won't render +from Python's standard library. Hopefully we won't render non-well-formed HTML. # Commands @@ -110,11 +110,17 @@ import os.path import re import shlex from collections import namedtuple -from HTMLParser import HTMLParser +try: + from html.parser import HTMLParser +except ImportError: + from HTMLParser import HTMLParser from xml.etree import cElementTree as ET # ⇤/⇥ are not in HTML 4 but are in HTML 5 -from htmlentitydefs import entitydefs +try: + from html.entities import entitydefs +except ImportError: + from htmlentitydefs import entitydefs entitydefs['larrb'] = u'\u21e4' entitydefs['rarrb'] = u'\u21e5' entitydefs['nbsp'] = ' ' @@ -123,6 +129,11 @@ entitydefs['nbsp'] = ' ' VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr']) +# Python 2 -> 3 compatibility +try: + unichr +except NameError: + unichr = chr class CustomHTMLParser(HTMLParser): """simplified HTML parser. @@ -184,12 +195,8 @@ def concat_multi_lines(f): # strip the common prefix from the current line if needed if lastline is not None: - maxprefix = 0 - for i in xrange(min(len(line), len(lastline))): - if line[i] != lastline[i]: - break - maxprefix += 1 - line = line[maxprefix:].lstrip() + common_prefix = os.path.commonprefix([line, lastline]) + line = line[len(common_prefix):].lstrip() firstlineno = firstlineno or lineno if line.endswith('\\'): @@ -213,7 +220,7 @@ LINE_PATTERN = re.compile(r''' def get_commands(template): - with open(template, 'rUb') as f: + with open(template, 'rU') as f: for lineno, line in concat_multi_lines(f): m = LINE_PATTERN.search(line) if not m: @@ -372,7 +379,7 @@ def check_command(c, cache): cache.get_file(c.args[0]) ret = True except FailedCheck as err: - cerr = err.message + cerr = str(err) ret = False elif len(c.args) == 2: # @has/matches <path> <pat> = string test cerr = "`PATTERN` did not match" @@ -413,9 +420,9 @@ def check_command(c, cache): except FailedCheck as err: message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd) - print_err(c.lineno, c.context, err.message, message) + print_err(c.lineno, c.context, str(err), message) except InvalidCheck as err: - print_err(c.lineno, c.context, err.message) + print_err(c.lineno, c.context, str(err)) def check(target, commands): cache = CachedFiles(target) diff --git a/src/etc/platform-intrinsics/powerpc.json b/src/etc/platform-intrinsics/powerpc.json index c70791be030..d615037b632 100644 --- a/src/etc/platform-intrinsics/powerpc.json +++ b/src/etc/platform-intrinsics/powerpc.json @@ -121,6 +121,41 @@ "llvm": "vavg{0.kind}{0.data_type_short}", "ret": "i(8-32)", "args": ["0", "0"] + }, + { + "intrinsic": "packs{0.kind}{1.data_type_short}", + "width": [128], + "llvm": "vpk{0.kind}{1.data_type_short}{0.kind}s", + "ret": "i(8-16)", + "args": ["0W", "1"] + }, + { + "intrinsic": "packsu{1.kind}{1.data_type_short}", + "width": [128], + "llvm": "vpk{1.kind}{1.data_type_short}{0.kind}s", + "ret": "u(8-16)", + "args": ["0Ws", "1"] + }, + { + "intrinsic": "packpx", + "width": [128], + "llvm": "vpkpx", + "ret": "s16", + "args": ["s32", "s32"] + }, + { + "intrinsic": "unpackl{1.kind}{1.data_type_short}", + "width": [128], + "llvm": "vupkl{1.kind}{1.data_type_short}", + "ret": "s(16-32)", + "args": ["0N"] + }, + { + "intrinsic": "unpackh{1.kind}{1.data_type_short}", + "width": [128], + "llvm": "vupkh{1.kind}{1.data_type_short}", + "ret": "s(16-32)", + "args": ["0N"] } ] } diff --git a/src/jemalloc b/src/jemalloc -Subproject 11bfb0dcf85f7aa92abd30524bb1e42e18d108c +Subproject 1f5a28755e301ac581e2048011e4e0ff3da482e diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 2b3df15f716..f14f2702324 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -110,7 +110,7 @@ impl Layout { /// Creates a layout, bypassing all checks. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe as it does not verify that `align` is /// a power-of-two that is also less than or equal to 2^31, nor @@ -293,7 +293,7 @@ impl Layout { /// Creates a layout describing the record for `self` followed by /// `next` with no additional padding between the two. Since no /// padding is inserted, the alignment of `next` is irrelevant, - /// and is not incoporated *at all* into the resulting layout. + /// and is not incorporated *at all* into the resulting layout. /// /// Returns `(k, offset)`, where `k` is layout of the concatenated /// record and `offset` is the relative location, in bytes, of the @@ -485,7 +485,7 @@ pub unsafe trait Alloc { /// behavior, e.g. to ensure initialization to particular sets of /// bit patterns.) /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure that `layout` has non-zero size. @@ -513,7 +513,7 @@ pub unsafe trait Alloc { /// Deallocate the memory referenced by `ptr`. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure all of the following: @@ -528,7 +528,7 @@ pub unsafe trait Alloc { /// to allocate that block of memory. unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout); - /// Allocator-specific method for signalling an out-of-memory + /// Allocator-specific method for signaling an out-of-memory /// condition. /// /// `oom` aborts the thread or process, optionally performing @@ -539,7 +539,7 @@ pub unsafe trait Alloc { /// unsatisfied allocation request (signaled by an error such as /// `AllocErr::Exhausted`), and wish to abandon computation rather /// than attempt to recover locally. Such clients should pass the - /// signalling error value back into `oom`, where the allocator + /// signaling error value back into `oom`, where the allocator /// may incorporate that error value into its diagnostic report /// before aborting. /// @@ -617,7 +617,7 @@ pub unsafe trait Alloc { /// behavior is well-defined (though underspecified) when this /// constraint is violated; further discussion below. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure all of the following: @@ -688,7 +688,7 @@ pub unsafe trait Alloc { /// Behaves like `alloc`, but also ensures that the contents /// are set to zero before being returned. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe for the same reasons that `alloc` is. /// @@ -714,7 +714,7 @@ pub unsafe trait Alloc { /// the returned block. For some `layout` inputs, like arrays, this /// may include extra storage usable for additional data. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe for the same reasons that `alloc` is. /// @@ -736,7 +736,7 @@ pub unsafe trait Alloc { /// the returned block. For some `layout` inputs, like arrays, this /// may include extra storage usable for additional data. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe for the same reasons that `realloc` is. /// @@ -770,7 +770,7 @@ pub unsafe trait Alloc { /// memory block referenced by `ptr` has not been transferred, and /// the contents of the memory block are unaltered. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure all of the following: @@ -827,7 +827,7 @@ pub unsafe trait Alloc { /// the memory block has not been transferred, and the contents of /// the memory block are unaltered. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure all of the following: @@ -920,7 +920,7 @@ pub unsafe trait Alloc { /// /// Captures a common usage pattern for allocators. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure both: @@ -993,7 +993,7 @@ pub unsafe trait Alloc { /// The returned block is suitable for passing to the /// `alloc`/`realloc` methods of this allocator. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure all of the following: @@ -1037,7 +1037,7 @@ pub unsafe trait Alloc { /// /// Captures a common usage pattern for allocators. /// - /// # Unsafety + /// # Safety /// /// This function is unsafe because undefined behavior can result /// if the caller does not ensure both: diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index daf556795fa..d734ae6a2cf 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -16,16 +16,13 @@ //! //! [arc]: struct.Arc.html -use boxed::Box; - use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; use core::borrow; use core::fmt; use core::cmp::Ordering; use core::intrinsics::abort; -use core::mem; -use core::mem::uninitialized; +use core::mem::{self, size_of_val, uninitialized}; use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; @@ -34,7 +31,10 @@ use core::hash::{Hash, Hasher}; use core::{isize, usize}; use core::convert::From; -use heap::{Heap, Alloc, Layout}; +use heap::{Heap, Alloc, Layout, box_free}; +use boxed::Box; +use string::String; +use vec::Vec; /// A soft limit on the amount of references that may be made to an `Arc`. /// @@ -278,7 +278,7 @@ impl<T> Arc<T> { let x: Box<_> = box ArcInner { strong: atomic::AtomicUsize::new(1), weak: atomic::AtomicUsize::new(1), - data: data, + data, }; Arc { ptr: Shared::from(Box::into_unique(x)) } } @@ -532,6 +532,141 @@ impl<T: ?Sized> Arc<T> { } } +impl<T: ?Sized> Arc<T> { + // Allocates an `ArcInner<T>` with sufficient space for an unsized value + unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> { + // Create a fake ArcInner to find allocation size and alignment + let fake_ptr = ptr as *mut ArcInner<T>; + + let layout = Layout::for_value(&*fake_ptr); + + let mem = Heap.alloc(layout) + .unwrap_or_else(|e| Heap.oom(e)); + + // Initialize the real ArcInner + let inner = set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>; + + ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1)); + + inner + } + + fn from_box(v: Box<T>) -> Arc<T> { + unsafe { + let bptr = Box::into_raw(v); + + let value_size = size_of_val(&*bptr); + let ptr = Self::allocate_for_ptr(bptr); + + // Copy value as bytes + ptr::copy_nonoverlapping( + bptr as *const T as *const u8, + &mut (*ptr).data as *mut _ as *mut u8, + value_size); + + // Free the allocation without dropping its contents + box_free(bptr); + + Arc { ptr: Shared::new_unchecked(ptr) } + } + } +} + +// Sets the data pointer of a `?Sized` raw pointer. +// +// For a slice/trait object, this sets the `data` field and leaves the rest +// unchanged. For a sized raw pointer, this simply sets the pointer. +unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T { + ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); + ptr +} + +impl<T> Arc<[T]> { + // Copy elements from slice into newly allocated Arc<[T]> + // + // Unsafe because the caller must either take ownership or bind `T: Copy` + unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> { + let v_ptr = v as *const [T]; + let ptr = Self::allocate_for_ptr(v_ptr); + + ptr::copy_nonoverlapping( + v.as_ptr(), + &mut (*ptr).data as *mut [T] as *mut T, + v.len()); + + Arc { ptr: Shared::new_unchecked(ptr) } + } +} + +// Specialization trait used for From<&[T]> +trait ArcFromSlice<T> { + fn from_slice(slice: &[T]) -> Self; +} + +impl<T: Clone> ArcFromSlice<T> for Arc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new ArcInner will be dropped, then the memory freed. + struct Guard<T> { + mem: *mut u8, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl<T> Drop for Guard<T> { + fn drop(&mut self) { + use core::slice::from_raw_parts_mut; + + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Heap.dealloc(self.mem, self.layout.clone()); + } + } + } + + unsafe { + let v_ptr = v as *const [T]; + let ptr = Self::allocate_for_ptr(v_ptr); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); + + // Pointer to first element + let elems = &mut (*ptr).data as *mut [T] as *mut T; + + let mut guard = Guard{ + mem: mem, + elems: elems, + layout: layout, + n_elems: 0, + }; + + for (i, item) in v.iter().enumerate() { + ptr::write(elems.offset(i as isize), item.clone()); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new ArcInner. + mem::forget(guard); + + Arc { ptr: Shared::new_unchecked(ptr) } + } + } +} + +impl<T: Copy> ArcFromSlice<T> for Arc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + unsafe { Arc::copy_from_slice(v) } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Clone for Arc<T> { /// Makes a clone of the `Arc` pointer. @@ -1216,8 +1351,56 @@ impl<T> From<T> for Arc<T> { } } +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<'a, T: Clone> From<&'a [T]> for Arc<[T]> { + #[inline] + fn from(v: &[T]) -> Arc<[T]> { + <Self as ArcFromSlice<T>>::from_slice(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<'a> From<&'a str> for Arc<str> { + #[inline] + fn from(v: &str) -> Arc<str> { + unsafe { mem::transmute(<Arc<[u8]>>::from(v.as_bytes())) } + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<String> for Arc<str> { + #[inline] + fn from(v: String) -> Arc<str> { + Arc::from(&v[..]) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<T: ?Sized> From<Box<T>> for Arc<T> { + #[inline] + fn from(v: Box<T>) -> Arc<T> { + Arc::from_box(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<T> From<Vec<T>> for Arc<[T]> { + #[inline] + fn from(mut v: Vec<T>) -> Arc<[T]> { + unsafe { + let arc = Arc::copy_from_slice(&v); + + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + + arc + } + } +} + #[cfg(test)] mod tests { + use std::boxed::Box; use std::clone::Clone; use std::sync::mpsc::channel; use std::mem::drop; @@ -1520,6 +1703,113 @@ mod tests { } t.join().unwrap(); } + + #[test] + fn test_from_str() { + let r: Arc<str> = Arc::from("foo"); + + assert_eq!(&r[..], "foo"); + } + + #[test] + fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); + } + + #[test] + fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Arc<[X]> = Arc::from(s); + + assert_eq!(&r[..], s); + } + + #[test] + #[should_panic] + fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = &[ + Fail(0, "foo".to_string()), + Fail(1, "bar".to_string()), + Fail(2, "baz".to_string()), + ]; + + // Should panic, but not cause memory corruption + let _r: Arc<[Fail]> = Arc::from(s); + } + + #[test] + fn test_from_box() { + let b: Box<u32> = box 123; + let r: Arc<u32> = Arc::from(b); + + assert_eq!(*r, 123); + } + + #[test] + fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Arc<str> = Arc::from(s); + + assert_eq!(&r[..], "foo"); + } + + #[test] + fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Arc<[u32]> = Arc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); + } + + #[test] + fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box<Display> = box 123; + let r: Arc<Display> = Arc::from(b); + + assert_eq!(r.to_string(), "123"); + } + + #[test] + fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box<Debug> = box (); + let r: Arc<Debug> = Arc::from(b); + + assert_eq!(format!("{:?}", r), "()"); + } + + #[test] + fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Arc<[u32]> = Arc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 988f8851625..57640af816a 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -853,9 +853,9 @@ impl<'a, T> Hole<'a, T> { debug_assert!(pos < data.len()); let elt = ptr::read(&data[pos]); Hole { - data: data, + data, elt: Some(elt), - pos: pos, + pos, } } @@ -1203,7 +1203,7 @@ where T: Clone + Ord { let place = Placer::make_place(self.data.place_back()); BinaryHeapPlace { heap: ptr, - place: place, + place, } } } diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6318d22059f..82aac4dbf63 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -169,7 +169,7 @@ fn make_place<T>() -> IntermediateBox<T> { IntermediateBox { ptr: p, - layout: layout, + layout, marker: marker::PhantomData, } } @@ -633,7 +633,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {} /// that `FnBox` may be deprecated in the future if `Box<FnOnce()>` /// closures become directly usable.) /// -/// ### Example +/// # Examples /// /// Here is a snippet of code which creates a hashmap full of boxed /// once closures and then removes them one by one, calling each diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index a51c70159db..f733c3332e2 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -234,7 +234,7 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()> match search::search_tree(self.root.as_mut(), key) { Found(handle) => { Some(OccupiedEntry { - handle: handle, + handle, length: &mut self.length, _marker: PhantomData, } @@ -250,8 +250,8 @@ impl<K, Q: ?Sized> super::Recover<Q> for BTreeMap<K, ()> Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)), GoDown(handle) => { VacantEntry { - key: key, - handle: handle, + key, + handle, length: &mut self.length, _marker: PhantomData, } @@ -695,7 +695,7 @@ impl<K: Ord, V> BTreeMap<K, V> { match search::search_tree(self.root.as_mut(), key) { Found(handle) => { Some(OccupiedEntry { - handle: handle, + handle, length: &mut self.length, _marker: PhantomData, } @@ -866,15 +866,15 @@ impl<K: Ord, V> BTreeMap<K, V> { match search::search_tree(self.root.as_mut(), &key) { Found(handle) => { Occupied(OccupiedEntry { - handle: handle, + handle, length: &mut self.length, _marker: PhantomData, }) } GoDown(handle) => { Vacant(VacantEntry { - key: key, - handle: handle, + key, + handle, length: &mut self.length, _marker: PhantomData, }) diff --git a/src/liballoc/btree/node.rs b/src/liballoc/btree/node.rs index 0e61905131f..c1618043ce6 100644 --- a/src/liballoc/btree/node.rs +++ b/src/liballoc/btree/node.rs @@ -763,7 +763,7 @@ impl<Node: Copy, Type> Clone for Handle<Node, Type> { } impl<Node, Type> Handle<Node, Type> { - /// Retrieves the node that contains the edge of key/value pair this handle pointes to. + /// Retrieves the node that contains the edge of key/value pair this handle points to. pub fn into_node(self) -> Node { self.node } @@ -776,8 +776,8 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar debug_assert!(idx < node.len()); Handle { - node: node, - idx: idx, + node, + idx, _marker: PhantomData } } @@ -850,8 +850,8 @@ impl<BorrowType, K, V, NodeType> debug_assert!(idx <= node.len()); Handle { - node: node, - idx: idx, + node, + idx, _marker: PhantomData } } @@ -1149,7 +1149,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker:: let mut new_root = Root { node: BoxedNode::from_internal(new_node), - height: height + height, }; for i in 0..(new_len+1) { @@ -1449,12 +1449,12 @@ impl<BorrowType, K, V, HandleType> > { match self.node.force() { ForceResult::Leaf(node) => ForceResult::Leaf(Handle { - node: node, + node, idx: self.idx, _marker: PhantomData }), ForceResult::Internal(node) => ForceResult::Internal(Handle { - node: node, + node, idx: self.idx, _marker: PhantomData }) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 480fb4b9eaa..578d90c5ba9 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -211,7 +211,7 @@ //! //! - [`fmt::Display`][`Display`] implementations assert that the type can be faithfully //! represented as a UTF-8 string at all times. It is **not** expected that -//! all types implement the `Display` trait. +//! all types implement the [`Display`] trait. //! - [`fmt::Debug`][`Debug`] implementations should be implemented for **all** public types. //! Output will typically represent the internal state as faithfully as possible. //! The purpose of the [`Debug`] trait is to facilitate debugging Rust code. In diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 227fcfabcf1..2d41ed64810 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -60,8 +60,6 @@ //! The [`heap`](heap/index.html) module defines the low-level interface to the //! default global allocator. It is not compatible with the libc allocator API. -#![crate_name = "alloc"] -#![crate_type = "rlib"] #![allow(unused_attributes)] #![unstable(feature = "alloc", reason = "this library is unlikely to be stabilized in its current \ @@ -121,7 +119,7 @@ #![feature(unsize)] #![feature(allocator_internals)] -#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))] +#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice))] #![cfg_attr(test, feature(test, box_heap))] // Allow testing this library diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index 850dd6adcf0..f9512cbe977 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -140,7 +140,7 @@ impl<T> Node<T> { Node { next: None, prev: None, - element: element, + element, } } @@ -924,7 +924,7 @@ impl<'a, T> IterMut<'a, T> { let node = Some(Shared::from(Box::into_unique(box Node { next: Some(head), prev: Some(prev), - element: element, + element, }))); prev.as_mut().next = node; diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 6090fc3942a..841f9dc6414 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -60,8 +60,8 @@ impl<T, A: Alloc> RawVec<T, A> { // Unique::empty() doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: Unique::empty(), - cap: cap, - a: a, + cap, + a, } } @@ -104,8 +104,8 @@ impl<T, A: Alloc> RawVec<T, A> { RawVec { ptr: Unique::new_unchecked(ptr as *mut _), - cap: cap, - a: a, + cap, + a, } } } @@ -159,8 +159,8 @@ impl<T, A: Alloc> RawVec<T, A> { pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: A) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap: cap, - a: a, + cap, + a, } } } @@ -176,7 +176,7 @@ impl<T> RawVec<T, Heap> { pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self { RawVec { ptr: Unique::new_unchecked(ptr), - cap: cap, + cap, a: Heap, } } @@ -544,12 +544,12 @@ impl<T, A: Alloc> RawVec<T, A> { /// Attempts to ensure that the buffer contains at least enough space to hold /// `used_cap + needed_extra_cap` elements. If it doesn't already have /// enough capacity, will reallocate in place enough space plus comfortable slack - /// space to get amortized `O(1)` behaviour. Will limit this behaviour + /// space to get amortized `O(1)` behavior. Will limit this behaviour /// if it would needlessly cause itself to panic. /// /// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate /// the requested space. This is not really unsafe, but the unsafe - /// code *you* write that relies on the behaviour of this function may break. + /// code *you* write that relies on the behavior of this function may break. /// /// Returns true if the reallocation attempt has succeeded, or false otherwise. /// diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a2184054b37..47f537caf31 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -252,14 +252,15 @@ use core::hash::{Hash, Hasher}; use core::intrinsics::abort; use core::marker; use core::marker::Unsize; -use core::mem::{self, forget, size_of, size_of_val, uninitialized}; +use core::mem::{self, forget, size_of_val, uninitialized}; use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; use core::convert::From; use heap::{Heap, Alloc, Layout, box_free}; -use raw_vec::RawVec; +use string::String; +use vec::Vec; struct RcBox<T: ?Sized> { strong: Cell<usize>, @@ -311,7 +312,7 @@ impl<T> Rc<T> { ptr: Shared::from(Box::into_unique(box RcBox { strong: Cell::new(1), weak: Cell::new(1), - value: value, + value, })), } } @@ -421,64 +422,6 @@ impl<T> Rc<T> { } } -impl Rc<str> { - /// Constructs a new `Rc<str>` from a string slice. - #[doc(hidden)] - #[unstable(feature = "rustc_private", - reason = "for internal use in rustc", - issue = "27812")] - pub fn __from_str(value: &str) -> Rc<str> { - unsafe { - // Allocate enough space for `RcBox<str>`. - let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>(); - let vec = RawVec::<usize>::with_capacity(aligned_len); - let ptr = vec.ptr(); - forget(vec); - // Initialize fields of `RcBox<str>`. - *ptr.offset(0) = 1; // strong: Cell::new(1) - *ptr.offset(1) = 1; // weak: Cell::new(1) - ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len()); - // Combine the allocation address and the string length into a fat pointer to `RcBox`. - let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]); - assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr)); - Rc { ptr: Shared::new_unchecked(rcbox_ptr) } - } - } -} - -impl<T> Rc<[T]> { - /// Constructs a new `Rc<[T]>` from a `Box<[T]>`. - #[doc(hidden)] - #[unstable(feature = "rustc_private", - reason = "for internal use in rustc", - issue = "27812")] - pub fn __from_array(value: Box<[T]>) -> Rc<[T]> { - unsafe { - let ptr: *mut RcBox<[T]> = - mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]); - // FIXME(custom-DST): creating this invalid &[T] is dubiously defined, - // we should have a better way of getting the size/align - // of a DST from its unsized part. - let ptr = Heap.alloc(Layout::for_value(&*ptr)) - .unwrap_or_else(|e| Heap.oom(e)); - let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]); - - // Initialize the new RcBox. - ptr::write(&mut (*ptr).strong, Cell::new(1)); - ptr::write(&mut (*ptr).weak, Cell::new(1)); - ptr::copy_nonoverlapping( - value.as_ptr(), - &mut (*ptr).value as *mut [T] as *mut T, - value.len()); - - // Free the original allocation without freeing its (moved) contents. - box_free(Box::into_raw(value)); - - Rc { ptr: Shared::new_unchecked(ptr as *mut _) } - } - } -} - impl<T: ?Sized> Rc<T> { /// Creates a new [`Weak`][weak] pointer to this value. /// @@ -665,6 +608,140 @@ impl<T: Clone> Rc<T> { } } +impl<T: ?Sized> Rc<T> { + // Allocates an `RcBox<T>` with sufficient space for an unsized value + unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> { + // Create a fake RcBox to find allocation size and alignment + let fake_ptr = ptr as *mut RcBox<T>; + + let layout = Layout::for_value(&*fake_ptr); + + let mem = Heap.alloc(layout) + .unwrap_or_else(|e| Heap.oom(e)); + + // Initialize the real RcBox + let inner = set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>; + + ptr::write(&mut (*inner).strong, Cell::new(1)); + ptr::write(&mut (*inner).weak, Cell::new(1)); + + inner + } + + fn from_box(v: Box<T>) -> Rc<T> { + unsafe { + let bptr = Box::into_raw(v); + + let value_size = size_of_val(&*bptr); + let ptr = Self::allocate_for_ptr(bptr); + + // Copy value as bytes + ptr::copy_nonoverlapping( + bptr as *const T as *const u8, + &mut (*ptr).value as *mut _ as *mut u8, + value_size); + + // Free the allocation without dropping its contents + box_free(bptr); + + Rc { ptr: Shared::new_unchecked(ptr) } + } + } +} + +// Sets the data pointer of a `?Sized` raw pointer. +// +// For a slice/trait object, this sets the `data` field and leaves the rest +// unchanged. For a sized raw pointer, this simply sets the pointer. +unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T { + ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8); + ptr +} + +impl<T> Rc<[T]> { + // Copy elements from slice into newly allocated Rc<[T]> + // + // Unsafe because the caller must either take ownership or bind `T: Copy` + unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> { + let v_ptr = v as *const [T]; + let ptr = Self::allocate_for_ptr(v_ptr); + + ptr::copy_nonoverlapping( + v.as_ptr(), + &mut (*ptr).value as *mut [T] as *mut T, + v.len()); + + Rc { ptr: Shared::new_unchecked(ptr) } + } +} + +trait RcFromSlice<T> { + fn from_slice(slice: &[T]) -> Self; +} + +impl<T: Clone> RcFromSlice<T> for Rc<[T]> { + #[inline] + default fn from_slice(v: &[T]) -> Self { + // Panic guard while cloning T elements. + // In the event of a panic, elements that have been written + // into the new RcBox will be dropped, then the memory freed. + struct Guard<T> { + mem: *mut u8, + elems: *mut T, + layout: Layout, + n_elems: usize, + } + + impl<T> Drop for Guard<T> { + fn drop(&mut self) { + use core::slice::from_raw_parts_mut; + + unsafe { + let slice = from_raw_parts_mut(self.elems, self.n_elems); + ptr::drop_in_place(slice); + + Heap.dealloc(self.mem, self.layout.clone()); + } + } + } + + unsafe { + let v_ptr = v as *const [T]; + let ptr = Self::allocate_for_ptr(v_ptr); + + let mem = ptr as *mut _ as *mut u8; + let layout = Layout::for_value(&*ptr); + + // Pointer to first element + let elems = &mut (*ptr).value as *mut [T] as *mut T; + + let mut guard = Guard{ + mem: mem, + elems: elems, + layout: layout, + n_elems: 0, + }; + + for (i, item) in v.iter().enumerate() { + ptr::write(elems.offset(i as isize), item.clone()); + guard.n_elems += 1; + } + + // All clear. Forget the guard so it doesn't free the new RcBox. + forget(guard); + + Rc { ptr: Shared::new_unchecked(ptr) } + } + } +} + +impl<T: Copy> RcFromSlice<T> for Rc<[T]> { + #[inline] + fn from_slice(v: &[T]) -> Self { + unsafe { Rc::copy_from_slice(v) } + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized> Deref for Rc<T> { type Target = T; @@ -959,6 +1036,53 @@ impl<T> From<T> for Rc<T> { } } +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> { + #[inline] + fn from(v: &[T]) -> Rc<[T]> { + <Self as RcFromSlice<T>>::from_slice(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<'a> From<&'a str> for Rc<str> { + #[inline] + fn from(v: &str) -> Rc<str> { + unsafe { mem::transmute(<Rc<[u8]>>::from(v.as_bytes())) } + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl From<String> for Rc<str> { + #[inline] + fn from(v: String) -> Rc<str> { + Rc::from(&v[..]) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<T: ?Sized> From<Box<T>> for Rc<T> { + #[inline] + fn from(v: Box<T>) -> Rc<T> { + Rc::from_box(v) + } +} + +#[stable(feature = "shared_from_slice", since = "1.21.0")] +impl<T> From<Vec<T>> for Rc<[T]> { + #[inline] + fn from(mut v: Vec<T>) -> Rc<[T]> { + unsafe { + let rc = Rc::copy_from_slice(&v); + + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + + rc + } + } +} + /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the /// managed value. The value is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`. @@ -1465,6 +1589,113 @@ mod tests { assert!(Rc::ptr_eq(&five, &same_five)); assert!(!Rc::ptr_eq(&five, &other_five)); } + + #[test] + fn test_from_str() { + let r: Rc<str> = Rc::from("foo"); + + assert_eq!(&r[..], "foo"); + } + + #[test] + fn test_copy_from_slice() { + let s: &[u32] = &[1, 2, 3]; + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); + } + + #[test] + fn test_clone_from_slice() { + #[derive(Clone, Debug, Eq, PartialEq)] + struct X(u32); + + let s: &[X] = &[X(1), X(2), X(3)]; + let r: Rc<[X]> = Rc::from(s); + + assert_eq!(&r[..], s); + } + + #[test] + #[should_panic] + fn test_clone_from_slice_panic() { + use std::string::{String, ToString}; + + struct Fail(u32, String); + + impl Clone for Fail { + fn clone(&self) -> Fail { + if self.0 == 2 { + panic!(); + } + Fail(self.0, self.1.clone()) + } + } + + let s: &[Fail] = &[ + Fail(0, "foo".to_string()), + Fail(1, "bar".to_string()), + Fail(2, "baz".to_string()), + ]; + + // Should panic, but not cause memory corruption + let _r: Rc<[Fail]> = Rc::from(s); + } + + #[test] + fn test_from_box() { + let b: Box<u32> = box 123; + let r: Rc<u32> = Rc::from(b); + + assert_eq!(*r, 123); + } + + #[test] + fn test_from_box_str() { + use std::string::String; + + let s = String::from("foo").into_boxed_str(); + let r: Rc<str> = Rc::from(s); + + assert_eq!(&r[..], "foo"); + } + + #[test] + fn test_from_box_slice() { + let s = vec![1, 2, 3].into_boxed_slice(); + let r: Rc<[u32]> = Rc::from(s); + + assert_eq!(&r[..], [1, 2, 3]); + } + + #[test] + fn test_from_box_trait() { + use std::fmt::Display; + use std::string::ToString; + + let b: Box<Display> = box 123; + let r: Rc<Display> = Rc::from(b); + + assert_eq!(r.to_string(), "123"); + } + + #[test] + fn test_from_box_trait_zero_sized() { + use std::fmt::Debug; + + let b: Box<Debug> = box (); + let r: Rc<Debug> = Rc::from(b); + + assert_eq!(format!("{:?}", r), "()"); + } + + #[test] + fn test_from_vec() { + let v = vec![1, 2, 3]; + let r: Rc<[u32]> = Rc::from(v); + + assert_eq!(&r[..], [1, 2, 3]); + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index ec7a2b6d0e8..7787ace9441 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -171,7 +171,7 @@ mod hack { impl<T> [T] { /// Returns the number of elements in the slice. /// - /// # Example + /// # Examples /// /// ``` /// let a = [1, 2, 3]; @@ -185,7 +185,7 @@ impl<T> [T] { /// Returns `true` if the slice has a length of 0. /// - /// # Example + /// # Examples /// /// ``` /// let a = [1, 2, 3]; @@ -523,7 +523,7 @@ impl<T> [T] { /// Reverses the order of elements in the slice, in place. /// - /// # Example + /// # Examples /// /// ``` /// let mut v = [1, 2, 3]; @@ -580,7 +580,7 @@ impl<T> [T] { /// /// Panics if `size` is 0. /// - /// # Example + /// # Examples /// /// ``` /// let slice = ['r', 'u', 's', 't']; @@ -613,7 +613,7 @@ impl<T> [T] { /// /// Panics if `size` is 0. /// - /// # Example + /// # Examples /// /// ``` /// let slice = ['l', 'o', 'r', 'e', 'm']; @@ -1040,7 +1040,7 @@ impl<T> [T] { /// `Err` is returned, containing the index where a matching /// element could be inserted while maintaining sorted order. /// - /// # Example + /// # Examples /// /// Looks up a series of four elements. The first is found, with a /// uniquely determined position; the second and third are not @@ -1074,7 +1074,7 @@ impl<T> [T] { /// `Err` is returned, containing the index where a matching /// element could be inserted while maintaining sorted order. /// - /// # Example + /// # Examples /// /// Looks up a series of four elements. The first is found, with a /// uniquely determined position; the second and third are not @@ -1419,7 +1419,7 @@ impl<T> [T] { /// /// This function will panic if the two slices have different lengths. /// - /// # Example + /// # Examples /// /// ``` /// let mut dst = [0, 0, 0]; @@ -1445,7 +1445,7 @@ impl<T> [T] { /// /// This function will panic if the two slices have different lengths. /// - /// # Example + /// # Examples /// /// ``` /// let mut dst = [0, 0, 0]; @@ -1461,6 +1461,31 @@ impl<T> [T] { core_slice::SliceExt::copy_from_slice(self, src) } + /// Swaps all elements in `self` with those in `src`. + /// + /// The length of `src` must be the same as `self`. + /// + /// # Panics + /// + /// This function will panic if the two slices have different lengths. + /// + /// # Example + /// + /// ``` + /// #![feature(swap_with_slice)] + /// + /// let mut src = [1, 2, 3]; + /// let mut dst = [7, 8, 9]; + /// + /// src.swap_with_slice(&mut dst); + /// assert_eq!(src, [7, 8, 9]); + /// assert_eq!(dst, [1, 2, 3]); + /// ``` + #[unstable(feature = "swap_with_slice", issue = "44030")] + pub fn swap_with_slice(&mut self, src: &mut [T]) { + core_slice::SliceExt::swap_with_slice(self, src) + } + /// Copies `self` into a new `Vec`. /// /// # Examples @@ -1886,7 +1911,7 @@ fn merge_sort<T, F>(v: &mut [T], mut is_less: F) // Push this run onto the stack. runs.push(Run { - start: start, + start, len: end - start, }); end = start; diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 80317cd763b..79b2bbce2af 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -1714,7 +1714,7 @@ impl str { /// /// [`Err`]: str/trait.FromStr.html#associatedtype.Err /// - /// # Example + /// # Examples /// /// Basic usage /// diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 3ed5d2df1ab..b1919c7c968 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -38,7 +38,7 @@ //! let message = s + " world!"; //! ``` //! -//! If you have a vector of valid UTF-8 bytes, you can make a `String` out of +//! If you have a vector of valid UTF-8 bytes, you can make a [`String`] out of //! it. You can do the reverse too. //! //! ``` @@ -82,7 +82,7 @@ use boxed::Box; /// /// # Examples /// -/// You can create a `String` from a literal string with `String::from`: +/// You can create a `String` from a literal string with [`String::from`]: /// /// ``` /// let hello = String::from("Hello, world!"); @@ -98,6 +98,7 @@ use boxed::Box; /// hello.push_str("orld!"); /// ``` /// +/// [`String::from`]: #method.from /// [`char`]: ../../std/primitive.char.html /// [`push`]: #method.push /// [`push_str`]: #method.push_str @@ -155,17 +156,14 @@ use boxed::Box; /// takes_str(&s); /// ``` /// -/// [`&str`]: ../../std/primitive.str.html -/// [`Deref`]: ../../std/ops/trait.Deref.html -/// /// This will create a [`&str`] from the `String` and pass it in. This /// conversion is very inexpensive, and so generally, functions will accept /// [`&str`]s as arguments unless they need a `String` for some specific /// reason. /// /// In certain cases Rust doesn't have enough information to make this -/// conversion, known as `Deref` coercion. In the following example a string -/// slice `&'a str` implements the trait `TraitExample`, and the function +/// conversion, known as [`Deref`] coercion. In the following example a string +/// slice [`&'a str`][`&str`] implements the trait `TraitExample`, and the function /// `example_func` takes anything that implements the trait. In this case Rust /// would need to make two implicit conversions, which Rust doesn't have the /// means to do. For that reason, the following example will not compile. @@ -185,13 +183,13 @@ use boxed::Box; /// /// There are two options that would work instead. The first would be to /// change the line `example_func(&example_string);` to -/// `example_func(example_string.as_str());`, using the method `as_str()` +/// `example_func(example_string.as_str());`, using the method [`as_str()`] /// to explicitly extract the string slice containing the string. The second /// way changes `example_func(&example_string);` to /// `example_func(&*example_string);`. In this case we are dereferencing a -/// `String` to a `str`, then referencing the `str` back to `&str`. The -/// second way is more idiomatic, however both work to do the conversion -/// explicitly rather than relying on the implicit conversion. +/// `String` to a [`str`][`&str`], then referencing the [`str`][`&str`] back to +/// [`&str`]. The second way is more idiomatic, however both work to do the +/// conversion explicitly rather than relying on the implicit conversion. /// /// # Representation /// @@ -287,6 +285,10 @@ use boxed::Box; /// ``` /// /// Here, there's no need to allocate more memory inside the loop. +/// +/// [`&str`]: ../../std/primitive.str.html +/// [`Deref`]: ../../std/ops/trait.Deref.html +/// [`as_str()`]: struct.String.html#method.as_str #[derive(PartialOrd, Eq, Ord)] #[stable(feature = "rust1", since = "1.0.0")] pub struct String { @@ -443,32 +445,22 @@ impl String { /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that /// the bytes are valid UTF-8, and then does the conversion. /// - /// [`&str`]: ../../std/primitive.str.html - /// [`u8`]: ../../std/primitive.u8.html - /// [`Vec<u8>`]: ../../std/vec/struct.Vec.html - /// /// If you are sure that the byte slice is valid UTF-8, and you don't want /// to incur the overhead of the validity check, there is an unsafe version /// of this function, [`from_utf8_unchecked`], which has the same behavior /// but skips the check. /// - /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked - /// /// This method will take care to not copy the vector, for efficiency's /// sake. /// - /// If you need a `&str` instead of a `String`, consider + /// If you need a [`&str`] instead of a `String`, consider /// [`str::from_utf8`]. /// - /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html - /// /// The inverse of this method is [`as_bytes`]. /// - /// [`as_bytes`]: #method.as_bytes - /// /// # Errors /// - /// Returns `Err` if the slice is not UTF-8 with a description as to why the + /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the /// provided bytes are not UTF-8. The vector you moved in is also included. /// /// # Examples @@ -497,7 +489,14 @@ impl String { /// See the docs for [`FromUtf8Error`] for more details on what you can do /// with this error. /// + /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked + /// [`&str`]: ../../std/primitive.str.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`Vec<u8>`]: ../../std/vec/struct.Vec.html + /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html + /// [`as_bytes`]: struct.String.html#method.as_bytes /// [`FromUtf8Error`]: struct.FromUtf8Error.html + /// [`Err`]: ../../stdresult/enum.Result.html#variant.Err #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> { @@ -594,9 +593,11 @@ impl String { Cow::Owned(res) } - /// Decode a UTF-16 encoded vector `v` into a `String`, returning `Err` + /// Decode a UTF-16 encoded vector `v` into a `String`, returning [`Err`] /// if `v` contains any invalid data. /// + /// [`Err`]: ../../std/result/enum.Result.htlm#variant.Err + /// /// # Examples /// /// Basic usage: @@ -618,7 +619,7 @@ impl String { decode_utf16(v.iter().cloned()).collect::<Result<_, _>>().map_err(|_| FromUtf16Error(())) } - /// Decode a UTF-16 encoded vector `v` into a string, replacing + /// Decode a UTF-16 encoded slice `v` into a `String`, replacing /// invalid data with the replacement character (U+FFFD). /// /// # Examples @@ -800,11 +801,12 @@ impl String { /// If you do not want this "at least" behavior, see the [`reserve_exact`] /// method. /// - /// [`reserve_exact`]: #method.reserve_exact - /// /// # Panics /// - /// Panics if the new capacity overflows `usize`. + /// Panics if the new capacity overflows [`usize`]. + /// + /// [`reserve_exact`]: struct.String.html#method.reserve_exact + /// [`usize`]: ../../std/primitive.usize.html /// /// # Examples /// @@ -909,7 +911,9 @@ impl String { self.vec.shrink_to_fit() } - /// Appends the given `char` to the end of this `String`. + /// Appends the given [`char`] to the end of this `String`. + /// + /// [`char`]: ../../std/primitive.char.html /// /// # Examples /// @@ -990,7 +994,9 @@ impl String { /// Removes the last character from the string buffer and returns it. /// - /// Returns `None` if this `String` is empty. + /// Returns [`None`] if this `String` is empty. + /// + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// # Examples /// @@ -1019,7 +1025,7 @@ impl String { Some(ch) } - /// Removes a `char` from this `String` at a byte position and returns it. + /// Removes a [`char`] from this `String` at a byte position and returns it. /// /// This is an `O(n)` operation, as it requires copying every element in the /// buffer. @@ -1061,6 +1067,57 @@ impl String { ch } + /// Retains only the characters specified by the predicate. + /// + /// In other words, remove all characters `c` such that `f(c)` returns `false`. + /// This method operates in place and preserves the order of the retained + /// characters. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_retain)] + /// + /// let mut s = String::from("f_o_ob_ar"); + /// + /// s.retain(|c| c != '_'); + /// + /// assert_eq!(s, "foobar"); + /// ``` + #[inline] + #[unstable(feature = "string_retain", issue = "43874")] + pub fn retain<F>(&mut self, mut f: F) + where F: FnMut(char) -> bool + { + let len = self.len(); + let mut del_bytes = 0; + let mut idx = 0; + + while idx < len { + let ch = unsafe { + self.slice_unchecked(idx, len).chars().next().unwrap() + }; + let ch_len = ch.len_utf8(); + + if !f(ch) { + del_bytes += ch_len; + } else if del_bytes > 0 { + unsafe { + ptr::copy(self.vec.as_ptr().offset(idx as isize), + self.vec.as_mut_ptr().offset((idx - del_bytes) as isize), + ch_len); + } + } + + // Point idx to the next char + idx += ch_len; + } + + if del_bytes > 0 { + unsafe { self.vec.set_len(len - del_bytes); } + } + } + /// Inserts a character into this `String` at a byte position. /// /// This is an `O(n)` operation as it requires copying every element in the @@ -1327,8 +1384,8 @@ impl String { let chars_iter = self[start..end].chars(); Drain { - start: start, - end: end, + start, + end, iter: chars_iter, string: self_ptr, } @@ -1338,7 +1395,7 @@ impl String { /// replaces with the given string, and yields the removed chars. /// The given string doesn’t need to be the same length as the range. /// - /// Note: The element range is removed when the `Splice` is dropped, + /// Note: The element range is removed when the [`Splice`] is dropped, /// even if the iterator is not consumed until the end. /// /// # Panics @@ -1347,6 +1404,7 @@ impl String { /// boundary, or if they're out of bounds. /// /// [`char`]: ../../std/primitive.char.html + /// [`Splice`]: ../../std/string/struct.Splice.html /// /// # Examples /// @@ -1391,18 +1449,21 @@ impl String { let chars_iter = self[start..end].chars(); Splice { - start: start, - end: end, + start, + end, iter: chars_iter, string: self_ptr, - replace_with: replace_with + replace_with, } } - /// Converts this `String` into a `Box<str>`. + /// Converts this `String` into a [`Box`]`<`[`str`]`>`. /// /// This will drop any excess capacity. /// + /// [`Box`]: ../../std/boxed/struct.Box.html + /// [`str`]: ../../std/primitive.str.html + /// /// # Examples /// /// Basic usage: diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 27b23d14059..8f3e71ef794 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -10,12 +10,12 @@ #![deny(warnings)] -#![feature(alloc)] #![feature(attr_literals)] #![feature(box_syntax)] #![feature(inclusive_range_syntax)] #![feature(collection_placement)] #![feature(const_fn)] +#![feature(drain_filter)] #![feature(exact_size_is_empty)] #![feature(iterator_step_by)] #![feature(pattern)] @@ -25,14 +25,11 @@ #![feature(slice_rotate)] #![feature(splice)] #![feature(str_escape)] -#![feature(test)] +#![feature(string_retain)] #![feature(unboxed_closures)] #![feature(unicode)] -extern crate alloc; -extern crate test; extern crate std_unicode; -extern crate core; use std::hash::{Hash, Hasher}; use std::collections::hash_map::DefaultHasher; diff --git a/src/liballoc/tests/string.rs b/src/liballoc/tests/string.rs index b1731b2a5dc..f5c124c6b44 100644 --- a/src/liballoc/tests/string.rs +++ b/src/liballoc/tests/string.rs @@ -333,6 +333,26 @@ fn remove_bad() { } #[test] +fn test_retain() { + let mut s = String::from("α_β_γ"); + + s.retain(|_| true); + assert_eq!(s, "α_β_γ"); + + s.retain(|c| c != '_'); + assert_eq!(s, "αβγ"); + + s.retain(|c| c != 'β'); + assert_eq!(s, "αγ"); + + s.retain(|c| c == 'α'); + assert_eq!(s, "α"); + + s.retain(|_| false); + assert_eq!(s, ""); +} + +#[test] fn insert() { let mut s = "foobar".to_string(); s.insert(0, 'ệ'); diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 17f1229c206..670ea8089fc 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -801,3 +801,170 @@ fn overaligned_allocations() { assert!(v.as_ptr() as usize & 0xff == 0); } } + +#[test] +fn drain_filter_empty() { + let mut vec: Vec<i32> = vec![]; + + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_zst() { + let mut vec = vec![(), (), (), (), ()]; + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_false() { + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| false); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + for _ in iter.by_ref() { + count += 1; + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, 0); + assert_eq!(vec.len(), initial_len); + assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); +} + +#[test] +fn drain_filter_true() { + let mut vec = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + + let initial_len = vec.len(); + let mut count = 0; + { + let mut iter = vec.drain_filter(|_| true); + assert_eq!(iter.size_hint(), (0, Some(initial_len))); + while let Some(_) = iter.next() { + count += 1; + assert_eq!(iter.size_hint(), (0, Some(initial_len - count))); + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.size_hint(), (0, Some(0))); + } + + assert_eq!(count, initial_len); + assert_eq!(vec.len(), 0); + assert_eq!(vec, vec![]); +} + +#[test] +fn drain_filter_complex() { + + { // [+xxx++++++xxxxx++++x+x++] + let mut vec = vec![1, + 2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36, + 37, 39]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 14); + assert_eq!(vec, vec![1, 7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); + } + + { // [xxx++++++xxxxx++++x+x++] + let mut vec = vec![2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36, + 37, 39]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 13); + assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35, 37, 39]); + } + + { // [xxx++++++xxxxx++++x+x] + let mut vec = vec![2, 4, 6, + 7, 9, 11, 13, 15, 17, + 18, 20, 22, 24, 26, + 27, 29, 31, 33, + 34, + 35, + 36]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 18, 20, 22, 24, 26, 34, 36]); + + assert_eq!(vec.len(), 11); + assert_eq!(vec, vec![7, 9, 11, 13, 15, 17, 27, 29, 31, 33, 35]); + } + + { // [xxxxxxxxxx+++++++++++] + let mut vec = vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 1, 3, 5, 7, 9, 11, 13, 15, 17, 19]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(vec.len(), 10); + assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } + + { // [+++++++++++xxxxxxxxxx] + let mut vec = vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19, + 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]; + + let removed = vec.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + assert_eq!(removed.len(), 10); + assert_eq!(removed, vec![2, 4, 6, 8, 10, 12, 14, 16, 18, 20]); + + assert_eq!(vec.len(), 10); + assert_eq!(vec, vec![1, 3, 5, 7, 9, 11, 13, 15, 17, 19]); + } +} + + diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 5f68e59289d..8141851b8c9 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1728,9 +1728,9 @@ impl<T> IntoIterator for Vec<T> { mem::forget(self); IntoIter { buf: Shared::new_unchecked(begin), - cap: cap, + cap, ptr: begin, - end: end, + end, } } } @@ -1960,6 +1960,65 @@ impl<T> Vec<T> { } } + /// Creates an iterator which uses a closure to determine if an element should be removed. + /// + /// If the closure returns true, then the element is removed and yielded. + /// If the closure returns false, it will try again, and call the closure + /// on the next element, seeing if it passes the test. + /// + /// Using this method is equivalent to the following code: + /// + /// ``` + /// # let some_predicate = |x: &mut i32| { *x == 2 }; + /// # let mut vec = vec![1, 2, 3, 4, 5]; + /// let mut i = 0; + /// while i != vec.len() { + /// if some_predicate(&mut vec[i]) { + /// let val = vec.remove(i); + /// // your code here + /// } + /// i += 1; + /// } + /// ``` + /// + /// But `drain_filter` is easier to use. `drain_filter` is also more efficient, + /// because it can backshift the elements of the array in bulk. + /// + /// Note that `drain_filter` also lets you mutate every element in the filter closure, + /// regardless of whether you choose to keep or remove it. + /// + /// + /// # Examples + /// + /// Splitting an array into evens and odds, reusing the original allocation: + /// + /// ``` + /// #![feature(drain_filter)] + /// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15]; + /// + /// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>(); + /// let odds = numbers; + /// + /// assert_eq!(evens, vec![2, 4, 6, 8, 14]); + /// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]); + /// ``` + #[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] + pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<T, F> + where F: FnMut(&mut T) -> bool, + { + let old_len = self.len(); + + // Guard against us getting leaked (leak amplification) + unsafe { self.set_len(0); } + + DrainFilter { + vec: self, + idx: 0, + del: 0, + old_len, + pred: filter, + } + } } /// Extend implementation that copies elements out of references before pushing them onto the Vec. @@ -2602,3 +2661,57 @@ impl<'a, T> Drain<'a, T> { self.tail_start = new_tail_start; } } + +/// An iterator produced by calling `drain_filter` on Vec. +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +#[derive(Debug)] +pub struct DrainFilter<'a, T: 'a, F> + where F: FnMut(&mut T) -> bool, +{ + vec: &'a mut Vec<T>, + idx: usize, + del: usize, + old_len: usize, + pred: F, +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl<'a, T, F> Iterator for DrainFilter<'a, T, F> + where F: FnMut(&mut T) -> bool, +{ + type Item = T; + + fn next(&mut self) -> Option<T> { + unsafe { + while self.idx != self.old_len { + let i = self.idx; + self.idx += 1; + let v = slice::from_raw_parts_mut(self.vec.as_mut_ptr(), self.old_len); + if (self.pred)(&mut v[i]) { + self.del += 1; + return Some(ptr::read(&v[i])); + } else if self.del > 0 { + v.swap(i - self.del, i); + } + } + None + } + } + + fn size_hint(&self) -> (usize, Option<usize>) { + (0, Some(self.old_len - self.idx)) + } +} + +#[unstable(feature = "drain_filter", reason = "recently added", issue = "43244")] +impl<'a, T, F> Drop for DrainFilter<'a, T, F> + where F: FnMut(&mut T) -> bool, +{ + fn drop(&mut self) { + for _ in self.by_ref() { } + + unsafe { + self.vec.set_len(self.old_len - self.del); + } + } +} diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 2068c2c9c5f..00def2a1eac 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -459,10 +459,12 @@ impl<T> VecDeque<T> { /// /// `i` and `j` may be equal. /// - /// Fails if there is no element with either index. - /// /// Element at index 0 is the front of the queue. /// + /// # Panics + /// + /// Panics if either index is out of bounds. + /// /// # Examples /// /// ``` @@ -2442,7 +2444,7 @@ impl<T> From<Vec<T>> for VecDeque<T> { VecDeque { tail: 0, head: len, - buf: buf, + buf, } } } diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs index 085f62f4b0f..41193f6a41f 100644 --- a/src/liballoc_jemalloc/build.rs +++ b/src/liballoc_jemalloc/build.rs @@ -93,29 +93,7 @@ fn main() { .env("AR", &ar) .env("RANLIB", format!("{} s", ar.display())); - if target.contains("windows") { - // A bit of history here, this used to be --enable-lazy-lock added in - // #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which - // was also reported to MinGW: - // - // http://sourceforge.net/p/mingw-w64/bugs/395/ - // - // When updating jemalloc to 4.0, however, it was found that binaries - // would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating - // that a thread was unlocking a mutex it never locked. Disabling this - // "lazy lock" option seems to fix the issue, but it was enabled by - // default for MinGW targets in 13473c7 for jemalloc. - // - // As a result of all that, force disabling lazy lock on Windows, and - // after reading some code it at least *appears* that the initialization - // of mutexes is otherwise ok in jemalloc, so shouldn't cause problems - // hopefully... - // - // tl;dr: make windows behave like other platforms by disabling lazy - // locking, but requires passing an option due to a historical - // default with jemalloc. - cmd.arg("--disable-lazy-lock"); - } else if target.contains("ios") { + if target.contains("ios") { cmd.arg("--disable-tls"); } else if target.contains("android") { // We force android to have prefixed symbols because apparently diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index 3a9cc1dd5a6..efefabc974c 100644 --- a/src/liballoc_jemalloc/lib.rs +++ b/src/liballoc_jemalloc/lib.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "alloc_jemalloc"] -#![crate_type = "rlib"] #![no_std] #![unstable(feature = "alloc_jemalloc", reason = "this library is unlikely to be stabilized in its current \ @@ -21,7 +19,7 @@ #![feature(libc)] #![feature(linkage)] #![feature(staged_api)] -#![cfg_attr(dummy_jemalloc, allow(dead_code))] +#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))] #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))] extern crate alloc; diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs index 9a7cba21e3c..1defe308713 100644 --- a/src/liballoc_system/lib.rs +++ b/src/liballoc_system/lib.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "alloc_system"] -#![crate_type = "rlib"] #![no_std] #![deny(warnings)] #![unstable(feature = "alloc_system", diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 8e3b3f2074d..96fcc81e8e6 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -18,9 +18,6 @@ //! This crate implements `TypedArena`, a simple arena that can only hold //! objects of a single type. -#![crate_name = "arena"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", diff --git a/src/libbacktrace/config.sub b/src/libbacktrace/config.sub index da6d1b6826a..40ea5dfe115 100644 --- a/src/libbacktrace/config.sub +++ b/src/libbacktrace/config.sub @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2016 Free Software Foundation, Inc. +# Copyright 1992-2017 Free Software Foundation, Inc. -timestamp='2016-01-01' +timestamp='2017-04-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2016 Free Software Foundation, Inc. +Copyright 1992-2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,7 +117,7 @@ case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ - kopensolaris*-gnu* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` @@ -263,7 +263,7 @@ case $basic_machine in | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ - | i370 | i860 | i960 | ia64 \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ @@ -301,6 +301,7 @@ case $basic_machine in | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ @@ -314,6 +315,7 @@ case $basic_machine in | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ + | wasm32 \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) @@ -387,7 +389,7 @@ case $basic_machine in | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ @@ -428,6 +430,7 @@ case $basic_machine in | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ @@ -444,6 +447,7 @@ case $basic_machine in | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ + | wasm32-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ @@ -643,6 +647,14 @@ case $basic_machine in basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -938,6 +950,9 @@ case $basic_machine in nsr-tandem) basic_machine=nsr-tandem ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -1022,7 +1037,7 @@ case $basic_machine in ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) @@ -1032,7 +1047,7 @@ case $basic_machine in ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) @@ -1233,6 +1248,9 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; + wasm32) + basic_machine=wasm32-unknown + ;; w65*) basic_machine=w65-wdc os=-none @@ -1382,14 +1400,14 @@ case $os in | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -bitrig* | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ @@ -1399,7 +1417,7 @@ case $os in | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ - | -onefs* | -tirtos*) + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1531,6 +1549,8 @@ case $os in ;; -nacl*) ;; + -ios) + ;; -none) ;; *) @@ -1626,6 +1646,9 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 38143593eb1..55316db3d5a 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "collections"] -#![crate_type = "rlib"] #![allow(unused_attributes)] #![unstable(feature = "collections", reason = "this library is unlikely to be stabilized in its current \ diff --git a/src/libcompiler_builtins b/src/libcompiler_builtins -Subproject 5e49856003f33aa5781a0edca148be21025e18e +Subproject 6b9281d2b2f0ebb94838814b1e8ace2de4b7035 diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 37bd57034a7..4b7706bac30 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -89,7 +89,7 @@ macro_rules! __impl_slice_eq2 { } } -// macro for implementing n-ary tuple functions and operations +// macro for implementing n-element array functions and operations macro_rules! array_impls { ($($N:expr)+) => { $( @@ -124,6 +124,7 @@ macro_rules! array_impls { } #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] impl<T:Copy> Clone for [T; $N] { fn clone(&self) -> [T; $N] { *self diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 6068f1a7961..e0a3b8d52f4 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -809,7 +809,7 @@ impl<T: ?Sized> RefCell<T> { /// [`borrow_mut`] method instead if `self` isn't mutable. /// /// Also, please be aware that this method is only for special circumstances and is usually - /// not you want. In case of doubt, use [`borrow_mut`] instead. + /// not what you want. In case of doubt, use [`borrow_mut`] instead. /// /// [`borrow_mut`]: #method.borrow_mut /// @@ -998,7 +998,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// A method would interfere with methods of the same name on the contents /// of a `RefCell` used through `Deref`. /// - /// # Example + /// # Examples /// /// ``` /// use std::cell::{RefCell, Ref}; @@ -1040,7 +1040,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// `RefMut::map(...)`. A method would interfere with methods of the same /// name on the contents of a `RefCell` used through `Deref`. /// - /// # Example + /// # Examples /// /// ``` /// use std::cell::{RefCell, RefMut}; diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 8856d0b8cb9..2dc51718b97 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -88,6 +88,7 @@ /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(stage0), lang = "clone")] pub trait Clone : Sized { /// Returns a copy of the value. /// @@ -131,6 +132,7 @@ pub struct AssertParamIsClone<T: Clone + ?Sized> { _field: ::marker::PhantomData pub struct AssertParamIsCopy<T: Copy + ?Sized> { _field: ::marker::PhantomData<T> } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] impl<'a, T: ?Sized> Clone for &'a T { /// Returns a shallow copy of the reference. #[inline] @@ -140,6 +142,7 @@ impl<'a, T: ?Sized> Clone for &'a T { macro_rules! clone_impl { ($t:ty) => { #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] impl Clone for $t { /// Returns a deep copy of the value. #[inline] diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 322df6e5b47..b594c886b64 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -18,7 +18,7 @@ struct PadAdapter<'a, 'b: 'a> { impl<'a, 'b: 'a> PadAdapter<'a, 'b> { fn new(fmt: &'a mut fmt::Formatter<'b>) -> PadAdapter<'a, 'b> { PadAdapter { - fmt: fmt, + fmt, on_newline: false, } } @@ -58,7 +58,7 @@ impl<'a, 'b: 'a> fmt::Write for PadAdapter<'a, 'b> { /// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct) /// method. /// -/// # Example +/// # Examples /// /// ``` /// use std::fmt; @@ -94,8 +94,8 @@ pub fn debug_struct_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, -> DebugStruct<'a, 'b> { let result = fmt.write_str(name); DebugStruct { - fmt: fmt, - result: result, + fmt, + result, has_fields: false, } } @@ -153,7 +153,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple) /// method. /// -/// # Example +/// # Examples /// /// ``` /// use std::fmt; @@ -185,8 +185,8 @@ pub struct DebugTuple<'a, 'b: 'a> { pub fn debug_tuple_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>, name: &str) -> DebugTuple<'a, 'b> { let result = fmt.write_str(name); DebugTuple { - fmt: fmt, - result: result, + fmt, + result, fields: 0, empty_name: name.is_empty(), } @@ -290,7 +290,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { /// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set) /// method. /// -/// # Example +/// # Examples /// /// ``` /// use std::fmt; @@ -317,8 +317,8 @@ pub fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b let result = write!(fmt, "{{"); DebugSet { inner: DebugInner { - fmt: fmt, - result: result, + fmt, + result, has_fields: false, }, } @@ -361,7 +361,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list) /// method. /// -/// # Example +/// # Examples /// /// ``` /// use std::fmt; @@ -388,8 +388,8 @@ pub fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, let result = write!(fmt, "["); DebugList { inner: DebugInner { - fmt: fmt, - result: result, + fmt, + result, has_fields: false, }, } @@ -432,7 +432,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map) /// method. /// -/// # Example +/// # Examples /// /// ``` /// use std::fmt; @@ -460,8 +460,8 @@ pub struct DebugMap<'a, 'b: 'a> { pub fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> { let result = write!(fmt, "{{"); DebugMap { - fmt: fmt, - result: result, + fmt, + result, has_fields: false, } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 97839844087..cf6262bda97 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -334,9 +334,9 @@ impl<'a> Arguments<'a> { pub fn new_v1(pieces: &'a [&'a str], args: &'a [ArgumentV1<'a>]) -> Arguments<'a> { Arguments { - pieces: pieces, + pieces, fmt: None, - args: args + args, } } @@ -353,9 +353,9 @@ impl<'a> Arguments<'a> { args: &'a [ArgumentV1<'a>], fmt: &'a [rt::v1::Argument]) -> Arguments<'a> { Arguments { - pieces: pieces, + pieces, fmt: Some(fmt), - args: args + args, } } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index 2000ba91460..a8b84203d6a 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -240,7 +240,12 @@ pub trait Hash { /// [`write_u8`]: #method.write_u8 #[stable(feature = "rust1", since = "1.0.0")] pub trait Hasher { - /// Completes a round of hashing, producing the output hash generated. + /// Returns the hash value for the values written so far. + /// + /// Despite its name, the method does not reset the hasher’s internal + /// state. Additional [`write`]s will continue from the current value. + /// If you need to start a fresh hash value, you will have to create + /// a new hasher. /// /// # Examples /// @@ -253,6 +258,8 @@ pub trait Hasher { /// /// println!("Hash is {:x}!", hasher.finish()); /// ``` + /// + /// ['write']: #tymethod.write #[stable(feature = "rust1", since = "1.0.0")] fn finish(&self) -> u64; diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 2472efa14b3..7c009114afe 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -605,7 +605,7 @@ pub trait Iterator { /// closure returns [`None`], it will try again, and call the closure on the /// next element, seeing if it will return [`Some`]. /// - /// Why `filter_map` and not just [`filter`].[`map`]? The key is in this + /// Why `filter_map` and not just [`filter`] and [`map`]? The key is in this /// part: /// /// [`filter`]: #method.filter diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 22b997a768e..ebedfe1d743 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -840,8 +840,8 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> type Item = (A::Item, B::Item); default fn new(a: A, b: B) -> Self { Zip { - a: a, - b: b, + a, + b, index: 0, // unused len: 0, // unused } @@ -903,10 +903,10 @@ impl<A, B> ZipImpl<A, B> for Zip<A, B> fn new(a: A, b: B) -> Self { let len = cmp::min(a.len(), b.len()); Zip { - a: a, - b: b, + a, + b, index: 0, - len: len, + len, } } diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 19098f036ac..2af129a67bd 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -744,7 +744,7 @@ impl<I, T, E> ResultShunt<I, E> fn new(iter: I) -> Self { ResultShunt { - iter: iter, + iter, error: None, } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 546d2a21939..c270c6ae0db 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -51,9 +51,7 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. -#![crate_name = "core"] #![stable(feature = "core", since = "1.6.0")] -#![crate_type = "rlib"] #![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/", diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 6f7adbe1e7a..4b866cab1ea 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -901,7 +901,7 @@ impl<T> ManuallyDrop<T> { /// Manually drops the contained value. /// - /// # Unsafety + /// # Safety /// /// This function runs the destructor of the contained value and thus the wrapped value /// now represents uninitialized data. It is up to the user of this method to ensure the diff --git a/src/libcore/num/dec2flt/rawfp.rs b/src/libcore/num/dec2flt/rawfp.rs index 2a60292d023..12960fed045 100644 --- a/src/libcore/num/dec2flt/rawfp.rs +++ b/src/libcore/num/dec2flt/rawfp.rs @@ -102,10 +102,10 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp /// The number of bits in the exponent. const EXP_BITS: u8; - /// The number of bits in the singificand, *including* the hidden bit. + /// The number of bits in the significand, *including* the hidden bit. const SIG_BITS: u8; - /// The number of bits in the singificand, *excluding* the hidden bit. + /// The number of bits in the significand, *excluding* the hidden bit. const EXPLICIT_SIG_BITS: u8; /// The maximum legal exponent in fractional representation. @@ -123,7 +123,7 @@ pub trait RawFloat : Float + Copy + Debug + LowerExp /// `MIN_EXP` for integral representation, i.e., with the shift applied. const MIN_EXP_INT: i16; - /// The maximum normalized singificand in integral representation. + /// The maximum normalized significand in integral representation. const MAX_SIG: u64; /// The minimal normalized significand in integral representation. diff --git a/src/libcore/num/diy_float.rs b/src/libcore/num/diy_float.rs index 6635d95155f..97bcba2f2ff 100644 --- a/src/libcore/num/diy_float.rs +++ b/src/libcore/num/diy_float.rs @@ -86,7 +86,7 @@ impl Fp { assert_eq!(self.f << edelta >> edelta, self.f); Fp { f: self.f << edelta, - e: e, + e, } } } diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 74b9e7bf37d..beaa6e140a6 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -442,7 +442,7 @@ pub fn to_shortest_str<'a, T, F>(mut format_shortest: F, v: T, } FullDecoded::Finite(ref decoded) => { let (len, exp) = format_shortest(decoded, buf); - Formatted { sign: sign, + Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } } } @@ -581,7 +581,7 @@ pub fn to_exact_exp_str<'a, T, F>(mut format_exact: F, v: T, let trunc = if ndigits < maxlen { ndigits } else { maxlen }; let (len, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN); - Formatted { sign: sign, + Formatted { sign, parts: digits_to_exp_str(&buf[..len], exp, ndigits, upper, parts) } } } @@ -652,7 +652,7 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T, Formatted { sign: sign, parts: &parts[..1] } } } else { - Formatted { sign: sign, + Formatted { sign, parts: digits_to_dec_str(&buf[..len], exp, frac_digits, parts) } } } diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index 4971e825a6f..78326c3e639 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -/// A trait for customizing the behaviour of the `?` operator. +/// A trait for customizing the behavior of the `?` operator. /// /// A type implementing `Try` is one that has a canonical way to view it /// in terms of a success/failure dichotomy. This trait allows both diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index e35777d222c..63e9373e936 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -876,6 +876,7 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] impl<T: ?Sized> Clone for *const T { #[inline] fn clone(&self) -> *const T { @@ -884,6 +885,7 @@ impl<T: ?Sized> Clone for *const T { } #[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] impl<T: ?Sized> Clone for *mut T { #[inline] fn clone(&self) -> *mut T { @@ -895,6 +897,7 @@ impl<T: ?Sized> Clone for *mut T { macro_rules! fnptr_impls_safety_abi { ($FnTy: ty, $($Arg: ident),*) => { #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] impl<Ret, $($Arg),*> Clone for $FnTy { #[inline] fn clone(&self) -> Self { diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 20cfb02afcc..ea064ca5c39 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -244,9 +244,12 @@ use fmt; use iter::{FromIterator, FusedIterator, TrustedLen}; use ops; -/// `Result` is a type that represents either success (`Ok`) or failure (`Err`). +/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]). /// /// See the [`std::result`](index.html) module documentation for details. +/// +/// [`Ok`]: enum.Result.html#variant.Ok +/// [`Err`]: enum.Result.html#variant.Err #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -269,7 +272,9 @@ impl<T, E> Result<T, E> { // Querying the contained values ///////////////////////////////////////////////////////////////////////// - /// Returns `true` if the result is `Ok`. + /// Returns `true` if the result is [`Ok`]. + /// + /// [`Ok`]: enum.Result.html#variant.Ok /// /// # Examples /// @@ -291,7 +296,9 @@ impl<T, E> Result<T, E> { } } - /// Returns `true` if the result is `Err`. + /// Returns `true` if the result is [`Err`]. + /// + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -433,10 +440,13 @@ impl<T, E> Result<T, E> { ///////////////////////////////////////////////////////////////////////// /// Maps a `Result<T, E>` to `Result<U, E>` by applying a function to a - /// contained `Ok` value, leaving an `Err` value untouched. + /// contained [`Ok`] value, leaving an [`Err`] value untouched. /// /// This function can be used to compose the results of two functions. /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err + /// /// # Examples /// /// Print the numbers on each line of a string multiplied by two. @@ -461,11 +471,14 @@ impl<T, E> Result<T, E> { } /// Maps a `Result<T, E>` to `Result<T, F>` by applying a function to a - /// contained `Err` value, leaving an `Ok` value untouched. + /// contained [`Err`] value, leaving an [`Ok`] value untouched. /// /// This function can be used to pass through a successful result while handling /// an error. /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err + /// /// # Examples /// /// Basic usage: @@ -546,7 +559,10 @@ impl<T, E> Result<T, E> { // Boolean operations on the values, eager and lazy ///////////////////////////////////////////////////////////////////////// - /// Returns `res` if the result is `Ok`, otherwise returns the `Err` value of `self`. + /// Returns `res` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -578,7 +594,10 @@ impl<T, E> Result<T, E> { } } - /// Calls `op` if the result is `Ok`, otherwise returns the `Err` value of `self`. + /// Calls `op` if the result is [`Ok`], otherwise returns the [`Err`] value of `self`. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// This function can be used for control flow based on `Result` values. /// @@ -604,7 +623,10 @@ impl<T, E> Result<T, E> { } } - /// Returns `res` if the result is `Err`, otherwise returns the `Ok` value of `self`. + /// Returns `res` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -636,10 +658,13 @@ impl<T, E> Result<T, E> { } } - /// Calls `op` if the result is `Err`, otherwise returns the `Ok` value of `self`. + /// Calls `op` if the result is [`Err`], otherwise returns the [`Ok`] value of `self`. /// /// This function can be used for control flow based on result values. /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err + /// /// # Examples /// /// Basic usage: @@ -662,9 +687,12 @@ impl<T, E> Result<T, E> { } } - /// Unwraps a result, yielding the content of an `Ok`. + /// Unwraps a result, yielding the content of an [`Ok`]. /// Else, it returns `optb`. /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err + /// /// # Examples /// /// Basic usage: @@ -686,8 +714,11 @@ impl<T, E> Result<T, E> { } } - /// Unwraps a result, yielding the content of an `Ok`. - /// If the value is an `Err` then it calls `op` with its value. + /// Unwraps a result, yielding the content of an [`Ok`]. + /// If the value is an [`Err`] then it calls `op` with its value. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -710,12 +741,15 @@ impl<T, E> Result<T, E> { } impl<T, E: fmt::Debug> Result<T, E> { - /// Unwraps a result, yielding the content of an `Ok`. + /// Unwraps a result, yielding the content of an [`Ok`]. /// /// # Panics /// - /// Panics if the value is an `Err`, with a panic message provided by the - /// `Err`'s value. + /// Panics if the value is an [`Err`], with a panic message provided by the + /// [`Err`]'s value. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -739,12 +773,15 @@ impl<T, E: fmt::Debug> Result<T, E> { } } - /// Unwraps a result, yielding the content of an `Ok`. + /// Unwraps a result, yielding the content of an [`Ok`]. /// /// # Panics /// - /// Panics if the value is an `Err`, with a panic message including the - /// passed message, and the content of the `Err`. + /// Panics if the value is an [`Err`], with a panic message including the + /// passed message, and the content of the [`Err`]. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -765,12 +802,16 @@ impl<T, E: fmt::Debug> Result<T, E> { } impl<T: fmt::Debug, E> Result<T, E> { - /// Unwraps a result, yielding the content of an `Err`. + /// Unwraps a result, yielding the content of an [`Err`]. /// /// # Panics /// - /// Panics if the value is an `Ok`, with a custom panic message provided - /// by the `Ok`'s value. + /// Panics if the value is an [`Ok`], with a custom panic message provided + /// by the [`Ok`]'s value. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err + /// /// /// # Examples /// @@ -792,12 +833,15 @@ impl<T: fmt::Debug, E> Result<T, E> { } } - /// Unwraps a result, yielding the content of an `Err`. + /// Unwraps a result, yielding the content of an [`Err`]. /// /// # Panics /// - /// Panics if the value is an `Ok`, with a panic message including the - /// passed message, and the content of the `Ok`. + /// Panics if the value is an [`Ok`], with a panic message including the + /// passed message, and the content of the [`Ok`]. + /// + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err /// /// # Examples /// @@ -820,8 +864,8 @@ impl<T: fmt::Debug, E> Result<T, E> { impl<T: Default, E> Result<T, E> { /// Returns the contained value or a default /// - /// Consumes the `self` argument then, if `Ok`, returns the contained - /// value, otherwise if `Err`, returns the default value for that + /// Consumes the `self` argument then, if [`Ok`], returns the contained + /// value, otherwise if [`Err`], returns the default value for that /// type. /// /// # Examples @@ -829,7 +873,7 @@ impl<T: Default, E> Result<T, E> { /// Convert a string to an integer, turning poorly-formed strings /// into 0 (the default value for integers). [`parse`] converts /// a string to any other type that implements [`FromStr`], returning an - /// `Err` on error. + /// [`Err`] on error. /// /// ``` /// let good_year_from_input = "1909"; @@ -843,6 +887,8 @@ impl<T: Default, E> Result<T, E> { /// /// [`parse`]: ../../std/primitive.str.html#method.parse /// [`FromStr`]: ../../std/str/trait.FromStr.html + /// [`Ok`]: enum.Result.html#variant.Ok + /// [`Err`]: enum.Result.html#variant.Err #[inline] #[stable(feature = "result_unwrap_or_default", since = "1.16.0")] pub fn unwrap_or_default(self) -> T { diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index fa0c482e55c..31d8266510a 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -212,6 +212,9 @@ pub trait SliceExt { #[stable(feature = "copy_from_slice", since = "1.9.0")] fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy; + #[unstable(feature = "swap_with_slice", issue = "44030")] + fn swap_with_slice(&mut self, src: &mut [Self::Item]); + #[stable(feature = "sort_unstable", since = "1.20.0")] fn sort_unstable(&mut self) where Self::Item: Ord; @@ -300,7 +303,7 @@ impl<T> SliceExt for [T] { { Split { v: self, - pred: pred, + pred, finished: false } } @@ -674,6 +677,16 @@ impl<T> SliceExt for [T] { } #[inline] + fn swap_with_slice(&mut self, src: &mut [T]) { + assert!(self.len() == src.len(), + "destination and source slices have different lengths"); + unsafe { + ptr::swap_nonoverlapping( + self.as_mut_ptr(), src.as_mut_ptr(), self.len()); + } + } + + #[inline] fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize> where F: FnMut(&'a Self::Item) -> B, B: Borrow<Q>, diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 4c99fe97daf..a5f6e49a53b 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2233,7 +2233,7 @@ impl StrExt for str { fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> { SplitN(SplitNInternal { iter: self.split(pat).0, - count: count, + count, }) } diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index c4ff95b1d6a..edb7bed4520 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -290,7 +290,7 @@ impl<'a, C: CharEq> Pattern<'a> for CharEqPattern<C> { fn into_searcher(self, haystack: &'a str) -> CharEqSearcher<'a, C> { CharEqSearcher { ascii_only: self.0.only_ascii(), - haystack: haystack, + haystack, char_eq: self.0, char_indices: haystack.char_indices(), } @@ -596,8 +596,8 @@ impl<'a, 'b> StrSearcher<'a, 'b> { fn new(haystack: &'a str, needle: &'b str) -> StrSearcher<'a, 'b> { if needle.is_empty() { StrSearcher { - haystack: haystack, - needle: needle, + haystack, + needle, searcher: StrSearcherImpl::Empty(EmptyNeedle { position: 0, end: haystack.len(), @@ -607,8 +607,8 @@ impl<'a, 'b> StrSearcher<'a, 'b> { } } else { StrSearcher { - haystack: haystack, - needle: needle, + haystack, + needle, searcher: StrSearcherImpl::TwoWay( TwoWaySearcher::new(needle.as_bytes(), haystack.len()) ), @@ -899,13 +899,13 @@ impl TwoWaySearcher { TwoWaySearcher::reverse_maximal_suffix(needle, period, true)); TwoWaySearcher { - crit_pos: crit_pos, - crit_pos_back: crit_pos_back, - period: period, + crit_pos, + crit_pos_back, + period, byteset: Self::byteset_create(&needle[..period]), position: 0, - end: end, + end, memory: 0, memory_back: needle.len(), } @@ -918,13 +918,13 @@ impl TwoWaySearcher { // reverse search. TwoWaySearcher { - crit_pos: crit_pos, + crit_pos, crit_pos_back: crit_pos, period: cmp::max(crit_pos, needle.len() - crit_pos) + 1, byteset: Self::byteset_create(needle), position: 0, - end: end, + end, memory: usize::MAX, // Dummy value to signify that the period is long memory_back: usize::MAX, } diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index d647a94a1ef..510e01db0e9 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -1632,7 +1632,7 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T { /// /// pub fn lock(&self) { /// while !self.flag.compare_and_swap(false, true, Ordering::Relaxed) {} -/// // This fence syncronizes-with store in `unlock`. +/// // This fence synchronizes-with store in `unlock`. /// fence(Ordering::Acquire); /// } /// diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index a1249a5f22c..ed6923929d6 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -392,7 +392,7 @@ pub struct CycleIter<'a, T: 'a> { pub fn cycle<T>(data: &[T]) -> CycleIter<T> { CycleIter { index: 0, - data: data, + data, } } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 84a3be99c27..ab2022b1824 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -26,7 +26,6 @@ #![feature(inclusive_range)] #![feature(inclusive_range_syntax)] #![feature(iter_rfind)] -#![feature(libc)] #![feature(nonzero)] #![feature(ord_max_min)] #![feature(rand)] @@ -41,13 +40,10 @@ #![feature(test)] #![feature(trusted_len)] #![feature(try_from)] -#![feature(unicode)] #![feature(unique)] extern crate core; extern crate test; -extern crate libc; -extern crate std_unicode; extern crate rand; mod any; diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs index 51b0655f680..6bac55575fb 100644 --- a/src/libcore/tests/option.rs +++ b/src/libcore/tests/option.rs @@ -53,7 +53,7 @@ fn test_get_resource() { fn r(i: Rc<RefCell<isize>>) -> R { R { - i: i + i, } } diff --git a/src/libcore/tuple.rs b/src/libcore/tuple.rs index 47e9c7c9038..555843dba41 100644 --- a/src/libcore/tuple.rs +++ b/src/libcore/tuple.rs @@ -22,6 +22,7 @@ macro_rules! tuple_impls { )+) => { $( #[stable(feature = "rust1", since = "1.0.0")] + #[cfg(stage0)] impl<$($T:Clone),+> Clone for ($($T,)+) { fn clone(&self) -> ($($T,)+) { ($(self.$idx.clone(),)+) diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 493ce04f672..24430b2e377 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -14,9 +14,6 @@ //! Parsing does not happen at runtime: structures of `std::fmt::rt` are //! generated instead. -#![crate_name = "fmt_macros"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -284,7 +281,7 @@ impl<'a> Parser<'a> { Argument { position: pos, - format: format, + format, } } diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index f41fc5aa29f..a0eacc817ca 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -77,9 +77,6 @@ //! } //! ``` -#![crate_name = "getopts"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -250,28 +247,28 @@ impl OptGroup { (0, _) => { Opt { name: Long((long_name)), - hasarg: hasarg, - occur: occur, + hasarg, + occur, aliases: Vec::new(), } } (1, 0) => { Opt { name: Short(short_name.chars().next().unwrap()), - hasarg: hasarg, - occur: occur, + hasarg, + occur, aliases: Vec::new(), } } (1, _) => { Opt { name: Long((long_name)), - hasarg: hasarg, - occur: occur, + hasarg, + occur, aliases: vec![Opt { name: Short(short_name.chars().next().unwrap()), - hasarg: hasarg, - occur: occur, + hasarg, + occur, aliases: Vec::new(), }], } @@ -530,8 +527,8 @@ pub fn opt(short_name: &str, long_name: long_name.to_owned(), hint: hint.to_owned(), desc: desc.to_owned(), - hasarg: hasarg, - occur: occur, + hasarg, + occur, } } @@ -681,9 +678,9 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { } } Ok(Matches { - opts: opts, - vals: vals, - free: free, + opts, + vals, + free, }) } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index c01938f5e11..5b1cf2dee9a 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -11,7 +11,7 @@ //! Generate files suitable for use with [Graphviz](http://www.graphviz.org/) //! //! The `render` function generates output (e.g. an `output.dot` file) for -//! use with [Graphviz](http://www.graphviz.org/) by walking a labelled +//! use with [Graphviz](http://www.graphviz.org/) by walking a labeled //! graph. (Graphviz can then automatically lay out the nodes and edges //! of the graph, and also optionally render the graph as an image or //! other [output formats]( @@ -150,7 +150,7 @@ //! //! The output from this example renders four nodes that make up the //! Hasse-diagram for the subsets of the set `{x, y}`. Each edge is -//! labelled with the ⊆ character (specified using the HTML character +//! labeled with the ⊆ character (specified using the HTML character //! entity `&sube`). //! //! ```rust @@ -283,9 +283,6 @@ //! //! * [DOT language](http://www.graphviz.org/doc/info/lang.html) -#![crate_name = "graphviz"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -781,15 +778,15 @@ mod tests { fn edge(from: usize, to: usize, label: &'static str, style: Style) -> Edge { Edge { - from: from, - to: to, - label: label, - style: style, + from, + to, + label, + style, } } struct LabelledGraph { - /// The name for this graph. Used for labelling generated `digraph`. + /// The name for this graph. Used for labeling generated `digraph`. name: &'static str, /// Each node is an index into `node_labels`; these labels are @@ -848,9 +845,9 @@ mod tests { -> LabelledGraph { let count = node_labels.len(); LabelledGraph { - name: name, + name, node_labels: node_labels.to_opt_strs(), - edges: edges, + edges, node_styles: match node_styles { Some(nodes) => nodes, None => vec![Style::None; count], diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 348180a48dc..8be6f647023 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -14,8 +14,6 @@ //! simpler! That being said, it's not quite as versatile, but here goes! #![no_std] -#![crate_name = "panic_abort"] -#![crate_type = "rlib"] #![unstable(feature = "panic_abort", issue = "32837")] #![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", diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index aadbeb96b2d..63e44f71a3a 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -74,7 +74,7 @@ pub unsafe fn panic(data: Box<Any + Send>) -> u32 { let exception = Box::new(Exception { _uwe: uw::_Unwind_Exception { exception_class: rust_exception_class(), - exception_cleanup: exception_cleanup, + exception_cleanup, private: [0; uw::unwinder_private_data_size], }, cause: Some(data), diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 90f4b364482..558286f4ec0 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -23,8 +23,6 @@ //! module. #![no_std] -#![crate_name = "panic_unwind"] -#![crate_type = "rlib"] #![unstable(feature = "panic_unwind", issue = "32837")] #![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", @@ -36,7 +34,9 @@ #![feature(core_intrinsics)] #![feature(lang_items)] #![feature(libc)] -#![feature(panic_unwind)] +#![cfg_attr(not(any(target_env = "msvc", + all(windows, target_arch = "x86_64", target_env = "gnu"))), + feature(panic_unwind))] #![feature(raw)] #![feature(staged_api)] #![feature(unwind_attributes)] @@ -47,6 +47,7 @@ extern crate alloc; extern crate libc; +#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))] extern crate unwind; use core::intrinsics; diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 6a71e67676a..3f425c24a91 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -23,10 +23,7 @@ //! //! See [the book](../book/first-edition/procedural-macros.html) for more. -#![crate_name = "proc_macro"] #![stable(feature = "proc_macro_lib", since = "1.15.0")] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![deny(warnings)] #![deny(missing_docs)] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", @@ -241,14 +238,14 @@ pub enum TokenNode { } /// Describes how a sequence of token trees is delimited. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "proc_macro", issue = "38356")] pub enum Delimiter { /// `( ... )` Parenthesis, - /// `[ ... ]` - Brace, /// `{ ... }` + Brace, + /// `[ ... ]` Bracket, /// An implicit delimiter, e.g. `$var`, where $var is `...`. None, @@ -274,7 +271,7 @@ impl Term { } /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "proc_macro", issue = "38356")] pub enum Spacing { /// e.g. `+` is `Alone` in `+ =`. diff --git a/src/libprofiler_builtins/lib.rs b/src/libprofiler_builtins/lib.rs index 1fb2c6b7dbb..6d0d6d115b7 100644 --- a/src/libprofiler_builtins/lib.rs +++ b/src/libprofiler_builtins/lib.rs @@ -14,7 +14,5 @@ #![unstable(feature = "profiler_runtime_lib", reason = "internal implementation detail of rustc right now", issue = "0")] -#![crate_name = "profiler_builtins"] -#![crate_type = "rlib"] #![allow(unused_features)] #![feature(staged_api)] diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 9a42b82beff..e796197ab5b 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -127,9 +127,9 @@ impl GammaLargeShape { fn new_raw(shape: f64, scale: f64) -> GammaLargeShape { let d = shape - 1. / 3.; GammaLargeShape { - scale: scale, + scale, c: 1. / (9. * d).sqrt(), - d: d, + d, } } } @@ -254,7 +254,7 @@ impl IndependentSample<f64> for ChiSquared { /// The Fisher F distribution `F(m, n)`. /// -/// This distribution is equivalent to the ratio of two normalised +/// This distribution is equivalent to the ratio of two normalized /// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) / /// (χ²(n)/n)`. pub struct FisherF { diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index 67b9449981e..47967a719d3 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -149,7 +149,7 @@ impl<'a, T: Clone> WeightedChoice<'a, T> { "WeightedChoice::new called with a total weight of 0"); WeightedChoice { - items: items, + items, // we're likely to be generating numbers in this range // relatively often, so might as well cache it weight_range: Range::new(0, running_total), diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index 33de11ab630..e1518dab21c 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -103,8 +103,8 @@ impl Normal { pub fn new(mean: f64, std_dev: f64) -> Normal { assert!(std_dev >= 0.0, "Normal::new called with `std_dev` < 0"); Normal { - mean: mean, - std_dev: std_dev, + mean, + std_dev, } } } diff --git a/src/librand/distributions/range.rs b/src/librand/distributions/range.rs index be238b0b1ab..f2f8132e5b4 100644 --- a/src/librand/distributions/range.rs +++ b/src/librand/distributions/range.rs @@ -104,7 +104,7 @@ macro_rules! integer_impl { let zone = unsigned_max - unsigned_max % range; Range { - low: low, + low, range: range as $ty, accept_zone: zone as $ty } @@ -143,7 +143,7 @@ macro_rules! float_impl { impl SampleRange for $ty { fn construct_range(low: $ty, high: $ty) -> Range<$ty> { Range { - low: low, + low, range: high - low, accept_zone: 0.0 // unused } diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 2baa07e370e..96ce0905e38 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -76,7 +76,7 @@ impl IsaacRng { rng } - /// Initialises `self`. If `use_rsl` is true, then use the current value + /// Initializes `self`. If `use_rsl` is true, then use the current value /// of `rsl` as a seed, otherwise construct one algorithmically (not /// randomly). fn init(&mut self, use_rsl: bool) { @@ -367,7 +367,7 @@ impl Isaac64Rng { rng } - /// Initialises `self`. If `use_rsl` is true, then use the current value + /// Initializes `self`. If `use_rsl` is true, then use the current value /// of `rsl` as a seed, otherwise construct one algorithmically (not /// randomly). fn init(&mut self, use_rsl: bool) { diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 5e56b0d8ab1..90b3020fff9 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -16,8 +16,6 @@ //! is not recommended to use this library directly, but rather the official //! interface through `std::rand`. -#![crate_name = "rand"] -#![crate_type = "rlib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -180,7 +178,7 @@ pub trait Rng: Sized { /// This method does *not* have a requirement to bear any fixed /// relationship to the other methods, for example, it does *not* /// have to result in the same output as progressively filling - /// `dest` with `self.gen::<u8>()`, and any such behaviour should + /// `dest` with `self.gen::<u8>()`, and any such behavior should /// not be relied upon. /// /// This method should guarantee that `dest` is entirely filled @@ -418,10 +416,10 @@ impl Rand for XorShiftRng { } let (x, y, z, w) = tuple; XorShiftRng { - x: x, - y: y, - z: z, - w: w, + x, + y, + z, + w, } } } diff --git a/src/librand/reseeding.rs b/src/librand/reseeding.rs index 21684e38f7b..2821b7a8232 100644 --- a/src/librand/reseeding.rs +++ b/src/librand/reseeding.rs @@ -24,7 +24,7 @@ pub struct ReseedingRng<R, Rsdr> { rng: R, generation_threshold: usize, bytes_generated: usize, - /// Controls the behaviour when reseeding the RNG. + /// Controls the behavior when reseeding the RNG. pub reseeder: Rsdr, } @@ -38,10 +38,10 @@ impl<R: Rng, Rsdr: Reseeder<R>> ReseedingRng<R, Rsdr> { /// * `reseeder`: the reseeding object to use. pub fn new(rng: R, generation_threshold: usize, reseeder: Rsdr) -> ReseedingRng<R, Rsdr> { ReseedingRng { - rng: rng, - generation_threshold: generation_threshold, + rng, + generation_threshold, bytes_generated: 0, - reseeder: reseeder, + reseeder, } } diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 5b609f192e1..01fff605283 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -411,6 +411,8 @@ define_dep_nodes!( <'tcx> [] BorrowCheckKrate, [] BorrowCheck(DefId), + [] MirBorrowCheck(DefId), + [] RvalueCheck(DefId), [] Reachability, [] MirKeys, @@ -520,6 +522,8 @@ define_dep_nodes!( <'tcx> [] DylibDepFormats(DefId), [] IsAllocator(DefId), [] IsPanicRuntime(DefId), + [] IsCompilerBuiltins(DefId), + [] HasGlobalAllocator(DefId), [] ExternCrate(DefId), [] LintLevels, ); diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs index 9aa634770df..809d1dfcf60 100644 --- a/src/librustc/dep_graph/edges.rs +++ b/src/librustc/dep_graph/edges.rs @@ -244,8 +244,8 @@ impl DepGraphEdges { self.edges.insert((source, target)); } - pub fn add_node(&mut self, node: DepNode) { - self.get_or_create_node(node); + pub fn add_node(&mut self, node: DepNode) -> DepNodeIndex { + self.get_or_create_node(node) } #[inline] diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 4ca59132e0a..c487fc963ca 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -12,6 +12,7 @@ use rustc_data_structures::fx::FxHashMap; use session::config::OutputType; use std::cell::{Ref, RefCell}; use std::rc::Rc; +use util::common::{ProfileQueriesMsg, profq_msg}; use super::dep_node::{DepNode, DepKind, WorkProductId}; use super::query::DepGraphQuery; @@ -118,7 +119,13 @@ impl DepGraph { { if let Some(ref data) = self.data { data.edges.borrow_mut().push_task(key); + if cfg!(debug_assertions) { + profq_msg(ProfileQueriesMsg::TaskBegin(key.clone())) + }; let result = task(cx, arg); + if cfg!(debug_assertions) { + profq_msg(ProfileQueriesMsg::TaskEnd) + }; let dep_node_index = data.edges.borrow_mut().pop_task(key); (result, dep_node_index) } else { @@ -166,6 +173,14 @@ impl DepGraph { self.data.as_ref().unwrap().edges.borrow_mut().add_node(node); } + pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex { + if let Some(ref data) = self.data { + data.edges.borrow_mut().add_node(node) + } else { + DepNodeIndex::INVALID + } + } + /// Indicates that a previous work product exists for `v`. This is /// invoked during initial start-up based on what nodes are clean /// (and what files exist in the incr. directory). diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index 522c1531c59..412759e1142 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -362,6 +362,10 @@ Here are some simple examples of where you'll run into this error: struct Foo { x: &bool } // error struct Foo<'a> { x: &'a bool } // correct +struct Bar { x: Foo } + ^^^ expected lifetime parameter +struct Bar<'a> { x: Foo<'a> } // correct + enum Bar { A(u8), B(&bool), } // error enum Bar<'a> { A(u8), B(&'a bool), } // correct @@ -683,6 +687,21 @@ attributes: See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html "##, +E0214: r##" +A generic type was described using parentheses rather than angle brackets. For +example: + +```compile_fail,E0214 +fn main() { + let v: Vec(&str) = vec!["foo"]; +} +``` + +This is not currently supported: `v` should be defined as `Vec<&str>`. +Parentheses are currently only used with generic types when defining parameters +for `Fn`-family traits. +"##, + E0261: r##" When using a lifetime like `'a` in a type, it must be declared before being used. diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 2a0c76d99bf..d52cc26eaeb 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -617,17 +617,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V, pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V, _path_span: Span, path_parameters: &'v PathParameters) { - match *path_parameters { - AngleBracketedParameters(ref data) => { - walk_list!(visitor, visit_ty, &data.types); - walk_list!(visitor, visit_lifetime, &data.lifetimes); - walk_list!(visitor, visit_assoc_type_binding, &data.bindings); - } - ParenthesizedParameters(ref data) => { - walk_list!(visitor, visit_ty, &data.inputs); - walk_list!(visitor, visit_ty, &data.output); - } - } + walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes); + walk_list!(visitor, visit_ty, &path_parameters.types); + walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings); } pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V, @@ -835,7 +827,16 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref: pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) { // NB: Deliberately force a compilation error if/when new fields are added. - let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item; + let ImplItem { + id: _, + hir_id: _, + name, + ref vis, + ref defaultness, + ref attrs, + ref node, + span + } = *impl_item; visitor.visit_name(span, name); visitor.visit_vis(vis); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 010c7f6171a..ac26cbc833d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -45,21 +45,22 @@ use hir::map::{Definitions, DefKey, REGULAR_SPACE}; use hir::map::definitions::DefPathData; use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX}; use hir::def::{Def, PathResolution}; +use lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES; use rustc_data_structures::indexed_vec::IndexVec; use session::Session; +use util::common::FN_OUTPUT_NAME; use util::nodemap::{DefIdMap, FxHashMap, NodeMap}; use std::collections::BTreeMap; use std::fmt::Debug; use std::iter; use std::mem; - use syntax::attr; use syntax::ast::*; use syntax::errors; use syntax::ext::hygiene::{Mark, SyntaxContext}; use syntax::ptr::P; -use syntax::codemap::{self, respan, Spanned}; +use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind}; use syntax::std_inject; use syntax::symbol::{Symbol, keywords}; use syntax::util::small_vector::SmallVector; @@ -160,6 +161,12 @@ struct LoweredNodeId { hir_id: hir::HirId, } +enum ParenthesizedGenericArgs { + Ok, + Warn, + Err, +} + impl<'a> LoweringContext<'a> { fn lower_crate(mut self, c: &Crate) -> hir::Crate { /// Full-crate AST visitor that inserts into a fresh @@ -414,12 +421,14 @@ impl<'a> LoweringContext<'a> { Symbol::gensym(s) } - fn allow_internal_unstable(&self, reason: &'static str, mut span: Span) -> Span { + fn allow_internal_unstable(&self, reason: CompilerDesugaringKind, mut span: Span) + -> Span + { let mark = Mark::fresh(Mark::root()); mark.set_expn_info(codemap::ExpnInfo { call_site: span, callee: codemap::NameAndSpan { - format: codemap::CompilerDesugaring(Symbol::intern(reason)), + format: codemap::CompilerDesugaring(reason), span: Some(span), allow_internal_unstable: true, allow_internal_unsafe: false, @@ -747,6 +756,21 @@ impl<'a> LoweringContext<'a> { Def::Trait(def_id) if i + 1 == proj_start => Some(def_id), _ => None }; + let parenthesized_generic_args = match resolution.base_def() { + // `a::b::Trait(Args)` + Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok, + // `a::b::Trait(Args)::TraitItem` + Def::Method(..) | + Def::AssociatedConst(..) | + Def::AssociatedTy(..) if i + 2 == proj_start => ParenthesizedGenericArgs::Ok, + // Avoid duplicated errors + Def::Err => ParenthesizedGenericArgs::Ok, + // An error + Def::Struct(..) | Def::Enum(..) | Def::Union(..) | Def::TyAlias(..) | + Def::Variant(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Err, + // A warning for now, for compatibility reasons + _ => ParenthesizedGenericArgs::Warn, + }; let num_lifetimes = type_def_id.map_or(0, |def_id| { if let Some(&n) = self.type_def_lifetime_params.get(&def_id) { @@ -757,7 +781,8 @@ impl<'a> LoweringContext<'a> { self.type_def_lifetime_params.insert(def_id, n); n }); - self.lower_path_segment(p.span, segment, param_mode, num_lifetimes) + self.lower_path_segment(p.span, segment, param_mode, num_lifetimes, + parenthesized_generic_args) }).collect(), span: p.span, }); @@ -792,7 +817,8 @@ impl<'a> LoweringContext<'a> { // 3. `<<std::vec::Vec<T>>::IntoIter>::Item` // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone` for (i, segment) in p.segments.iter().enumerate().skip(proj_start) { - let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0)); + let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0, + ParenthesizedGenericArgs::Warn)); let qpath = hir::QPath::TypeRelative(ty, segment); // It's finished, return the extension of the right node type. @@ -825,7 +851,8 @@ impl<'a> LoweringContext<'a> { hir::Path { def: self.expect_full_def(id), segments: segments.map(|segment| { - self.lower_path_segment(p.span, segment, param_mode, 0) + self.lower_path_segment(p.span, segment, param_mode, 0, + ParenthesizedGenericArgs::Err) }).chain(name.map(|name| { hir::PathSegment { name, @@ -849,29 +876,37 @@ impl<'a> LoweringContext<'a> { path_span: Span, segment: &PathSegment, param_mode: ParamMode, - expected_lifetimes: usize) + expected_lifetimes: usize, + parenthesized_generic_args: ParenthesizedGenericArgs) -> hir::PathSegment { let mut parameters = if let Some(ref parameters) = segment.parameters { + let msg = "parenthesized parameters may only be used with a trait"; match **parameters { PathParameters::AngleBracketed(ref data) => { - let data = self.lower_angle_bracketed_parameter_data(data, param_mode); - hir::AngleBracketedParameters(data) + self.lower_angle_bracketed_parameter_data(data, param_mode) } - PathParameters::Parenthesized(ref data) => { - hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data)) + PathParameters::Parenthesized(ref data) => match parenthesized_generic_args { + ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data), + ParenthesizedGenericArgs::Warn => { + self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, + CRATE_NODE_ID, data.span, msg.into()); + hir::PathParameters::none() + } + ParenthesizedGenericArgs::Err => { + struct_span_err!(self.sess, data.span, E0214, "{}", msg) + .span_label(data.span, "only traits may use parentheses").emit(); + hir::PathParameters::none() + } } } } else { - let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode); - hir::AngleBracketedParameters(data) + self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode) }; - if let hir::AngleBracketedParameters(ref mut data) = parameters { - if data.lifetimes.is_empty() { - data.lifetimes = (0..expected_lifetimes).map(|_| { - self.elided_lifetime(path_span) - }).collect(); - } + if !parameters.parenthesized && parameters.lifetimes.is_empty() { + parameters.lifetimes = (0..expected_lifetimes).map(|_| { + self.elided_lifetime(path_span) + }).collect(); } hir::PathSegment { @@ -883,24 +918,38 @@ impl<'a> LoweringContext<'a> { fn lower_angle_bracketed_parameter_data(&mut self, data: &AngleBracketedParameterData, param_mode: ParamMode) - -> hir::AngleBracketedParameterData { + -> hir::PathParameters { let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data; - hir::AngleBracketedParameterData { + hir::PathParameters { lifetimes: self.lower_lifetimes(lifetimes), types: types.iter().map(|ty| self.lower_ty(ty)).collect(), infer_types: types.is_empty() && param_mode == ParamMode::Optional, bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(), + parenthesized: false, } } fn lower_parenthesized_parameter_data(&mut self, data: &ParenthesizedParameterData) - -> hir::ParenthesizedParameterData { + -> hir::PathParameters { let &ParenthesizedParameterData { ref inputs, ref output, span } = data; - hir::ParenthesizedParameterData { - inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(), - output: output.as_ref().map(|ty| self.lower_ty(ty)), - span, + let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect(); + let mk_tup = |this: &mut Self, tys, span| { + P(hir::Ty { node: hir::TyTup(tys), id: this.next_id().node_id, span }) + }; + + hir::PathParameters { + lifetimes: hir::HirVec::new(), + types: hir_vec![mk_tup(self, inputs, span)], + infer_types: false, + bindings: hir_vec![hir::TypeBinding { + id: self.next_id().node_id, + name: Symbol::intern(FN_OUTPUT_NAME), + ty: output.as_ref().map(|ty| self.lower_ty(&ty)) + .unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)), + span: output.as_ref().map_or(span, |ty| ty.span), + }], + parenthesized: true, } } @@ -1266,7 +1315,12 @@ impl<'a> LoweringContext<'a> { path.span = span; self.allocate_hir_id_counter(import.id, import); - self.with_hir_id_owner(import.id, |this| { + let LoweredNodeId { + node_id: import_node_id, + hir_id: import_hir_id, + } = self.lower_node_id(import.id); + + self.with_hir_id_owner(import_node_id, |this| { let vis = match *vis { hir::Visibility::Public => hir::Visibility::Public, hir::Visibility::Crate => hir::Visibility::Crate, @@ -1280,8 +1334,9 @@ impl<'a> LoweringContext<'a> { } }; - this.items.insert(import.id, hir::Item { - id: import.id, + this.items.insert(import_node_id, hir::Item { + id: import_node_id, + hir_id: import_hir_id, name: import.rename.unwrap_or(ident).name, attrs: attrs.clone(), node: hir::ItemUse(P(path), hir::UseKind::Single), @@ -1412,8 +1467,11 @@ impl<'a> LoweringContext<'a> { fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem { self.with_parent_def(i.id, |this| { + let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id); + hir::TraitItem { - id: this.lower_node_id(i.id).node_id, + id: node_id, + hir_id, name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), node: match i.node { @@ -1473,8 +1531,11 @@ impl<'a> LoweringContext<'a> { fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem { self.with_parent_def(i.id, |this| { + let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id); + hir::ImplItem { - id: this.lower_node_id(i.id).node_id, + id: node_id, + hir_id, name: this.lower_ident(i.ident), attrs: this.lower_attrs(&i.attrs), vis: this.lower_visibility(&i.vis, None), @@ -1565,8 +1626,11 @@ impl<'a> LoweringContext<'a> { this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node) }); + let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id); + Some(hir::Item { - id: self.lower_node_id(i.id).node_id, + id: node_id, + hir_id, name, attrs, node, @@ -1790,7 +1854,8 @@ impl<'a> LoweringContext<'a> { let move_val_init = ["intrinsics", "move_val_init"]; let inplace_finalize = ["ops", "InPlace", "finalize"]; - let unstable_span = self.allow_internal_unstable("<-", e.span); + let unstable_span = + self.allow_internal_unstable(CompilerDesugaringKind::BackArrow, e.span); let make_call = |this: &mut LoweringContext, p, args| { let path = P(this.expr_std_path(unstable_span, p, ThinVec::new())); P(this.expr_call(e.span, path, args)) @@ -1874,7 +1939,8 @@ impl<'a> LoweringContext<'a> { hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect()) } ExprKind::MethodCall(ref seg, ref args) => { - let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0); + let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0, + ParenthesizedGenericArgs::Err); let args = args.iter().map(|x| self.lower_expr(x)).collect(); hir::ExprMethodCall(hir_seg, seg.span, args) } @@ -2007,12 +2073,14 @@ impl<'a> LoweringContext<'a> { e1.iter().map(|e| ("start", e)).chain(e2.iter().map(|e| ("end", e))) .map(|(s, e)| { let expr = P(self.lower_expr(&e)); - let unstable_span = self.allow_internal_unstable("...", e.span); + let unstable_span = + self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); self.field(Symbol::intern(s), expr, unstable_span) }).collect::<P<[hir::Field]>>(); let is_unit = fields.is_empty(); - let unstable_span = self.allow_internal_unstable("...", e.span); + let unstable_span = + self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); let struct_path = iter::once("ops").chain(iter::once(path)) .collect::<Vec<_>>(); @@ -2353,7 +2421,8 @@ impl<'a> LoweringContext<'a> { // return Try::from_error(From::from(err)), // } - let unstable_span = self.allow_internal_unstable("?", e.span); + let unstable_span = + self.allow_internal_unstable(CompilerDesugaringKind::QuestionMark, e.span); // Try::into_result(<expr>) let discr = { diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index d3ae3e0e8e8..a54068c6483 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -10,33 +10,55 @@ use super::*; +use dep_graph::{DepGraph, DepKind, DepNodeIndex}; use hir::intravisit::{Visitor, NestedVisitorMap}; use std::iter::repeat; use syntax::ast::{NodeId, CRATE_NODE_ID}; use syntax_pos::Span; /// A Visitor that walks over the HIR and collects Nodes into a HIR map -pub struct NodeCollector<'hir> { +pub(super) struct NodeCollector<'a, 'hir> { /// The crate - pub krate: &'hir Crate, + krate: &'hir Crate, /// The node map - pub(super) map: Vec<MapEntry<'hir>>, + map: Vec<MapEntry<'hir>>, /// The parent of this node - pub parent_node: NodeId, + parent_node: NodeId, + + current_dep_node_owner: DefIndex, + current_dep_node_index: DepNodeIndex, + + dep_graph: &'a DepGraph, + definitions: &'a definitions::Definitions, } -impl<'hir> NodeCollector<'hir> { - pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> { +impl<'a, 'hir> NodeCollector<'a, 'hir> { + pub(super) fn root(krate: &'hir Crate, + dep_graph: &'a DepGraph, + definitions: &'a definitions::Definitions) + -> NodeCollector<'a, 'hir> { + let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); + let root_mod_dep_node = root_mod_def_path_hash.to_dep_node(DepKind::Hir); + let root_mod_dep_node_index = dep_graph.alloc_input_node(root_mod_dep_node); + let mut collector = NodeCollector { krate, map: vec![], parent_node: CRATE_NODE_ID, + current_dep_node_index: root_mod_dep_node_index, + current_dep_node_owner: CRATE_DEF_INDEX, + dep_graph, + definitions, }; - collector.insert_entry(CRATE_NODE_ID, RootCrate); + collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index)); collector } + pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> { + self.map + } + fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) { debug!("hir_map: {:?} => {:?}", id, entry); let len = self.map.len(); @@ -47,8 +69,55 @@ impl<'hir> NodeCollector<'hir> { } fn insert(&mut self, id: NodeId, node: Node<'hir>) { - let entry = MapEntry::from_node(self.parent_node, node); + let parent = self.parent_node; + let dep_node_index = self.current_dep_node_index; + + let entry = match node { + NodeItem(n) => EntryItem(parent, dep_node_index, n), + NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n), + NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n), + NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n), + NodeVariant(n) => EntryVariant(parent, dep_node_index, n), + NodeField(n) => EntryField(parent, dep_node_index, n), + NodeExpr(n) => EntryExpr(parent, dep_node_index, n), + NodeStmt(n) => EntryStmt(parent, dep_node_index, n), + NodeTy(n) => EntryTy(parent, dep_node_index, n), + NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n), + NodeBinding(n) => EntryBinding(parent, dep_node_index, n), + NodePat(n) => EntryPat(parent, dep_node_index, n), + NodeBlock(n) => EntryBlock(parent, dep_node_index, n), + NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n), + NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n), + NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n), + NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n), + NodeLocal(n) => EntryLocal(parent, dep_node_index, n), + }; + + // Make sure that the DepNode of some node coincides with the HirId + // owner of that node. + if cfg!(debug_assertions) { + let hir_id_owner = self.definitions.node_to_hir_id(id).owner; + + if hir_id_owner != self.current_dep_node_owner { + let node_str = match self.definitions.opt_def_index(id) { + Some(def_index) => { + self.definitions.def_path(def_index).to_string_no_crate() + } + None => format!("{:?}", node) + }; + + bug!("inconsistent DepNode for `{}`: \ + current_dep_node_owner={}, hir_id.owner={}", + node_str, + self.definitions + .def_path(self.current_dep_node_owner) + .to_string_no_crate(), + self.definitions.def_path(hir_id_owner).to_string_no_crate()) + } + } + self.insert_entry(id, entry); + } fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) { @@ -57,9 +126,27 @@ impl<'hir> NodeCollector<'hir> { f(self); self.parent_node = parent_node; } + + fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self, + dep_node_owner: DefIndex, + f: F) { + let prev_owner = self.current_dep_node_owner; + let prev_index = self.current_dep_node_index; + + // When we enter a new owner (item, impl item, or trait item), we always + // start out again with DepKind::Hir. + let new_dep_node = self.definitions + .def_path_hash(dep_node_owner) + .to_dep_node(DepKind::Hir); + self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node); + self.current_dep_node_owner = dep_node_owner; + f(self); + self.current_dep_node_index = prev_index; + self.current_dep_node_owner = prev_owner; + } } -impl<'hir> Visitor<'hir> for NodeCollector<'hir> { +impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { /// Because we want to track parent items and so forth, enable /// deep walking so that we walk nested items in the context of /// their outer items. @@ -82,25 +169,37 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> { } fn visit_nested_body(&mut self, id: BodyId) { + // When we enter a body, we switch to DepKind::HirBody. + // Note that current_dep_node_index might already be DepKind::HirBody, + // e.g. when entering the body of a closure that is already part of a + // surrounding body. That's expected and not a problem. + let prev_index = self.current_dep_node_index; + let new_dep_node = self.definitions + .def_path_hash(self.current_dep_node_owner) + .to_dep_node(DepKind::HirBody); + self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node); self.visit_body(self.krate.body(id)); + self.current_dep_node_index = prev_index; } fn visit_item(&mut self, i: &'hir Item) { debug!("visit_item: {:?}", i); - - self.insert(i.id, NodeItem(i)); - - self.with_parent(i.id, |this| { - match i.node { - ItemStruct(ref struct_def, _) => { - // If this is a tuple-like struct, register the constructor. - if !struct_def.is_struct() { - this.insert(struct_def.id(), NodeStructCtor(struct_def)); + debug_assert_eq!(i.hir_id.owner, + self.definitions.opt_def_index(i.id).unwrap()); + self.with_dep_node_owner(i.hir_id.owner, |this| { + this.insert(i.id, NodeItem(i)); + this.with_parent(i.id, |this| { + match i.node { + ItemStruct(ref struct_def, _) => { + // If this is a tuple-like struct, register the constructor. + if !struct_def.is_struct() { + this.insert(struct_def.id(), NodeStructCtor(struct_def)); + } } + _ => {} } - _ => {} - } - intravisit::walk_item(this, i); + intravisit::walk_item(this, i); + }); }); } @@ -121,24 +220,32 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> { } fn visit_trait_item(&mut self, ti: &'hir TraitItem) { - self.insert(ti.id, NodeTraitItem(ti)); - - self.with_parent(ti.id, |this| { - intravisit::walk_trait_item(this, ti); + debug_assert_eq!(ti.hir_id.owner, + self.definitions.opt_def_index(ti.id).unwrap()); + self.with_dep_node_owner(ti.hir_id.owner, |this| { + this.insert(ti.id, NodeTraitItem(ti)); + + this.with_parent(ti.id, |this| { + intravisit::walk_trait_item(this, ti); + }); }); } fn visit_impl_item(&mut self, ii: &'hir ImplItem) { - self.insert(ii.id, NodeImplItem(ii)); - - self.with_parent(ii.id, |this| { - intravisit::walk_impl_item(this, ii); + debug_assert_eq!(ii.hir_id.owner, + self.definitions.opt_def_index(ii.id).unwrap()); + self.with_dep_node_owner(ii.hir_id.owner, |this| { + this.insert(ii.id, NodeImplItem(ii)); + + this.with_parent(ii.id, |this| { + intravisit::walk_impl_item(this, ii); + }); }); } fn visit_pat(&mut self, pat: &'hir Pat) { let node = if let PatKind::Binding(..) = pat.node { - NodeLocal(pat) + NodeBinding(pat) } else { NodePat(pat) }; @@ -195,6 +302,13 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> { }); } + fn visit_local(&mut self, l: &'hir Local) { + self.insert(l.id, NodeLocal(l)); + self.with_parent(l.id, |this| { + intravisit::walk_local(this, l) + }) + } + fn visit_lifetime(&mut self, lifetime: &'hir Lifetime) { self.insert(lifetime.id, NodeLifetime(lifetime)); } @@ -231,4 +345,33 @@ impl<'hir> Visitor<'hir> for NodeCollector<'hir> { intravisit::walk_struct_field(this, field); }); } + + fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) { + // Do not visit the duplicate information in TraitItemRef. We want to + // map the actual nodes, not the duplicate ones in the *Ref. + let TraitItemRef { + id, + name: _, + kind: _, + span: _, + defaultness: _, + } = *ii; + + self.visit_nested_trait_item(id); + } + + fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) { + // Do not visit the duplicate information in ImplItemRef. We want to + // map the actual nodes, not the duplicate ones in the *Ref. + let ImplItemRef { + id, + name: _, + kind: _, + span: _, + vis: _, + defaultness: _, + } = *ii; + + self.visit_nested_impl_item(id); + } } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ed4e28cc9eb..63a5b70cb81 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -15,7 +15,7 @@ pub use self::def_collector::{DefCollector, MacroInvocationData}; pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData, DisambiguatedDefPathData, DefPathHash}; -use dep_graph::{DepGraph, DepNode, DepKind}; +use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex}; use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndexAddressSpace}; @@ -53,9 +53,10 @@ pub enum Node<'hir> { NodeStmt(&'hir Stmt), NodeTy(&'hir Ty), NodeTraitRef(&'hir TraitRef), - NodeLocal(&'hir Pat), + NodeBinding(&'hir Pat), NodePat(&'hir Pat), NodeBlock(&'hir Block), + NodeLocal(&'hir Local), /// NodeStructCtor represents a tuple struct. NodeStructCtor(&'hir VariantData), @@ -73,26 +74,28 @@ enum MapEntry<'hir> { NotPresent, /// All the node types, with a parent ID. - EntryItem(NodeId, &'hir Item), - EntryForeignItem(NodeId, &'hir ForeignItem), - EntryTraitItem(NodeId, &'hir TraitItem), - EntryImplItem(NodeId, &'hir ImplItem), - EntryVariant(NodeId, &'hir Variant), - EntryField(NodeId, &'hir StructField), - EntryExpr(NodeId, &'hir Expr), - EntryStmt(NodeId, &'hir Stmt), - EntryTy(NodeId, &'hir Ty), - EntryTraitRef(NodeId, &'hir TraitRef), - EntryLocal(NodeId, &'hir Pat), - EntryPat(NodeId, &'hir Pat), - EntryBlock(NodeId, &'hir Block), - EntryStructCtor(NodeId, &'hir VariantData), - EntryLifetime(NodeId, &'hir Lifetime), - EntryTyParam(NodeId, &'hir TyParam), - EntryVisibility(NodeId, &'hir Visibility), - - /// Roots for node trees. - RootCrate, + EntryItem(NodeId, DepNodeIndex, &'hir Item), + EntryForeignItem(NodeId, DepNodeIndex, &'hir ForeignItem), + EntryTraitItem(NodeId, DepNodeIndex, &'hir TraitItem), + EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem), + EntryVariant(NodeId, DepNodeIndex, &'hir Variant), + EntryField(NodeId, DepNodeIndex, &'hir StructField), + EntryExpr(NodeId, DepNodeIndex, &'hir Expr), + EntryStmt(NodeId, DepNodeIndex, &'hir Stmt), + EntryTy(NodeId, DepNodeIndex, &'hir Ty), + EntryTraitRef(NodeId, DepNodeIndex, &'hir TraitRef), + EntryBinding(NodeId, DepNodeIndex, &'hir Pat), + EntryPat(NodeId, DepNodeIndex, &'hir Pat), + EntryBlock(NodeId, DepNodeIndex, &'hir Block), + EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData), + EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime), + EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam), + EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility), + EntryLocal(NodeId, DepNodeIndex, &'hir Local), + + /// Roots for node trees. The DepNodeIndex is the dependency node of the + /// crate's root module. + RootCrate(DepNodeIndex), } impl<'hir> Clone for MapEntry<'hir> { @@ -102,79 +105,59 @@ impl<'hir> Clone for MapEntry<'hir> { } impl<'hir> MapEntry<'hir> { - fn from_node(p: NodeId, node: Node<'hir>) -> MapEntry<'hir> { - match node { - NodeItem(n) => EntryItem(p, n), - NodeForeignItem(n) => EntryForeignItem(p, n), - NodeTraitItem(n) => EntryTraitItem(p, n), - NodeImplItem(n) => EntryImplItem(p, n), - NodeVariant(n) => EntryVariant(p, n), - NodeField(n) => EntryField(p, n), - NodeExpr(n) => EntryExpr(p, n), - NodeStmt(n) => EntryStmt(p, n), - NodeTy(n) => EntryTy(p, n), - NodeTraitRef(n) => EntryTraitRef(p, n), - NodeLocal(n) => EntryLocal(p, n), - NodePat(n) => EntryPat(p, n), - NodeBlock(n) => EntryBlock(p, n), - NodeStructCtor(n) => EntryStructCtor(p, n), - NodeLifetime(n) => EntryLifetime(p, n), - NodeTyParam(n) => EntryTyParam(p, n), - NodeVisibility(n) => EntryVisibility(p, n), - } - } - fn parent_node(self) -> Option<NodeId> { Some(match self { - EntryItem(id, _) => id, - EntryForeignItem(id, _) => id, - EntryTraitItem(id, _) => id, - EntryImplItem(id, _) => id, - EntryVariant(id, _) => id, - EntryField(id, _) => id, - EntryExpr(id, _) => id, - EntryStmt(id, _) => id, - EntryTy(id, _) => id, - EntryTraitRef(id, _) => id, - EntryLocal(id, _) => id, - EntryPat(id, _) => id, - EntryBlock(id, _) => id, - EntryStructCtor(id, _) => id, - EntryLifetime(id, _) => id, - EntryTyParam(id, _) => id, - EntryVisibility(id, _) => id, + EntryItem(id, _, _) => id, + EntryForeignItem(id, _, _) => id, + EntryTraitItem(id, _, _) => id, + EntryImplItem(id, _, _) => id, + EntryVariant(id, _, _) => id, + EntryField(id, _, _) => id, + EntryExpr(id, _, _) => id, + EntryStmt(id, _, _) => id, + EntryTy(id, _, _) => id, + EntryTraitRef(id, _, _) => id, + EntryBinding(id, _, _) => id, + EntryPat(id, _, _) => id, + EntryBlock(id, _, _) => id, + EntryStructCtor(id, _, _) => id, + EntryLifetime(id, _, _) => id, + EntryTyParam(id, _, _) => id, + EntryVisibility(id, _, _) => id, + EntryLocal(id, _, _) => id, NotPresent | - RootCrate => return None, + RootCrate(_) => return None, }) } fn to_node(self) -> Option<Node<'hir>> { Some(match self { - EntryItem(_, n) => NodeItem(n), - EntryForeignItem(_, n) => NodeForeignItem(n), - EntryTraitItem(_, n) => NodeTraitItem(n), - EntryImplItem(_, n) => NodeImplItem(n), - EntryVariant(_, n) => NodeVariant(n), - EntryField(_, n) => NodeField(n), - EntryExpr(_, n) => NodeExpr(n), - EntryStmt(_, n) => NodeStmt(n), - EntryTy(_, n) => NodeTy(n), - EntryTraitRef(_, n) => NodeTraitRef(n), - EntryLocal(_, n) => NodeLocal(n), - EntryPat(_, n) => NodePat(n), - EntryBlock(_, n) => NodeBlock(n), - EntryStructCtor(_, n) => NodeStructCtor(n), - EntryLifetime(_, n) => NodeLifetime(n), - EntryTyParam(_, n) => NodeTyParam(n), - EntryVisibility(_, n) => NodeVisibility(n), + EntryItem(_, _, n) => NodeItem(n), + EntryForeignItem(_, _, n) => NodeForeignItem(n), + EntryTraitItem(_, _, n) => NodeTraitItem(n), + EntryImplItem(_, _, n) => NodeImplItem(n), + EntryVariant(_, _, n) => NodeVariant(n), + EntryField(_, _, n) => NodeField(n), + EntryExpr(_, _, n) => NodeExpr(n), + EntryStmt(_, _, n) => NodeStmt(n), + EntryTy(_, _, n) => NodeTy(n), + EntryTraitRef(_, _, n) => NodeTraitRef(n), + EntryBinding(_, _, n) => NodeBinding(n), + EntryPat(_, _, n) => NodePat(n), + EntryBlock(_, _, n) => NodeBlock(n), + EntryStructCtor(_, _, n) => NodeStructCtor(n), + EntryLifetime(_, _, n) => NodeLifetime(n), + EntryTyParam(_, _, n) => NodeTyParam(n), + EntryVisibility(_, _, n) => NodeVisibility(n), + EntryLocal(_, _, n) => NodeLocal(n), _ => return None }) } fn associated_body(self) -> Option<BodyId> { match self { - EntryItem(_, item) => { + EntryItem(_, _, item) => { match item.node { ItemConst(_, body) | ItemStatic(.., body) | @@ -183,7 +166,7 @@ impl<'hir> MapEntry<'hir> { } } - EntryTraitItem(_, item) => { + EntryTraitItem(_, _, item) => { match item.node { TraitItemKind::Const(_, Some(body)) | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), @@ -191,7 +174,7 @@ impl<'hir> MapEntry<'hir> { } } - EntryImplItem(_, item) => { + EntryImplItem(_, _, item) => { match item.node { ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), @@ -199,7 +182,7 @@ impl<'hir> MapEntry<'hir> { } } - EntryExpr(_, expr) => { + EntryExpr(_, _, expr) => { match expr.node { ExprClosure(.., body, _) => Some(body), _ => None, @@ -277,82 +260,40 @@ impl<'hir> Map<'hir> { /// read recorded). If the function just returns a DefId or /// NodeId, no actual content was returned, so no read is needed. pub fn read(&self, id: NodeId) { - self.dep_graph.read(self.dep_node(id)); - } - - fn dep_node(&self, id0: NodeId) -> DepNode { - let mut id = id0; - let mut last_expr = None; - loop { - let entry = self.map[id.as_usize()]; - match entry { - EntryItem(..) | - EntryTraitItem(..) | - EntryImplItem(..) => { - let def_index = self.definitions.opt_def_index(id).unwrap(); + let entry = self.map[id.as_usize()]; + match entry { + EntryItem(_, dep_node_index, _) | + EntryTraitItem(_, dep_node_index, _) | + EntryImplItem(_, dep_node_index, _) | + EntryVariant(_, dep_node_index, _) | + EntryForeignItem(_, dep_node_index, _) | + EntryField(_, dep_node_index, _) | + EntryStmt(_, dep_node_index, _) | + EntryTy(_, dep_node_index, _) | + EntryTraitRef(_, dep_node_index, _) | + EntryBinding(_, dep_node_index, _) | + EntryPat(_, dep_node_index, _) | + EntryBlock(_, dep_node_index, _) | + EntryStructCtor(_, dep_node_index, _) | + EntryLifetime(_, dep_node_index, _) | + EntryTyParam(_, dep_node_index, _) | + EntryVisibility(_, dep_node_index, _) | + EntryExpr(_, dep_node_index, _) | + EntryLocal(_, dep_node_index, _) | + RootCrate(dep_node_index) => { + self.dep_graph.read_index(dep_node_index); + } + NotPresent => { + // Some nodes, notably macro definitions, are not + // present in the map for whatever reason, but + // they *do* have def-ids. So if we encounter an + // empty hole, check for that case. + if let Some(def_index) = self.definitions.opt_def_index(id) { let def_path_hash = self.definitions.def_path_hash(def_index); - - if let Some(last_id) = last_expr { - // The body may have a separate dep node - if entry.is_body_owner(last_id) { - return def_path_hash.to_dep_node(DepKind::HirBody); - } - } - return def_path_hash.to_dep_node(DepKind::Hir); - } - - EntryVariant(p, v) => { - id = p; - - if last_expr.is_some() { - if v.node.disr_expr.map(|e| e.node_id) == last_expr { - // The enum parent holds both Hir and HirBody nodes. - let def_index = self.definitions.opt_def_index(id).unwrap(); - let def_path_hash = self.definitions.def_path_hash(def_index); - return def_path_hash.to_dep_node(DepKind::HirBody); - } - } - } - - EntryForeignItem(p, _) | - EntryField(p, _) | - EntryStmt(p, _) | - EntryTy(p, _) | - EntryTraitRef(p, _) | - EntryLocal(p, _) | - EntryPat(p, _) | - EntryBlock(p, _) | - EntryStructCtor(p, _) | - EntryLifetime(p, _) | - EntryTyParam(p, _) | - EntryVisibility(p, _) => - id = p, - - EntryExpr(p, _) => { - last_expr = Some(id); - id = p; - } - - RootCrate => { - let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); - return def_path_hash.to_dep_node(DepKind::Hir); + self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); + } else { + bug!("called HirMap::read() with invalid NodeId") } - - NotPresent => - // Some nodes, notably macro definitions, are not - // present in the map for whatever reason, but - // they *do* have def-ids. So if we encounter an - // empty hole, check for that case. - return self.definitions.opt_def_index(id) - .map(|def_index| { - let def_path_hash = self.definitions.def_path_hash(def_index); - def_path_hash.to_dep_node(DepKind::Hir) - }) - .unwrap_or_else(|| { - bug!("Walking parents from `{}` \ - led to `NotPresent` at `{}`", - id0, id) - }), } } } @@ -475,7 +416,7 @@ impl<'hir> Map<'hir> { Some(body_id) } else { // For some expressions, the expression is its own body. - if let EntryExpr(_, expr) = entry { + if let EntryExpr(_, _, expr) = entry { Some(BodyId { node_id: expr.id }) } else { None @@ -589,7 +530,7 @@ impl<'hir> Map<'hir> { /// immediate parent is an item or a closure. pub fn is_argument(&self, id: NodeId) -> bool { match self.find(id) { - Some(NodeLocal(_)) => (), + Some(NodeBinding(_)) => (), _ => return false, } match self.find(self.get_parent_node(id)) { @@ -731,7 +672,7 @@ impl<'hir> Map<'hir> { /// Returns the nearest enclosing scope. A scope is an item or block. /// FIXME it is not clear to me that all items qualify as scopes - statics - /// and associated types probably shouldn't, for example. Behaviour in this + /// and associated types probably shouldn't, for example. Behavior in this /// regard should be expected to be highly unstable. pub fn get_enclosing_scope(&self, id: NodeId) -> Option<NodeId> { match self.walk_parent_nodes(id, |node| match *node { @@ -754,7 +695,7 @@ impl<'hir> Map<'hir> { pub fn get_foreign_abi(&self, id: NodeId) -> Abi { let parent = self.get_parent(id); let abi = match self.find_entry(parent) { - Some(EntryItem(_, i)) => { + Some(EntryItem(_, _, i)) => { match i.node { ItemForeignMod(ref nm) => Some(nm.abi), _ => None @@ -856,7 +797,7 @@ impl<'hir> Map<'hir> { NodeField(f) => f.name, NodeLifetime(lt) => lt.name, NodeTyParam(tp) => tp.name, - NodeLocal(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, + NodeBinding(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node, NodeStructCtor(_) => self.name(self.get_parent(id)), _ => bug!("no name for {}", self.node_to_string(id)) } @@ -905,26 +846,27 @@ impl<'hir> Map<'hir> { pub fn span(&self, id: NodeId) -> Span { self.read(id); // reveals span from node match self.find_entry(id) { - Some(EntryItem(_, item)) => item.span, - Some(EntryForeignItem(_, foreign_item)) => foreign_item.span, - Some(EntryTraitItem(_, trait_method)) => trait_method.span, - Some(EntryImplItem(_, impl_item)) => impl_item.span, - Some(EntryVariant(_, variant)) => variant.span, - Some(EntryField(_, field)) => field.span, - Some(EntryExpr(_, expr)) => expr.span, - Some(EntryStmt(_, stmt)) => stmt.span, - Some(EntryTy(_, ty)) => ty.span, - Some(EntryTraitRef(_, tr)) => tr.path.span, - Some(EntryLocal(_, pat)) => pat.span, - Some(EntryPat(_, pat)) => pat.span, - Some(EntryBlock(_, block)) => block.span, - Some(EntryStructCtor(_, _)) => self.expect_item(self.get_parent(id)).span, - Some(EntryLifetime(_, lifetime)) => lifetime.span, - Some(EntryTyParam(_, ty_param)) => ty_param.span, - Some(EntryVisibility(_, &Visibility::Restricted { ref path, .. })) => path.span, - Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v), - - Some(RootCrate) => self.forest.krate.span, + Some(EntryItem(_, _, item)) => item.span, + Some(EntryForeignItem(_, _, foreign_item)) => foreign_item.span, + Some(EntryTraitItem(_, _, trait_method)) => trait_method.span, + Some(EntryImplItem(_, _, impl_item)) => impl_item.span, + Some(EntryVariant(_, _, variant)) => variant.span, + Some(EntryField(_, _, field)) => field.span, + Some(EntryExpr(_, _, expr)) => expr.span, + Some(EntryStmt(_, _, stmt)) => stmt.span, + Some(EntryTy(_, _, ty)) => ty.span, + Some(EntryTraitRef(_, _, tr)) => tr.path.span, + Some(EntryBinding(_, _, pat)) => pat.span, + Some(EntryPat(_, _, pat)) => pat.span, + Some(EntryBlock(_, _, block)) => block.span, + Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span, + Some(EntryLifetime(_, _, lifetime)) => lifetime.span, + Some(EntryTyParam(_, _, ty_param)) => ty_param.span, + Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span, + Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v), + Some(EntryLocal(_, _, local)) => local.span, + + Some(RootCrate(_)) => self.forest.krate.span, Some(NotPresent) | None => { bug!("hir::map::Map::span: id not in map: {:?}", id) } @@ -1022,12 +964,12 @@ impl<'a, 'hir> Iterator for NodesMatchingSuffix<'a, 'hir> { } self.idx = NodeId::from_u32(self.idx.as_u32() + 1); let name = match self.map.find_entry(idx) { - Some(EntryItem(_, n)) => n.name(), - Some(EntryForeignItem(_, n))=> n.name(), - Some(EntryTraitItem(_, n)) => n.name(), - Some(EntryImplItem(_, n)) => n.name(), - Some(EntryVariant(_, n)) => n.name(), - Some(EntryField(_, n)) => n.name(), + Some(EntryItem(_, _, n)) => n.name(), + Some(EntryForeignItem(_, _, n))=> n.name(), + Some(EntryTraitItem(_, _, n)) => n.name(), + Some(EntryImplItem(_, _, n)) => n.name(), + Some(EntryVariant(_, _, n)) => n.name(), + Some(EntryField(_, _, n)) => n.name(), _ => continue, }; if self.matches_names(self.map.get_parent(idx), name) { @@ -1053,9 +995,13 @@ impl Named for ImplItem { fn name(&self) -> Name { self.name } } pub fn map_crate<'hir>(forest: &'hir mut Forest, definitions: Definitions) -> Map<'hir> { - let mut collector = NodeCollector::root(&forest.krate); - intravisit::walk_crate(&mut collector, &forest.krate); - let map = collector.map; + let map = { + let mut collector = NodeCollector::root(&forest.krate, + &forest.dep_graph, + &definitions); + intravisit::walk_crate(&mut collector, &forest.krate); + collector.into_map() + }; if log_enabled!(::log::LogLevel::Debug) { // This only makes sense for ordered stores; note the @@ -1112,7 +1058,7 @@ impl<'a> print::State<'a> { NodeStmt(a) => self.print_stmt(&a), NodeTy(a) => self.print_type(&a), NodeTraitRef(a) => self.print_trait_ref(&a), - NodeLocal(a) | + NodeBinding(a) | NodePat(a) => self.print_pat(&a), NodeBlock(a) => { use syntax::print::pprust::PrintState; @@ -1131,6 +1077,7 @@ impl<'a> print::State<'a> { // hir_map to reconstruct their full structure for pretty // printing. NodeStructCtor(_) => bug!("cannot print isolated StructCtor"), + NodeLocal(a) => self.print_local_decl(&a), } } } @@ -1223,7 +1170,7 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeTraitRef(_)) => { format!("trait_ref {}{}", map.node_to_pretty_string(id), id_str) } - Some(NodeLocal(_)) => { + Some(NodeBinding(_)) => { format!("local {}{}", map.node_to_pretty_string(id), id_str) } Some(NodePat(_)) => { @@ -1232,6 +1179,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String { Some(NodeBlock(_)) => { format!("block {}{}", map.node_to_pretty_string(id), id_str) } + Some(NodeLocal(_)) => { + format!("local {}{}", map.node_to_pretty_string(id), id_str) + } Some(NodeStructCtor(_)) => { format!("struct_ctor {}{}", path_str(), id_str) } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3806b517f77..df67f841621 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -26,7 +26,6 @@ pub use self::TyParamBound::*; pub use self::UnOp::*; pub use self::UnsafeSource::*; pub use self::Visibility::{Public, Inherited}; -pub use self::PathParameters::*; use hir::def::Def; use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; @@ -42,6 +41,7 @@ use syntax::ptr::P; use syntax::symbol::{Symbol, keywords}; use syntax::tokenstream::TokenStream; use syntax::util::ThinVec; +use ty::AdtKind; use rustc_data_structures::indexed_vec; @@ -226,65 +226,7 @@ impl PathSegment { } #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub enum PathParameters { - /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>` - AngleBracketedParameters(AngleBracketedParameterData), - /// The `(A,B)` and `C` in `Foo(A,B) -> C` - ParenthesizedParameters(ParenthesizedParameterData), -} - -impl PathParameters { - pub fn none() -> PathParameters { - AngleBracketedParameters(AngleBracketedParameterData { - lifetimes: HirVec::new(), - types: HirVec::new(), - infer_types: true, - bindings: HirVec::new(), - }) - } - - /// Returns the types that the user wrote. Note that these do not necessarily map to the type - /// parameters in the parenthesized case. - pub fn types(&self) -> HirVec<&P<Ty>> { - match *self { - AngleBracketedParameters(ref data) => { - data.types.iter().collect() - } - ParenthesizedParameters(ref data) => { - data.inputs - .iter() - .chain(data.output.iter()) - .collect() - } - } - } - - pub fn lifetimes(&self) -> HirVec<&Lifetime> { - match *self { - AngleBracketedParameters(ref data) => { - data.lifetimes.iter().collect() - } - ParenthesizedParameters(_) => { - HirVec::new() - } - } - } - - pub fn bindings(&self) -> HirVec<&TypeBinding> { - match *self { - AngleBracketedParameters(ref data) => { - data.bindings.iter().collect() - } - ParenthesizedParameters(_) => { - HirVec::new() - } - } - } -} - -/// A path like `Foo<'a, T>` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct AngleBracketedParameterData { +pub struct PathParameters { /// The lifetime parameters for this path segment. pub lifetimes: HirVec<Lifetime>, /// The type parameters for this path segment, if present. @@ -297,19 +239,33 @@ pub struct AngleBracketedParameterData { /// Bindings (equality constraints) on associated types, if present. /// E.g., `Foo<A=Bar>`. pub bindings: HirVec<TypeBinding>, + /// Were parameters written in parenthesized form `Fn(T) -> U`? + /// This is required mostly for pretty-printing and diagnostics, + /// but also for changing lifetime elision rules to be "function-like". + pub parenthesized: bool, } -/// A path like `Foo(A,B) -> C` -#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] -pub struct ParenthesizedParameterData { - /// Overall span - pub span: Span, - - /// `(A,B)` - pub inputs: HirVec<P<Ty>>, +impl PathParameters { + pub fn none() -> Self { + Self { + lifetimes: HirVec::new(), + types: HirVec::new(), + infer_types: true, + bindings: HirVec::new(), + parenthesized: false, + } + } - /// `C` - pub output: Option<P<Ty>>, + pub fn inputs(&self) -> &[P<Ty>] { + if self.parenthesized { + if let Some(ref ty) = self.types.get(0) { + if let TyTup(ref tys) = ty.node { + return tys; + } + } + } + bug!("PathParameters::inputs: not a `Fn(T) -> U`"); + } } /// The AST represents all type param bounds as types. @@ -1264,6 +1220,7 @@ pub struct TraitItemId { pub struct TraitItem { pub id: NodeId, pub name: Name, + pub hir_id: HirId, pub attrs: HirVec<Attribute>, pub node: TraitItemKind, pub span: Span, @@ -1305,6 +1262,7 @@ pub struct ImplItemId { pub struct ImplItem { pub id: NodeId, pub name: Name, + pub hir_id: HirId, pub vis: Visibility, pub defaultness: Defaultness, pub attrs: HirVec<Attribute>, @@ -1711,8 +1669,9 @@ pub struct ItemId { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct Item { pub name: Name, - pub attrs: HirVec<Attribute>, pub id: NodeId, + pub hir_id: HirId, + pub attrs: HirVec<Attribute>, pub node: Item_, pub vis: Visibility, pub span: Span, @@ -1789,6 +1748,15 @@ impl Item_ { ItemDefaultImpl(..) => "item", } } + + pub fn adt_kind(&self) -> Option<AdtKind> { + match *self { + ItemStruct(..) => Some(AdtKind::Struct), + ItemUnion(..) => Some(AdtKind::Union), + ItemEnum(..) => Some(AdtKind::Enum), + _ => None, + } + } } /// A reference from an trait to one of its associated items. This diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index abfb00a24a1..876875bce4a 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1194,9 +1194,9 @@ impl<'a> State<'a> { self.print_expr(&args[0])?; self.s.word(".")?; self.print_name(segment.name)?; - if !segment.parameters.lifetimes().is_empty() || - !segment.parameters.types().is_empty() || - !segment.parameters.bindings().is_empty() { + if !segment.parameters.lifetimes.is_empty() || + !segment.parameters.types.is_empty() || + !segment.parameters.bindings.is_empty() { self.print_path_parameters(&segment.parameters, true)?; } self.print_call_post(base_args) @@ -1581,61 +1581,55 @@ impl<'a> State<'a> { parameters: &hir::PathParameters, colons_before_params: bool) -> io::Result<()> { - match *parameters { - hir::AngleBracketedParameters(ref data) => { - let start = if colons_before_params { "::<" } else { "<" }; - let empty = Cell::new(true); - let start_or_comma = |this: &mut Self| { - if empty.get() { - empty.set(false); - this.s.word(start) - } else { - this.word_space(",") - } - }; + if parameters.parenthesized { + self.s.word("(")?; + self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?; + self.s.word(")")?; - if !data.lifetimes.iter().all(|lt| lt.is_elided()) { - for lifetime in &data.lifetimes { - start_or_comma(self)?; - self.print_lifetime(lifetime)?; - } - } - - if !data.types.is_empty() { - start_or_comma(self)?; - self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?; + self.space_if_not_bol()?; + self.word_space("->")?; + self.print_type(¶meters.bindings[0].ty)?; + } else { + let start = if colons_before_params { "::<" } else { "<" }; + let empty = Cell::new(true); + let start_or_comma = |this: &mut Self| { + if empty.get() { + empty.set(false); + this.s.word(start) + } else { + this.word_space(",") } + }; - // FIXME(eddyb) This would leak into error messages, e.g.: - // "non-exhaustive patterns: `Some::<..>(_)` not covered". - if data.infer_types && false { + if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) { + for lifetime in ¶meters.lifetimes { start_or_comma(self)?; - self.s.word("..")?; + self.print_lifetime(lifetime)?; } + } - for binding in data.bindings.iter() { - start_or_comma(self)?; - self.print_name(binding.name)?; - self.s.space()?; - self.word_space("=")?; - self.print_type(&binding.ty)?; - } + if !parameters.types.is_empty() { + start_or_comma(self)?; + self.commasep(Inconsistent, ¶meters.types, |s, ty| s.print_type(&ty))?; + } - if !empty.get() { - self.s.word(">")? - } + // FIXME(eddyb) This would leak into error messages, e.g.: + // "non-exhaustive patterns: `Some::<..>(_)` not covered". + if parameters.infer_types && false { + start_or_comma(self)?; + self.s.word("..")?; } - hir::ParenthesizedParameters(ref data) => { - self.s.word("(")?; - self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?; - self.s.word(")")?; + for binding in parameters.bindings.iter() { + start_or_comma(self)?; + self.print_name(binding.name)?; + self.s.space()?; + self.word_space("=")?; + self.print_type(&binding.ty)?; + } - if let Some(ref ty) = data.output { - self.space_if_not_bol()?; - self.word_space("->")?; - self.print_type(&ty)?; - } + if !empty.get() { + self.s.word(">")? } } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 4c70816c0b8..a7913318789 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -133,22 +133,12 @@ impl_stable_hash_for!(struct hir::PathSegment { parameters }); -impl_stable_hash_for!(enum hir::PathParameters { - AngleBracketedParameters(data), - ParenthesizedParameters(data) -}); - -impl_stable_hash_for!(struct hir::AngleBracketedParameterData { +impl_stable_hash_for!(struct hir::PathParameters { lifetimes, types, infer_types, - bindings -}); - -impl_stable_hash_for!(struct hir::ParenthesizedParameterData { - span, - inputs, - output + bindings, + parenthesized }); impl_stable_hash_for!(enum hir::TyParamBound { @@ -741,6 +731,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::T hasher: &mut StableHasher<W>) { let hir::TraitItem { id, + hir_id: _, name, ref attrs, ref node, @@ -774,6 +765,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I hasher: &mut StableHasher<W>) { let hir::ImplItem { id, + hir_id: _, name, ref vis, defaultness, @@ -930,6 +922,7 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for hir::I name, ref attrs, id, + hir_id: _, ref node, ref vis, span diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 45b2a4a1e96..5f51579945e 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -663,6 +663,10 @@ impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for ty::In def_id.hash_stable(hcx, hasher); t.hash_stable(hcx, hasher); } + ty::InstanceDef::CloneShim(def_id, t) => { + def_id.hash_stable(hcx, hasher); + t.hash_stable(hcx, hasher); + } } } } diff --git a/src/librustc/infer/error_reporting/anon_anon_conflict.rs b/src/librustc/infer/error_reporting/anon_anon_conflict.rs index 2e910968818..c80ce3c96f1 100644 --- a/src/librustc/infer/error_reporting/anon_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/anon_anon_conflict.rs @@ -27,65 +27,84 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // { x.push(y); }. // The example gives // fn foo(x: &mut Vec<&u8>, y: &u8) { - // --- --- these references must have the same lifetime + // --- --- these references are declared with different lifetimes... // x.push(y); - // ^ data from `y` flows into `x` here - // It will later be extended to trait objects and structs. + // ^ ...but data from `y` flows into `x` here + // It has been extended for the case of structs too. + // Consider the example + // struct Ref<'a> { x: &'a u32 } + // fn foo(mut x: Vec<Ref>, y: Ref) { + // --- --- these structs are declared with different lifetimes... + // x.push(y); + // ^ ...but data from `y` flows into `x` here + // } + // It will later be extended to trait objects. pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool { - let (span, sub, sup) = match *error { ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup), _ => return false, // inapplicable }; // Determine whether the sub and sup consist of both anonymous (elided) regions. - let (ty1, ty2) = if self.is_suitable_anonymous_region(sup).is_some() && - self.is_suitable_anonymous_region(sub).is_some() { - if let (Some(anon_reg1), Some(anon_reg2)) = - (self.is_suitable_anonymous_region(sup), self.is_suitable_anonymous_region(sub)) { - let ((_, br1), (_, br2)) = (anon_reg1, anon_reg2); - if self.find_anon_type(sup, &br1).is_some() && - self.find_anon_type(sub, &br2).is_some() { - (self.find_anon_type(sup, &br1).unwrap(), - self.find_anon_type(sub, &br2).unwrap()) - } else { - return false; - } - } else { - return false; - } - } else { - return false; // inapplicable - }; + let anon_reg_sup = or_false!(self.is_suitable_anonymous_region(sup)); - if let (Some(sup_arg), Some(sub_arg)) = + let anon_reg_sub = or_false!(self.is_suitable_anonymous_region(sub)); + let scope_def_id_sup = anon_reg_sup.def_id; + let bregion_sup = anon_reg_sup.boundregion; + let scope_def_id_sub = anon_reg_sub.def_id; + let bregion_sub = anon_reg_sub.boundregion; + + let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup)); + + let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub)); + + let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) = (self.find_arg_with_anonymous_region(sup, sup), self.find_arg_with_anonymous_region(sub, sub)) { - let ((anon_arg1, _, _, _), (anon_arg2, _, _, _)) = (sup_arg, sub_arg); - let span_label_var1 = if let Some(simple_name) = anon_arg1.pat.simple_name() { - format!(" from `{}` ", simple_name) - } else { - format!(" ") - }; + let (anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) = + (sup_arg.arg, sup_arg.is_first, sub_arg.arg, sub_arg.is_first); + if self.is_self_anon(is_first_sup, scope_def_id_sup) || + self.is_self_anon(is_first_sub, scope_def_id_sub) { + return false; + } - let span_label_var2 = if let Some(simple_name) = anon_arg2.pat.simple_name() { - format!(" into `{}` ", simple_name) + if self.is_return_type_anon(scope_def_id_sup, bregion_sup) || + self.is_return_type_anon(scope_def_id_sub, bregion_sub) { + return false; + } + + if anon_arg_sup == anon_arg_sub { + (format!("this type was declared with multiple lifetimes..."), + format!(" with one lifetime"), + format!(" into the other")) } else { - format!(" ") - }; - - struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch") - .span_label(ty1.span, - format!("these references are not declared with the same lifetime...")) - .span_label(ty2.span, format!("")) - .span_label(span, - format!("...but data{}flows{}here", span_label_var1, span_label_var2)) - .emit(); + let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() { + format!(" from `{}`", simple_name) + } else { + format!("") + }; + + let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() { + format!(" into `{}`", simple_name) + } else { + format!("") + }; + + let span_label = + format!("these two types are declared with different lifetimes...",); + + (span_label, span_label_var1, span_label_var2) + } } else { return false; - } + }; + struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch") + .span_label(ty_sup.span, main_label) + .span_label(ty_sub.span, format!("")) + .span_label(span, format!("...but data{} flows{} here", label1, label2)) + .emit(); return true; } @@ -94,7 +113,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// contains the anonymous type. /// /// # Arguments - /// /// region - the anonymous region corresponding to the anon_anon conflict /// br - the bound region corresponding to the above region which is of type `BrAnon(_)` /// @@ -105,39 +123,56 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// ``` /// The function returns the nested type corresponding to the anonymous region /// for e.g. `&u8` and Vec<`&u8`. - fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> { + pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> { if let Some(anon_reg) = self.is_suitable_anonymous_region(region) { - let (def_id, _) = anon_reg; + let def_id = anon_reg.def_id; if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) { let ret_ty = self.tcx.type_of(def_id); if let ty::TyFnDef(_, _) = ret_ty.sty { - if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) { - if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node { - return fndecl - .inputs - .iter() - .filter_map(|arg| { - let mut nested_visitor = FindNestedTypeVisitor { - infcx: &self, - hir_map: &self.tcx.hir, - bound_region: *br, - found_type: None, - }; - nested_visitor.visit_ty(&**arg); - if nested_visitor.found_type.is_some() { - nested_visitor.found_type - } else { - None - } - }) - .next(); - } - } + let inputs: &[_] = + match self.tcx.hir.get(node_id) { + hir_map::NodeItem(&hir::Item { + node: hir::ItemFn(ref fndecl, ..), .. + }) => &fndecl.inputs, + hir_map::NodeTraitItem(&hir::TraitItem { + node: hir::TraitItemKind::Method(ref fndecl, ..), + .. + }) => &fndecl.decl.inputs, + hir_map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(ref fndecl, ..), + .. + }) => &fndecl.decl.inputs, + + _ => &[], + }; + + return inputs + .iter() + .filter_map(|arg| { + self.find_component_for_bound_region(&**arg, br) + }) + .next(); } } } None } + + // This method creates a FindNestedTypeVisitor which returns the type corresponding + // to the anonymous region. + fn find_component_for_bound_region(&self, + arg: &'gcx hir::Ty, + br: &ty::BoundRegion) + -> Option<(&'gcx hir::Ty)> { + let mut nested_visitor = FindNestedTypeVisitor { + infcx: &self, + hir_map: &self.tcx.hir, + bound_region: *br, + found_type: None, + }; + nested_visitor.visit_ty(arg); + nested_visitor.found_type + } } // The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the @@ -176,8 +211,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { hir::TyRptr(ref lifetime, _) => { match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) { // the lifetime of the TyRptr - Some(&rl::Region::LateBoundAnon(debuijn_index, anon_index)) => { - if debuijn_index.depth == 1 && anon_index == br_index { + Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => { + if debruijn_index.depth == 1 && anon_index == br_index { self.found_type = Some(arg); return; // we can stop visiting now } @@ -191,6 +226,20 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { } } } + // Checks if it is of type `hir::TyPath` which corresponds to a struct. + hir::TyPath(_) => { + let subvisitor = &mut TyPathVisitor { + infcx: self.infcx, + found_it: false, + bound_region: self.bound_region, + hir_map: self.hir_map, + }; + intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty, + // this will visit only outermost type + if subvisitor.found_it { + self.found_type = Some(arg); + } + } _ => {} } // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`, @@ -198,3 +247,56 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindNestedTypeVisitor<'a, 'gcx, 'tcx> { intravisit::walk_ty(self, arg); } } + +// The visitor captures the corresponding `hir::Ty` of the anonymous region +// in the case of structs ie. `hir::TyPath`. +// This visitor would be invoked for each lifetime corresponding to a struct, +// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR +// where that lifetime appears. This allows us to highlight the +// specific part of the type in the error message. +struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { + infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, + hir_map: &'a hir::map::Map<'gcx>, + found_it: bool, + bound_region: ty::BoundRegion, +} + +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> { + NestedVisitorMap::OnlyBodies(&self.hir_map) + } + + fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { + let br_index = match self.bound_region { + ty::BrAnon(index) => index, + _ => return, + }; + + match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) { + // the lifetime of the TyPath! + Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => { + if debruijn_index.depth == 1 && anon_index == br_index { + self.found_it = true; + } + } + Some(&rl::Region::Static) | + Some(&rl::Region::EarlyBound(_, _)) | + Some(&rl::Region::LateBound(_, _)) | + Some(&rl::Region::Free(_, _)) | + None => { + debug!("no arg found"); + } + } + } + + fn visit_ty(&mut self, arg: &'gcx hir::Ty) { + // ignore nested types + // + // If you have a type like `Foo<'a, &Ty>` we + // are only interested in the immediate lifetimes ('a). + // + // Making `visit_ty` empty will ignore the `&Ty` embedded + // inside, it will get reached by the outer visitor. + debug!("`Ty` corresponding to a struct is {:?}", arg); + } +} diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b5390da7e85..edf9ca89b33 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -24,7 +24,7 @@ //! a span, but also more information so that we can generate a meaningful //! error message. //! -//! Having a catalogue of all the different reasons an error can arise is +//! Having a catalog of all the different reasons an error can arise is //! also useful for other reasons, like cross-referencing FAQs etc, though //! we are not really taking advantage of this yet. //! @@ -75,8 +75,10 @@ use errors::{DiagnosticBuilder, DiagnosticStyledString}; mod note; mod need_type_info; -mod util; + mod named_anon_conflict; +#[macro_use] +mod util; mod anon_anon_conflict; impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -899,9 +901,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { infer::LateBoundRegion(_, br, infer::HigherRankedType) => { format!(" for lifetime parameter {}in generic type", br_string(br)) } - infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => { + infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => { format!(" for lifetime parameter {}in trait containing associated type `{}`", - br_string(br), type_name) + br_string(br), self.tcx.associated_item(def_id).name) } infer::EarlyBoundRegion(_, name) => { format!(" for lifetime parameter `{}`", diff --git a/src/librustc/infer/error_reporting/named_anon_conflict.rs b/src/librustc/infer/error_reporting/named_anon_conflict.rs index 491079a1f92..0aae008396a 100644 --- a/src/librustc/infer/error_reporting/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/named_anon_conflict.rs @@ -11,7 +11,6 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where one region is named and the other is anonymous. use infer::InferCtxt; -use ty; use infer::region_inference::RegionResolutionError::*; use infer::region_inference::RegionResolutionError; @@ -30,8 +29,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // where the anonymous region appears (there must always be one; we // only introduced anonymous regions in parameters) as well as a // version new_ty of its type where the anonymous region is replaced - // with the named one. - let (named, (arg, new_ty, br, is_first), (scope_def_id, _)) = + // with the named one.//scope_def_id + let (named, anon_arg_info, region_info) = if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() { (sub, self.find_arg_with_anonymous_region(sup, sub).unwrap(), @@ -44,50 +43,38 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return false; // inapplicable }; - // Here, we check for the case where the anonymous region - // is in the return type. - // FIXME(#42703) - Need to handle certain cases here. - let ret_ty = self.tcx.type_of(scope_def_id); - match ret_ty.sty { - ty::TyFnDef(_, _) => { - let sig = ret_ty.fn_sig(self.tcx); - let late_bound_regions = self.tcx - .collect_referenced_late_bound_regions(&sig.output()); - if late_bound_regions.iter().any(|r| *r == br) { - return false; - } - } - _ => {} - } - - // Here we check for the case where anonymous region - // corresponds to self and if yes, we display E0312. - // FIXME(#42700) - Need to format self properly to - // enable E0621 for it. - if is_first && - self.tcx - .opt_associated_item(scope_def_id) - .map(|i| i.method_has_self_argument) - .unwrap_or(false) { + let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg, + anon_arg_info.arg_ty, + anon_arg_info.bound_region, + anon_arg_info.is_first, + region_info.def_id, + region_info.is_impl_item); + if is_impl_item { return false; } - let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { - (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) + if self.is_return_type_anon(scope_def_id, br) || self.is_self_anon(is_first, scope_def_id) { + return false; } else { - ("parameter type".to_owned(), "type".to_owned()) - }; - struct_span_err!(self.tcx.sess, - span, - E0621, - "explicit lifetime required in {}", - error_var) - .span_label(arg.pat.span, - format!("consider changing {} to `{}`", span_label_var, new_ty)) - .span_label(span, format!("lifetime `{}` required", named)) - .emit(); + let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() { + (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name)) + } else { + ("parameter type".to_owned(), "type".to_owned()) + }; + + struct_span_err!(self.tcx.sess, + span, + E0621, + "explicit lifetime required in {}", + error_var) + .span_label(arg.pat.span, + format!("consider changing {} to `{}`", span_label_var, new_ty)) + .span_label(span, format!("lifetime `{}` required", named)) + .emit(); + + } return true; } } diff --git a/src/librustc/infer/error_reporting/util.rs b/src/librustc/infer/error_reporting/util.rs index c8f78367420..04153038da8 100644 --- a/src/librustc/infer/error_reporting/util.rs +++ b/src/librustc/infer/error_reporting/util.rs @@ -16,6 +16,40 @@ use ty::{self, Region}; use hir::def_id::DefId; use hir::map as hir_map; +macro_rules! or_false { + ($v:expr) => { + match $v { + Some(v) => v, + None => return false, + } + } +} + +// The struct contains the information about the anonymous region +// we are searching for. +pub struct AnonymousArgInfo<'tcx> { + // the argument corresponding to the anonymous region + pub arg: &'tcx hir::Arg, + // the type corresponding to the anonymopus region argument + pub arg_ty: ty::Ty<'tcx>, + // the ty::BoundRegion corresponding to the anonymous region + pub bound_region: ty::BoundRegion, + // corresponds to id the argument is the first parameter + // in the declaration + pub is_first: bool, +} + +// This struct contains information regarding the +// Refree((FreeRegion) corresponding to lifetime conflict +pub struct FreeRegionInfo { + // def id corresponding to FreeRegion + pub def_id: DefId, + // the bound region corresponding to FreeRegion + pub boundregion: ty::BoundRegion, + // checks if bound region is in Impl Item + pub is_impl_item: bool, +} + impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method walks the Type of the function body arguments using // `fold_regions()` function and returns the @@ -28,14 +62,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // i32, which is the type of y but with the anonymous region replaced // with 'a, the corresponding bound region and is_first which is true if // the hir::Arg is the first argument in the function declaration. - pub fn find_arg_with_anonymous_region - (&self, - anon_region: Region<'tcx>, - replace_region: Region<'tcx>) - -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> { + pub fn find_arg_with_anonymous_region(&self, + anon_region: Region<'tcx>, + replace_region: Region<'tcx>) + -> Option<AnonymousArgInfo> { if let ty::ReFree(ref free_region) = *anon_region { - let id = free_region.scope; let hir = &self.tcx.hir; if let Some(node_id) = hir.as_local_node_id(id) { @@ -57,7 +89,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }); if found_anon_region { let is_first = index == 0; - Some((arg, new_arg_ty, free_region.bound_region, is_first)) + Some(AnonymousArgInfo { + arg: arg, + arg_ty: new_arg_ty, + bound_region: free_region.bound_region, + is_first: is_first, + }) } else { None } @@ -79,42 +116,81 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // This method returns whether the given Region is Anonymous // and returns the DefId and the BoundRegion corresponding to the given region. - pub fn is_suitable_anonymous_region(&self, - region: Region<'tcx>) - -> Option<(DefId, ty::BoundRegion)> { + pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> { if let ty::ReFree(ref free_region) = *region { - if let ty::BrAnon(..) = free_region.bound_region{ - let anonymous_region_binding_scope = free_region.scope; - let node_id = self.tcx - .hir - .as_local_node_id(anonymous_region_binding_scope) - .unwrap(); - match self.tcx.hir.find(node_id) { - Some(hir_map::NodeItem(..)) | - Some(hir_map::NodeTraitItem(..)) => { - // Success -- proceed to return Some below - } - Some(hir_map::NodeImplItem(..)) => { - let container_id = self.tcx - .associated_item(anonymous_region_binding_scope) - .container - .id(); - if self.tcx.impl_trait_ref(container_id).is_some() { - // For now, we do not try to target impls of traits. This is - // because this message is going to suggest that the user - // change the fn signature, but they may not be free to do so, - // since the signature must match the trait. - // - // FIXME(#42706) -- in some cases, we could do better here. - return None; - } - } - _ => return None, // inapplicable - // we target only top-level functions + if let ty::BrAnon(..) = free_region.bound_region { + let anonymous_region_binding_scope = free_region.scope; + let node_id = self.tcx + .hir + .as_local_node_id(anonymous_region_binding_scope) + .unwrap(); + let mut is_impl_item = false; + match self.tcx.hir.find(node_id) { + + Some(hir_map::NodeItem(..)) | + Some(hir_map::NodeTraitItem(..)) => { + // Success -- proceed to return Some below } - return Some((anonymous_region_binding_scope, free_region.bound_region)); + Some(hir_map::NodeImplItem(..)) => { + is_impl_item = + self.is_bound_region_in_impl_item(anonymous_region_binding_scope); + } + _ => return None, } + return Some(FreeRegionInfo { + def_id: anonymous_region_binding_scope, + boundregion: free_region.bound_region, + is_impl_item: is_impl_item, + }); } - None } + None + } + + // Here, we check for the case where the anonymous region + // is in the return type. + // FIXME(#42703) - Need to handle certain cases here. + pub fn is_return_type_anon(&self, scope_def_id: DefId, br: ty::BoundRegion) -> bool { + let ret_ty = self.tcx.type_of(scope_def_id); + match ret_ty.sty { + ty::TyFnDef(_, _) => { + let sig = ret_ty.fn_sig(self.tcx); + let late_bound_regions = self.tcx + .collect_referenced_late_bound_regions(&sig.output()); + if late_bound_regions.iter().any(|r| *r == br) { + return true; + } + } + _ => {} + } + false + } + // Here we check for the case where anonymous region + // corresponds to self and if yes, we display E0312. + // FIXME(#42700) - Need to format self properly to + // enable E0621 for it. + pub fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool { + is_first && + self.tcx + .opt_associated_item(scope_def_id) + .map(|i| i.method_has_self_argument) == Some(true) + } + + // Here we check if the bound region is in Impl Item. + pub fn is_bound_region_in_impl_item(&self, anonymous_region_binding_scope: DefId) -> bool { + let container_id = self.tcx + .associated_item(anonymous_region_binding_scope) + .container + .id(); + if self.tcx.impl_trait_ref(container_id).is_some() { + // For now, we do not try to target impls of traits. This is + // because this message is going to suggest that the user + // change the fn signature, but they may not be free to do so, + // since the signature must match the trait. + // + // FIXME(#42706) -- in some cases, we could do better here. + return true; + } + false + } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 186eab724db..6c9b9d853f4 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -274,7 +274,7 @@ pub enum LateBoundRegionConversionTime { HigherRankedType, /// when projecting an associated type - AssocTypeProjection(ast::Name), // FIXME(tschottdorf): should contain DefId, not Name + AssocTypeProjection(DefId), } /// Reasons to create a region inference variable diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index 6a1f8f1d069..639a330dc6e 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -46,7 +46,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for OpportunisticTypeResolver<'a, 'g } /// The opportunistic type and region resolver is similar to the -/// opportunistic type resolver, but also opportunistly resolves +/// opportunistic type resolver, but also opportunistically resolves /// regions. It is useful for canonicalization. pub struct OpportunisticTypeAndRegionResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 5b0760e561e..152b2e2aa5e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -29,7 +26,7 @@ #![feature(core_intrinsics)] #![feature(discriminant_value)] #![feature(i128_type)] -#![feature(libc)] +#![cfg_attr(windows, feature(libc))] #![feature(never_type)] #![feature(nonzero)] #![feature(quote)] @@ -48,6 +45,7 @@ extern crate core; extern crate fmt_macros; extern crate getopts; extern crate graphviz; +#[cfg(windows)] extern crate libc; extern crate owning_ref; extern crate rustc_back; @@ -65,7 +63,9 @@ extern crate serialize as rustc_serialize; // used by deriving // Note that librustc doesn't actually depend on these crates, see the note in // `Cargo.toml` for this crate about why these are here. +#[allow(unused_extern_crates)] extern crate flate2; +#[allow(unused_extern_crates)] extern crate test; #[macro_use] diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index cbe642a9a76..811bf977610 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -30,7 +30,7 @@ declare_lint! { declare_lint! { pub UNUSED_EXTERN_CRATES, - Allow, + Warn, "extern crates that are never used" } diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 40d78d0138b..4d1374b69b8 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -101,7 +101,7 @@ pub struct FutureIncompatibleInfo { pub reference: &'static str // e.g., a URL for an issue/PR/RFC or error code } -/// The targed of the `by_name` map, which accounts for renaming/deprecation. +/// The target of the `by_name` map, which accounts for renaming/deprecation. enum TargetLint { /// A direct lint target Id(LintId), @@ -121,10 +121,10 @@ pub enum FindLintError { pub enum CheckLintNameResult<'a> { Ok(&'a [LintId]), - // Lint doesn't exist + /// Lint doesn't exist NoLint, - // The lint is either renamed or removed. This is the warning - // message. + /// The lint is either renamed or removed. This is the warning + /// message. Warning(String), } @@ -253,7 +253,7 @@ impl LintStore { } } - // Checks the validity of lint names derived from the command line + /// Checks the validity of lint names derived from the command line pub fn check_lint_name_cmdline(&self, sess: &Session, lint_name: &str, diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index ab9d4f75597..ab086e5b8e9 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -83,10 +83,13 @@ impl LintLevelSets { }); } - fn get_lint_level(&self, lint: &'static Lint, idx: u32) + fn get_lint_level(&self, + lint: &'static Lint, + idx: u32, + aux: Option<&FxHashMap<LintId, (Level, LintSource)>>) -> (Level, LintSource) { - let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx); + let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux); // If `level` is none then we actually assume the default level for this // lint. @@ -97,7 +100,9 @@ impl LintLevelSets { // `allow(warnings)` in scope then we want to respect that instead. if level == Level::Warn { let (warnings_level, warnings_src) = - self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), idx); + self.get_lint_id_level(LintId::of(lint::builtin::WARNINGS), + idx, + aux); if let Some(configured_warning_level) = warnings_level { if configured_warning_level != Level::Warn { level = configured_warning_level; @@ -112,9 +117,17 @@ impl LintLevelSets { return (level, src) } - fn get_lint_id_level(&self, id: LintId, mut idx: u32) + fn get_lint_id_level(&self, + id: LintId, + mut idx: u32, + aux: Option<&FxHashMap<LintId, (Level, LintSource)>>) -> (Option<Level>, LintSource) { + if let Some(specs) = aux { + if let Some(&(level, src)) = specs.get(&id) { + return (Some(level), src) + } + } loop { match self.list[idx as usize] { LintSet::CommandLine { ref specs } => { @@ -212,21 +225,35 @@ impl<'a> LintLevelsBuilder<'a> { specs.insert(*id, (level, src)); } } + + _ if !self.warn_about_weird_lints => {} + CheckLintNameResult::Warning(ref msg) => { - if self.warn_about_weird_lints { - self.struct_lint(builtin::RENAMED_AND_REMOVED_LINTS, - Some(li.span.into()), - msg) - .emit(); - } + let lint = builtin::RENAMED_AND_REMOVED_LINTS; + let (level, src) = self.sets.get_lint_level(lint, + self.cur, + Some(&specs)); + lint::struct_lint_level(self.sess, + lint, + level, + src, + Some(li.span.into()), + msg) + .emit(); } CheckLintNameResult::NoLint => { - if self.warn_about_weird_lints { - self.struct_lint(builtin::UNKNOWN_LINTS, - Some(li.span.into()), - &format!("unknown lint: `{}`", name)) - .emit(); - } + let lint = builtin::UNKNOWN_LINTS; + let (level, src) = self.sets.get_lint_level(lint, + self.cur, + Some(&specs)); + let msg = format!("unknown lint: `{}`", name); + lint::struct_lint_level(self.sess, + lint, + level, + src, + Some(li.span.into()), + &msg) + .emit(); } } } @@ -236,7 +263,7 @@ impl<'a> LintLevelsBuilder<'a> { if level == Level::Forbid { continue } - let forbid_src = match self.sets.get_lint_id_level(*id, self.cur) { + let forbid_src = match self.sets.get_lint_id_level(*id, self.cur, None) { (Some(Level::Forbid), src) => src, _ => continue, }; @@ -298,7 +325,7 @@ impl<'a> LintLevelsBuilder<'a> { msg: &str) -> DiagnosticBuilder<'a> { - let (level, src) = self.sets.get_lint_level(lint, self.cur); + let (level, src) = self.sets.get_lint_level(lint, self.cur, None); lint::struct_lint_level(self.sess, lint, level, src, span, msg) } @@ -337,7 +364,7 @@ impl LintLevelMap { -> Option<(Level, LintSource)> { self.id_to_set.get(&id).map(|idx| { - self.sets.get_lint_level(lint, *idx) + self.sets.get_lint_level(lint, *idx, None) }) } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 8a2b115e58d..b8624722692 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -630,8 +630,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let krate = tcx.hir.krate(); let live_symbols = find_live(tcx, access_levels, krate); let mut visitor = DeadVisitor { - tcx: tcx, - live_symbols: live_symbols, + tcx, + live_symbols, }; intravisit::walk_crate(&mut visitor, krate); } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 01ed79096b1..9ba4252b52e 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -274,6 +274,7 @@ language_item_table! { SizedTraitLangItem, "sized", sized_trait; UnsizeTraitLangItem, "unsize", unsize_trait; CopyTraitLangItem, "copy", copy_trait; + CloneTraitLangItem, "clone", clone_trait; SyncTraitLangItem, "sync", sync_trait; FreezeTraitLangItem, "freeze", freeze_trait; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 070ad515908..8e5f748c78e 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1482,12 +1482,16 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { }; if is_assigned { - self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, + self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp, &format!("variable `{}` is assigned to, but never used", + name), + &format!("to disable this warning, consider using `_{}` instead", name)); } else if name != "self" { - self.ir.tcx.lint_node(lint::builtin::UNUSED_VARIABLES, id, sp, - &format!("unused variable: `{}`", name)); + self.ir.tcx.lint_node_note(lint::builtin::UNUSED_VARIABLES, id, sp, + &format!("unused variable: `{}`", name), + &format!("to disable this warning, consider using `_{}` instead", + name)); } } true diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 8919d0afc1d..8cd023b8e63 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -332,7 +332,7 @@ impl MutabilityCategory { fn from_local(tcx: TyCtxt, tables: &ty::TypeckTables, id: ast::NodeId) -> MutabilityCategory { let ret = match tcx.hir.get(id) { - hir_map::NodeLocal(p) => match p.node { + hir_map::NodeBinding(p) => match p.node { PatKind::Binding(..) => { let bm = *tables.pat_binding_modes() .get(p.hir_id) @@ -873,10 +873,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let promotable = self.tcx.rvalue_promotable_to_static.borrow().get(&id).cloned() .unwrap_or(false); - // When the corresponding feature isn't toggled, only promote `[T; 0]`. + // Always promote `[T; 0]` (even when e.g. borrowed mutably). let promotable = match expr_ty.sty { ty::TyArray(_, 0) => true, - _ => promotable && self.tcx.sess.features.borrow().rvalue_static_promotion, + _ => promotable, }; // Compute maximum lifetime of this rvalue. This is 'static if diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 9133a5e777d..45a3080ed91 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -72,7 +72,7 @@ use mir::transform::MirSource; /// (M1.): Misc extent of the whole `let a = ...;` statement. /// (M2.): Misc extent of the `f()` expression. /// (M3.): Misc extent of the `f().g(..)` expression. -/// (M4.): Misc extent of the block labelled `'b:`. +/// (M4.): Misc extent of the block labeled `'b:`. /// (M5.): Misc extent of the `let x = d();` statement /// (D6.): DestructionScope for temporaries created during M5. /// (R7.): Remainder extent for block `'b:`, stmt 0 (let x = ...). diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 13efa94a5c9..a8e98e53db3 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -915,18 +915,15 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { def: Def, depth: usize, params: &'tcx hir::PathParameters) { - let data = match *params { - hir::ParenthesizedParameters(ref data) => { - self.visit_fn_like_elision(&data.inputs, data.output.as_ref()); - return; - } - hir::AngleBracketedParameters(ref data) => data - }; + if params.parenthesized { + self.visit_fn_like_elision(params.inputs(), Some(¶ms.bindings[0].ty)); + return; + } - if data.lifetimes.iter().all(|l| l.is_elided()) { - self.resolve_elided_lifetimes(&data.lifetimes); + if params.lifetimes.iter().all(|l| l.is_elided()) { + self.resolve_elided_lifetimes(¶ms.lifetimes); } else { - for l in &data.lifetimes { self.visit_lifetime(l); } + for l in ¶ms.lifetimes { self.visit_lifetime(l); } } // Figure out if this is a type/trait segment, @@ -995,13 +992,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Some(Region::Static) } } - Set1::One(r) => r.subst(&data.lifetimes, map), + Set1::One(r) => r.subst(¶ms.lifetimes, map), Set1::Many => None } }).collect() }); - for (i, ty) in data.types.iter().enumerate() { + for (i, ty) in params.types.iter().enumerate() { if let Some(<) = object_lifetime_defaults.get(i) { let scope = Scope::ObjectLifetimeDefault { lifetime: lt, @@ -1013,7 +1010,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } - for b in &data.bindings { self.visit_assoc_type_binding(b); } + for b in ¶ms.bindings { self.visit_assoc_type_binding(b); } } fn visit_fn_like_elision(&mut self, inputs: &'tcx [P<hir::Ty>], @@ -1081,20 +1078,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Some(body) } - // `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). - hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None, - - // Foreign `fn` decls are terrible because we messed up, - // and their return types get argument type elision. - // And now too much code out there is abusing this rule. - hir::map::NodeForeignItem(_) => { - let arg_scope = Scope::Elision { - elide: arg_elide, - s: self.scope - }; - self.with(arg_scope, |_, this| this.visit_ty(output)); - return; - } + // Foreign functions, `fn(...) -> R` and `Trait(...) -> R` (both types and bounds). + hir::map::NodeForeignItem(_) | hir::map::NodeTy(_) | hir::map::NodeTraitRef(_) => None, // Everything else (only closures?) doesn't // actually enjoy elision in return types. diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5158c7e94af..d2ed29a3a0f 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -123,7 +123,8 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { item_sp: Span, kind: AnnotationKind, visit_children: F) where F: FnOnce(&mut Self) { - if self.index.staged_api[&LOCAL_CRATE] { + if self.tcx.sess.features.borrow().staged_api { + // This crate explicitly wants staged API. debug!("annotate(id = {:?}, attrs = {:?})", id, attrs); if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) { self.tcx.sess.span_err(item_sp, "`#[deprecated]` cannot be used in staged api, \ @@ -204,6 +205,15 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } } + // Propagate unstability. This can happen even for non-staged-api crates in case + // -Zforce-unstable-if-unmarked is set. + if let Some(stab) = self.parent_stab { + if stab.level.is_unstable() { + let def_id = self.tcx.hir.local_def_id(id); + self.index.stab_map.insert(def_id, Some(stab)); + } + } + if let Some(depr) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) { if kind == AnnotationKind::Prohibited { self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless"); diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 5aab46b3cef..74c3408c4c2 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -216,7 +216,7 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> { /// /// Reverse postorder is the reverse order of a postorder traversal. /// This is different to a preorder traversal and represents a natural -/// linearisation of control-flow. +/// linearization of control-flow. /// /// ```text /// diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 6995f099677..99fe8e60ae5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -918,6 +918,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path identify_regions: bool = (false, parse_bool, [UNTRACKED], "make unnamed regions display as '# (where # is some non-ident unique id)"), + borrowck_mir: bool = (false, parse_bool, [UNTRACKED], + "implicitly treat functions as if they have `#[rustc_mir_borrowck]` attribute"), time_passes: bool = (false, parse_bool, [UNTRACKED], "measure time of each rustc pass"), count_llvm_insns: bool = (false, parse_bool, @@ -993,6 +995,10 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing"), + profile_queries: bool = (false, parse_bool, [UNTRACKED], + "trace and profile the queries of the incremental compilation framework"), + profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED], + "trace and profile the queries and keys of the incremental compilation framework"), no_analysis: bool = (false, parse_bool, [UNTRACKED], "parse and expand the source, but run no analysis"), extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 3aea0722d0e..823a637c7e0 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -389,6 +389,13 @@ impl Session { } pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose } pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes } + pub fn profile_queries(&self) -> bool { + self.opts.debugging_opts.profile_queries || + self.opts.debugging_opts.profile_queries_and_keys + } + pub fn profile_queries_and_keys(&self) -> bool { + self.opts.debugging_opts.profile_queries_and_keys + } pub fn count_llvm_insns(&self) -> bool { self.opts.debugging_opts.count_llvm_insns } @@ -429,6 +436,31 @@ impl Session { .unwrap_or(self.opts.debug_assertions) } + pub fn crt_static(&self) -> bool { + // If the target does not opt in to crt-static support, use its default. + if self.target.target.options.crt_static_respected { + self.crt_static_feature() + } else { + self.target.target.options.crt_static_default + } + } + + pub fn crt_static_feature(&self) -> bool { + let requested_features = self.opts.cg.target_feature.split(','); + let found_negative = requested_features.clone().any(|r| r == "-crt-static"); + let found_positive = requested_features.clone().any(|r| r == "+crt-static"); + + // If the target we're compiling for requests a static crt by default, + // then see if the `-crt-static` feature was passed to disable that. + // Otherwise if we don't have a static crt by default then see if the + // `+crt-static` feature was passed. + if self.target.target.options.crt_static_default { + !found_negative + } else { + found_positive + } + } + pub fn must_not_eliminate_frame_pointers(&self) -> bool { self.opts.debuginfo != DebugInfoLevel::NoDebugInfo || !self.target.target.options.eliminate_frame_pointer diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c04d448716c..3e64c8c7dea 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1111,8 +1111,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } - ObligationCauseCode::FieldSized => { - err.note("only the last field of a struct may have a dynamically sized type"); + ObligationCauseCode::FieldSized(ref item) => { + match *item { + AdtKind::Struct => { + err.note("only the last field of a struct may have a dynamically \ + sized type"); + } + AdtKind::Union => { + err.note("no field of a union may have a dynamically sized type"); + } + AdtKind::Enum => { + err.note("no field of an enum variant may have a dynamically sized type"); + } + } } ObligationCauseCode::ConstSized => { err.note("constant expressions must have a statically known size"); @@ -1154,8 +1165,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { let current_limit = self.tcx.sess.recursion_limit.get(); let suggested_limit = current_limit * 2; - err.help(&format!( - "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", + err.help(&format!("consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", suggested_limit)); } } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 4f1eb616920..78e47693caa 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -37,7 +37,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// consists of a list of obligations that must be (eventually) /// satisfied. The job is to track which are satisfied, which yielded /// errors, and which are still pending. At any point, users can call -/// `select_where_possible`, and the fulfilment context will try to do +/// `select_where_possible`, and the fulfillment context will try to do /// selection, retaining only those obligations that remain /// ambiguous. This may be helpful in pushing type inference /// along. Once all type inference constraints have been generated, the diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index d1938197e65..5bae82c1a33 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -20,7 +20,7 @@ use hir::def_id::DefId; use middle::region::RegionMaps; use middle::free_region::FreeRegionMap; use ty::subst::Substs; -use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate}; +use ty::{self, AdtKind, Ty, TyCtxt, TypeFoldable, ToPredicate}; use ty::error::{ExpectedFound, TypeError}; use infer::{InferCtxt}; @@ -133,7 +133,7 @@ pub enum ObligationCauseCode<'tcx> { RepeatVec, /// Types of fields (other than the last) in a struct must be sized. - FieldSized, + FieldSized(AdtKind), /// Constant expressions must be sized. ConstSized, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 3e39d592135..46bdb1344b2 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1296,6 +1296,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } else if self.tcx().lang_items.unsize_trait() == Some(def_id) { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } else { + if self.tcx().lang_items.clone_trait() == Some(def_id) { + // Same builtin conditions as `Copy`, i.e. every type which has builtin support + // for `Copy` also has builtin support for `Clone`, + tuples and arrays of `Clone` + // types have builtin support for `Clone`. + let clone_conditions = self.copy_conditions(obligation); + self.assemble_builtin_bound_candidates(clone_conditions, &mut candidates)?; + } + self.assemble_closure_candidates(obligation, &mut candidates)?; self.assemble_fn_pointer_candidates(obligation, &mut candidates)?; self.assemble_candidates_from_impls(obligation, &mut candidates)?; @@ -2164,8 +2172,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match candidate { BuiltinCandidate { has_nested } => { - Ok(VtableBuiltin( - self.confirm_builtin_candidate(obligation, has_nested))) + let data = self.confirm_builtin_candidate(obligation, has_nested); + Ok(VtableBuiltin(data)) } ParamCandidate(param) => { @@ -2271,6 +2279,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ if Some(trait_def) == self.tcx().lang_items.copy_trait() => { self.copy_conditions(obligation) } + _ if Some(trait_def) == self.tcx().lang_items.clone_trait() => { + self.copy_conditions(obligation) + } _ => bug!("unexpected builtin trait {:?}", trait_def) }; let nested = match conditions { @@ -2291,6 +2302,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("confirm_builtin_candidate: obligations={:?}", obligations); + VtableBuiltinData { nested: obligations } } @@ -2598,8 +2610,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn confirm_builtin_unsize_candidate(&mut self, obligation: &TraitObligation<'tcx>,) - -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, - SelectionError<'tcx>> { + -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> + { let tcx = self.tcx(); // assemble_candidates_for_unsizing should ensure there are no late bound diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index f1c176561ea..d913c76ec3c 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::ReturnType(id) => Some(super::ReturnType(id)), super::SizedReturnType => Some(super::SizedReturnType), super::RepeatVec => Some(super::RepeatVec), - super::FieldSized => Some(super::FieldSized), + super::FieldSized(item) => Some(super::FieldSized(item)), super::ConstSized => Some(super::ConstSized), super::SharedStatic => Some(super::SharedStatic), super::BuiltinDerivedObligation(ref cause) => { @@ -300,7 +300,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { }) } traits::VtableParam(n) => Some(traits::VtableParam(n)), - traits::VtableBuiltin(d) => Some(traits::VtableBuiltin(d)), + traits::VtableBuiltin(n) => Some(traits::VtableBuiltin(n)), traits::VtableObject(traits::VtableObjectData { upcast_trait_ref, vtable_base, @@ -484,7 +484,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | - super::FieldSized | + super::FieldSized(_) | super::ConstSized | super::SharedStatic | super::BlockTailExpression(_) | @@ -532,7 +532,7 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::SizedReturnType | super::ReturnNoExpression | super::RepeatVec | - super::FieldSized | + super::FieldSized(_) | super::ConstSized | super::SharedStatic | super::BlockTailExpression(_) | diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f71ad67bd1d..6ce2232eb3e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -797,6 +797,8 @@ pub struct GlobalCtxt<'tcx> { pub maybe_unused_trait_imports: NodeSet, + pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, + // Internal cache for metadata decoding. No need to track deps on this. pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>, @@ -851,7 +853,7 @@ pub struct GlobalCtxt<'tcx> { /// A vector of every trait accessible in the whole crate /// (i.e. including those from subcrates). This is used only for - /// error reporting, and so is lazily initialised and generally + /// error reporting, and so is lazily initialized and generally /// shouldn't taint the common path (hence the RefCell). pub all_traits: RefCell<Option<Vec<DefId>>>, } @@ -1038,6 +1040,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { mir_passes, freevars: RefCell::new(resolutions.freevars), maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports, + maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates, rcache: RefCell::new(FxHashMap()), normalized_cache: RefCell::new(FxHashMap()), inhabitedness_cache: RefCell::new(FxHashMap()), @@ -1695,8 +1698,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { self.mk_ty(TyProjection(ProjectionTy { - item_def_id: item_def_id, - substs: substs, + item_def_id, + substs, })) } @@ -1840,6 +1843,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.struct_span_lint_node(lint, id, span.into(), msg).emit() } + pub fn lint_node_note<S: Into<MultiSpan>>(self, + lint: &'static Lint, + id: NodeId, + span: S, + msg: &str, + note: &str) { + let mut err = self.struct_span_lint_node(lint, id, span.into(), msg); + err.note(note); + err.emit() + } + pub fn lint_level_at_node(self, lint: &'static Lint, mut id: NodeId) -> (lint::Level, lint::LintSource) { diff --git a/src/librustc/ty/inhabitedness/def_id_forest.rs b/src/librustc/ty/inhabitedness/def_id_forest.rs index 896682e2370..3629709e6a4 100644 --- a/src/librustc/ty/inhabitedness/def_id_forest.rs +++ b/src/librustc/ty/inhabitedness/def_id_forest.rs @@ -26,7 +26,7 @@ pub struct DefIdForest { /// The minimal set of DefIds required to represent the whole set. /// If A and B are DefIds in the DefIdForest, and A is a descendant /// of B, then only B will be in root_ids. - /// We use a SmallVec here because (for its use for cacheing inhabitedness) + /// We use a SmallVec here because (for its use for caching inhabitedness) /// its rare that this will contain even two ids. root_ids: SmallVec<[DefId; 1]>, } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 32063a2dda6..7d543f689c2 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -24,15 +24,22 @@ pub struct Instance<'tcx> { pub enum InstanceDef<'tcx> { Item(DefId), Intrinsic(DefId), - // <fn() as FnTrait>::call_* - // def-id is FnTrait::call_* + + /// <fn() as FnTrait>::call_* + /// def-id is FnTrait::call_* FnPtrShim(DefId, Ty<'tcx>), - // <Trait as Trait>::fn + + /// <Trait as Trait>::fn Virtual(DefId, usize), - // <[mut closure] as FnOnce>::call_once + + /// <[mut closure] as FnOnce>::call_once ClosureOnceShim { call_once: DefId }, - // drop_in_place::<T>; None for empty drop glue. + + /// drop_in_place::<T>; None for empty drop glue. DropGlue(DefId, Option<Ty<'tcx>>), + + /// Builtin method implementation, e.g. `Clone::clone`. + CloneShim(DefId, Ty<'tcx>), } impl<'tcx> InstanceDef<'tcx> { @@ -43,9 +50,9 @@ impl<'tcx> InstanceDef<'tcx> { InstanceDef::FnPtrShim(def_id, _) | InstanceDef::Virtual(def_id, _) | InstanceDef::Intrinsic(def_id, ) | - InstanceDef::ClosureOnceShim { call_once: def_id } - => def_id, - InstanceDef::DropGlue(def_id, _) => def_id + InstanceDef::ClosureOnceShim { call_once: def_id } | + InstanceDef::DropGlue(def_id, _) | + InstanceDef::CloneShim(def_id, _) => def_id } } @@ -80,6 +87,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> { InstanceDef::DropGlue(_, ty) => { write!(f, " - shim({:?})", ty) } + InstanceDef::CloneShim(_, ty) => { + write!(f, " - shim({:?})", ty) + } } } } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 76a20ed8f30..5caf5139812 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -13,7 +13,6 @@ use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, Ty, TyCtxt}; use syntax::ast; use syntax::symbol::Symbol; -use syntax_pos::DUMMY_SP; use std::cell::Cell; @@ -222,11 +221,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || { // Otherwise, use filename/line-number if forced. let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types && { - // Otherwise, use types if we can query them without inducing a cycle. - ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() && - ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok() - } + !force_no_types }); if !use_types { diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs index a640da31eec..a73202ced61 100644 --- a/src/librustc/ty/maps.rs +++ b/src/librustc/ty/maps.rs @@ -9,6 +9,7 @@ // except according to those terms. use dep_graph::{DepConstructor, DepNode, DepNodeIndex}; +use errors::{Diagnostic, DiagnosticBuilder}; use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use hir::def::Def; use hir; @@ -28,10 +29,11 @@ use ty::steal::Steal; use ty::subst::Substs; use ty::fast_reject::SimplifiedType; use util::nodemap::{DefIdSet, NodeSet}; +use util::common::{profq_msg, ProfileQueriesMsg}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::fx::FxHashMap; -use std::cell::{RefCell, RefMut}; +use std::cell::{RefCell, RefMut, Cell}; use std::fmt::Debug; use std::hash::Hash; use std::marker::PhantomData; @@ -187,7 +189,18 @@ impl<'tcx> Value<'tcx> for ty::SymbolName { struct QueryMap<D: QueryDescription> { phantom: PhantomData<D>, - map: FxHashMap<D::Key, (D::Value, DepNodeIndex)>, + map: FxHashMap<D::Key, QueryValue<D::Value>>, +} + +struct QueryValue<T> { + value: T, + index: DepNodeIndex, + diagnostics: Option<Box<QueryDiagnostics>>, +} + +struct QueryDiagnostics { + diagnostics: Vec<Diagnostic>, + emitted_diagnostics: Cell<bool>, } impl<M: QueryDescription> QueryMap<M> { @@ -199,13 +212,15 @@ impl<M: QueryDescription> QueryMap<M> { } } -pub struct CycleError<'a, 'tcx: 'a> { +struct CycleError<'a, 'tcx: 'a> { span: Span, cycle: RefMut<'a, [(Span, Query<'tcx>)]>, } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn report_cycle(self, CycleError { span, cycle }: CycleError) { + fn report_cycle(self, CycleError { span, cycle }: CycleError) + -> DiagnosticBuilder<'a> + { // Subtle: release the refcell lock before invoking `describe()` // below by dropping `cycle`. let stack = cycle.to_vec(); @@ -234,8 +249,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { err.note(&format!("...which then again requires {}, completing the cycle.", stack[0].1.describe(self))); - err.emit(); - }); + return err + }) } fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F) @@ -501,6 +516,18 @@ impl<'tcx> QueryDescription for queries::is_panic_runtime<'tcx> { } } +impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + "checking if the crate is_compiler_builtins".to_string() + } +} + +impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> { + fn describe(_: TyCtxt, _: DefId) -> String { + "checking if the crate has_global_allocator".to_string() + } +} + impl<'tcx> QueryDescription for queries::extern_crate<'tcx> { fn describe(_: TyCtxt, _: DefId) -> String { "getting crate's ExternCrateData".to_string() @@ -513,6 +540,29 @@ impl<'tcx> QueryDescription for queries::lint_levels<'tcx> { } } +// If enabled, send a message to the profile-queries thread +macro_rules! profq_msg { + ($tcx:expr, $msg:expr) => { + if cfg!(debug_assertions) { + if $tcx.sess.profile_queries() { + profq_msg($msg) + } + } + } +} + +// If enabled, format a key using its debug string, which can be +// expensive to compute (in terms of time). +macro_rules! profq_key { + ($tcx:expr, $key:expr) => { + if cfg!(debug_assertions) { + if $tcx.sess.profile_queries_and_keys() { + Some(format!("{:?}", $key)) + } else { None } + } else { None } + } +} + macro_rules! define_maps { (<$tcx:tt> $($(#[$attr:meta])* @@ -539,6 +589,12 @@ macro_rules! define_maps { $($(#[$attr])* $name($K)),* } + #[allow(bad_style)] + #[derive(Clone, Debug, PartialEq, Eq)] + pub enum QueryMsg { + $($name(Option<String>)),* + } + impl<$tcx> Query<$tcx> { pub fn describe(&self, tcx: TyCtxt) -> String { match *self { @@ -581,10 +637,30 @@ macro_rules! define_maps { key, span); - if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) { - tcx.dep_graph.read_index(dep_node_index); - return Ok(f(result)); + profq_msg!(tcx, + ProfileQueriesMsg::QueryBegin( + span.clone(), + QueryMsg::$name(profq_key!(tcx, key)) + ) + ); + + if let Some(value) = tcx.maps.$name.borrow().map.get(&key) { + if let Some(ref d) = value.diagnostics { + if !d.emitted_diagnostics.get() { + d.emitted_diagnostics.set(true); + let handle = tcx.sess.diagnostic(); + for diagnostic in d.diagnostics.iter() { + DiagnosticBuilder::new_diagnostic(handle, diagnostic.clone()) + .emit(); + } + } + } + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + tcx.dep_graph.read_index(value.index); + return Ok(f(&value.value)); } + // else, we are going to run the provider: + profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin); // FIXME(eddyb) Get more valid Span's on queries. // def_span guard is necessary to prevent a recursive loop, @@ -593,40 +669,60 @@ macro_rules! define_maps { span = key.default_span(tcx) } - let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || { + let res = tcx.cycle_check(span, Query::$name(key), || { let dep_node = Self::to_dep_node(tcx, &key); - if dep_node.kind.is_anon() { - tcx.dep_graph.with_anon_task(dep_node.kind, || { - let provider = tcx.maps.providers[key.map_crate()].$name; - provider(tcx.global_tcx(), key) - }) - } else { - fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>, - key: $K) - -> $V { - let provider = tcx.maps.providers[key.map_crate()].$name; - provider(tcx.global_tcx(), key) + tcx.sess.diagnostic().track_diagnostics(|| { + if dep_node.kind.is_anon() { + tcx.dep_graph.with_anon_task(dep_node.kind, || { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + }) + } else { + fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>, + key: $K) + -> $V { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + } + + tcx.dep_graph.with_task(dep_node, tcx, key, run_provider) } - - tcx.dep_graph.with_task(dep_node, tcx, key, run_provider) - } + }) })?; + profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); + let ((result, dep_node_index), diagnostics) = res; tcx.dep_graph.read_index(dep_node_index); + let value = QueryValue { + value: result, + index: dep_node_index, + diagnostics: if diagnostics.len() == 0 { + None + } else { + Some(Box::new(QueryDiagnostics { + diagnostics, + emitted_diagnostics: Cell::new(true), + })) + }, + }; + Ok(f(&tcx.maps .$name .borrow_mut() .map .entry(key) - .or_insert((result, dep_node_index)) - .0)) + .or_insert(value) + .value)) } pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) - -> Result<$V, CycleError<'a, $tcx>> { - Self::try_get_with(tcx, span, key, Clone::clone) + -> Result<$V, DiagnosticBuilder<'a>> { + match Self::try_get_with(tcx, span, key, Clone::clone) { + Ok(e) => Ok(e), + Err(e) => Err(tcx.report_cycle(e)), + } } pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) { @@ -635,7 +731,7 @@ macro_rules! define_maps { match Self::try_get_with(tcx, span, key, |_| ()) { Ok(()) => {} - Err(e) => tcx.report_cycle(e) + Err(e) => tcx.report_cycle(e).emit(), } } })* @@ -672,8 +768,8 @@ macro_rules! define_maps { impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> { $($(#[$attr])* pub fn $name(self, key: $K) -> $V { - queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|e| { - self.report_cycle(e); + queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| { + e.emit(); Value::from_cycle_error(self.global_tcx()) }) })* @@ -923,6 +1019,8 @@ define_maps! { <'tcx> [] coherent_trait: coherent_trait_dep_node((CrateNum, DefId)) -> (), [] borrowck: BorrowCheck(DefId) -> (), + // FIXME: shouldn't this return a `Result<(), BorrowckErrors>` instead? + [] mir_borrowck: MirBorrowCheck(DefId) -> (), /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. @@ -993,6 +1091,8 @@ define_maps! { <'tcx> [] is_allocator: IsAllocator(DefId) -> bool, [] is_panic_runtime: IsPanicRuntime(DefId) -> bool, + [] is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool, + [] has_global_allocator: HasGlobalAllocator(DefId) -> bool, [] extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 1daabd744ae..6597dccf258 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -131,6 +131,7 @@ pub struct Resolutions { pub freevars: FreevarMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, + pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, pub export_map: ExportMap, } @@ -1684,12 +1685,15 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] { match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) { Ok(tys) => tys, - Err(_) => { + Err(mut bug) => { debug!("adt_sized_constraint: {:?} is recursive", self); // This should be reported as an error by `check_representable`. // // Consider the type as Sized in the meanwhile to avoid - // further errors. + // further errors. Delay our `bug` diagnostic here to get + // emitted later as well in case we accidentally otherwise don't + // emit an error. + bug.delay_as_bug(); tcx.intern_type_list(&[tcx.types.err]) } } @@ -1971,7 +1975,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn local_var_name_str(self, id: NodeId) -> InternedString { match self.hir.find(id) { - Some(hir_map::NodeLocal(pat)) => { + Some(hir_map::NodeBinding(pat)) => { match pat.node { hir::PatKind::Binding(_, _, ref path1, _) => path1.node.as_str(), _ => { @@ -2232,7 +2236,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::ClosureOnceShim { .. } | - ty::InstanceDef::DropGlue(..) => { + ty::InstanceDef::DropGlue(..) | + ty::InstanceDef::CloneShim(..) => { self.mir_shims(instance) } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 0d9ef8196c7..c035817d66d 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -253,7 +253,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { let substs = relation.relate(&a.substs, &b.substs)?; Ok(ty::ExistentialProjection { item_def_id: a.item_def_id, - substs: substs, + substs, ty, }) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 48ace804995..e41eb079b37 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -137,7 +137,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionTy<'a> { tcx.lift(&self.substs).map(|substs| { ty::ProjectionTy { item_def_id: self.item_def_id, - substs: substs, + substs, } }) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index b42180b288b..8d6b7b7ac9f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -569,7 +569,7 @@ impl<'a, 'tcx> ProjectionTy<'tcx> { pub fn trait_ref(&self, tcx: TyCtxt) -> ty::TraitRef<'tcx> { let def_id = tcx.associated_item(self.item_def_id).container.id(); ty::TraitRef { - def_id: def_id, + def_id, substs: self.substs, } } @@ -739,7 +739,7 @@ pub type Region<'tcx> = &'tcx RegionKind; /// /// The process of doing that is called "skolemization". The bound regions /// are replaced by skolemized markers, which don't satisfy any relation -/// not explicity provided. +/// not explicitly provided. /// /// There are 2 kinds of skolemized regions in rustc: `ReFree` and /// `ReSkolemized`. When checking an item's body, `ReFree` is supposed @@ -874,7 +874,7 @@ impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { pub fn trait_ref(&self, tcx: TyCtxt) -> ty::ExistentialTraitRef<'tcx> { let def_id = tcx.associated_item(self.item_def_id).container.id(); ty::ExistentialTraitRef{ - def_id: def_id, + def_id, substs: self.substs, } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 9cd6aa21118..bbbb8611f98 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1069,11 +1069,15 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let needs_drop = |ty: Ty<'tcx>| -> bool { match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) { Ok(v) => v, - Err(_) => { + Err(mut bug) => { // Cycles should be reported as an error by `check_representable`. // - // Consider the type as not needing drop in the meanwhile to avoid - // further errors. + // Consider the type as not needing drop in the meanwhile to + // avoid further errors. + // + // In case we forgot to emit a bug elsewhere, delay our + // diagnostic to get emitted as a compiler bug. + bug.delay_as_bug(); false } } diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index c24c583ad1e..6d9e648452f 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -58,7 +58,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, -> Vec<traits::PredicateObligation<'tcx>> { let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] }; - wf.compute_trait_ref(trait_ref); + wf.compute_trait_ref(trait_ref, Elaborate::All); wf.normalize() } @@ -74,7 +74,7 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, // (*) ok to skip binders, because wf code is prepared for it match *predicate { ty::Predicate::Trait(ref t) => { - wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*) + wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*) } ty::Predicate::Equate(ref t) => { wf.compute(t.skip_binder().0); @@ -114,6 +114,35 @@ struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { out: Vec<traits::PredicateObligation<'tcx>>, } +/// Controls whether we "elaborate" supertraits and so forth on the WF +/// predicates. This is a kind of hack to address #43784. The +/// underlying problem in that issue was a trait structure like: +/// +/// ``` +/// trait Foo: Copy { } +/// trait Bar: Foo { } +/// impl<T: Bar> Foo for T { } +/// impl<T> Bar for T { } +/// ``` +/// +/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but +/// we decide that this is true because `T: Bar` is in the +/// where-clauses (and we can elaborate that to include `T: +/// Copy`). This wouldn't be a problem, except that when we check the +/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo` +/// impl. And so nowhere did we check that `T: Copy` holds! +/// +/// To resolve this, we elaborate the WF requirements that must be +/// proven when checking impls. This means that (e.g.) the `impl Bar +/// for T` will be forced to prove not only that `T: Foo` but also `T: +/// Copy` (which it won't be able to do, because there is no `Copy` +/// impl for `T`). +#[derive(Debug, PartialEq, Eq, Copy, Clone)] +enum Elaborate { + All, + None, +} + impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> { traits::ObligationCause::new(self.span, self.body_id, code) @@ -135,12 +164,25 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// Pushes the obligations required for `trait_ref` to be WF into /// `self.out`. - fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) { + fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) { let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs); - self.out.extend(obligations); let cause = self.cause(traits::MiscObligation); let param_env = self.param_env; + + if let Elaborate::All = elaborate { + let predicates = obligations.iter() + .map(|obligation| obligation.predicate.clone()) + .collect(); + let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates); + let implied_obligations = implied_obligations.map(|pred| { + traits::Obligation::new(cause.clone(), param_env, pred) + }); + self.out.extend(implied_obligations); + } + + self.out.extend(obligations); + self.out.extend( trait_ref.substs.types() .filter(|ty| !ty.has_escaping_regions()) @@ -156,7 +198,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // WF and (b) the trait-ref holds. (It may also be // normalizable and be WF that way.) let trait_ref = data.trait_ref(self.infcx.tcx); - self.compute_trait_ref(&trait_ref); + self.compute_trait_ref(&trait_ref, Elaborate::None); if !data.has_escaping_regions() { let predicate = trait_ref.to_predicate(); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 885be8464eb..618a4ed331e 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -19,6 +19,11 @@ use std::iter::repeat; use std::path::Path; use std::time::{Duration, Instant}; +use std::sync::mpsc::{Sender}; +use syntax_pos::{Span}; +use ty::maps::{QueryMsg}; +use dep_graph::{DepNode}; + // The name of the associated type for `Fn` return types pub const FN_OUTPUT_NAME: &'static str = "Output"; @@ -29,6 +34,72 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0)); +/// Initialized for -Z profile-queries +thread_local!(static PROFQ_CHAN: RefCell<Option<Sender<ProfileQueriesMsg>>> = RefCell::new(None)); + +/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`. +#[derive(Clone,Debug)] +pub struct ProfQDumpParams { + /// A base path for the files we will dump + pub path:String, + /// To ensure that the compiler waits for us to finish our dumps + pub ack:Sender<()>, + /// toggle dumping a log file with every `ProfileQueriesMsg` + pub dump_profq_msg_log:bool, +} + +/// A sequence of these messages induce a trace of query-based incremental compilation. +/// FIXME(matthewhammer): Determine whether we should include cycle detection here or not. +#[derive(Clone,Debug)] +pub enum ProfileQueriesMsg { + /// begin a timed pass + TimeBegin(String), + /// end a timed pass + TimeEnd, + /// begin a task (see dep_graph::graph::with_task) + TaskBegin(DepNode), + /// end a task + TaskEnd, + /// begin a new query + QueryBegin(Span, QueryMsg), + /// query is satisfied by using an already-known value for the given key + CacheHit, + /// query requires running a provider; providers may nest, permitting queries to nest. + ProviderBegin, + /// query is satisfied by a provider terminating with a value + ProviderEnd, + /// dump a record of the queries to the given path + Dump(ProfQDumpParams), + /// halt the profiling/monitoring background thread + Halt +} + +/// If enabled, send a message to the profile-queries thread +pub fn profq_msg(msg: ProfileQueriesMsg) { + PROFQ_CHAN.with(|sender|{ + if let Some(s) = sender.borrow().as_ref() { + s.send(msg).unwrap() + } else { + // Do nothing. + // + // FIXME(matthewhammer): Multi-threaded translation phase triggers the panic below. + // From backtrace: rustc_trans::back::write::spawn_work::{{closure}}. + // + // panic!("no channel on which to send profq_msg: {:?}", msg) + } + }) +} + +/// Set channel for profile queries channel +pub fn profq_set_chan(s: Sender<ProfileQueriesMsg>) -> bool { + PROFQ_CHAN.with(|chan|{ + if chan.borrow().is_none() { + *chan.borrow_mut() = Some(s); + true + } else { false } + }) +} + /// Read the current depth of `time()` calls. This is used to /// encourage indentation across threads. pub fn time_depth() -> usize { @@ -53,9 +124,15 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where r }); + if cfg!(debug_assertions) { + profq_msg(ProfileQueriesMsg::TimeBegin(what.to_string())) + }; let start = Instant::now(); let rv = f(); let dur = start.elapsed(); + if cfg!(debug_assertions) { + profq_msg(ProfileQueriesMsg::TimeEnd) + }; print_time_passes_entry_internal(what, dur); diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index 78b07a33389..f99c6a29ff0 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -36,9 +36,9 @@ pub fn modify(sess: &ParseSess, krate: Crate, handler: &rustc_errors::Handler) -> ast::Crate { ExpandAllocatorDirectives { - handler: handler, - sess: sess, - resolver: resolver, + handler, + sess, + resolver, found: false, }.fold_crate(krate) } @@ -88,7 +88,7 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> { }; let ecfg = ExpansionConfig::default(name.to_string()); let mut f = AllocFnFactory { - span: span, + span, kind: AllocatorKind::Global, global: item.ident, alloc: Ident::from_str("alloc"), diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs index d0ea40d1e36..e17fce5a2ec 100644 --- a/src/librustc_allocator/lib.rs +++ b/src/librustc_allocator/lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![deny(warnings)] + #![feature(rustc_private)] extern crate rustc; @@ -22,61 +24,51 @@ pub static ALLOCATOR_METHODS: &[AllocatorMethod] = &[ name: "alloc", inputs: &[AllocatorTy::Layout], output: AllocatorTy::ResultPtr, - is_unsafe: true, }, AllocatorMethod { name: "oom", inputs: &[AllocatorTy::AllocErr], output: AllocatorTy::Bang, - is_unsafe: false, }, AllocatorMethod { name: "dealloc", inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout], output: AllocatorTy::Unit, - is_unsafe: true, }, AllocatorMethod { name: "usable_size", inputs: &[AllocatorTy::LayoutRef], output: AllocatorTy::UsizePair, - is_unsafe: false, }, AllocatorMethod { name: "realloc", inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], output: AllocatorTy::ResultPtr, - is_unsafe: true, }, AllocatorMethod { name: "alloc_zeroed", inputs: &[AllocatorTy::Layout], output: AllocatorTy::ResultPtr, - is_unsafe: true, }, AllocatorMethod { name: "alloc_excess", inputs: &[AllocatorTy::Layout], output: AllocatorTy::ResultExcess, - is_unsafe: true, }, AllocatorMethod { name: "realloc_excess", inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], output: AllocatorTy::ResultExcess, - is_unsafe: true, }, AllocatorMethod { name: "grow_in_place", inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], output: AllocatorTy::ResultUnit, - is_unsafe: true, }, AllocatorMethod { name: "shrink_in_place", inputs: &[AllocatorTy::Ptr, AllocatorTy::Layout, AllocatorTy::Layout], output: AllocatorTy::ResultUnit, - is_unsafe: true, }, ]; @@ -84,7 +76,6 @@ pub struct AllocatorMethod { pub name: &'static str, pub inputs: &'static [AllocatorTy], pub output: AllocatorTy, - pub is_unsafe: bool, } pub enum AllocatorTy { diff --git a/src/librustc_apfloat/ieee.rs b/src/librustc_apfloat/ieee.rs index 3545a77c75d..124c840cc56 100644 --- a/src/librustc_apfloat/ieee.rs +++ b/src/librustc_apfloat/ieee.rs @@ -460,18 +460,15 @@ impl<S: Semantics> fmt::Display for IeeeFloat<S> { // rem <- sig % 10 // sig <- sig / 10 let mut rem = 0; - for limb in sig.iter_mut().rev() { - // We don't have an integer doubly wide than Limb, - // so we have to split the divrem on two halves. - const HALF_BITS: usize = LIMB_BITS / 2; - let mut halves = [*limb & ((1 << HALF_BITS) - 1), *limb >> HALF_BITS]; - for half in halves.iter_mut().rev() { - *half |= rem << HALF_BITS; - rem = *half % 10; - *half /= 10; - } - *limb = halves[0] | (halves[1] << HALF_BITS); - } + + // Use 64-bit division and remainder, with 32-bit chunks from sig. + sig::each_chunk(&mut sig, 32, |chunk| { + let chunk = chunk as u32; + let combined = ((rem as u64) << 32) | (chunk as u64); + rem = (combined % 10) as u8; + (combined / 10) as u32 as Limb + }); + // Reduce the sigificand to avoid wasting time dividing 0's. while sig.last() == Some(&0) { sig.pop(); @@ -491,7 +488,7 @@ impl<S: Semantics> fmt::Display for IeeeFloat<S> { exp += 1; } else { in_trail = false; - buffer.push(b'0' + digit as u8); + buffer.push(b'0' + digit); } } @@ -2065,7 +2062,7 @@ impl<S: Semantics> IeeeFloat<S> { }; // Attempt dec_sig * 10^dec_exp with increasing precision. - let mut attempt = 1; + let mut attempt = 0; loop { let calc_precision = (LIMB_BITS << attempt) - 1; attempt += 1; @@ -2310,6 +2307,17 @@ mod sig { limbs.iter().all(|&l| l == 0) } + /// One, not zero, based LSB. That is, returns 0 for a zeroed significand. + pub(super) fn olsb(limbs: &[Limb]) -> usize { + for i in 0..limbs.len() { + if limbs[i] != 0 { + return i * LIMB_BITS + limbs[i].trailing_zeros() as usize + 1; + } + } + + 0 + } + /// One, not zero, based MSB. That is, returns 0 for a zeroed significand. pub(super) fn omsb(limbs: &[Limb]) -> usize { for i in (0..limbs.len()).rev() { @@ -2468,6 +2476,20 @@ mod sig { } } + /// For every consecutive chunk of `bits` bits from `limbs`, + /// going from most significant to the least significant bits, + /// call `f` to transform those bits and store the result back. + pub(super) fn each_chunk<F: FnMut(Limb) -> Limb>(limbs: &mut [Limb], bits: usize, mut f: F) { + assert_eq!(LIMB_BITS % bits, 0); + for limb in limbs.iter_mut().rev() { + let mut r = 0; + for i in (0..LIMB_BITS / bits).rev() { + r |= f((*limb >> (i * bits)) & ((1 << bits) - 1)) << (i * bits); + } + *limb = r; + } + } + /// Increment in-place, return the carry flag. pub(super) fn increment(dst: &mut [Limb]) -> Limb { for x in dst { @@ -2686,10 +2708,6 @@ mod sig { divisor: &mut [Limb], precision: usize, ) -> Loss { - // Zero the quotient before setting bits in it. - for x in &mut quotient[..limbs_for_bits(precision)] { - *x = 0; - } // Normalize the divisor. let bits = precision - omsb(divisor); @@ -2700,6 +2718,13 @@ mod sig { let bits = precision - omsb(dividend); shift_left(dividend, exp, bits); + // Division by 1. + let olsb_divisor = olsb(divisor); + if olsb_divisor == precision { + quotient.copy_from_slice(dividend); + return Loss::ExactlyZero; + } + // Ensure the dividend >= divisor initially for the loop below. // Incidentally, this means that the division loop below is // guaranteed to set the integer bit to one. @@ -2708,6 +2733,58 @@ mod sig { assert_ne!(cmp(dividend, divisor), Ordering::Less) } + // Helper for figuring out the lost fraction. + let lost_fraction = |dividend: &[Limb], divisor: &[Limb]| { + match cmp(dividend, divisor) { + Ordering::Greater => Loss::MoreThanHalf, + Ordering::Equal => Loss::ExactlyHalf, + Ordering::Less => { + if is_all_zeros(dividend) { + Loss::ExactlyZero + } else { + Loss::LessThanHalf + } + } + } + }; + + // Try to perform a (much faster) short division for small divisors. + let divisor_bits = precision - (olsb_divisor - 1); + macro_rules! try_short_div { + ($W:ty, $H:ty, $half:expr) => { + if divisor_bits * 2 <= $half { + // Extract the small divisor. + let _: Loss = shift_right(divisor, &mut 0, olsb_divisor - 1); + let divisor = divisor[0] as $H as $W; + + // Shift the dividend to produce a quotient with the unit bit set. + let top_limb = *dividend.last().unwrap(); + let mut rem = (top_limb >> (LIMB_BITS - (divisor_bits - 1))) as $H; + shift_left(dividend, &mut 0, divisor_bits - 1); + + // Apply short division in place on $H (of $half bits) chunks. + each_chunk(dividend, $half, |chunk| { + let chunk = chunk as $H; + let combined = ((rem as $W) << $half) | (chunk as $W); + rem = (combined % divisor) as $H; + (combined / divisor) as $H as Limb + }); + quotient.copy_from_slice(dividend); + + return lost_fraction(&[(rem as Limb) << 1], &[divisor as Limb]); + } + } + } + + try_short_div!(u32, u16, 16); + try_short_div!(u64, u32, 32); + try_short_div!(u128, u64, 64); + + // Zero the quotient before setting bits in it. + for x in &mut quotient[..limbs_for_bits(precision)] { + *x = 0; + } + // Long division. for bit in (0..precision).rev() { if cmp(dividend, divisor) != Ordering::Less { @@ -2717,17 +2794,6 @@ mod sig { shift_left(dividend, &mut 0, 1); } - // Figure out the lost fraction. - match cmp(dividend, divisor) { - Ordering::Greater => Loss::MoreThanHalf, - Ordering::Equal => Loss::ExactlyHalf, - Ordering::Less => { - if is_all_zeros(dividend) { - Loss::ExactlyZero - } else { - Loss::LessThanHalf - } - } - } + lost_fraction(dividend, divisor) } } diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs index d9dbf787856..d4a02065761 100644 --- a/src/librustc_apfloat/lib.rs +++ b/src/librustc_apfloat/lib.rs @@ -39,7 +39,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_apfloat"] #![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/")] diff --git a/src/librustc_back/dynamic_lib.rs b/src/librustc_back/dynamic_lib.rs index e6f305c22b2..1b42fa03a4f 100644 --- a/src/librustc_back/dynamic_lib.rs +++ b/src/librustc_back/dynamic_lib.rs @@ -12,9 +12,8 @@ //! //! A simple wrapper over the platform's dynamic library facilities -use std::env; -use std::ffi::{CString, OsString}; -use std::path::{Path, PathBuf}; +use std::ffi::CString; +use std::path::Path; pub struct DynamicLibrary { handle: *mut u8 @@ -43,24 +42,6 @@ impl DynamicLibrary { } } - /// Prepends a path to this process's search path for dynamic libraries - pub fn prepend_search_path(path: &Path) { - let mut search_path = DynamicLibrary::search_path(); - search_path.insert(0, path.to_path_buf()); - env::set_var(DynamicLibrary::envvar(), &DynamicLibrary::create_path(&search_path)); - } - - /// From a slice of paths, create a new vector which is suitable to be an - /// environment variable for this platforms dylib search path. - pub fn create_path(path: &[PathBuf]) -> OsString { - let mut newvar = OsString::new(); - for (i, path) in path.iter().enumerate() { - if i > 0 { newvar.push(DynamicLibrary::separator()); } - newvar.push(path); - } - return newvar; - } - /// Returns the environment variable for this process's dynamic library /// search path pub fn envvar() -> &'static str { @@ -75,19 +56,6 @@ impl DynamicLibrary { } } - fn separator() -> &'static str { - if cfg!(windows) { ";" } else { ":" } - } - - /// Returns the current search path for dynamic libraries being used by this - /// process - pub fn search_path() -> Vec<PathBuf> { - match env::var_os(DynamicLibrary::envvar()) { - Some(var) => env::split_paths(&var).collect(), - None => Vec::new(), - } - } - /// Accesses the value at the symbol of the dynamic library. pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<*mut T, String> { // This function should have a lifetime constraint of 'a on diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index 55b39f22670..6a9833d3784 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -21,9 +21,6 @@ //! one that doesn't; the one that doesn't might get decent parallel //! build speedups. -#![crate_name = "rustc_back"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_back/target/apple_ios_base.rs index 2e7d30d969e..4b02d0b60b8 100644 --- a/src/librustc_back/target/apple_ios_base.rs +++ b/src/librustc_back/target/apple_ios_base.rs @@ -97,7 +97,7 @@ pub fn opts(arch: Arch) -> Result<TargetOptions, String> { cpu: target_cpu(arch), dynamic_linking: false, executables: true, - pre_link_args: pre_link_args, + pre_link_args, has_elf_tls: false, .. super::apple_base::opts() }) diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs index 21410dcd412..112f424f7a8 100644 --- a/src/librustc_back/target/haiku_base.rs +++ b/src/librustc_back/target/haiku_base.rs @@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions { target_family: Some("unix".to_string()), relro_level: RelroLevel::Full, linker_is_gnu: true, - no_integrated_as: true, .. Default::default() } } diff --git a/src/librustc_back/target/l4re_base.rs b/src/librustc_back/target/l4re_base.rs index 998183d4015..31d428d2668 100644 --- a/src/librustc_back/target/l4re_base.rs +++ b/src/librustc_back/target/l4re_base.rs @@ -12,21 +12,71 @@ use PanicStrategy; use LinkerFlavor; use target::{LinkArgs, TargetOptions}; use std::default::Default; +use std::env; +use std::process::Command; -pub fn opts() -> TargetOptions { +// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note +// that a few files also come from L4Re, for these, the function shouldn't be +// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway. +fn get_path_or(filename: &str) -> String { + let child = Command::new("gcc") + .arg(format!("-print-file-name={}", filename)).output() + .expect("Failed to execute GCC"); + String::from_utf8(child.stdout) + .expect("Couldn't read path from GCC").trim().into() +} + +pub fn opts() -> Result<TargetOptions, String> { + let l4re_lib_path = env::var_os("L4RE_LIBDIR").ok_or("Unable to find L4Re \ + library directory: L4RE_LIBDIR not set.")?.into_string().unwrap(); let mut pre_link_args = LinkArgs::new(); pre_link_args.insert(LinkerFlavor::Ld, vec![ - "-nostdlib".to_string(), + format!("-T{}/main_stat.ld", l4re_lib_path), + "--defsym=__executable_start=0x01000000".to_string(), + "--defsym=__L4_KIP_ADDR__=0x6ffff000".to_string(), + format!("{}/crt1.o", l4re_lib_path), + format!("{}/crti.o", l4re_lib_path), + get_path_or("crtbeginT.o"), + ]); + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Ld, vec![ + format!("{}/l4f/libpthread.a", l4re_lib_path), + format!("{}/l4f/libc_be_sig.a", l4re_lib_path), + format!("{}/l4f/libc_be_sig_noop.a", l4re_lib_path), + format!("{}/l4f/libc_be_socket_noop.a", l4re_lib_path), + format!("{}/l4f/libc_be_fs_noop.a", l4re_lib_path), + format!("{}/l4f/libc_be_sem_noop.a", l4re_lib_path), + format!("{}/l4f/libl4re-vfs.o.a", l4re_lib_path), + format!("{}/l4f/lib4re.a", l4re_lib_path), + format!("{}/l4f/lib4re-util.a", l4re_lib_path), + format!("{}/l4f/libc_support_misc.a", l4re_lib_path), + format!("{}/l4f/libsupc++.a", l4re_lib_path), + format!("{}/l4f/lib4shmc.a", l4re_lib_path), + format!("{}/l4f/lib4re-c.a", l4re_lib_path), + format!("{}/l4f/lib4re-c-util.a", l4re_lib_path), + get_path_or("libgcc_eh.a"), + format!("{}/l4f/libdl.a", l4re_lib_path), + "--start-group".to_string(), + format!("{}/l4f/libl4util.a", l4re_lib_path), + format!("{}/l4f/libc_be_l4re.a", l4re_lib_path), + format!("{}/l4f/libuc_c.a", l4re_lib_path), + format!("{}/l4f/libc_be_l4refile.a", l4re_lib_path), + "--end-group".to_string(), + format!("{}/l4f/libl4sys.a", l4re_lib_path), + "-gc-sections".to_string(), + get_path_or("crtend.o"), + format!("{}/crtn.o", l4re_lib_path), ]); - TargetOptions { + Ok(TargetOptions { executables: true, has_elf_tls: false, - exe_allocation_crate: Some("alloc_system".to_string()), + exe_allocation_crate: None, panic_strategy: PanicStrategy::Abort, linker: "ld".to_string(), - pre_link_args: pre_link_args, + pre_link_args, + post_link_args, target_family: Some("unix".to_string()), .. Default::default() - } + }) } diff --git a/src/librustc_back/target/le32_unknown_nacl.rs b/src/librustc_back/target/le32_unknown_nacl.rs index f4265e0eb14..51eeae50e22 100644 --- a/src/librustc_back/target/le32_unknown_nacl.rs +++ b/src/librustc_back/target/le32_unknown_nacl.rs @@ -25,8 +25,8 @@ pub fn target() -> TargetResult { linker: "pnacl-clang".to_string(), ar: "pnacl-ar".to_string(), - pre_link_args: pre_link_args, - post_link_args: post_link_args, + pre_link_args, + post_link_args, dynamic_linking: false, executables: true, exe_suffix: ".pexe".to_string(), diff --git a/src/librustc_back/target/linux_musl_base.rs b/src/librustc_back/target/linux_musl_base.rs index 236f2c1ef0a..6e5e139715c 100644 --- a/src/librustc_back/target/linux_musl_base.rs +++ b/src/librustc_back/target/linux_musl_base.rs @@ -60,15 +60,10 @@ pub fn opts() -> TargetOptions { base.pre_link_objects_exe.push("crti.o".to_string()); base.post_link_objects.push("crtn.o".to_string()); - // MUSL support doesn't currently include dynamic linking, so there's no - // need for dylibs or rpath business. Additionally `-pie` is incompatible - // with `-static`, so we can't pass `-pie`. - base.dynamic_linking = false; - base.has_rpath = false; - base.position_independent_executables = false; - // These targets statically link libc by default base.crt_static_default = true; + // These targets allow the user to choose between static and dynamic linking. + base.crt_static_respected = true; base } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 08b94d5a01c..130e1b695db 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -416,8 +416,12 @@ pub struct TargetOptions { /// ABIs are considered to be supported on all platforms and cannot be blacklisted. pub abi_blacklist: Vec<Abi>, + /// Whether or not linking dylibs to a static CRT is allowed. + pub crt_static_allows_dylibs: bool, /// Whether or not the CRT is statically linked by default. pub crt_static_default: bool, + /// Whether or not crt-static is respected by the compiler (or is a no-op). + pub crt_static_respected: bool, /// Whether or not stack probes (__rust_probestack) are enabled pub stack_probes: bool, @@ -478,7 +482,9 @@ impl Default for TargetOptions { max_atomic_width: None, panic_strategy: PanicStrategy::Unwind, abi_blacklist: vec![], + crt_static_allows_dylibs: false, crt_static_default: false, + crt_static_respected: false, stack_probes: false, } } @@ -714,7 +720,9 @@ impl Target { key!(max_atomic_width, Option<u64>); key!(min_atomic_width, Option<u64>); try!(key!(panic_strategy, PanicStrategy)); + key!(crt_static_allows_dylibs, bool); key!(crt_static_default, bool); + key!(crt_static_respected, bool); key!(stack_probes, bool); if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) { @@ -902,7 +910,9 @@ impl ToJson for Target { target_option_val!(min_atomic_width); target_option_val!(max_atomic_width); target_option_val!(panic_strategy); + target_option_val!(crt_static_allows_dylibs); target_option_val!(crt_static_default); + target_option_val!(crt_static_respected); target_option_val!(stack_probes); if default.abi_blacklist != self.options.abi_blacklist { diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_back/target/redox_base.rs index 2eae0a12408..c7915d4de72 100644 --- a/src/librustc_back/target/redox_base.rs +++ b/src/librustc_back/target/redox_base.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use {LinkerFlavor, PanicStrategy}; +use LinkerFlavor; use target::{LinkArgs, TargetOptions}; use std::default::Default; @@ -37,7 +37,6 @@ pub fn opts() -> TargetOptions { target_family: None, linker_is_gnu: true, has_elf_tls: true, - panic_strategy: PanicStrategy::Abort, .. Default::default() } } diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_back/target/wasm32_experimental_emscripten.rs index db47040bf3a..42ab1940404 100644 --- a/src/librustc_back/target/wasm32_experimental_emscripten.rs +++ b/src/librustc_back/target/wasm32_experimental_emscripten.rs @@ -38,7 +38,7 @@ pub fn target() -> Result<Target, String> { obj_is_bitcode: true, is_like_emscripten: true, max_atomic_width: Some(32), - post_link_args: post_link_args, + post_link_args, target_family: Some("unix".to_string()), .. Default::default() }; diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs index f5fb63038e9..a0a2699d8f9 100644 --- a/src/librustc_back/target/wasm32_unknown_emscripten.rs +++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs @@ -34,7 +34,7 @@ pub fn target() -> Result<Target, String> { obj_is_bitcode: true, is_like_emscripten: true, max_atomic_width: Some(32), - post_link_args: post_link_args, + post_link_args, target_family: Some("unix".to_string()), .. Default::default() }; diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs index 9bde24a28dd..e6aa745d54e 100644 --- a/src/librustc_back/target/windows_base.rs +++ b/src/librustc_back/target/windows_base.rs @@ -78,7 +78,7 @@ pub fn opts() -> TargetOptions { target_family: Some("windows".to_string()), is_like_windows: true, allows_weak_linkage: false, - pre_link_args: pre_link_args, + pre_link_args, pre_link_objects_exe: vec![ "crt2.o".to_string(), // mingw C runtime initialization for executables "rsbegin.o".to_string(), // Rust compiler runtime initialization, see rsbegin.rs @@ -87,7 +87,7 @@ pub fn opts() -> TargetOptions { "dllcrt2.o".to_string(), // mingw C runtime initialization for dlls "rsbegin.o".to_string(), ], - late_link_args: late_link_args, + late_link_args, post_link_objects: vec![ "rsend.o".to_string() ], diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_back/target/windows_msvc_base.rs index c07321e418e..42a4e6f5f11 100644 --- a/src/librustc_back/target/windows_msvc_base.rs +++ b/src/librustc_back/target/windows_msvc_base.rs @@ -63,6 +63,8 @@ pub fn opts() -> TargetOptions { is_like_windows: true, is_like_msvc: true, pre_link_args: args, + crt_static_allows_dylibs: true, + crt_static_respected: true, .. Default::default() } diff --git a/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs b/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs index b447f8a989d..99d3171e1c0 100644 --- a/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs +++ b/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs @@ -12,7 +12,7 @@ use LinkerFlavor; use target::{Target, TargetResult}; pub fn target() -> TargetResult { - let mut base = super::l4re_base::opts(); + let mut base = super::l4re_base::opts()?; base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); diff --git a/src/librustc_back/tempdir.rs b/src/librustc_back/tempdir.rs index e3e89223f2d..8ffaddd7c29 100644 --- a/src/librustc_back/tempdir.rs +++ b/src/librustc_back/tempdir.rs @@ -95,15 +95,6 @@ impl TempDir { self.path.as_ref().unwrap() } - /// Close and remove the temporary directory - /// - /// Although `TempDir` removes the directory on drop, in the destructor - /// any errors are ignored. To detect errors cleaning up the temporary - /// directory, call `close` instead. - pub fn close(mut self) -> io::Result<()> { - self.cleanup_dir() - } - fn cleanup_dir(&mut self) -> io::Result<()> { match self.path { Some(ref p) => fs::remove_dir_all(p), diff --git a/src/librustc_bitflags/lib.rs b/src/librustc_bitflags/lib.rs index 73125655792..eb47144d1f9 100644 --- a/src/librustc_bitflags/lib.rs +++ b/src/librustc_bitflags/lib.rs @@ -9,8 +9,6 @@ // except according to those terms. -#![crate_name = "rustc_bitflags"] -#![crate_type = "rlib"] #![no_std] #![deny(warnings)] diff --git a/src/librustc_borrowck/Cargo.toml b/src/librustc_borrowck/Cargo.toml index af99c0e9387..25f02537490 100644 --- a/src/librustc_borrowck/Cargo.toml +++ b/src/librustc_borrowck/Cargo.toml @@ -15,6 +15,5 @@ syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } graphviz = { path = "../libgraphviz" } rustc = { path = "../librustc" } -rustc_data_structures = { path = "../librustc_data_structures" } rustc_mir = { path = "../librustc_mir" } rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index c34bf4c3d28..4058f3198af 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -29,6 +29,7 @@ use rustc::ty::{self, TyCtxt}; use syntax::ast; use syntax_pos::Span; use rustc::hir; +use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; use std::rc::Rc; @@ -194,10 +195,10 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let def_id = bccx.tcx.hir.body_owner_def_id(body.id()); let param_env = bccx.tcx.param_env(def_id); let mut clcx = CheckLoanCtxt { - bccx: bccx, - dfcx_loans: dfcx_loans, - move_data: move_data, - all_loans: all_loans, + bccx, + dfcx_loans, + move_data, + all_loans, param_env, }; euv::ExprUseVisitor::new(&mut clcx, bccx.tcx, param_env, &bccx.region_maps, bccx.tables) @@ -465,10 +466,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let mut err = match (new_loan.kind, old_loan.kind) { (ty::MutBorrow, ty::MutBorrow) => { - let mut err = struct_span_err!(self.bccx, new_loan.span, E0499, - "cannot borrow `{}`{} as mutable \ - more than once at a time", - nl, new_loan_msg); + let mut err = self.bccx.cannot_mutably_borrow_multiply( + new_loan.span, &nl, &new_loan_msg, Origin::Ast); if new_loan.span == old_loan.span { // Both borrows are happening in the same place @@ -496,10 +495,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } (ty::UniqueImmBorrow, ty::UniqueImmBorrow) => { - let mut err = struct_span_err!(self.bccx, new_loan.span, E0524, - "two closures require unique access to `{}` \ - at the same time", - nl); + let mut err = self.bccx.cannot_uniquely_borrow_by_two_closures( + new_loan.span, &nl, Origin::Ast); err.span_label( old_loan.span, "first closure is constructed here"); @@ -513,10 +510,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } (ty::UniqueImmBorrow, _) => { - let mut err = struct_span_err!(self.bccx, new_loan.span, E0500, - "closure requires unique access to `{}` \ - but {} is already borrowed{}", - nl, ol_pronoun, old_loan_msg); + let mut err = self.bccx.cannot_uniquely_borrow_by_one_closure( + new_loan.span, &nl, &ol_pronoun, &old_loan_msg, Origin::Ast); err.span_label( new_loan.span, format!("closure construction occurs here{}", new_loan_msg)); @@ -530,10 +525,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } (_, ty::UniqueImmBorrow) => { - let mut err = struct_span_err!(self.bccx, new_loan.span, E0501, - "cannot borrow `{}`{} as {} because \ - previous closure requires unique access", - nl, new_loan_msg, new_loan.kind.to_user_str()); + let new_loan_str = &new_loan.kind.to_user_str(); + let mut err = self.bccx.cannot_reborrow_already_uniquely_borrowed( + new_loan.span, &nl, &new_loan_msg, new_loan_str, Origin::Ast); err.span_label( new_loan.span, format!("borrow occurs here{}", new_loan_msg)); @@ -547,15 +541,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } (..) => { - let mut err = struct_span_err!(self.bccx, new_loan.span, E0502, - "cannot borrow `{}`{} as {} because \ - {} is also borrowed as {}{}", - nl, - new_loan_msg, - new_loan.kind.to_user_str(), - ol_pronoun, - old_loan.kind.to_user_str(), - old_loan_msg); + let mut err = self.bccx.cannot_reborrow_already_borrowed( + new_loan.span, + &nl, &new_loan_msg, &new_loan.kind.to_user_str(), + &ol_pronoun, &old_loan.kind.to_user_str(), &old_loan_msg, Origin::Ast); err.span_label( new_loan.span, format!("{} borrow occurs here{}", @@ -645,9 +634,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) { UseOk => { } UseWhileBorrowed(loan_path, loan_span) => { - struct_span_err!(self.bccx, span, E0503, - "cannot use `{}` because it was mutably borrowed", - &self.bccx.loan_path_to_string(copy_path)) + let desc = self.bccx.loan_path_to_string(copy_path); + self.bccx.cannot_use_when_mutably_borrowed(span, &desc, Origin::Ast) .span_label(loan_span, format!("borrow of `{}` occurs here", &self.bccx.loan_path_to_string(&loan_path)) @@ -673,9 +661,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { UseWhileBorrowed(loan_path, loan_span) => { let mut err = match move_kind { move_data::Captured => { - let mut err = struct_span_err!(self.bccx, span, E0504, - "cannot move `{}` into closure because it is borrowed", - &self.bccx.loan_path_to_string(move_path)); + let mut err = self.bccx.cannot_move_into_closure( + span, &self.bccx.loan_path_to_string(move_path), Origin::Ast); err.span_label( loan_span, format!("borrow of `{}` occurs here", @@ -690,9 +677,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { move_data::Declared | move_data::MoveExpr | move_data::MovePat => { - let mut err = struct_span_err!(self.bccx, span, E0505, - "cannot move out of `{}` because it is borrowed", - &self.bccx.loan_path_to_string(move_path)); + let desc = self.bccx.loan_path_to_string(move_path); + let mut err = self.bccx.cannot_move_when_borrowed(span, &desc, Origin::Ast); err.span_label( loan_span, format!("borrow of `{}` occurs here", @@ -874,9 +860,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { span: Span, loan_path: &LoanPath<'tcx>, loan: &Loan) { - struct_span_err!(self.bccx, span, E0506, - "cannot assign to `{}` because it is borrowed", - self.bccx.loan_path_to_string(loan_path)) + self.bccx.cannot_assign_to_borrowed( + span, &self.bccx.loan_path_to_string(loan_path), Origin::Ast) .span_label(loan.span, format!("borrow of `{}` occurs here", self.bccx.loan_path_to_string(loan_path))) diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 3d98c2a23dc..78787627889 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -68,19 +68,7 @@ fn get_pattern_source<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &Pat) -> Patte }); PatternSource::MatchExpr(e) } - NodeStmt(ref s) => { - // the enclosing statement must be a `let` or something else - match s.node { - StmtDecl(ref decl, _) => { - match decl.node { - DeclLocal(ref local) => PatternSource::LetDecl(local), - _ => return PatternSource::Other, - } - } - _ => return PatternSource::Other, - } - } - + NodeLocal(local) => PatternSource::LetDecl(local), _ => return PatternSource::Other, } @@ -106,44 +94,13 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, }; let move_info = GatherMoveInfo { id: move_expr_id, - kind: kind, - cmt: cmt, + kind, + cmt, span_path_opt: None, }; gather_move(bccx, move_data, move_error_collector, move_info); } -pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - move_data: &MoveData<'tcx>, - _move_error_collector: &mut MoveErrorCollector<'tcx>, - move_pat: &hir::Pat, - cmt: mc::cmt<'tcx>, - mode: euv::MatchMode) { - let tcx = bccx.tcx; - debug!("gather_match_variant(move_pat={}, cmt={:?}, mode={:?})", - move_pat.id, cmt, mode); - - let opt_lp = opt_loan_path(&cmt); - match opt_lp { - Some(lp) => { - match lp.kind { - LpDowncast(ref base_lp, _) => - move_data.add_variant_match( - tcx, lp.clone(), move_pat.id, base_lp.clone(), mode), - _ => bug!("should only call gather_match_variant \ - for cat_downcast cmt"), - } - } - None => { - // We get None when input to match is non-path (e.g. - // temporary result like a function call). Since no - // loan-path is being matched, no need to record a - // downcast. - return; - } - } -} - pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>, @@ -163,7 +120,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let move_info = GatherMoveInfo { id: move_pat.id, kind: MovePat, - cmt: cmt, + cmt, span_path_opt: pat_span_path_opt, }; diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 89c60da3969..22de3c75913 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -37,10 +37,10 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, debug!("guarantee_lifetime(cmt={:?}, loan_region={:?})", cmt, loan_region); let ctxt = GuaranteeLifetimeContext {bccx: bccx, - item_scope: item_scope, - span: span, - cause: cause, - loan_region: loan_region, + item_scope, + span, + cause, + loan_region, cmt_original: cmt.clone()}; ctxt.check(&cmt, None) } diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 35af83c8ae2..00ebf5de44a 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -41,7 +41,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let def_id = bccx.tcx.hir.body_owner_def_id(body); let param_env = bccx.tcx.param_env(def_id); let mut glcx = GatherLoanCtxt { - bccx: bccx, + bccx, all_loans: Vec::new(), item_ub: region::CodeExtent::Misc(body.node_id), move_data: MoveData::new(), @@ -94,12 +94,6 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { matched_pat, cmt, mode); - - if let Categorization::Downcast(..) = cmt.cat { - gather_moves::gather_match_variant( - self.bccx, &self.move_data, &mut self.move_error_collector, - matched_pat, cmt, mode); - } } fn consume_pat(&mut self, @@ -230,8 +224,8 @@ fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, // Only mutable data can be lent as mutable. if !cmt.mutbl.is_mutable() { Err(bccx.report(BckError { span: borrow_span, - cause: cause, - cmt: cmt, + cause, + cmt, code: err_mutbl })) } else { Ok(()) @@ -389,13 +383,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { Loan { index: self.all_loans.len(), - loan_path: loan_path, + loan_path, kind: req_kind, - gen_scope: gen_scope, - kill_scope: kill_scope, + gen_scope, + kill_scope, span: borrow_span, - restricted_paths: restricted_paths, - cause: cause, + restricted_paths, + cause, } } }; @@ -423,13 +417,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // let all_loans = &mut *self.all_loans; // FIXME(#5074) // Loan { // index: all_loans.len(), - // loan_path: loan_path, - // cmt: cmt, + // loan_path, + // cmt, // mutbl: ConstMutability, // gen_scope: borrow_id, - // kill_scope: kill_scope, + // kill_scope, // span: borrow_span, - // restrictions: restrictions + // restrictions, // } // } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs index bfd883be848..57b92eb8f88 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs @@ -49,8 +49,8 @@ impl<'tcx> MoveError<'tcx> { move_to: Option<MovePlace<'tcx>>) -> MoveError<'tcx> { MoveError { - move_from: move_from, - move_to: move_to, + move_from, + move_to, } } } @@ -153,20 +153,19 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, } Categorization::Interior(ref b, mc::InteriorElement(ik)) => { - match (&b.ty.sty, ik) { - (&ty::TySlice(..), _) | - (_, Kind::Index) => { - let mut err = struct_span_err!(bccx, move_from.span, E0508, - "cannot move out of type `{}`, \ - a non-copy array", - b.ty); - err.span_label(move_from.span, "cannot move out of here"); - err - } - (_, Kind::Pattern) => { + let type_name = match (&b.ty.sty, ik) { + (&ty::TyArray(_, _), Kind::Index) => "array", + (&ty::TySlice(_), _) => "slice", + _ => { span_bug!(move_from.span, "this path should not cause illegal move"); - } - } + }, + }; + let mut err = struct_span_err!(bccx, move_from.span, E0508, + "cannot move out of type `{}`, \ + a non-copy {}", + b.ty, type_name); + err.span_label(move_from.span, "cannot move out of here"); + err } Categorization::Downcast(ref b, _) | diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index b7965f81b88..bc01f22d388 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -34,10 +34,10 @@ pub fn compute_restrictions<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, loan_region: ty::Region<'tcx>) -> RestrictionResult<'tcx> { let ctxt = RestrictionsContext { - bccx: bccx, - span: span, - cause: cause, - loan_region: loan_region, + bccx, + span, + cause, + loan_region, }; ctxt.restrict(cmt) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 412af05f5bd..38336655f21 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -37,6 +37,8 @@ use rustc::middle::free_region::RegionRelations; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; +use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; + use std::fmt; use std::rc::Rc; use std::hash::{Hash, Hasher}; @@ -180,7 +182,7 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc id_range, body); - Some(AnalysisData { all_loans: all_loans, + Some(AnalysisData { all_loans, loans: loan_dfcx, move_data:flowed_moves }) } @@ -218,6 +220,25 @@ pub struct BorrowckCtxt<'a, 'tcx: 'a> { owner_def_id: DefId, } +impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> { + fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self, + sp: S, + msg: &str, + code: &str) + -> DiagnosticBuilder<'a> + { + self.tcx.sess.struct_span_err_with_code(sp, msg, code) + } + + fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'a> + { + self.tcx.sess.struct_span_err(sp, msg) + } +} + /////////////////////////////////////////////////////////////////////////// // Loans and loan paths @@ -549,14 +570,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { move_data::Declared => { // If this is an uninitialized variable, just emit a simple warning // and return. - struct_span_err!( - self.tcx.sess, use_span, E0381, - "{} of possibly uninitialized variable: `{}`", - verb, - self.loan_path_to_string(lp)) - .span_label(use_span, format!("use of possibly uninitialized `{}`", - self.loan_path_to_string(lp))) - .emit(); + self.cannot_act_on_uninitialized_variable(use_span, + verb, + &self.loan_path_to_string(lp), + Origin::Ast) + .span_label(use_span, format!("use of possibly uninitialized `{}`", + self.loan_path_to_string(lp))) + .emit(); return; } _ => { @@ -683,10 +703,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { lp: &LoanPath<'tcx>, assign: &move_data::Assignment) { - let mut err = struct_span_err!( - self.tcx.sess, span, E0384, - "re-assignment of immutable variable `{}`", - self.loan_path_to_string(lp)); + let mut err = self.cannot_reassign_immutable(span, + &self.loan_path_to_string(lp), + Origin::Ast); err.span_label(span, "re-assignment of immutable variable"); if span != assign.span { err.span_label(assign.span, format!("first assignment to `{}`", @@ -695,15 +714,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { err.emit(); } - pub fn span_err(&self, s: Span, m: &str) { - self.tcx.sess.span_err(s, m); - } - - pub fn struct_span_err<S: Into<MultiSpan>>(&self, s: S, m: &str) - -> DiagnosticBuilder<'a> { - self.tcx.sess.struct_span_err(s, m) - } - pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self, s: S, msg: &str, @@ -712,10 +722,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.struct_span_err_with_code(s, msg, code) } - pub fn span_err_with_code<S: Into<MultiSpan>>(&self, s: S, msg: &str, code: &str) { - self.tcx.sess.span_err_with_code(s, msg, code); - } - fn bckerr_to_diag(&self, err: &BckError<'tcx>) -> DiagnosticBuilder<'a> { let span = err.span.clone(); @@ -897,7 +903,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn local_binding_mode(&self, node_id: ast::NodeId) -> ty::BindingMode { let pat = match self.tcx.hir.get(node_id) { - hir_map::Node::NodeLocal(pat) => pat, + hir_map::Node::NodeBinding(pat) => pat, node => bug!("bad node for local: {:?}", node) }; diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index fd80e8320d6..217bd6e6ca1 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -53,10 +53,6 @@ pub struct MoveData<'tcx> { /// kill move bits. pub path_assignments: RefCell<Vec<Assignment>>, - /// Enum variant matched within a pattern on some match arm, like - /// `SomeStruct{ f: Variant1(x, y) } => ...` - pub variant_matches: RefCell<Vec<VariantMatch>>, - /// Assignments to a variable or path, like `x = foo`, but not `x += foo`. pub assignee_ids: RefCell<NodeSet>, } @@ -161,21 +157,6 @@ pub struct Assignment { pub assignee_id: ast::NodeId, } -#[derive(Copy, Clone)] -pub struct VariantMatch { - /// downcast to the variant. - pub path: MovePathIndex, - - /// path being downcast to the variant. - pub base_path: MovePathIndex, - - /// id where variant's pattern occurs - pub id: ast::NodeId, - - /// says if variant established by move (and why), by copy, or by borrow. - pub mode: euv::MatchMode -} - #[derive(Clone, Copy)] pub struct MoveDataFlowOperator; @@ -215,7 +196,6 @@ impl<'a, 'tcx> MoveData<'tcx> { moves: RefCell::new(Vec::new()), path_assignments: RefCell::new(Vec::new()), var_assignments: RefCell::new(Vec::new()), - variant_matches: RefCell::new(Vec::new()), assignee_ids: RefCell::new(NodeSet()), } } @@ -310,7 +290,7 @@ impl<'a, 'tcx> MoveData<'tcx> { parent: parent_index, first_move: InvalidMoveIndex, first_child: InvalidMovePathIndex, - next_sibling: next_sibling, + next_sibling, }); index @@ -408,9 +388,9 @@ impl<'a, 'tcx> MoveData<'tcx> { self.moves.borrow_mut().push(Move { path: path_index, - id: id, - kind: kind, - next_move: next_move + id, + kind, + next_move, }); } @@ -468,8 +448,8 @@ impl<'a, 'tcx> MoveData<'tcx> { let assignment = Assignment { path: path_index, id: assign_id, - span: span, - assignee_id: assignee_id, + span, + assignee_id, }; if self.is_var_path(path_index) { @@ -485,31 +465,6 @@ impl<'a, 'tcx> MoveData<'tcx> { } } - /// Adds a new record for a match of `base_lp`, downcast to - /// variant `lp`, that occurs at location `pattern_id`. (One - /// should be able to recover the span info from the - /// `pattern_id` and the hir_map, I think.) - pub fn add_variant_match(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - lp: Rc<LoanPath<'tcx>>, - pattern_id: ast::NodeId, - base_lp: Rc<LoanPath<'tcx>>, - mode: euv::MatchMode) { - debug!("add_variant_match(lp={:?}, pattern_id={})", - lp, pattern_id); - - let path_index = self.move_path(tcx, lp.clone()); - let base_path_index = self.move_path(tcx, base_lp.clone()); - - let variant_match = VariantMatch { - path: path_index, - base_path: base_path_index, - id: pattern_id, - mode: mode, - }; - - self.variant_matches.borrow_mut().push(variant_match); - } - /// Adds the gen/kills for the various moves and /// assignments into the provided data flow contexts. /// Moves are generated by moves and killed by assignments and @@ -680,9 +635,9 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { dfcx_assign.propagate(cfg, body); FlowedMoveData { - move_data: move_data, - dfcx_moves: dfcx_moves, - dfcx_assign: dfcx_assign, + move_data, + dfcx_moves, + dfcx_assign, } } diff --git a/src/librustc_borrowck/diagnostics.rs b/src/librustc_borrowck/diagnostics.rs index fea9d0d6f13..1f1fc4cc65f 100644 --- a/src/librustc_borrowck/diagnostics.rs +++ b/src/librustc_borrowck/diagnostics.rs @@ -63,27 +63,6 @@ Now that the closure has its own copy of the data, there's no need to worry about safety. "##, -E0381: r##" -It is not allowed to use or capture an uninitialized variable. For example: - -```compile_fail,E0381 -fn main() { - let x: i32; - let y = x; // error, use of possibly uninitialized variable -} -``` - -To fix this, ensure that any declared variables are initialized before being -used. Example: - -``` -fn main() { - let x: i32 = 0; - let y = x; // ok! -} -``` -"##, - E0382: r##" This error occurs when an attempt is made to use a variable after its contents have been moved elsewhere. For example: @@ -182,28 +161,6 @@ x = Foo { a: 2 }; ``` "##, -E0384: r##" -This error occurs when an attempt is made to reassign an immutable variable. -For example: - -```compile_fail,E0384 -fn main() { - let x = 3; - x = 5; // error, reassignment of immutable variable -} -``` - -By default, variables in Rust are immutable. To fix this error, add the keyword -`mut` after the keyword `let` when declaring the variable. For example: - -``` -fn main() { - let mut x = 3; - x = 5; -} -``` -"##, - /*E0386: r##" This error occurs when an attempt is made to mutate the target of a mutable reference stored inside an immutable container. @@ -360,512 +317,6 @@ fn main() { ``` "##, -E0499: r##" -A variable was borrowed as mutable more than once. Erroneous code example: - -```compile_fail,E0499 -let mut i = 0; -let mut x = &mut i; -let mut a = &mut i; -// error: cannot borrow `i` as mutable more than once at a time -``` - -Please note that in rust, you can either have many immutable references, or one -mutable reference. Take a look at -https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html -for more information. Example: - - -``` -let mut i = 0; -let mut x = &mut i; // ok! - -// or: -let mut i = 0; -let a = &i; // ok! -let b = &i; // still ok! -let c = &i; // still ok! -``` -"##, - -E0500: r##" -A borrowed variable was used in another closure. Example of erroneous code: - -```compile_fail -fn you_know_nothing(jon_snow: &mut i32) { - let nights_watch = || { - *jon_snow = 2; - }; - let starks = || { - *jon_snow = 3; // error: closure requires unique access to `jon_snow` - // but it is already borrowed - }; -} -``` - -In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it -cannot be borrowed by the `starks` closure at the same time. To fix this issue, -you can put the closure in its own scope: - -``` -fn you_know_nothing(jon_snow: &mut i32) { - { - let nights_watch = || { - *jon_snow = 2; - }; - } // At this point, `jon_snow` is free. - let starks = || { - *jon_snow = 3; - }; -} -``` - -Or, if the type implements the `Clone` trait, you can clone it between -closures: - -``` -fn you_know_nothing(jon_snow: &mut i32) { - let mut jon_copy = jon_snow.clone(); - let nights_watch = || { - jon_copy = 2; - }; - let starks = || { - *jon_snow = 3; - }; -} -``` -"##, - -E0501: r##" -This error indicates that a mutable variable is being used while it is still -captured by a closure. Because the closure has borrowed the variable, it is not -available for use until the closure goes out of scope. - -Note that a capture will either move or borrow a variable, but in this -situation, the closure is borrowing the variable. Take a look at -http://rustbyexample.com/fn/closures/capture.html for more information about -capturing. - -Example of erroneous code: - -```compile_fail,E0501 -fn inside_closure(x: &mut i32) { - // Actions which require unique access -} - -fn outside_closure(x: &mut i32) { - // Actions which require unique access -} - -fn foo(a: &mut i32) { - let bar = || { - inside_closure(a) - }; - outside_closure(a); // error: cannot borrow `*a` as mutable because previous - // closure requires unique access. -} -``` - -To fix this error, you can place the closure in its own scope: - -``` -fn inside_closure(x: &mut i32) {} -fn outside_closure(x: &mut i32) {} - -fn foo(a: &mut i32) { - { - let bar = || { - inside_closure(a) - }; - } // borrow on `a` ends. - outside_closure(a); // ok! -} -``` - -Or you can pass the variable as a parameter to the closure: - -``` -fn inside_closure(x: &mut i32) {} -fn outside_closure(x: &mut i32) {} - -fn foo(a: &mut i32) { - let bar = |s: &mut i32| { - inside_closure(s) - }; - outside_closure(a); - bar(a); -} -``` - -It may be possible to define the closure later: - -``` -fn inside_closure(x: &mut i32) {} -fn outside_closure(x: &mut i32) {} - -fn foo(a: &mut i32) { - outside_closure(a); - let bar = || { - inside_closure(a) - }; -} -``` -"##, - -E0502: r##" -This error indicates that you are trying to borrow a variable as mutable when it -has already been borrowed as immutable. - -Example of erroneous code: - -```compile_fail,E0502 -fn bar(x: &mut i32) {} -fn foo(a: &mut i32) { - let ref y = a; // a is borrowed as immutable. - bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed - // as immutable -} -``` - -To fix this error, ensure that you don't have any other references to the -variable before trying to access it mutably: - -``` -fn bar(x: &mut i32) {} -fn foo(a: &mut i32) { - bar(a); - let ref y = a; // ok! -} -``` - -For more information on the rust ownership system, take a look at -https://doc.rust-lang.org/book/first-edition/references-and-borrowing.html. -"##, - -E0503: r##" -A value was used after it was mutably borrowed. - -Example of erroneous code: - -```compile_fail,E0503 -fn main() { - let mut value = 3; - // Create a mutable borrow of `value`. This borrow - // lives until the end of this function. - let _borrow = &mut value; - let _sum = value + 1; // error: cannot use `value` because - // it was mutably borrowed -} -``` - -In this example, `value` is mutably borrowed by `borrow` and cannot be -used to calculate `sum`. This is not possible because this would violate -Rust's mutability rules. - -You can fix this error by limiting the scope of the borrow: - -``` -fn main() { - let mut value = 3; - // By creating a new block, you can limit the scope - // of the reference. - { - let _borrow = &mut value; // Use `_borrow` inside this block. - } - // The block has ended and with it the borrow. - // You can now use `value` again. - let _sum = value + 1; -} -``` - -Or by cloning `value` before borrowing it: - -``` -fn main() { - let mut value = 3; - // We clone `value`, creating a copy. - let value_cloned = value.clone(); - // The mutable borrow is a reference to `value` and - // not to `value_cloned`... - let _borrow = &mut value; - // ... which means we can still use `value_cloned`, - let _sum = value_cloned + 1; - // even though the borrow only ends here. -} -``` - -You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html -"##, - -E0504: r##" -This error occurs when an attempt is made to move a borrowed variable into a -closure. - -Example of erroneous code: - -```compile_fail,E0504 -struct FancyNum { - num: u8, -} - -fn main() { - let fancy_num = FancyNum { num: 5 }; - let fancy_ref = &fancy_num; - - let x = move || { - println!("child function: {}", fancy_num.num); - // error: cannot move `fancy_num` into closure because it is borrowed - }; - - x(); - println!("main function: {}", fancy_ref.num); -} -``` - -Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into -the closure `x`. There is no way to move a value into a closure while it is -borrowed, as that would invalidate the borrow. - -If the closure can't outlive the value being moved, try using a reference -rather than moving: - -``` -struct FancyNum { - num: u8, -} - -fn main() { - let fancy_num = FancyNum { num: 5 }; - let fancy_ref = &fancy_num; - - let x = move || { - // fancy_ref is usable here because it doesn't move `fancy_num` - println!("child function: {}", fancy_ref.num); - }; - - x(); - - println!("main function: {}", fancy_num.num); -} -``` - -If the value has to be borrowed and then moved, try limiting the lifetime of -the borrow using a scoped block: - -``` -struct FancyNum { - num: u8, -} - -fn main() { - let fancy_num = FancyNum { num: 5 }; - - { - let fancy_ref = &fancy_num; - println!("main function: {}", fancy_ref.num); - // `fancy_ref` goes out of scope here - } - - let x = move || { - // `fancy_num` can be moved now (no more references exist) - println!("child function: {}", fancy_num.num); - }; - - x(); -} -``` - -If the lifetime of a reference isn't enough, such as in the case of threading, -consider using an `Arc` to create a reference-counted value: - -``` -use std::sync::Arc; -use std::thread; - -struct FancyNum { - num: u8, -} - -fn main() { - let fancy_ref1 = Arc::new(FancyNum { num: 5 }); - let fancy_ref2 = fancy_ref1.clone(); - - let x = thread::spawn(move || { - // `fancy_ref1` can be moved and has a `'static` lifetime - println!("child thread: {}", fancy_ref1.num); - }); - - x.join().expect("child thread should finish"); - println!("main thread: {}", fancy_ref2.num); -} -``` -"##, - -E0505: r##" -A value was moved out while it was still borrowed. - -Erroneous code example: - -```compile_fail,E0505 -struct Value {} - -fn eat(val: Value) {} - -fn main() { - let x = Value{}; - { - let _ref_to_val: &Value = &x; - eat(x); - } -} -``` - -Here, the function `eat` takes the ownership of `x`. However, -`x` cannot be moved because it was borrowed to `_ref_to_val`. -To fix that you can do few different things: - -* Try to avoid moving the variable. -* Release borrow before move. -* Implement the `Copy` trait on the type. - -Examples: - -``` -struct Value {} - -fn eat(val: &Value) {} - -fn main() { - let x = Value{}; - { - let _ref_to_val: &Value = &x; - eat(&x); // pass by reference, if it's possible - } -} -``` - -Or: - -``` -struct Value {} - -fn eat(val: Value) {} - -fn main() { - let x = Value{}; - { - let _ref_to_val: &Value = &x; - } - eat(x); // release borrow and then move it. -} -``` - -Or: - -``` -#[derive(Clone, Copy)] // implement Copy trait -struct Value {} - -fn eat(val: Value) {} - -fn main() { - let x = Value{}; - { - let _ref_to_val: &Value = &x; - eat(x); // it will be copied here. - } -} -``` - -You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/book/first-edition/references-and-borrowing.html -"##, - -E0506: r##" -This error occurs when an attempt is made to assign to a borrowed value. - -Example of erroneous code: - -```compile_fail,E0506 -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy_num = FancyNum { num: 5 }; - let fancy_ref = &fancy_num; - fancy_num = FancyNum { num: 6 }; - // error: cannot assign to `fancy_num` because it is borrowed - - println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); -} -``` - -Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't -be assigned to a new value as it would invalidate the reference. - -Alternatively, we can move out of `fancy_num` into a second `fancy_num`: - -``` -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy_num = FancyNum { num: 5 }; - let moved_num = fancy_num; - fancy_num = FancyNum { num: 6 }; - - println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num); -} -``` - -If the value has to be borrowed, try limiting the lifetime of the borrow using -a scoped block: - -``` -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy_num = FancyNum { num: 5 }; - - { - let fancy_ref = &fancy_num; - println!("Ref: {}", fancy_ref.num); - } - - // Works because `fancy_ref` is no longer in scope - fancy_num = FancyNum { num: 6 }; - println!("Num: {}", fancy_num.num); -} -``` - -Or by moving the reference into a function: - -``` -struct FancyNum { - num: u8, -} - -fn main() { - let mut fancy_num = FancyNum { num: 5 }; - - print_fancy_ref(&fancy_num); - - // Works because function borrow has ended - fancy_num = FancyNum { num: 6 }; - println!("Num: {}", fancy_num.num); -} - -fn print_fancy_ref(fancy_ref: &FancyNum){ - println!("Ref: {}", fancy_ref.num); -} -``` -"##, - E0507: r##" You tried to move out of a value which was borrowed. Erroneous code example: @@ -1205,7 +656,6 @@ x.x = Some(&y); register_diagnostics! { // E0385, // {} in an aliasable location - E0524, // two closures require unique access to `..` at the same time E0594, // cannot assign to {} E0598, // lifetime of {} is too short to guarantee its contents can be... } diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index 7a63592828f..9bedbfed5db 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_borrowck"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -31,17 +28,14 @@ extern crate rustc_errors as errors; extern crate graphviz as dot; #[macro_use] extern crate rustc; -extern crate rustc_data_structures; extern crate rustc_mir; -extern crate core; // for NonZero pub use borrowck::check_crate; pub use borrowck::build_borrowck_dataflow_data_for_fn; -pub use borrowck::{AnalysisData, BorrowckCtxt}; // NB: This module needs to be declared first so diagnostics are // registered before they are used. -pub mod diagnostics; +mod diagnostics; mod borrowck; diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index bae44c0047e..bc9aa9665c1 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -166,8 +166,8 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { let pattern_arena = TypedArena::new(); f(MatchCheckCtxt { - tcx: tcx, - module: module, + tcx, + module, pattern_arena: &pattern_arena, byte_array_map: FxHashMap(), }) @@ -296,7 +296,7 @@ impl<'tcx> Witness<'tcx> { let sub_pattern_tys = constructor_sub_pattern_tys(cx, ctor, ty); self.0.extend(sub_pattern_tys.into_iter().map(|ty| { Pattern { - ty: ty, + ty, span: DUMMY_SP, kind: box PatternKind::Wild, } @@ -344,7 +344,7 @@ impl<'tcx> Witness<'tcx> { if adt.variants.len() > 1 { PatternKind::Variant { adt_def: adt, - substs: substs, + substs, variant_index: ctor.variant_index_for_adt(adt), subpatterns: pats } @@ -378,7 +378,7 @@ impl<'tcx> Witness<'tcx> { }; self.0.push(Pattern { - ty: ty, + ty, span: DUMMY_SP, kind: Box::new(pat), }); @@ -673,7 +673,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>( let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty); let wild_patterns_owned: Vec<_> = sub_pat_tys.iter().map(|ty| { Pattern { - ty: ty, + ty, span: DUMMY_SP, kind: box PatternKind::Wild, } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index ea7deef4724..2bed1950afc 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -524,7 +524,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, /// FIXME: this should be done by borrowck. fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) { let mut checker = MutationChecker { - cx: cx, + cx, }; ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_maps, cx.tables) .walk_expr(guard); diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 20ca218571c..c7def0b834c 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -379,7 +379,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, tcx, param_env: cx.param_env, tables: tcx.typeck_tables_of(def_id), - substs: substs, + substs, fn_args: Some(call_args) }; callee_cx.eval(&body.value)? diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs index 5a61f35ed1c..9fedee80d46 100644 --- a/src/librustc_const_eval/lib.rs +++ b/src/librustc_const_eval/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_const_eval"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -41,7 +38,7 @@ extern crate syntax_pos; // NB: This module needs to be declared first so diagnostics are // registered before they are used. -pub mod diagnostics; +mod diagnostics; mod eval; mod _match; diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index d151e817040..ba79f775ef7 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -407,8 +407,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } PatternKind::Binding { - mutability: mutability, - mode: mode, + mutability, + mode, name: ident.node, var: id, ty: var_ty, @@ -470,7 +470,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { Pattern { span: pat.span, - ty: ty, + ty, kind: Box::new(kind), } } @@ -569,10 +569,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { _ => bug!("inappropriate type for def: {:?}", ty.sty), }; PatternKind::Variant { - adt_def: adt_def, - substs: substs, + adt_def, + substs, variant_index: adt_def.variant_index_with_id(variant_id), - subpatterns: subpatterns, + subpatterns, } } else { PatternKind::Leaf { subpatterns: subpatterns } @@ -626,8 +626,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; Pattern { - span: span, - ty: ty, + span, + ty, kind: Box::new(kind), } } @@ -762,7 +762,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; Pattern { - span: span, + span, ty: pat_ty, kind: Box::new(kind), } diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs index 719f6b6a7b3..b67048939e4 100644 --- a/src/librustc_const_math/float.rs +++ b/src/librustc_const_math/float.rs @@ -37,13 +37,6 @@ impl ConstFloat { self.ty.ty_to_string() } - pub fn is_nan(&self) -> bool { - match self.ty { - ast::FloatTy::F32 => Single::from_bits(self.bits).is_nan(), - ast::FloatTy::F64 => Double::from_bits(self.bits).is_nan(), - } - } - /// Compares the values if they are of the same type pub fn try_cmp(self, rhs: Self) -> Result<Ordering, ConstMathErr> { match (self.ty, rhs.ty) { diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 3947edecb5a..93b70ef8e4a 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_const_math"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] diff --git a/src/librustc_data_structures/accumulate_vec.rs b/src/librustc_data_structures/accumulate_vec.rs index c03c2890ba3..52306de74cb 100644 --- a/src/librustc_data_structures/accumulate_vec.rs +++ b/src/librustc_data_structures/accumulate_vec.rs @@ -13,7 +13,7 @@ //! Space for up to N elements is provided on the stack. If more elements are collected, Vec is //! used to store the values on the heap. //! -//! The N above is determined by Array's implementor, by way of an associatated constant. +//! The N above is determined by Array's implementor, by way of an associated constant. use std::ops::{Deref, DerefMut}; use std::iter::{self, IntoIterator, FromIterator}; diff --git a/src/librustc_data_structures/array_vec.rs b/src/librustc_data_structures/array_vec.rs index df660d08603..1e67461e055 100644 --- a/src/librustc_data_structures/array_vec.rs +++ b/src/librustc_data_structures/array_vec.rs @@ -281,8 +281,8 @@ impl<A: Array> IntoIterator for ArrayVec<A> { let indices = 0..self.count; mem::forget(self); Iter { - indices: indices, - store: store, + indices, + store, } } } diff --git a/src/librustc_data_structures/bitvec.rs b/src/librustc_data_structures/bitvec.rs index 7fc59be780f..7331016c2d2 100644 --- a/src/librustc_data_structures/bitvec.rs +++ b/src/librustc_data_structures/bitvec.rs @@ -151,7 +151,7 @@ impl BitMatrix { // element. Round up to an even number of u64s. let u64s_per_row = u64s(columns); BitMatrix { - columns: columns, + columns, vector: vec![0; rows * u64s_per_row], } } diff --git a/src/librustc_data_structures/blake2b.rs b/src/librustc_data_structures/blake2b.rs index 5adeef1ab3a..6b8bf8df0d3 100644 --- a/src/librustc_data_structures/blake2b.rs +++ b/src/librustc_data_structures/blake2b.rs @@ -24,7 +24,7 @@ use std::mem; use std::slice; #[repr(C)] -pub struct Blake2bCtx { +struct Blake2bCtx { b: [u8; 128], h: [u64; 8], t: [u64; 2], diff --git a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs index ab675db2150..90670517f59 100644 --- a/src/librustc_data_structures/control_flow_graph/dominators/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/dominators/mod.rs @@ -71,8 +71,8 @@ pub fn dominators_given_rpo<G: ControlFlowGraph>(graph: &G, } Dominators { - post_order_rank: post_order_rank, - immediate_dominators: immediate_dominators, + post_order_rank, + immediate_dominators, } } @@ -134,56 +134,10 @@ impl<Node: Idx> Dominators<Node> { self.dominators(node).any(|n| n == dom) } - pub fn mutual_dominator_node(&self, node1: Node, node2: Node) -> Node { - assert!(self.is_reachable(node1), - "node {:?} is not reachable", - node1); - assert!(self.is_reachable(node2), - "node {:?} is not reachable", - node2); - intersect::<Node>(&self.post_order_rank, - &self.immediate_dominators, - node1, - node2) - } - - pub fn mutual_dominator<I>(&self, iter: I) -> Option<Node> - where I: IntoIterator<Item = Node> - { - let mut iter = iter.into_iter(); - iter.next() - .map(|dom| iter.fold(dom, |dom, node| self.mutual_dominator_node(dom, node))) - } - - pub fn all_immediate_dominators(&self) -> &IndexVec<Node, Option<Node>> { + #[cfg(test)] + fn all_immediate_dominators(&self) -> &IndexVec<Node, Option<Node>> { &self.immediate_dominators } - - pub fn dominator_tree(&self) -> DominatorTree<Node> { - let elem: Vec<Node> = Vec::new(); - let mut children: IndexVec<Node, Vec<Node>> = - IndexVec::from_elem_n(elem, self.immediate_dominators.len()); - let mut root = None; - for (index, immed_dom) in self.immediate_dominators.iter().enumerate() { - let node = Node::new(index); - match *immed_dom { - None => { - // node not reachable - } - Some(immed_dom) => { - if node == immed_dom { - root = Some(node); - } else { - children[immed_dom].push(node); - } - } - } - } - DominatorTree { - root: root.unwrap(), - children: children, - } - } } pub struct Iter<'dom, Node: Idx + 'dom> { @@ -215,38 +169,9 @@ pub struct DominatorTree<N: Idx> { } impl<Node: Idx> DominatorTree<Node> { - pub fn root(&self) -> Node { - self.root - } - pub fn children(&self, node: Node) -> &[Node] { &self.children[node] } - - pub fn iter_children_of(&self, node: Node) -> IterChildrenOf<Node> { - IterChildrenOf { - tree: self, - stack: vec![node], - } - } -} - -pub struct IterChildrenOf<'iter, Node: Idx + 'iter> { - tree: &'iter DominatorTree<Node>, - stack: Vec<Node>, -} - -impl<'iter, Node: Idx> Iterator for IterChildrenOf<'iter, Node> { - type Item = Node; - - fn next(&mut self) -> Option<Node> { - if let Some(node) = self.stack.pop() { - self.stack.extend(self.tree.children(node)); - Some(node) - } else { - None - } - } } impl<Node: Idx> fmt::Debug for DominatorTree<Node> { diff --git a/src/librustc_data_structures/control_flow_graph/iterate/mod.rs b/src/librustc_data_structures/control_flow_graph/iterate/mod.rs index 11b557cbcad..2d70b406342 100644 --- a/src/librustc_data_structures/control_flow_graph/iterate/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/iterate/mod.rs @@ -47,22 +47,6 @@ fn post_order_walk<G: ControlFlowGraph>(graph: &G, result.push(node); } -pub fn pre_order_walk<G: ControlFlowGraph>(graph: &G, - node: G::Node, - result: &mut Vec<G::Node>, - visited: &mut IndexVec<G::Node, bool>) { - if visited[node] { - return; - } - visited[node] = true; - - result.push(node); - - for successor in graph.successors(node) { - pre_order_walk(graph, successor, result, visited); - } -} - pub fn reverse_post_order<G: ControlFlowGraph>(graph: &G, start_node: G::Node) -> Vec<G::Node> { let mut vec = post_order_from(graph, start_node); vec.reverse(); diff --git a/src/librustc_data_structures/control_flow_graph/iterate/test.rs b/src/librustc_data_structures/control_flow_graph/iterate/test.rs index dca45602f17..100881ddfdd 100644 --- a/src/librustc_data_structures/control_flow_graph/iterate/test.rs +++ b/src/librustc_data_structures/control_flow_graph/iterate/test.rs @@ -9,7 +9,6 @@ // except according to those terms. use super::super::test::TestGraph; -use super::super::transpose::TransposedGraph; use super::*; @@ -20,22 +19,3 @@ fn diamond_post_order() { let result = post_order_from(&graph, 0); assert_eq!(result, vec![3, 1, 2, 0]); } - - -#[test] -fn rev_post_order_inner_loop() { - // 0 -> 1 -> 2 -> 3 -> 5 - // ^ ^ v | - // | 6 <- 4 | - // +-----------------+ - let graph = TestGraph::new(0, - &[(0, 1), (1, 2), (2, 3), (3, 5), (3, 1), (2, 4), (4, 6), (6, 2)]); - - let rev_graph = TransposedGraph::new(&graph); - - let result = post_order_from_to(&rev_graph, 6, Some(2)); - assert_eq!(result, vec![4, 6]); - - let result = post_order_from_to(&rev_graph, 3, Some(1)); - assert_eq!(result, vec![4, 6, 2, 3]); -} diff --git a/src/librustc_data_structures/control_flow_graph/mod.rs b/src/librustc_data_structures/control_flow_graph/mod.rs index eb6839df627..7bf776675c6 100644 --- a/src/librustc_data_structures/control_flow_graph/mod.rs +++ b/src/librustc_data_structures/control_flow_graph/mod.rs @@ -9,13 +9,10 @@ // except according to those terms. use super::indexed_vec::Idx; -pub use std::slice::Iter; pub mod dominators; pub mod iterate; -pub mod reachable; mod reference; -pub mod transpose; #[cfg(test)] mod test; diff --git a/src/librustc_data_structures/control_flow_graph/reachable/mod.rs b/src/librustc_data_structures/control_flow_graph/reachable/mod.rs deleted file mode 100644 index 24210ebb95d..00000000000 --- a/src/librustc_data_structures/control_flow_graph/reachable/mod.rs +++ /dev/null @@ -1,62 +0,0 @@ -// 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. - -//! Compute reachability using a simple dataflow propagation. -//! Store end-result in a big NxN bit matrix. - -use super::ControlFlowGraph; -use super::super::bitvec::BitVector; -use super::iterate::reverse_post_order; -use super::super::indexed_vec::{IndexVec, Idx}; - -#[cfg(test)] -mod test; - -pub fn reachable<G: ControlFlowGraph>(graph: &G) -> Reachability<G::Node> { - let reverse_post_order = reverse_post_order(graph, graph.start_node()); - reachable_given_rpo(graph, &reverse_post_order) -} - -pub fn reachable_given_rpo<G: ControlFlowGraph>(graph: &G, - reverse_post_order: &[G::Node]) - -> Reachability<G::Node> { - let mut reachability = Reachability::new(graph); - let mut changed = true; - while changed { - changed = false; - for &node in reverse_post_order.iter().rev() { - // every node can reach itself - changed |= reachability.bits[node].insert(node.index()); - - // and every pred can reach everything node can reach - for pred in graph.predecessors(node) { - let nodes_bits = reachability.bits[node].clone(); - changed |= reachability.bits[pred].insert_all(&nodes_bits); - } - } - } - reachability -} - -pub struct Reachability<Node: Idx> { - bits: IndexVec<Node, BitVector>, -} - -impl<Node: Idx> Reachability<Node> { - fn new<G: ControlFlowGraph>(graph: &G) -> Self { - let num_nodes = graph.num_nodes(); - Reachability { bits: IndexVec::from_elem_n(BitVector::new(num_nodes), num_nodes) } - } - - pub fn can_reach(&self, source: Node, target: Node) -> bool { - let bit: usize = target.index(); - self.bits[source].contains(bit) - } -} diff --git a/src/librustc_data_structures/control_flow_graph/reachable/test.rs b/src/librustc_data_structures/control_flow_graph/reachable/test.rs deleted file mode 100644 index ef45deeaafc..00000000000 --- a/src/librustc_data_structures/control_flow_graph/reachable/test.rs +++ /dev/null @@ -1,50 +0,0 @@ -// 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. - -use super::super::test::TestGraph; - -use super::*; - -#[test] -fn test1() { - // 0 -> 1 -> 2 -> 3 - // ^ v - // 6 <- 4 -> 5 - let graph = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (2, 4), (4, 5), (4, 6), (6, 1)]); - let reachable = reachable(&graph); - assert!((0..6).all(|i| reachable.can_reach(0, i))); - assert!((1..6).all(|i| reachable.can_reach(1, i))); - assert!((1..6).all(|i| reachable.can_reach(2, i))); - assert!((1..6).all(|i| reachable.can_reach(4, i))); - assert!((1..6).all(|i| reachable.can_reach(6, i))); - assert!(reachable.can_reach(3, 3)); - assert!(!reachable.can_reach(3, 5)); - assert!(!reachable.can_reach(5, 3)); -} - -/// use bigger indices to cross between words in the bit set -#[test] -fn test2() { - // 30 -> 31 -> 32 -> 33 - // ^ v - // 36 <- 34 -> 35 - let graph = TestGraph::new(30, - &[(30, 31), (31, 32), (32, 33), (32, 34), (34, 35), (34, 36), - (36, 31)]); - let reachable = reachable(&graph); - assert!((30..36).all(|i| reachable.can_reach(30, i))); - assert!((31..36).all(|i| reachable.can_reach(31, i))); - assert!((31..36).all(|i| reachable.can_reach(32, i))); - assert!((31..36).all(|i| reachable.can_reach(34, i))); - assert!((31..36).all(|i| reachable.can_reach(36, i))); - assert!(reachable.can_reach(33, 33)); - assert!(!reachable.can_reach(33, 35)); - assert!(!reachable.can_reach(35, 33)); -} diff --git a/src/librustc_data_structures/control_flow_graph/test.rs b/src/librustc_data_structures/control_flow_graph/test.rs index d48a6e684ad..f04b536bc18 100644 --- a/src/librustc_data_structures/control_flow_graph/test.rs +++ b/src/librustc_data_structures/control_flow_graph/test.rs @@ -26,7 +26,7 @@ impl TestGraph { pub fn new(start_node: usize, edges: &[(usize, usize)]) -> Self { let mut graph = TestGraph { num_nodes: start_node + 1, - start_node: start_node, + start_node, successors: HashMap::new(), predecessors: HashMap::new(), }; diff --git a/src/librustc_data_structures/control_flow_graph/transpose.rs b/src/librustc_data_structures/control_flow_graph/transpose.rs deleted file mode 100644 index a1a117edb94..00000000000 --- a/src/librustc_data_structures/control_flow_graph/transpose.rs +++ /dev/null @@ -1,64 +0,0 @@ -// 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. - -use super::*; - -pub struct TransposedGraph<G: ControlFlowGraph> { - base_graph: G, - start_node: G::Node, -} - -impl<G: ControlFlowGraph> TransposedGraph<G> { - pub fn new(base_graph: G) -> Self { - let start_node = base_graph.start_node(); - Self::with_start(base_graph, start_node) - } - - pub fn with_start(base_graph: G, start_node: G::Node) -> Self { - TransposedGraph { - base_graph: base_graph, - start_node: start_node, - } - } -} - -impl<G: ControlFlowGraph> ControlFlowGraph for TransposedGraph<G> { - type Node = G::Node; - - fn num_nodes(&self) -> usize { - self.base_graph.num_nodes() - } - - fn start_node(&self) -> Self::Node { - self.start_node - } - - fn predecessors<'graph>(&'graph self, - node: Self::Node) - -> <Self as GraphPredecessors<'graph>>::Iter { - self.base_graph.successors(node) - } - - fn successors<'graph>(&'graph self, - node: Self::Node) - -> <Self as GraphSuccessors<'graph>>::Iter { - self.base_graph.predecessors(node) - } -} - -impl<'graph, G: ControlFlowGraph> GraphPredecessors<'graph> for TransposedGraph<G> { - type Item = G::Node; - type Iter = <G as GraphSuccessors<'graph>>::Iter; -} - -impl<'graph, G: ControlFlowGraph> GraphSuccessors<'graph> for TransposedGraph<G> { - type Item = G::Node; - type Iter = <G as GraphPredecessors<'graph>>::Iter; -} diff --git a/src/librustc_data_structures/fmt_wrap.rs b/src/librustc_data_structures/fmt_wrap.rs deleted file mode 100644 index 50fd1d802b7..00000000000 --- a/src/librustc_data_structures/fmt_wrap.rs +++ /dev/null @@ -1,31 +0,0 @@ -// 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. - -use std::fmt; - -// Provide some more formatting options for some data types (at the moment -// that's just `{:x}` for slices of u8). - -pub struct FmtWrap<T>(pub T); - -impl<'a> fmt::LowerHex for FmtWrap<&'a [u8]> { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - for byte in self.0.iter() { - try!(write!(formatter, "{:02x}", byte)); - } - Ok(()) - } -} - -#[test] -fn test_lower_hex() { - let bytes: &[u8] = &[0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; - assert_eq!("0123456789abcdef", &format!("{:x}", FmtWrap(bytes))); -} diff --git a/src/librustc_data_structures/fx.rs b/src/librustc_data_structures/fx.rs index 00dfc1617a8..5bf25437763 100644 --- a/src/librustc_data_structures/fx.rs +++ b/src/librustc_data_structures/fx.rs @@ -107,9 +107,3 @@ impl Hasher for FxHasher { self.hash as u64 } } - -pub fn hash<T: Hash>(v: &T) -> u64 { - let mut state = FxHasher::default(); - v.hash(&mut state); - state.finish() -} diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index f562ae0e3b8..a5f83ce05f5 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -106,13 +106,6 @@ impl NodeIndex { } } -impl EdgeIndex { - /// Returns unique id (unique with respect to the graph holding associated edge). - pub fn edge_id(&self) -> usize { - self.0 - } -} - impl<N: Debug, E: Debug> Graph<N, E> { pub fn new() -> Graph<N, E> { Graph { @@ -153,7 +146,7 @@ impl<N: Debug, E: Debug> Graph<N, E> { let idx = self.next_node_index(); self.nodes.push(Node { first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX], - data: data, + data, }); idx } @@ -189,9 +182,9 @@ impl<N: Debug, E: Debug> Graph<N, E> { // as the next pointers self.edges.push(Edge { next_edge: [source_first, target_first], - source: source, - target: target, - data: data, + source, + target, + data, }); // adjust the firsts for each node target be the next object. @@ -201,34 +194,10 @@ impl<N: Debug, E: Debug> Graph<N, E> { return idx; } - pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E { - &mut self.edges[idx.0].data - } - - pub fn edge_data(&self, idx: EdgeIndex) -> &E { - &self.edges[idx.0].data - } - pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> { &self.edges[idx.0] } - pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex { - //! Accesses the index of the first edge adjacent to `node`. - //! This is useful if you wish to modify the graph while walking - //! the linked list of edges. - - self.nodes[node.0].first_edge[dir.repr] - } - - pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex { - //! Accesses the next edge in a given direction. - //! This is useful if you wish to modify the graph while walking - //! the linked list of edges. - - self.edges[edge.0].next_edge[dir.repr] - } - // # Iterating over nodes, edges pub fn enumerated_nodes(&self) -> EnumeratedNodes<N> { @@ -269,7 +238,7 @@ impl<N: Debug, E: Debug> Graph<N, E> { let first_edge = self.node(source).first_edge[direction.repr]; AdjacentEdges { graph: self, - direction: direction, + direction, next: first_edge, } } @@ -282,25 +251,6 @@ impl<N: Debug, E: Debug> Graph<N, E> { self.incoming_edges(target).sources() } - /// A common use for graphs in our compiler is to perform - /// fixed-point iteration. In this case, each edge represents a - /// constraint, and the nodes themselves are associated with - /// variables or other bitsets. This method facilitates such a - /// computation. - pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F) - where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool - { - let mut iteration = 0; - let mut changed = true; - while changed { - changed = false; - iteration += 1; - for (edge_index, edge) in self.enumerated_edges() { - changed |= op(iteration, edge_index, edge); - } - } - } - pub fn depth_traverse<'a>(&'a self, start: NodeIndex, direction: Direction) @@ -343,35 +293,6 @@ impl<N: Debug, E: Debug> Graph<N, E> { assert_eq!(result.len(), self.len_nodes()); result } - - /// Whether or not a node can be reached from itself. - pub fn is_node_cyclic(&self, starting_node_index: NodeIndex) -> bool { - // This is similar to depth traversal below, but we - // can't use that, because depth traversal doesn't show - // the starting node a second time. - let mut visited = BitVector::new(self.len_nodes()); - let mut stack = vec![starting_node_index]; - - while let Some(current_node_index) = stack.pop() { - visited.insert(current_node_index.0); - - // Directionality doesn't change the answer, - // so just use outgoing edges. - for (_, edge) in self.outgoing_edges(current_node_index) { - let target_node_index = edge.target(); - - if target_node_index == starting_node_index { - return true; - } - - if !visited.contains(target_node_index.0) { - stack.push(target_node_index); - } - } - } - - false - } } // # Iterators @@ -479,16 +400,6 @@ pub struct DepthFirstTraversal<'g, N, E> } impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> { - pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self { - let visited = BitVector::new(graph.len_nodes()); - DepthFirstTraversal { - graph: graph, - stack: vec![], - visited: visited, - direction: direction, - } - } - pub fn with_start_node(graph: &'g Graph<N, E>, start_node: NodeIndex, direction: Direction) @@ -496,20 +407,13 @@ impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> { let mut visited = BitVector::new(graph.len_nodes()); visited.insert(start_node.node_id()); DepthFirstTraversal { - graph: graph, + graph, stack: vec![start_node], - visited: visited, - direction: direction, + visited, + direction, } } - pub fn reset(&mut self, start_node: NodeIndex) { - self.stack.truncate(0); - self.stack.push(start_node); - self.visited.clear(); - self.visited.insert(start_node.node_id()); - } - fn visit(&mut self, node: NodeIndex) { if self.visited.insert(node.node_id()) { self.stack.push(node); @@ -532,19 +436,6 @@ impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> { } } -pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F) - where F: FnMut(EdgeIndex) -> bool -{ - let mut i = 0; - let n = max_edge_index.0; - while i < n { - if !f(EdgeIndex(i)) { - return; - } - i += 1; - } -} - impl<E> Edge<E> { pub fn source(&self) -> NodeIndex { self.source diff --git a/src/librustc_data_structures/graph/tests.rs b/src/librustc_data_structures/graph/tests.rs index b6a0d4cff5a..007704357af 100644 --- a/src/librustc_data_structures/graph/tests.rs +++ b/src/librustc_data_structures/graph/tests.rs @@ -43,29 +43,6 @@ fn create_graph() -> TestGraph { return graph; } -fn create_graph_with_cycle() -> TestGraph { - let mut graph = Graph::new(); - - // Create a graph with a cycle. - // - // A --> B <-- + - // | | - // v | - // C --> D - - let a = graph.add_node("A"); - let b = graph.add_node("B"); - let c = graph.add_node("C"); - let d = graph.add_node("D"); - - graph.add_edge(a, b, "AB"); - graph.add_edge(b, c, "BC"); - graph.add_edge(c, d, "CD"); - graph.add_edge(d, b, "DB"); - - return graph; -} - #[test] fn each_node() { let graph = create_graph(); @@ -82,7 +59,6 @@ fn each_edge() { let graph = create_graph(); let expected = ["AB", "BC", "BD", "DE", "EC", "FB"]; graph.each_edge(|idx, edge| { - assert_eq!(&expected[idx.0], graph.edge_data(idx)); assert_eq!(expected[idx.0], edge.data); true }); @@ -97,7 +73,6 @@ fn test_adjacent_edges<N: PartialEq + Debug, E: PartialEq + Debug>(graph: &Graph let mut counter = 0; for (edge_index, edge) in graph.incoming_edges(start_index) { - assert!(graph.edge_data(edge_index) == &edge.data); assert!(counter < expected_incoming.len()); debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}", counter, @@ -117,7 +92,6 @@ fn test_adjacent_edges<N: PartialEq + Debug, E: PartialEq + Debug>(graph: &Graph let mut counter = 0; for (edge_index, edge) in graph.outgoing_edges(start_index) { - assert!(graph.edge_data(edge_index) == &edge.data); assert!(counter < expected_outgoing.len()); debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}", counter, @@ -163,58 +137,3 @@ fn each_adjacent_from_d() { let graph = create_graph(); test_adjacent_edges(&graph, NodeIndex(3), "D", &[("BD", "B")], &[("DE", "E")]); } - -#[test] -fn is_node_cyclic_a() { - let graph = create_graph_with_cycle(); - assert!(!graph.is_node_cyclic(NodeIndex(0))); -} - -#[test] -fn is_node_cyclic_b() { - let graph = create_graph_with_cycle(); - assert!(graph.is_node_cyclic(NodeIndex(1))); -} - -#[test] -fn nodes_in_postorder() { - let expected = vec![ - ("A", vec!["C", "E", "D", "B", "A", "F"]), - ("B", vec!["C", "E", "D", "B", "A", "F"]), - ("C", vec!["C", "E", "D", "B", "A", "F"]), - ("D", vec!["C", "E", "D", "B", "A", "F"]), - ("E", vec!["C", "E", "D", "B", "A", "F"]), - ("F", vec!["C", "E", "D", "B", "F", "A"]) - ]; - - let graph = create_graph(); - - for ((idx, node), &(node_name, ref expected)) - in graph.enumerated_nodes().zip(&expected) - { - assert_eq!(node.data, node_name); - assert_eq!(expected, - &graph.nodes_in_postorder(OUTGOING, idx) - .into_iter().map(|idx| *graph.node_data(idx)) - .collect::<Vec<&str>>()); - } - - let expected = vec![ - ("A", vec!["D", "C", "B", "A"]), - ("B", vec!["D", "C", "B", "A"]), - ("C", vec!["B", "D", "C", "A"]), - ("D", vec!["C", "B", "D", "A"]), - ]; - - let graph = create_graph_with_cycle(); - - for ((idx, node), &(node_name, ref expected)) - in graph.enumerated_nodes().zip(&expected) - { - assert_eq!(node.data, node_name); - assert_eq!(expected, - &graph.nodes_in_postorder(OUTGOING, idx) - .into_iter().map(|idx| *graph.node_data(idx)) - .collect::<Vec<&str>>()); - } -} diff --git a/src/librustc_data_structures/indexed_set.rs b/src/librustc_data_structures/indexed_set.rs index 572ce98d3ae..9cb6806e9ad 100644 --- a/src/librustc_data_structures/indexed_set.rs +++ b/src/librustc_data_structures/indexed_set.rs @@ -153,4 +153,68 @@ impl<T: Idx> IdxSet<T> { pub fn subtract(&mut self, other: &IdxSet<T>) -> bool { bitwise(self.words_mut(), other.words(), &Subtract) } + + /// Calls `f` on each index value held in this set, up to the + /// bound `max_bits` on the size of universe of indexes. + pub fn each_bit<F>(&self, max_bits: usize, f: F) where F: FnMut(T) { + each_bit(self, max_bits, f) + } + + /// Removes all elements from this set. + pub fn reset_to_empty(&mut self) { + for word in self.words_mut() { *word = 0; } + } + + pub fn elems(&self, universe_size: usize) -> Elems<T> { + Elems { i: 0, set: self, universe_size: universe_size } + } +} + +pub struct Elems<'a, T: Idx> { i: usize, set: &'a IdxSet<T>, universe_size: usize } + +impl<'a, T: Idx> Iterator for Elems<'a, T> { + type Item = T; + fn next(&mut self) -> Option<T> { + if self.i >= self.universe_size { return None; } + let mut i = self.i; + loop { + if i >= self.universe_size { + self.i = i; // (mark iteration as complete.) + return None; + } + if self.set.contains(&T::new(i)) { + self.i = i + 1; // (next element to start at.) + return Some(T::new(i)); + } + i = i + 1; + } + } +} + +fn each_bit<T: Idx, F>(words: &IdxSet<T>, max_bits: usize, mut f: F) where F: FnMut(T) { + let usize_bits: usize = mem::size_of::<usize>() * 8; + + for (word_index, &word) in words.words().iter().enumerate() { + if word != 0 { + let base_index = word_index * usize_bits; + for offset in 0..usize_bits { + let bit = 1 << offset; + if (word & bit) != 0 { + // NB: we round up the total number of bits + // that we store in any given bit set so that + // it is an even multiple of usize::BITS. This + // means that there may be some stray bits at + // the end that do not correspond to any + // actual value; that's why we first check + // that we are in range of bits_per_block. + let bit_index = base_index + offset as usize; + if bit_index >= max_bits { + return; + } else { + f(Idx::new(bit_index)); + } + } + } + } + } } diff --git a/src/librustc_data_structures/ivar.rs b/src/librustc_data_structures/ivar.rs deleted file mode 100644 index f842f4a41a1..00000000000 --- a/src/librustc_data_structures/ivar.rs +++ /dev/null @@ -1,71 +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. - -use std::fmt; -use std::cell::Cell; - -/// A write-once variable. When constructed, it is empty, and -/// can only be set once. -/// -/// Ivars ensure that data that can only be initialised once. A full -/// implementation is used for concurrency and blocks on a read of an -/// unfulfilled value. This implementation is more minimal and panics -/// if you attempt to read the value before it has been set. It is also -/// not `Sync`, but may be extended in the future to be usable as a true -/// concurrency type. -/// -/// The `T: Copy` bound is not strictly needed, but it is required by -/// Cell (so removing it would require using UnsafeCell), and it -/// suffices for the current purposes. -#[derive(PartialEq)] -pub struct Ivar<T: Copy> { - data: Cell<Option<T>>, -} - -impl<T: Copy> Ivar<T> { - pub fn new() -> Ivar<T> { - Ivar { data: Cell::new(None) } - } - - pub fn get(&self) -> Option<T> { - self.data.get() - } - - pub fn fulfill(&self, value: T) { - assert!(self.data.get().is_none(), "Value already set!"); - self.data.set(Some(value)); - } - - pub fn is_fulfilled(&self) -> bool { - self.data.get().is_some() - } - - pub fn unwrap(&self) -> T { - self.get().unwrap() - } -} - -impl<T: Copy + fmt::Debug> fmt::Debug for Ivar<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.get() { - Some(val) => write!(f, "Ivar({:?})", val), - None => f.write_str("Ivar(<unfulfilled>)"), - } - } -} - -impl<T: Copy> Clone for Ivar<T> { - fn clone(&self) -> Ivar<T> { - match self.get() { - Some(val) => Ivar { data: Cell::new(Some(val)) }, - None => Ivar::new(), - } - } -} diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 3cb3e088364..da00ebc4b9e 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -16,9 +16,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_data_structures"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] @@ -52,11 +49,9 @@ pub mod accumulate_vec; pub mod small_vec; pub mod base_n; pub mod bitslice; -pub mod blake2b; pub mod bitvec; -pub mod fmt_wrap; +pub mod blake2b; pub mod graph; -pub mod ivar; pub mod indexed_set; pub mod indexed_vec; pub mod obligation_forest; diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 6e70944ce64..02cae52166a 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -57,11 +57,6 @@ pub trait ObligationProcessor { where I: Clone + Iterator<Item=&'c Self::Obligation>; } -struct SnapshotData { - node_len: usize, - cache_list_len: usize, -} - pub struct ObligationForest<O: ForestObligation> { /// The list of obligations. In between calls to /// `process_obligations`, this list only contains nodes in the @@ -83,14 +78,9 @@ pub struct ObligationForest<O: ForestObligation> { /// A list of the obligations added in snapshots, to allow /// for their removal. cache_list: Vec<O::Predicate>, - snapshots: Vec<SnapshotData>, scratch: Option<Vec<usize>>, } -pub struct Snapshot { - len: usize, -} - #[derive(Debug)] struct Node<O> { obligation: O, @@ -166,7 +156,6 @@ impl<O: ForestObligation> ObligationForest<O> { pub fn new() -> ObligationForest<O> { ObligationForest { nodes: vec![], - snapshots: vec![], done_cache: FxHashSet(), waiting_cache: FxHashMap(), cache_list: vec![], @@ -180,39 +169,6 @@ impl<O: ForestObligation> ObligationForest<O> { self.nodes.len() } - pub fn start_snapshot(&mut self) -> Snapshot { - self.snapshots.push(SnapshotData { - node_len: self.nodes.len(), - cache_list_len: self.cache_list.len() - }); - Snapshot { len: self.snapshots.len() } - } - - pub fn commit_snapshot(&mut self, snapshot: Snapshot) { - assert_eq!(snapshot.len, self.snapshots.len()); - let info = self.snapshots.pop().unwrap(); - assert!(self.nodes.len() >= info.node_len); - assert!(self.cache_list.len() >= info.cache_list_len); - } - - pub fn rollback_snapshot(&mut self, snapshot: Snapshot) { - // Check that we are obeying stack discipline. - assert_eq!(snapshot.len, self.snapshots.len()); - let info = self.snapshots.pop().unwrap(); - - for entry in &self.cache_list[info.cache_list_len..] { - self.done_cache.remove(entry); - self.waiting_cache.remove(entry); - } - - self.nodes.truncate(info.node_len); - self.cache_list.truncate(info.cache_list_len); - } - - pub fn in_snapshot(&self) -> bool { - !self.snapshots.is_empty() - } - /// Registers an obligation /// /// This CAN be done in a snapshot @@ -262,14 +218,13 @@ impl<O: ForestObligation> ObligationForest<O> { /// /// This cannot be done during a snapshot. pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> { - assert!(!self.in_snapshot()); let mut errors = vec![]; for index in 0..self.nodes.len() { if let NodeState::Pending = self.nodes[index].state.get() { let backtrace = self.error_at(index); errors.push(Error { error: error.clone(), - backtrace: backtrace, + backtrace, }); } } @@ -297,7 +252,6 @@ impl<O: ForestObligation> ObligationForest<O> { where P: ObligationProcessor<Obligation=O> { debug!("process_obligations(len={})", self.nodes.len()); - assert!(!self.in_snapshot()); // cannot unroll this action let mut errors = vec![]; let mut stalled = true; @@ -346,7 +300,7 @@ impl<O: ForestObligation> ObligationForest<O> { let backtrace = self.error_at(index); errors.push(Error { error: err, - backtrace: backtrace, + backtrace, }); } } @@ -357,8 +311,8 @@ impl<O: ForestObligation> ObligationForest<O> { // changed. return Outcome { completed: vec![], - errors: errors, - stalled: stalled, + errors, + stalled, }; } @@ -372,8 +326,8 @@ impl<O: ForestObligation> ObligationForest<O> { Outcome { completed: completed_obligations, - errors: errors, - stalled: stalled, + errors, + stalled, } } @@ -528,8 +482,6 @@ impl<O: ForestObligation> ObligationForest<O> { /// on these nodes may be present. This is done by e.g. `process_cycles`. #[inline(never)] fn compress(&mut self) -> Vec<O> { - assert!(!self.in_snapshot()); // didn't write code to unroll this action - let nodes_len = self.nodes.len(); let mut node_rewrites: Vec<_> = self.scratch.take().unwrap(); node_rewrites.extend(0..nodes_len); @@ -638,8 +590,8 @@ impl<O: ForestObligation> ObligationForest<O> { impl<O> Node<O> { fn new(parent: Option<NodeIndex>, obligation: O) -> Node<O> { Node { - obligation: obligation, - parent: parent, + obligation, + parent, state: Cell::new(NodeState::Pending), dependents: vec![], } diff --git a/src/librustc_data_structures/small_vec.rs b/src/librustc_data_structures/small_vec.rs index 4e2b3786021..74738e61b44 100644 --- a/src/librustc_data_structures/small_vec.rs +++ b/src/librustc_data_structures/small_vec.rs @@ -14,7 +14,7 @@ //! used to store the values on the heap. SmallVec is similar to AccumulateVec, but adds //! the ability to push elements. //! -//! The N above is determined by Array's implementor, by way of an associatated constant. +//! The N above is determined by Array's implementor, by way of an associated constant. use std::ops::{Deref, DerefMut}; use std::iter::{IntoIterator, FromIterator}; diff --git a/src/librustc_data_structures/unify/mod.rs b/src/librustc_data_structures/unify/mod.rs index e2d3a4f4537..7853bf9478a 100644 --- a/src/librustc_data_structures/unify/mod.rs +++ b/src/librustc_data_structures/unify/mod.rs @@ -87,8 +87,8 @@ impl<K: UnifyKey> VarValue<K> { fn new(parent: K, value: K::Value, rank: u32) -> VarValue<K> { VarValue { parent: parent, // this is a root - value: value, - rank: rank, + value, + rank, } } @@ -98,8 +98,8 @@ impl<K: UnifyKey> VarValue<K> { fn root(self, rank: u32, value: K::Value) -> VarValue<K> { VarValue { - rank: rank, - value: value, + rank, + value, ..self } } @@ -275,7 +275,8 @@ impl<'tcx, K: UnifyKey> UnificationTable<K> self.get(id).value } - pub fn unioned(&mut self, a_id: K, b_id: K) -> bool { + #[cfg(test)] + fn unioned(&mut self, a_id: K, b_id: K) -> bool { self.find(a_id) == self.find(b_id) } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 1444dcf4271..96688c6ac9c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -64,6 +64,8 @@ use arena::DroplessArena; use derive_registrar; +use profile; + pub fn compile_input(sess: &Session, cstore: &CStore, input: &Input, @@ -105,6 +107,10 @@ pub fn compile_input(sess: &Session, sess.abort_if_errors(); } + if sess.profile_queries() { + profile::begin(); + } + // We need nested scopes here, because the intermediate results can keep // large chunks of memory alive and we want to free them as soon as // possible to keep the peak memory usage low @@ -306,7 +312,7 @@ pub fn source_name(input: &Input) -> String { } } -/// CompileController is used to customise compilation, it allows compilation to +/// CompileController is used to customize compilation, it allows compilation to /// be stopped and/or to call arbitrary code at various points in compilation. /// It also allows for various flags to be set to influence what information gets /// collected during compilation. @@ -401,8 +407,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { out_dir: &'a Option<PathBuf>) -> Self { CompileState { - input: input, - session: session, + input, + session, out_dir: out_dir.as_ref().map(|s| &**s), out_file: None, arena: None, @@ -537,6 +543,10 @@ pub fn phase_1_parse_input<'a>(control: &CompileController, -> PResult<'a, ast::Crate> { sess.diagnostic().set_continue_after_error(control.continue_parse_after_error); + if sess.profile_queries() { + profile::begin(); + } + let krate = time(sess.time_passes(), "parsing", || { match *input { Input::File(ref file) => { @@ -833,10 +843,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session, }) })?; - time(time_passes, - "early lint checks", - || lint::check_ast_crate(sess, &krate)); - // Lower ast -> hir. let hir_forest = time(time_passes, "lowering ast -> hir", || { let hir_crate = lower_crate(sess, &krate, &mut resolver); @@ -848,6 +854,10 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session, hir_map::Forest::new(hir_crate, &sess.dep_graph) }); + time(time_passes, + "early lint checks", + || lint::check_ast_crate(sess, &krate)); + // Discard hygiene data, which isn't required after lowering to HIR. if !keep_hygiene_data(sess) { syntax::ext::hygiene::clear_markings(); @@ -867,8 +877,9 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session, export_map: resolver.export_map, trait_map: resolver.trait_map, maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, + maybe_unused_extern_crates: resolver.maybe_unused_extern_crates, }, - hir_forest: hir_forest, + hir_forest, }) } @@ -970,7 +981,12 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, // We compute "constant qualifications" between MIR_CONST and MIR_VALIDATED. // What we need to run borrowck etc. + passes.push_pass(MIR_VALIDATED, mir::transform::qualify_consts::QualifyAndPromoteConstants); + + // FIXME: ariel points SimplifyBranches should run after + // mir-borrowck; otherwise code within `if false { ... }` would + // not be checked. passes.push_pass(MIR_VALIDATED, mir::transform::simplify_branches::SimplifyBranches::new("initial")); passes.push_pass(MIR_VALIDATED, mir::transform::simplify::SimplifyCfg::new("qualify-consts")); @@ -1066,6 +1082,10 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, "borrow checking", || borrowck::check_crate(tcx)); + time(time_passes, + "MIR borrow checking", + || for def_id in tcx.body_owners() { tcx.mir_borrowck(def_id) }); + // Avoid overwhelming user with errors if type checking failed. // I'm not sure how helpful this is, to be honest, but it avoids // a @@ -1111,6 +1131,10 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "translation", move || trans::trans_crate(tcx, analysis, incremental_hashes_map, output_filenames)); + if tcx.sess.profile_queries() { + profile::dump("profile_queries".to_string()) + } + translation } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f8cd2280caf..1915a1c8648 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -14,16 +14,13 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_driver"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] #![deny(warnings)] #![feature(box_syntax)] -#![feature(libc)] +#![cfg_attr(unix, feature(libc))] #![feature(quote)] #![feature(rustc_diagnostic_macros)] #![feature(set_stdio)] @@ -32,6 +29,7 @@ extern crate arena; extern crate getopts; extern crate graphviz; extern crate env_logger; +#[cfg(unix)] extern crate libc; extern crate rustc; extern crate rustc_allocator; @@ -102,8 +100,9 @@ use syntax::parse::{self, PResult}; use syntax_pos::{DUMMY_SP, MultiSpan}; #[cfg(test)] -pub mod test; +mod test; +pub mod profile; pub mod driver; pub mod pretty; pub mod target_features; @@ -802,7 +801,7 @@ impl RustcDefaultCalls { let mut cfgs = Vec::new(); for &(name, ref value) in sess.parse_sess.config.iter() { let gated_cfg = GatedCfg::gate(&ast::MetaItem { - name: name, + name, node: ast::MetaItemKind::Word, span: DUMMY_SP, }); @@ -859,17 +858,17 @@ impl RustcDefaultCalls { } /// Returns a version string such as "0.12.0-dev". -pub fn release_str() -> Option<&'static str> { +fn release_str() -> Option<&'static str> { option_env!("CFG_RELEASE") } /// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built. -pub fn commit_hash_str() -> Option<&'static str> { +fn commit_hash_str() -> Option<&'static str> { option_env!("CFG_VER_HASH") } /// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string. -pub fn commit_date_str() -> Option<&'static str> { +fn commit_date_str() -> Option<&'static str> { option_env!("CFG_VER_DATE") } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 84d3ab65b1c..20f2a146b0b 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -174,7 +174,7 @@ impl PpSourceMode { match *self { PpmNormal | PpmEveryBodyLoops | PpmExpanded => { let annotation = NoAnn { - sess: sess, + sess, hir_map: hir_map.map(|m| m.clone()), }; f(&annotation) @@ -182,14 +182,14 @@ impl PpSourceMode { PpmIdentified | PpmExpandedIdentified => { let annotation = IdentifiedAnnotation { - sess: sess, + sess, hir_map: hir_map.map(|m| m.clone()), }; f(&annotation) } PpmExpandedHygiene => { let annotation = HygieneAnnotation { - sess: sess, + sess, }; f(&annotation) } @@ -211,7 +211,7 @@ impl PpSourceMode { match *self { PpmNormal => { let annotation = NoAnn { - sess: sess, + sess, hir_map: Some(hir_map.clone()), }; f(&annotation, hir_map.forest.krate()) @@ -219,7 +219,7 @@ impl PpSourceMode { PpmIdentified => { let annotation = IdentifiedAnnotation { - sess: sess, + sess, hir_map: Some(hir_map.clone()), }; f(&annotation, hir_map.forest.krate()) @@ -235,7 +235,7 @@ impl PpSourceMode { |tcx, _, _, _| { let empty_tables = ty::TypeckTables::empty(None); let annotation = TypedAnnotation { - tcx: tcx, + tcx, tables: Cell::new(&empty_tables) }; let _ignore = tcx.dep_graph.in_ignore(); @@ -620,6 +620,15 @@ impl UserIdentifiedItem { } // Note: Also used by librustdoc, see PR #43348. Consider moving this struct elsewhere. +// +// FIXME: Currently the `everybody_loops` transformation is not applied to: +// * `const fn`, due to issue #43636 that `loop` is not supported for const evaluation. We are +// waiting for miri to fix that. +// * `impl Trait`, due to issue #43869 that functions returning impl Trait cannot be diverging. +// Solving this may require `!` to implement every trait, which relies on the an even more +// ambitious form of the closed RFC #1637. See also [#34511]. +// +// [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 pub struct ReplaceBodyWithLoop { within_static_or_const: bool, } @@ -635,14 +644,34 @@ impl ReplaceBodyWithLoop { self.within_static_or_const = old_const; ret } + + fn should_ignore_fn(ret_ty: &ast::FnDecl) -> bool { + if let ast::FunctionRetTy::Ty(ref ty) = ret_ty.output { + fn involves_impl_trait(ty: &ast::Ty) -> bool { + match ty.node { + ast::TyKind::ImplTrait(_) => true, + ast::TyKind::Slice(ref subty) | + ast::TyKind::Array(ref subty, _) | + ast::TyKind::Ptr(ast::MutTy { ty: ref subty, .. }) | + ast::TyKind::Rptr(_, ast::MutTy { ty: ref subty, .. }) | + ast::TyKind::Paren(ref subty) => involves_impl_trait(subty), + ast::TyKind::Tup(ref tys) => tys.iter().any(|subty| involves_impl_trait(subty)), + _ => false, + } + } + involves_impl_trait(ty) + } else { + false + } + } } impl fold::Folder for ReplaceBodyWithLoop { fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, - ast::ItemKind::Fn(_, _, ref constness, _, _, _) => - constness.node == ast::Constness::Const, + ast::ItemKind::Fn(ref decl, _, ref constness, _, _, _) => + constness.node == ast::Constness::Const || Self::should_ignore_fn(decl), _ => false, }; self.run(is_const, |s| fold::noop_fold_item_kind(i, s)) @@ -651,8 +680,8 @@ impl fold::Folder for ReplaceBodyWithLoop { fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> { let is_const = match i.node { ast::TraitItemKind::Const(..) => true, - ast::TraitItemKind::Method(ast::MethodSig { ref constness, .. }, _) => - constness.node == ast::Constness::Const, + ast::TraitItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) => + constness.node == ast::Constness::Const || Self::should_ignore_fn(decl), _ => false, }; self.run(is_const, |s| fold::noop_fold_trait_item(i, s)) @@ -661,8 +690,8 @@ impl fold::Folder for ReplaceBodyWithLoop { fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> { let is_const = match i.node { ast::ImplItemKind::Const(..) => true, - ast::ImplItemKind::Method(ast::MethodSig { ref constness, .. }, _) => - constness.node == ast::Constness::Const, + ast::ImplItemKind::Method(ast::MethodSig { ref decl, ref constness, .. }, _) => + constness.node == ast::Constness::Const || Self::should_ignore_fn(decl), _ => false, }; self.run(is_const, |s| fold::noop_fold_impl_item(i, s)) @@ -680,7 +709,7 @@ impl fold::Folder for ReplaceBodyWithLoop { }) .into_iter() .collect(), - rules: rules, + rules, id: ast::DUMMY_NODE_ID, span: syntax_pos::DUMMY_SP, }) @@ -739,7 +768,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>, hir_map: &tcx.hir, cfg: &cfg, name: format!("node_{}", code.id()), - labelled_edges: labelled_edges, + labelled_edges, }; match code { @@ -758,7 +787,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>, let lcfg = borrowck_dot::DataflowLabeller { inner: lcfg, - variants: variants, + variants, borrowck_ctxt: &bccx, analysis_data: &analysis_data, }; diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs new file mode 100644 index 00000000000..061077d05a4 --- /dev/null +++ b/src/librustc_driver/profile/mod.rs @@ -0,0 +1,316 @@ +// 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 rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan}; +use std::sync::mpsc::{Receiver}; +use std::io::{Write}; +use rustc::dep_graph::{DepNode}; +use std::time::{Duration, Instant}; + +pub mod trace; + +/// begin a profile thread, if not already running +pub fn begin() { + use std::thread; + use std::sync::mpsc::{channel}; + let (tx, rx) = channel(); + if profq_set_chan(tx) { + thread::spawn(move||profile_queries_thread(rx)); + } +} + +/// dump files with profiling information to the given base path, and +/// wait for this dump to complete. +/// +/// wraps the RPC (send/recv channel logic) of requesting a dump. +pub fn dump(path:String) { + use std::sync::mpsc::{channel}; + let (tx, rx) = channel(); + let params = ProfQDumpParams{ + path, ack:tx, + // FIXME: Add another compiler flag to toggle whether this log + // is written; false for now + dump_profq_msg_log:true, + }; + profq_msg(ProfileQueriesMsg::Dump(params)); + let _ = rx.recv().unwrap(); +} + +// State for parsing recursive trace structure in separate thread, via messages +#[derive(Clone, Eq, PartialEq)] +enum ParseState { + // No (local) parse state; may be parsing a tree, focused on a + // sub-tree that could be anything. + Clear, + // Have Query information from the last message + HaveQuery(trace::Query, Instant), + // Have "time-begin" information from the last message (doit flag, and message) + HaveTimeBegin(String, Instant), + // Have "task-begin" information from the last message + HaveTaskBegin(DepNode, Instant), +} +struct StackFrame { + pub parse_st: ParseState, + pub traces: Vec<trace::Rec>, +} + +fn total_duration(traces: &Vec<trace::Rec>) -> Duration { + let mut sum : Duration = Duration::new(0,0); + for t in traces.iter() { sum += t.dur_total; } + return sum +} + +// profiling thread; retains state (in local variables) and dump traces, upon request. +fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) { + use self::trace::*; + use std::fs::File; + use std::time::{Instant}; + + let mut profq_msgs : Vec<ProfileQueriesMsg> = vec![]; + let mut frame : StackFrame = StackFrame{ parse_st:ParseState::Clear, traces:vec![] }; + let mut stack : Vec<StackFrame> = vec![]; + loop { + let msg = r.recv(); + if let Err(_recv_err) = msg { + // FIXME: Perhaps do something smarter than simply quitting? + break + }; + let msg = msg.unwrap(); + debug!("profile_queries_thread: {:?}", msg); + + // Meta-level versus _actual_ queries messages + match msg { + ProfileQueriesMsg::Halt => return, + ProfileQueriesMsg::Dump(params) => { + assert!(stack.len() == 0); + assert!(frame.parse_st == ParseState::Clear); + { + // write log of all messages + if params.dump_profq_msg_log { + let mut log_file = + File::create(format!("{}.log.txt", params.path)).unwrap(); + for m in profq_msgs.iter() { + writeln!(&mut log_file, "{:?}", m).unwrap() + }; + } + + // write HTML file, and counts file + let html_path = format!("{}.html", params.path); + let mut html_file = File::create(&html_path).unwrap(); + + let counts_path = format!("{}.counts.txt", params.path); + let mut counts_file = File::create(&counts_path).unwrap(); + + write!(html_file, "<html>\n").unwrap(); + write!(html_file, + "<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n", + "profile_queries.css").unwrap(); + write!(html_file, "<style>\n").unwrap(); + trace::write_style(&mut html_file); + write!(html_file, "</style>\n").unwrap(); + write!(html_file, "</head>\n").unwrap(); + write!(html_file, "<body>\n").unwrap(); + trace::write_traces(&mut html_file, &mut counts_file, &frame.traces); + write!(html_file, "</body>\n</html>\n").unwrap(); + + let ack_path = format!("{}.ack", params.path); + let ack_file = File::create(&ack_path).unwrap(); + drop(ack_file); + + // Tell main thread that we are done, e.g., so it can exit + params.ack.send(()).unwrap(); + } + continue + } + // Actual query message: + msg => { + // Record msg in our log + profq_msgs.push(msg.clone()); + // Respond to the message, knowing that we've already handled Halt and Dump, above. + match (frame.parse_st.clone(), msg) { + (_,ProfileQueriesMsg::Halt) => unreachable!(), + (_,ProfileQueriesMsg::Dump(_)) => unreachable!(), + + // Parse State: Clear + (ParseState::Clear, + ProfileQueriesMsg::QueryBegin(span,querymsg)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveQuery + (Query{span:span, msg:querymsg}, start) + }, + (ParseState::Clear, + ProfileQueriesMsg::CacheHit) => { + panic!("parse error: unexpected CacheHit; expected QueryBegin") + }, + (ParseState::Clear, + ProfileQueriesMsg::ProviderBegin) => { + panic!("parse error: expected QueryBegin before beginning a provider") + }, + (ParseState::Clear, + ProfileQueriesMsg::ProviderEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::HaveQuery(q, start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st:ParseState::Clear, + traces:old_frame.traces + }; + let dur_extent = total_duration(&provider_extent); + let trace = Rec { + effect: Effect::QueryBegin(q, CacheCase::Miss), + extent: Box::new(provider_extent), + start: start, + dur_self: duration - dur_extent, + dur_total: duration, + }; + frame.traces.push( trace ); + }, + _ => panic!("internal parse error: malformed parse stack") + } + } + } + }, + + + (ParseState::Clear, + ProfileQueriesMsg::TimeBegin(msg)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveTimeBegin(msg, start); + stack.push(frame); + frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]}; + }, + (_, ProfileQueriesMsg::TimeBegin(_)) => + panic!("parse error; did not expect time begin here"), + + (ParseState::Clear, + ProfileQueriesMsg::TimeEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::HaveTimeBegin(msg, start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st:ParseState::Clear, + traces:old_frame.traces + }; + let dur_extent = total_duration(&provider_extent); + let trace = Rec { + effect: Effect::TimeBegin(msg), + extent: Box::new(provider_extent), + start: start, + dur_total: duration, + dur_self: duration - dur_extent, + }; + frame.traces.push( trace ); + }, + _ => panic!("internal parse error: malformed parse stack") + } + } + } + }, + (_, ProfileQueriesMsg::TimeEnd) => { panic!("parse error") } + + (ParseState::Clear, + ProfileQueriesMsg::TaskBegin(key)) => { + let start = Instant::now(); + frame.parse_st = ParseState::HaveTaskBegin(key, start); + stack.push(frame); + frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]}; + }, + (_, ProfileQueriesMsg::TaskBegin(_)) => + panic!("parse error; did not expect time begin here"), + + (ParseState::Clear, + ProfileQueriesMsg::TaskEnd) => { + let provider_extent = frame.traces; + match stack.pop() { + None => + panic!("parse error: expected a stack frame; found an empty stack"), + Some(old_frame) => { + match old_frame.parse_st { + ParseState::HaveTaskBegin(key, start) => { + let duration = start.elapsed(); + frame = StackFrame{ + parse_st:ParseState::Clear, + traces:old_frame.traces + }; + let dur_extent = total_duration(&provider_extent); + let trace = Rec { + effect: Effect::TaskBegin(key), + extent: Box::new(provider_extent), + start: start, + dur_total: duration, + dur_self: duration - dur_extent, + }; + frame.traces.push( trace ); + }, + _ => panic!("internal parse error: malformed parse stack") + } + } + } + }, + (_, ProfileQueriesMsg::TaskEnd) => { panic!("parse error") } + + // Parse State: HaveQuery + (ParseState::HaveQuery(q,start), + ProfileQueriesMsg::CacheHit) => { + let duration = start.elapsed(); + let trace : Rec = Rec{ + effect: Effect::QueryBegin(q, CacheCase::Hit), + extent: Box::new(vec![]), + start: start, + dur_self: duration, + dur_total: duration, + }; + frame.traces.push( trace ); + frame.parse_st = ParseState::Clear; + }, + (ParseState::HaveQuery(_,_), + ProfileQueriesMsg::ProviderBegin) => { + stack.push(frame); + frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]}; + }, + + // + // + // Parse errors: + + (ParseState::HaveQuery(q,_), + ProfileQueriesMsg::ProviderEnd) => { + panic!("parse error: unexpected ProviderEnd; \ + expected something else to follow BeginQuery for {:?}", q) + }, + (ParseState::HaveQuery(q1,_), + ProfileQueriesMsg::QueryBegin(span2,querymsg2)) => { + panic!("parse error: unexpected QueryBegin; \ + earlier query is unfinished: {:?} and now {:?}", + q1, Query{span:span2, msg:querymsg2}) + }, + + (ParseState::HaveTimeBegin(_, _), _) => { + unreachable!() + }, + (ParseState::HaveTaskBegin(_, _), _) => { + unreachable!() + }, + } + + } + } + } +} diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs new file mode 100644 index 00000000000..f5079836c3c --- /dev/null +++ b/src/librustc_driver/profile/trace.rs @@ -0,0 +1,315 @@ +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::*; +use syntax_pos::Span; +use rustc::ty::maps::QueryMsg; +use std::fs::File; +use std::time::{Duration, Instant}; +use std::collections::hash_map::HashMap; +use rustc::dep_graph::{DepNode}; + +#[derive(Debug, Clone, Eq, PartialEq)] +pub struct Query { + pub span: Span, + pub msg: QueryMsg, +} +pub enum Effect { + QueryBegin(Query, CacheCase), + TimeBegin(String), + TaskBegin(DepNode), +} +pub enum CacheCase { + Hit, Miss +} +/// Recursive trace structure +pub struct Rec { + pub effect: Effect, + pub start: Instant, + pub dur_self: Duration, + pub dur_total: Duration, + pub extent: Box<Vec<Rec>>, +} +pub struct QueryMetric { + pub count: usize, + pub dur_self: Duration, + pub dur_total: Duration, +} + +pub fn cons_of_query_msg(q: &trace::Query) -> String { + let s = format!("{:?}", q.msg); + let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect(); + assert!(cons.len() > 0 && cons[0] != ""); + cons[0].to_string() +} + +pub fn cons_of_key(k: &DepNode) -> String { + let s = format!("{:?}", k); + let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect(); + assert!(cons.len() > 0 && cons[0] != ""); + cons[0].to_string() +} + +// First return value is text; second return value is a CSS class +pub fn html_of_effect(eff: &Effect) -> (String, String) { + match *eff { + Effect::TimeBegin(ref msg) => { + (msg.clone(), + format!("time-begin")) + }, + Effect::TaskBegin(ref key) => { + let cons = cons_of_key(key); + (cons.clone(), format!("{} task-begin", cons)) + }, + Effect::QueryBegin(ref qmsg, ref cc) => { + let cons = cons_of_query_msg(qmsg); + (cons.clone(), + format!("{} {}", + cons, + match *cc { + CacheCase::Hit => "hit", + CacheCase::Miss => "miss", + })) + } + } +} + +// First return value is text; second return value is a CSS class +fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) { + use rustc::util::common::duration_to_secs_str; + (duration_to_secs_str(dur.clone()), + "".to_string() + ) +} + +fn html_of_fraction(frac: f64) -> (String, String) { + let css = { + if frac > 0.50 { format!("frac-50") } + else if frac > 0.40 { format!("frac-40") } + else if frac > 0.30 { format!("frac-30") } + else if frac > 0.20 { format!("frac-20") } + else if frac > 0.10 { format!("frac-10") } + else if frac > 0.05 { format!("frac-05") } + else if frac > 0.02 { format!("frac-02") } + else if frac > 0.01 { format!("frac-01") } + else if frac > 0.001 { format!("frac-001") } + else { format!("frac-0") } + }; + let percent = frac * 100.0; + if percent > 0.1 { (format!("{:.1}%", percent), css) } + else { (format!("< 0.1%", ), css) } +} + +fn total_duration(traces: &Vec<Rec>) -> Duration { + let mut sum : Duration = Duration::new(0,0); + for t in traces.iter() { + sum += t.dur_total; + } + return sum +} + +fn duration_div(nom: Duration, den: Duration) -> f64 { + fn to_nanos(d: Duration) -> u64 { + d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64 + } + + to_nanos(nom) as f64 / to_nanos(den) as f64 +} + +fn write_traces_rec(file: &mut File, traces: &Vec<Rec>, total: Duration, depth: usize) { + for t in traces { + let (eff_text, eff_css_classes) = html_of_effect(&t.effect); + let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total); + let fraction = duration_div(t.dur_total, total); + let percent = fraction * 100.0; + let (frc_text, frc_css_classes) = html_of_fraction(fraction); + write!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">\n", + depth, + t.extent.len(), + /* Heuristic for 'important' CSS class: */ + if t.extent.len() > 5 || percent >= 1.0 { + " important" } + else { "" }, + eff_css_classes, + dur_css_classes, + frc_css_classes, + ).unwrap(); + write!(file, "<div class=\"eff\">{}</div>\n", eff_text).unwrap(); + write!(file, "<div class=\"dur\">{}</div>\n", dur_text).unwrap(); + write!(file, "<div class=\"frc\">{}</div>\n", frc_text).unwrap(); + write_traces_rec(file, &t.extent, total, depth + 1); + write!(file, "</div>\n").unwrap(); + } +} + +fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &Vec<Rec>) { + for t in traces.iter() { + match t.effect { + Effect::TimeBegin(ref msg) => { + let qm = match counts.get(msg) { + Some(_qm) => { panic!("TimeBegin with non-unique, repeat message") } + None => QueryMetric{ + count: 1, + dur_self: t.dur_self, + dur_total: t.dur_total, + }}; + counts.insert(msg.clone(), qm); + }, + Effect::TaskBegin(ref key) => { + let cons = cons_of_key(key); + let qm = match counts.get(&cons) { + Some(qm) => + QueryMetric{ + count: qm.count + 1, + dur_self: qm.dur_self + t.dur_self, + dur_total: qm.dur_total + t.dur_total, + }, + None => QueryMetric{ + count: 1, + dur_self: t.dur_self, + dur_total: t.dur_total, + }}; + counts.insert(cons, qm); + }, + Effect::QueryBegin(ref qmsg, ref _cc) => { + let qcons = cons_of_query_msg(qmsg); + let qm = match counts.get(&qcons) { + Some(qm) => + QueryMetric{ + count: qm.count + 1, + dur_total: qm.dur_total + t.dur_total, + dur_self: qm.dur_self + t.dur_self + }, + None => QueryMetric{ + count: 1, + dur_total: t.dur_total, + dur_self: t.dur_self, + } + }; + counts.insert(qcons, qm); + } + } + compute_counts_rec(counts, &t.extent) + } +} + +pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) { + use rustc::util::common::duration_to_secs_str; + use std::cmp::Ordering; + + let mut data = vec![]; + for (ref cons, ref qm) in counts.iter() { + data.push((cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone())); + }; + data.sort_by(|&(_,_,_,self1),&(_,_,_,self2)| + if self1 > self2 { Ordering::Less } else { Ordering::Greater } ); + for (cons, count, dur_total, dur_self) in data { + write!(count_file, "{}, {}, {}, {}\n", + cons, count, + duration_to_secs_str(dur_total), + duration_to_secs_str(dur_self) + ).unwrap(); + } +} + +pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &Vec<Rec>) { + let mut counts : HashMap<String,QueryMetric> = HashMap::new(); + compute_counts_rec(&mut counts, traces); + write_counts(counts_file, &mut counts); + + let total : Duration = total_duration(traces); + write_traces_rec(html_file, traces, total, 0) +} + +pub fn write_style(html_file: &mut File) { + write!(html_file,"{}", " +body { + font-family: sans-serif; + background: black; +} +.trace { + color: black; + display: inline-block; + border-style: solid; + border-color: red; + border-width: 1px; + border-radius: 5px; + padding: 0px; + margin: 1px; + font-size: 0px; +} +.task-begin { + border-width: 1px; + color: white; + border-color: #ff8; + font-size: 0px; +} +.miss { + border-color: red; + border-width: 1px; +} +.extent-0 { + padding: 2px; +} +.time-begin { + border-width: 4px; + font-size: 12px; + color: white; + border-color: #afa; +} +.important { + border-width: 3px; + font-size: 12px; + color: white; + border-color: #f77; +} +.hit { + padding: 0px; + border-color: blue; + border-width: 3px; +} +.eff { + color: #fff; + display: inline-block; +} +.frc { + color: #7f7; + display: inline-block; +} +.dur { + display: none +} +.frac-50 { + padding: 10px; + border-width: 10px; + font-size: 32px; +} +.frac-40 { + padding: 8px; + border-width: 8px; + font-size: 24px; +} +.frac-30 { + padding: 6px; + border-width: 6px; + font-size: 18px; +} +.frac-20 { + padding: 4px; + border-width: 6px; + font-size: 16px; +} +.frac-10 { + padding: 2px; + border-width: 6px; + font-size: 14px; +} +").unwrap(); +} diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs index bee61bb3980..96264472b5f 100644 --- a/src/librustc_driver/target_features.rs +++ b/src/librustc_driver/target_features.rs @@ -25,21 +25,7 @@ pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { cfg.insert((tf, Some(feat))); } - let requested_features = sess.opts.cg.target_feature.split(','); - let found_negative = requested_features.clone().any(|r| r == "-crt-static"); - let found_positive = requested_features.clone().any(|r| r == "+crt-static"); - - // If the target we're compiling for requests a static crt by default, - // then see if the `-crt-static` feature was passed to disable that. - // Otherwise if we don't have a static crt by default then see if the - // `+crt-static` feature was passed. - let crt_static = if sess.target.target.options.crt_static_default { - !found_negative - } else { - found_positive - }; - - if crt_static { + if sess.crt_static_feature() { cfg.insert((tf, Some(Symbol::intern("crt-static")))); } } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 91d32dbb84f..0f063542383 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -83,9 +83,9 @@ impl Diagnostic { pub fn new_with_code(level: Level, code: Option<String>, message: &str) -> Self { Diagnostic { - level: level, + level, message: vec![(message.to_owned(), Style::NoStyle)], - code: code, + code, span: MultiSpan::new(), children: vec![], suggestions: vec![], @@ -93,9 +93,9 @@ impl Diagnostic { } /// Cancel the diagnostic (a structured diagnostic must either be emitted or - /// cancelled or it will panic when dropped). + /// canceled or it will panic when dropped). /// BEWARE: if this DiagnosticBuilder is an error, then creating it will - /// bump the error count on the Handler and cancelling it won't undo that. + /// bump the error count on the Handler and canceling it won't undo that. /// If you want to decrement the error count you should use `Handler::cancel`. pub fn cancel(&mut self) { self.level = Level::Cancelled; @@ -105,10 +105,6 @@ impl Diagnostic { self.level == Level::Cancelled } - pub fn is_fatal(&self) -> bool { - self.level == Level::Fatal - } - /// Add a span/label to be included in the resulting snippet. /// This is pushed onto the `MultiSpan` that was created when the /// diagnostic was first built. If you don't call this function at @@ -278,18 +274,10 @@ impl Diagnostic { self.message.iter().map(|i| i.0.to_owned()).collect::<String>() } - pub fn set_message(&mut self, message: &str) { - self.message = vec![(message.to_owned(), Style::NoStyle)]; - } - pub fn styled_message(&self) -> &Vec<(String, Style)> { &self.message } - pub fn level(&self) -> Level { - self.level - } - /// Used by a lint. Copies over all details *but* the "main /// message". pub fn copy_details_not_message(&mut self, from: &Diagnostic) { @@ -306,10 +294,10 @@ impl Diagnostic { span: MultiSpan, render_span: Option<RenderSpan>) { let sub = SubDiagnostic { - level: level, + level, message: vec![(message.to_owned(), Style::NoStyle)], - span: span, - render_span: render_span, + span, + render_span, }; self.children.push(sub); } @@ -322,10 +310,10 @@ impl Diagnostic { span: MultiSpan, render_span: Option<RenderSpan>) { let sub = SubDiagnostic { - level: level, - message: message, - span: span, - render_span: render_span, + level, + message, + span, + render_span, }; self.children.push(sub); } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 5d7c5e2829a..2c8d8b4691f 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -98,7 +98,7 @@ impl<'a> DiagnosticBuilder<'a> { } }; - self.handler.emitter.borrow_mut().emit(&self); + self.handler.emit_db(&self); self.cancel(); if is_error { @@ -110,6 +110,22 @@ impl<'a> DiagnosticBuilder<'a> { // } } + /// Delay emission of this diagnostic as a bug. + /// + /// This can be useful in contexts where an error indicates a bug but + /// typically this only happens when other compilation errors have already + /// happened. In those cases this can be used to defer emission of this + /// diagnostic as a bug in the compiler only if no other errors have been + /// emitted. + /// + /// In the meantime, though, callsites are required to deal with the "bug" + /// locally in whichever way makes the most sense. + pub fn delay_as_bug(&mut self) { + self.level = Level::Bug; + *self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone()); + self.cancel(); + } + /// Add a span/label to be included in the resulting snippet. /// This is pushed onto the `MultiSpan` that was created when the /// diagnostic was first built. If you don't call this function at @@ -178,17 +194,15 @@ impl<'a> DiagnosticBuilder<'a> { code: Option<String>, message: &str) -> DiagnosticBuilder<'a> { - DiagnosticBuilder { - handler: handler, - diagnostic: Diagnostic::new_with_code(level, code, message) - } + let diagnostic = Diagnostic::new_with_code(level, code, message); + DiagnosticBuilder::new_diagnostic(handler, diagnostic) } - pub fn into_diagnostic(mut self) -> Diagnostic { - // annoyingly, the Drop impl means we can't actually move - let result = self.diagnostic.clone(); - self.cancel(); - result + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) + -> DiagnosticBuilder<'a> { + DiagnosticBuilder { handler, diagnostic } } } @@ -198,7 +212,7 @@ impl<'a> Debug for DiagnosticBuilder<'a> { } } -/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or cancelled +/// Destructor bomb - a `DiagnosticBuilder` must be either emitted or canceled /// or we emit a bug. impl<'a> Drop for DiagnosticBuilder<'a> { fn drop(&mut self) { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 3cfa635f5b2..53d90531cc9 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -120,7 +120,7 @@ impl EmitterWriter { if color_config.use_color() { let dst = Destination::from_stderr(); EmitterWriter { - dst: dst, + dst, cm: code_map, } } else { @@ -156,7 +156,7 @@ impl EmitterWriter { } // We don't have a line yet, create one slot.lines.push(Line { - line_index: line_index, + line_index, annotations: vec![ann], }); slot.lines.sort(); @@ -165,9 +165,9 @@ impl EmitterWriter { } // This is the first time we're seeing the file file_vec.push(FileWithAnnotatedLines { - file: file, + file, lines: vec![Line { - line_index: line_index, + line_index, annotations: vec![ann], }], multiline_depth: 0, @@ -311,7 +311,9 @@ impl EmitterWriter { if line.annotations.len() == 1 { if let Some(ref ann) = line.annotations.get(0) { if let AnnotationType::MultilineStart(depth) = ann.annotation_type { - if source_string[0..ann.start_col].trim() == "" { + if source_string.chars() + .take(ann.start_col) + .all(|c| c.is_whitespace()) { let style = if ann.is_primary { Style::UnderlinePrimary } else { @@ -822,7 +824,7 @@ impl EmitterWriter { .map(|_| " ") .collect::<String>(); - /// Return wether `style`, or the override if present and the style is `NoStyle`. + /// Return whether `style`, or the override if present and the style is `NoStyle`. fn style_or_override(style: Style, override_style: Option<Style>) -> Style { if let Some(o) = override_style { if style == Style::NoStyle { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 159d2c7a2df..870bb01bb9f 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_errors"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -19,10 +16,11 @@ #![feature(custom_attribute)] #![allow(unused_attributes)] #![feature(range_contains)] -#![feature(libc)] +#![cfg_attr(unix, feature(libc))] #![feature(conservative_impl_trait)] extern crate term; +#[cfg(unix)] extern crate libc; extern crate serialize as rustc_serialize; extern crate syntax_pos; @@ -35,11 +33,12 @@ use emitter::{Emitter, EmitterWriter}; use std::borrow::Cow; use std::cell::{RefCell, Cell}; -use std::{error, fmt}; +use std::mem; use std::rc::Rc; +use std::{error, fmt}; -pub mod diagnostic; -pub mod diagnostic_builder; +mod diagnostic; +mod diagnostic_builder; pub mod emitter; mod snippet; pub mod registry; @@ -111,7 +110,7 @@ impl CodeSuggestion { } /// Returns the number of substitutions - pub fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a { + fn substitution_spans<'a>(&'a self) -> impl Iterator<Item = Span> + 'a { self.substitution_parts.iter().map(|sub| sub.span) } @@ -155,8 +154,8 @@ impl CodeSuggestion { let lo = primary_spans.iter().map(|sp| sp.0.lo).min().unwrap(); let hi = primary_spans.iter().map(|sp| sp.0.hi).min().unwrap(); let bounding_span = Span { - lo: lo, - hi: hi, + lo, + hi, ctxt: NO_EXPANSION, }; let lines = cm.span_to_lines(bounding_span).unwrap(); @@ -217,8 +216,10 @@ impl CodeSuggestion { if !buf.ends_with('\n') { push_trailing(buf, prev_line.as_ref(), &prev_hi, None); } - // remove trailing newline - buf.pop(); + // remove trailing newlines + while buf.ends_with('\n') { + buf.pop(); + } } bufs } @@ -260,7 +261,7 @@ impl error::Error for ExplicitBug { } } -pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString, StringPart}; +pub use diagnostic::{Diagnostic, SubDiagnostic, DiagnosticStyledString}; pub use diagnostic_builder::DiagnosticBuilder; /// A handler deals with errors; certain errors @@ -272,7 +273,8 @@ pub struct Handler { pub can_emit_warnings: bool, treat_err_as_bug: bool, continue_after_error: Cell<bool>, - delayed_span_bug: RefCell<Option<(MultiSpan, String)>>, + delayed_span_bug: RefCell<Option<Diagnostic>>, + tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>, } impl Handler { @@ -292,10 +294,11 @@ impl Handler { Handler { err_count: Cell::new(0), emitter: RefCell::new(e), - can_emit_warnings: can_emit_warnings, - treat_err_as_bug: treat_err_as_bug, + can_emit_warnings, + treat_err_as_bug, continue_after_error: Cell::new(true), delayed_span_bug: RefCell::new(None), + tracked_diagnostics: RefCell::new(None), } } @@ -437,8 +440,9 @@ impl Handler { if self.treat_err_as_bug { self.span_bug(sp, msg); } - let mut delayed = self.delayed_span_bug.borrow_mut(); - *delayed = Some((sp.into(), msg.to_string())); + let mut diagnostic = Diagnostic::new(Level::Bug, msg); + diagnostic.set_span(sp.into()); + *self.delayed_span_bug.borrow_mut() = Some(diagnostic); } pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { self.emit(&sp.into(), msg, Bug); @@ -489,7 +493,7 @@ impl Handler { self.bug(&format!("unimplemented {}", msg)); } - pub fn bump_err_count(&self) { + fn bump_err_count(&self) { self.panic_if_treat_err_as_bug(); self.err_count.set(self.err_count.get() + 1); } @@ -505,14 +509,9 @@ impl Handler { let s; match self.err_count.get() { 0 => { - let delayed_bug = self.delayed_span_bug.borrow(); - match *delayed_bug { - Some((ref span, ref errmsg)) => { - self.span_bug(span.clone(), errmsg); - } - _ => {} + if let Some(bug) = self.delayed_span_bug.borrow_mut().take() { + DiagnosticBuilder::new_diagnostic(self, bug).emit(); } - return; } 1 => s = "aborting due to previous error".to_string(), @@ -545,6 +544,24 @@ impl Handler { self.abort_if_errors(); } } + + pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>) + where F: FnOnce() -> R + { + let prev = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), + Some(Vec::new())); + let ret = f(); + let diagnostics = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), prev) + .unwrap(); + (ret, diagnostics) + } + + fn emit_db(&self, db: &DiagnosticBuilder) { + if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() { + list.push((**db).clone()); + } + self.emitter.borrow_mut().emit(db); + } } @@ -569,7 +586,7 @@ impl fmt::Display for Level { } impl Level { - pub fn color(self) -> term::color::Color { + fn color(self) -> term::color::Color { match self { Bug | Fatal | PhaseFatal | Error => term::color::BRIGHT_RED, Warning => { @@ -596,12 +613,3 @@ impl Level { } } } - -pub fn expect<T, M>(diag: &Handler, opt: Option<T>, msg: M) -> T - where M: FnOnce() -> String -{ - match opt { - Some(t) => t, - None => diag.bug(&msg()), - } -} diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index 3c5a6c031e1..52e3fcc1b47 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -141,7 +141,7 @@ pub struct Annotation { } impl Annotation { - /// Wether this annotation is a vertical line placeholder. + /// Whether this annotation is a vertical line placeholder. pub fn is_line(&self) -> bool { if let AnnotationType::MultilineLine(_) = self.annotation_type { true diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 04192c35ef3..1d58d179960 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -76,7 +76,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // Find annotations supplied by user (if any). let (if_this_changed, then_this_would_need) = { - let mut visitor = IfThisChanged { tcx: tcx, + let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; visitor.process_attrs(ast::CRATE_NODE_ID, &tcx.hir.krate().attrs); diff --git a/src/librustc_incremental/calculate_svh/mod.rs b/src/librustc_incremental/calculate_svh/mod.rs index f30a0f553b9..94400890c56 100644 --- a/src/librustc_incremental/calculate_svh/mod.rs +++ b/src/librustc_incremental/calculate_svh/mod.rs @@ -62,10 +62,6 @@ impl IncrementalHashesMap { } } - pub fn get(&self, k: &DepNode) -> Option<&Fingerprint> { - self.hashes.get(k) - } - pub fn insert(&mut self, k: DepNode, v: Fingerprint) { assert!(self.hashes.insert(k, v).is_none()); } diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index ac3149b90b8..8870033095c 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -10,9 +10,6 @@ //! Support for serializing the dep-graph and reloading it. -#![crate_name = "rustc_incremental"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -44,4 +41,3 @@ pub use persist::save_trans_partition; pub use persist::save_work_products; pub use persist::in_incr_comp_dir; pub use persist::finalize_session_directory; -pub use persist::delete_workproduct_files; diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 3f3dc10365c..126057fd043 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -83,15 +83,15 @@ pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("query-nodes: {:?}", query.nodes()); let krate = tcx.hir.krate(); let mut dirty_clean_visitor = DirtyCleanVisitor { - tcx: tcx, + tcx, query: &query, - dirty_inputs: dirty_inputs, + dirty_inputs, checked_attrs: FxHashSet(), }; krate.visit_all_item_likes(&mut dirty_clean_visitor); let mut all_attrs = FindAllAttrs { - tcx: tcx, + tcx, attr_names: vec![ATTR_DIRTY, ATTR_CLEAN], found_attrs: vec![], }; @@ -243,15 +243,15 @@ pub fn check_dirty_clean_metadata<'a, 'tcx>( tcx.dep_graph.with_ignore(||{ let krate = tcx.hir.krate(); let mut dirty_clean_visitor = DirtyCleanMetadataVisitor { - tcx: tcx, - prev_metadata_hashes: prev_metadata_hashes, - current_metadata_hashes: current_metadata_hashes, + tcx, + prev_metadata_hashes, + current_metadata_hashes, checked_attrs: FxHashSet(), }; intravisit::walk_crate(&mut dirty_clean_visitor, krate); let mut all_attrs = FindAllAttrs { - tcx: tcx, + tcx, attr_names: vec![ATTR_DIRTY_METADATA, ATTR_CLEAN_METADATA], found_attrs: vec![], }; diff --git a/src/librustc_incremental/persist/hash.rs b/src/librustc_incremental/persist/hash.rs index 0e8ffb9ee3c..9d762a74bfe 100644 --- a/src/librustc_incremental/persist/hash.rs +++ b/src/librustc_incremental/persist/hash.rs @@ -38,8 +38,8 @@ impl<'a, 'tcx> HashContext<'a, 'tcx> { incremental_hashes_map: &'a IncrementalHashesMap) -> Self { HashContext { - tcx: tcx, - incremental_hashes_map: incremental_hashes_map, + tcx, + incremental_hashes_map, metadata_hashes: FxHashMap(), crate_hashes: FxHashMap(), } diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs index c03a0ab4ba2..5c1582daa78 100644 --- a/src/librustc_incremental/persist/mod.rs +++ b/src/librustc_incremental/persist/mod.rs @@ -28,4 +28,3 @@ pub use self::load::load_dep_graph; pub use self::save::save_dep_graph; pub use self::save::save_work_products; pub use self::work_product::save_trans_partition; -pub use self::work_product::delete_workproduct_files; diff --git a/src/librustc_incremental/persist/preds/compress/classify/mod.rs b/src/librustc_incremental/persist/preds/compress/classify/mod.rs index 559bdbdd1e2..aa29afd543c 100644 --- a/src/librustc_incremental/persist/preds/compress/classify/mod.rs +++ b/src/librustc_incremental/persist/preds/compress/classify/mod.rs @@ -45,7 +45,7 @@ impl<'a, 'g, N, I, O> Classify<'a, 'g, N, I, O> { pub(super) fn new(r: &'a mut GraphReduce<'g, N, I, O>) -> Self { Classify { - r: r, + r, colors: vec![Color::White; r.in_graph.len_nodes()], stack: vec![], dag: Dag { diff --git a/src/librustc_incremental/persist/preds/compress/construct.rs b/src/librustc_incremental/persist/preds/compress/construct.rs index 394be74f783..0ad8d178916 100644 --- a/src/librustc_incremental/persist/preds/compress/construct.rs +++ b/src/librustc_incremental/persist/preds/compress/construct.rs @@ -14,7 +14,7 @@ //! representation of the DAG): //! //! - SCCs, in the form of a union-find repr that can convert each node to -//! its *cycle head* (an arbitrarly chosen representative from the cycle) +//! its *cycle head* (an arbitrarily chosen representative from the cycle) //! - a vector of *leaf nodes*, just a convenience //! - a vector of *parents* for each node (in some cases, nodes have no parents, //! or their parent is another member of same cycle; in that case, the vector diff --git a/src/librustc_incremental/persist/preds/mod.rs b/src/librustc_incremental/persist/preds/mod.rs index f7b6b7376d1..5483134523c 100644 --- a/src/librustc_incremental/persist/preds/mod.rs +++ b/src/librustc_incremental/persist/preds/mod.rs @@ -103,8 +103,8 @@ impl<'q> Predecessors<'q> { Predecessors { reduced_graph: graph, - bootstrap_outputs: bootstrap_outputs, - hashes: hashes, + bootstrap_outputs, + hashes, } } } diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 8f99ce91a67..e20d7a006b0 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -57,7 +57,7 @@ pub fn save_trans_partition(sess: &Session, let work_product = WorkProduct { cgu_name: cgu_name.to_string(), input_hash: partition_hash, - saved_files: saved_files, + saved_files, }; sess.dep_graph.insert_work_product(&work_product_id, work_product); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 83c00c178a0..5ef277f02ac 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -19,9 +19,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_lint"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -45,10 +42,10 @@ extern crate rustc_back; extern crate rustc_const_eval; extern crate syntax_pos; -pub use rustc::lint; -pub use rustc::middle; -pub use rustc::session; -pub use rustc::util; +use rustc::lint; +use rustc::middle; +use rustc::session; +use rustc::util; use session::Session; use lint::LintId; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 195bd2acce0..cbc4ebe90fd 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -160,21 +160,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { }; let mut fn_warned = false; - let maybe_def = match expr.node { - hir::ExprCall(ref callee, _) => { - match callee.node { - hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)), - _ => None - } - }, - hir::ExprMethodCall(..) => { - cx.tables.type_dependent_defs().get(expr.hir_id).cloned() - }, - _ => { None } - }; - if let Some(def) = maybe_def { - let def_id = def.def_id(); - fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + if cx.tcx.sess.features.borrow().fn_must_use { + let maybe_def = match expr.node { + hir::ExprCall(ref callee, _) => { + match callee.node { + hir::ExprPath(ref qpath) => { + Some(cx.tables.qpath_def(qpath, callee.hir_id)) + }, + _ => None + } + }, + hir::ExprMethodCall(..) => { + cx.tables.type_dependent_defs().get(expr.hir_id).cloned() + }, + _ => None + }; + if let Some(def) = maybe_def { + let def_id = def.def_id(); + fn_warned = check_must_use(cx, def_id, s.span, "return value of "); + } } if !(ty_warned || fn_warned) { diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index 0b24e55541b..6c3626cd880 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -94,7 +94,7 @@ impl<'a> Iterator for Iter<'a> { ::last_error().map(Err) } else { Some(Ok(Child { - ptr: ptr, + ptr, _data: marker::PhantomData, })) } diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_llvm/diagnostic.rs index c5276e0c971..c5cdf656692 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_llvm/diagnostic.rs @@ -82,12 +82,12 @@ impl OptimizationDiagnostic { } OptimizationDiagnostic { - kind: kind, + kind, pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"), - function: function, - line: line, - column: column, - filename: filename, + function, + line, + column, + filename, message: message.expect("got a non-UTF8 OptimizationDiagnostic message from LLVM") } } diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 5b823f91f5f..3c3e627ee4b 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -13,9 +13,6 @@ #![allow(non_snake_case)] #![allow(dead_code)] -#![crate_name = "rustc_llvm"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -38,9 +35,7 @@ pub use self::TypeKind::*; pub use self::AtomicRmwBinOp::*; pub use self::MetadataType::*; pub use self::CodeGenOptSize::*; -pub use self::DiagnosticKind::*; pub use self::CallConv::*; -pub use self::DiagnosticSeverity::*; pub use self::Linkage::*; use std::str::FromStr; @@ -51,7 +46,7 @@ use libc::{c_uint, c_char, size_t}; pub mod archive_ro; pub mod diagnostic; -pub mod ffi; +mod ffi; pub use ffi::*; @@ -120,7 +115,7 @@ impl FromStr for ArchiveKind { #[allow(missing_copy_implementations)] pub enum RustString_opaque {} -pub type RustStringRef = *mut RustString_opaque; +type RustStringRef = *mut RustString_opaque; type RustStringRepr = *mut RefCell<Vec<u8>>; /// Appending to a Rust string -- used by RawRustStringOstream. @@ -199,8 +194,8 @@ impl Attribute { // Memory-managed interface to target data. -pub struct TargetData { - pub lltd: TargetDataRef, +struct TargetData { + lltd: TargetDataRef, } impl Drop for TargetData { @@ -211,7 +206,7 @@ impl Drop for TargetData { } } -pub fn mk_target_data(string_rep: &str) -> TargetData { +fn mk_target_data(string_rep: &str) -> TargetData { let string_rep = CString::new(string_rep).unwrap(); TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } } } @@ -272,7 +267,7 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef { } } -pub fn get_params(llfn: ValueRef) -> Vec<ValueRef> { +fn get_params(llfn: ValueRef) -> Vec<ValueRef> { unsafe { let num_params = LLVMCountParams(llfn); let mut params = Vec::with_capacity(num_params as usize); diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 67b459ea18f..40b75be36fe 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -15,7 +15,6 @@ owning_ref = "0.3.3" proc_macro = { path = "../libproc_macro" } rustc = { path = "../librustc" } rustc_back = { path = "../librustc_back" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } serialize = { path = "../libserialize" } diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 6c02ac7eafe..b1b3e92347a 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -53,7 +53,7 @@ impl<'a, 'b, 'tcx> IsolatedEncoder<'a, 'b, 'tcx> { body: lazy_body, tables: lazy_tables, nested_bodies: lazy_nested_bodies, - rvalue_promotable_to_static: rvalue_promotable_to_static + rvalue_promotable_to_static, }) } } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index d15843b4f31..4c25d03b441 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -162,8 +162,8 @@ enum LoadResult { impl<'a> CrateLoader<'a> { pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self { CrateLoader { - sess: sess, - cstore: cstore, + sess, + cstore, next_crate_num: cstore.next_crate_num(), local_crate_name: Symbol::intern(local_crate_name), } @@ -184,7 +184,7 @@ impl<'a> CrateLoader<'a> { }; Some(ExternCrateInfo { ident: i.ident.name, - name: name, + name, id: i.id, dep_kind: if attr::contains_name(&i.attrs, "no_link") { DepKind::UnexportedMacrosOnly @@ -325,25 +325,25 @@ impl<'a> CrateLoader<'a> { }); let mut cmeta = cstore::CrateMetadata { - name: name, + name, extern_crate: Cell::new(None), def_path_table: Rc::new(def_path_table), - exported_symbols: exported_symbols, - trait_impls: trait_impls, + exported_symbols, + trait_impls, proc_macros: crate_root.macro_derive_registrar.map(|_| { self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) }), root: crate_root, blob: metadata, cnum_map: RefCell::new(cnum_map), - cnum: cnum, + cnum, codemap_import_info: RefCell::new(vec![]), attribute_cache: RefCell::new([Vec::new(), Vec::new()]), dep_kind: Cell::new(dep_kind), source: cstore::CrateSource { - dylib: dylib, - rlib: rlib, - rmeta: rmeta, + dylib, + rlib, + rmeta, }, // Initialize this with an empty set. The field is populated below // after we were able to deserialize its contents. @@ -388,14 +388,14 @@ impl<'a> CrateLoader<'a> { info!("falling back to a load"); let mut locate_ctxt = locator::Context { sess: self.sess, - span: span, - ident: ident, + span, + ident, crate_name: name, hash: hash.map(|a| &*a), filesearch: self.sess.target_filesearch(path_kind), target: &self.sess.target.target, triple: &self.sess.opts.target_triple, - root: root, + root, rejected_via_hash: vec![], rejected_via_triple: vec![], rejected_via_kind: vec![], @@ -547,7 +547,7 @@ impl<'a> CrateLoader<'a> { let mut target_only = false; let mut locate_ctxt = locator::Context { sess: self.sess, - span: span, + span, ident: info.ident, crate_name: info.name, hash: None, @@ -596,9 +596,9 @@ impl<'a> CrateLoader<'a> { }; ExtensionCrate { - metadata: metadata, + metadata, dylib: dylib.map(|p| p.0), - target_only: target_only, + target_only, } } @@ -1221,9 +1221,9 @@ impl<'a> CrateLoader<'a> { .collect(); let lib = NativeLibrary { name: n, - kind: kind, - cfg: cfg, - foreign_items: foreign_items, + kind, + cfg, + foreign_items, }; register_native_lib(self.sess, self.cstore, Some(m.span), lib); } diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index fb43f91c46d..0ed8ab2bc55 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -32,7 +32,7 @@ use syntax_pos; pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference}; pub use rustc::middle::cstore::NativeLibraryKind::*; -pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource}; +pub use rustc::middle::cstore::{CrateSource, LibSource}; pub use cstore_impl::{provide, provide_local}; @@ -114,7 +114,7 @@ impl CStore { statically_included_foreign_items: RefCell::new(FxHashSet()), dllimport_foreign_items: RefCell::new(FxHashSet()), visible_parent_map: RefCell::new(FxHashMap()), - metadata_loader: metadata_loader, + metadata_loader, } } @@ -142,14 +142,6 @@ impl CStore { } } - pub fn reset(&self) { - self.metas.borrow_mut().clear(); - self.extern_mod_crate_map.borrow_mut().clear(); - self.used_libraries.borrow_mut().clear(); - self.used_link_args.borrow_mut().clear(); - self.statically_included_foreign_items.borrow_mut().clear(); - } - pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> { let mut ordering = Vec::new(); self.push_dependencies_in_postorder(&mut ordering, krate); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index d2ab9b2fbce..ad320a7ff3d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -137,6 +137,8 @@ provide! { <'tcx> tcx, def_id, cdata, dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) } is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) } + is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) } + has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) } extern_crate => { Rc::new(cdata.extern_crate.get()) } } @@ -282,7 +284,7 @@ impl CrateStore for cstore::CStore { { self.get_crate_data(cnum).root.plugin_registrar_fn.map(|index| DefId { krate: cnum, - index: index + index, }) } @@ -290,7 +292,7 @@ impl CrateStore for cstore::CStore { { self.get_crate_data(cnum).root.macro_derive_registrar.map(|index| DefId { krate: cnum, - index: index + index, }) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ad3a9dd9fef..73b2e972b93 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -69,7 +69,7 @@ pub trait Metadata<'a, 'tcx>: Copy { opaque: opaque::Decoder::new(self.raw_bytes(), pos), cdata: self.cdata(), sess: self.sess().or(tcx.map(|tcx| tcx.sess)), - tcx: tcx, + tcx, last_filemap_index: 0, lazy_state: LazyState::NoNode, } @@ -468,7 +468,7 @@ impl<'a, 'tcx> CrateMetadata { fn local_def_id(&self, index: DefIndex) -> DefId { DefId { krate: self.cnum, - index: index, + index, } } @@ -703,7 +703,7 @@ impl<'a, 'tcx> CrateMetadata { for child_index in child.children.decode((self, sess)) { if let Some(def) = self.get_def(child_index) { callback(def::Export { - def: def, + def, ident: Ident::with_empty_ctxt(self.item_name(child_index)), span: self.entry(child_index).span.decode((self, sess)), }); @@ -835,8 +835,8 @@ impl<'a, 'tcx> CrateMetadata { }; ty::AssociatedItem { - name: name, - kind: kind, + name, + kind, vis: item.visibility.decode(self), defaultness: container.defaultness(), def_id: self.local_def_id(id), @@ -892,7 +892,7 @@ impl<'a, 'tcx> CrateMetadata { if def_key.disambiguated_data.data == DefPathData::StructCtor { item = self.entry(def_key.parent.unwrap()); } - let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice()); + let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item)); let vec_ = &mut self.attribute_cache.borrow_mut()[node_as]; if vec_.len() < node_index + 1 { vec_.resize(node_index + 1, None); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 8a753a0ae4b..1dc5d695348 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -422,16 +422,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { None }, - crate_deps: crate_deps, - dylib_dependency_formats: dylib_dependency_formats, - lang_items: lang_items, - lang_items_missing: lang_items_missing, - native_libraries: native_libraries, - codemap: codemap, - def_path_table: def_path_table, - impls: impls, - exported_symbols: exported_symbols, - index: index, + crate_deps, + dylib_dependency_formats, + lang_items, + lang_items_missing, + native_libraries, + codemap, + def_path_table, + impls, + exported_symbols, + index, }); let total_bytes = self.position(); @@ -719,15 +719,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; FnData { constness: hir::Constness::NotConst, - arg_names: arg_names, + arg_names, sig: self.lazy(&tcx.fn_sig(def_id)), } } else { bug!() }; EntryKind::Method(self.lazy(&MethodData { - fn_data: fn_data, - container: container, + fn_data, + container, has_self: trait_item.method_has_self_argument, })) } @@ -735,7 +735,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; Entry { - kind: kind, + kind, visibility: self.lazy(&trait_item.vis), span: self.lazy(&ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), @@ -805,8 +805,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { bug!() }; EntryKind::Method(self.lazy(&MethodData { - fn_data: fn_data, - container: container, + fn_data, + container, has_self: impl_item.method_has_self_argument, })) } @@ -828,7 +828,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; Entry { - kind: kind, + kind, visibility: self.lazy(&impl_item.vis), span: self.lazy(&ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), @@ -915,7 +915,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } hir::ItemFn(_, _, constness, .., body) => { let data = FnData { - constness: constness, + constness, arg_names: self.encode_fn_arg_names_for_body(body), sig: self.lazy(&tcx.fn_sig(def_id)), }; @@ -946,7 +946,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Struct(self.lazy(&VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, - struct_ctor: struct_ctor, + struct_ctor, ctor_sig: None, }), repr_options) } @@ -998,10 +998,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }); let data = ImplData { - polarity: polarity, - defaultness: defaultness, + polarity, + defaultness, parent_impl: parent, - coerce_unsized_info: coerce_unsized_info, + coerce_unsized_info, trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)), }; @@ -1023,7 +1023,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; Entry { - kind: kind, + kind, visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.id, tcx)), span: self.lazy(&item.span), attributes: self.encode_attributes(&item.attrs), @@ -1333,7 +1333,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { debug!("IsolatedEncoder::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { - tcx: tcx, + tcx, impls: FxHashMap(), }; tcx.hir.krate().visit_all_item_likes(&mut visitor); @@ -1412,7 +1412,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { }; Entry { - kind: kind, + kind, visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.id, tcx)), span: self.lazy(&nitem.span), attributes: self.encode_attributes(&nitem.attrs), @@ -1653,14 +1653,14 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (root, metadata_hashes) = { let mut ecx = EncodeContext { opaque: opaque::Encoder::new(&mut cursor), - tcx: tcx, - link_meta: link_meta, - exported_symbols: exported_symbols, + tcx, + link_meta, + exported_symbols, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), metadata_hashes: EncodedMetadataHashes::new(), - compute_ich: compute_ich, + compute_ich, }; // Encode the rustc version string in a predictable location. diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index ebf9910e9c9..69fbc935461 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -100,32 +100,6 @@ impl<'tcx> LazySeq<Index> { Some(Lazy::with_position(position as usize)) } } - - pub fn iter_enumerated<'a>(&self, - bytes: &'a [u8]) - -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a { - let words = &bytes_to_words(&bytes[self.position..])[..self.len]; - let lo_count = u32::from_le(words[0].get()) as usize; - let lo = &words[1 .. lo_count + 1]; - let hi = &words[1 + lo_count ..]; - - lo.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| { - if pos == u32::MAX { - None - } else { - let pos = u32::from_le(pos) as usize; - Some((DefIndex::new(index), Lazy::with_position(pos))) - } - }).chain(hi.iter().map(|word| word.get()).enumerate().filter_map(|(index, pos)| { - if pos == u32::MAX { - None - } else { - let pos = u32::from_le(pos) as usize; - Some((DefIndex::new(index + DefIndexAddressSpace::High.start()), - Lazy::with_position(pos))) - } - })) - } } #[repr(packed)] diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 2db9c6a4ff8..1d2b6cc33d4 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -92,7 +92,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { IndexBuilder { items: Index::new(ecx.tcx.hir.definitions().def_index_counts_lo_hi()), - ecx: ecx, + ecx, } } @@ -137,7 +137,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { if let Some(hash) = fingerprint { ecx.metadata_hashes.hashes.push(EncodedMetadataHash { def_index: id.index, - hash: hash, + hash, }); } diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs index c4116489357..b9ad9086c03 100644 --- a/src/librustc_metadata/isolated_encoder.rs +++ b/src/librustc_metadata/isolated_encoder.rs @@ -32,8 +32,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { let tcx = ecx.tcx; let compute_ich = ecx.compute_ich; IsolatedEncoder { - tcx: tcx, - ecx: ecx, + tcx, + ecx, hcx: if compute_ich { // We are always hashing spans for things in metadata because // don't know if a downstream crate will use them or not. diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 99b718ea07b..f79abecf9da 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_metadata"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -42,13 +39,10 @@ extern crate proc_macro; #[macro_use] extern crate rustc; extern crate rustc_back; -extern crate rustc_const_math; extern crate rustc_data_structures; mod diagnostics; -pub use rustc::middle; - mod astencode; mod index_builder; mod index; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 9bcf590eb8b..19f7cb0ee23 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -306,10 +306,6 @@ impl<'a> Context<'a> { self.find_library_crate() } - pub fn load_library_crate(&mut self) -> Library { - self.find_library_crate().unwrap_or_else(|| self.report_errs()) - } - pub fn report_errs(&mut self) -> ! { let add = match self.root { &None => String::new(), @@ -518,9 +514,9 @@ impl<'a> Context<'a> { if let Some((h, m)) = slot { libraries.insert(h, Library { - dylib: dylib, - rlib: rlib, - rmeta: rmeta, + dylib, + rlib, + rmeta, metadata: m, }); } @@ -808,10 +804,10 @@ impl<'a> Context<'a> { match slot { Some((_, metadata)) => { Some(Library { - dylib: dylib, - rlib: rlib, - rmeta: rmeta, - metadata: metadata, + dylib, + rlib, + rmeta, + metadata, }) } None => None, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 0b670121ba2..b71f4d0d98c 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -84,7 +84,7 @@ pub struct Lazy<T> { impl<T> Lazy<T> { pub fn with_position(position: usize) -> Lazy<T> { Lazy { - position: position, + position, _marker: PhantomData, } } @@ -141,8 +141,8 @@ impl<T> LazySeq<T> { pub fn with_position_and_length(position: usize, len: usize) -> LazySeq<T> { LazySeq { - len: len, - position: position, + len, + position, _marker: PhantomData, } } @@ -199,7 +199,7 @@ pub struct Tracked<T> { impl<T> Tracked<T> { pub fn new(state: T) -> Tracked<T> { Tracked { - state: state, + state, } } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 6e42e02d510..49e626c5400 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,6 +15,7 @@ rustc = { path = "../librustc" } rustc_const_eval = { path = "../librustc_const_eval" } rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } rustc_bitflags = { path = "../librustc_bitflags" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs new file mode 100644 index 00000000000..eda2bacb11f --- /dev/null +++ b/src/librustc_mir/borrow_check.rs @@ -0,0 +1,1258 @@ +// 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. + +//! This query borrow-checks the MIR to (further) ensure it is not broken. + +use rustc::hir::def_id::{DefId}; +use rustc::infer::{InferCtxt}; +use rustc::ty::{self, TyCtxt, ParamEnv}; +use rustc::ty::maps::Providers; +use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Lvalue}; +use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; +use rustc::mir::{Statement, StatementKind, Terminator, TerminatorKind}; +use rustc::mir::transform::{MirSource}; + +use rustc_data_structures::indexed_set::{self, IdxSetBuf}; +use rustc_data_structures::indexed_vec::{Idx}; + +use syntax::ast::{self}; +use syntax_pos::{DUMMY_SP, Span}; + +use dataflow::{do_dataflow}; +use dataflow::{MoveDataParamEnv}; +use dataflow::{BitDenotation, BlockSets, DataflowResults, DataflowResultsConsumer}; +use dataflow::{MaybeInitializedLvals, MaybeUninitializedLvals}; +use dataflow::{Borrows, BorrowData, BorrowIndex}; +use dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex, LookupResult}; +use util::borrowck_errors::{BorrowckErrors, Origin}; + +use self::MutateMode::{JustWrite, WriteAndRead}; +use self::ConsumeKind::{Consume}; + + +pub fn provide(providers: &mut Providers) { + *providers = Providers { + mir_borrowck, + ..*providers + }; +} + +fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { + let mir = tcx.mir_validated(def_id); + let src = MirSource::from_local_def_id(tcx, def_id); + debug!("run query mir_borrowck: {}", tcx.node_path_str(src.item_id())); + + let mir: &Mir<'tcx> = &mir.borrow(); + if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.opts.debugging_opts.borrowck_mir { + return; + } + + let id = src.item_id(); + let attributes = tcx.get_attrs(def_id); + let param_env = tcx.param_env(def_id); + tcx.infer_ctxt().enter(|_infcx| { + + let move_data = MoveData::gather_moves(mir, tcx, param_env); + let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len()); + let flow_borrows = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + Borrows::new(tcx, mir), + |bd, i| bd.location(i)); + let flow_inits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeInitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + let flow_uninits = do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + MaybeUninitializedLvals::new(tcx, mir, &mdpe), + |bd, i| &bd.move_data().move_paths[i]); + + let mut mbcx = MirBorrowckCtxt { + tcx: tcx, + mir: mir, + node_id: id, + move_data: &mdpe.move_data, + param_env: param_env, + fake_infer_ctxt: &_infcx, + }; + + let mut state = InProgress::new(flow_borrows, + flow_inits, + flow_uninits); + + mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer + }); + + debug!("mir_borrowck done"); +} + +#[allow(dead_code)] +pub struct MirBorrowckCtxt<'c, 'b, 'a: 'b+'c, 'gcx: 'a+'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'gcx>, + mir: &'b Mir<'gcx>, + node_id: ast::NodeId, + move_data: &'b MoveData<'gcx>, + param_env: ParamEnv<'tcx>, + fake_infer_ctxt: &'c InferCtxt<'c, 'gcx, 'tcx>, +} + +// (forced to be `pub` due to its use as an associated type below.) +pub struct InProgress<'b, 'tcx: 'b> { + borrows: FlowInProgress<Borrows<'b, 'tcx>>, + inits: FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>, + uninits: FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>, +} + +struct FlowInProgress<BD> where BD: BitDenotation { + base_results: DataflowResults<BD>, + curr_state: IdxSetBuf<BD::Idx>, + stmt_gen: IdxSetBuf<BD::Idx>, + stmt_kill: IdxSetBuf<BD::Idx>, +} + +// Check that: +// 1. assignments are always made to mutable locations (FIXME: does that still really go here?) +// 2. loans made in overlapping scopes do not conflict +// 3. assignments do not affect things loaned out as immutable +// 4. moves do not affect things loaned out in any way +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx> + for MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> +{ + type FlowState = InProgress<'b, 'gcx>; + + fn mir(&self) -> &'b Mir<'gcx> { self.mir } + + fn reset_to_entry_of(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) { + flow_state.each_flow(|b| b.reset_to_entry_of(bb), + |i| i.reset_to_entry_of(bb), + |u| u.reset_to_entry_of(bb)); + } + + fn reconstruct_statement_effect(&mut self, + location: Location, + flow_state: &mut Self::FlowState) { + flow_state.each_flow(|b| b.reconstruct_statement_effect(location), + |i| i.reconstruct_statement_effect(location), + |u| u.reconstruct_statement_effect(location)); + } + + fn apply_local_effect(&mut self, + _location: Location, + flow_state: &mut Self::FlowState) { + flow_state.each_flow(|b| b.apply_local_effect(), + |i| i.apply_local_effect(), + |u| u.apply_local_effect()); + } + + fn reconstruct_terminator_effect(&mut self, + location: Location, + flow_state: &mut Self::FlowState) { + flow_state.each_flow(|b| b.reconstruct_terminator_effect(location), + |i| i.reconstruct_terminator_effect(location), + |u| u.reconstruct_terminator_effect(location)); + } + + fn visit_block_entry(&mut self, + bb: BasicBlock, + flow_state: &Self::FlowState) { + let summary = flow_state.summary(); + debug!("MirBorrowckCtxt::process_block({:?}): {}", bb, summary); + } + + fn visit_statement_entry(&mut self, + location: Location, + stmt: &Statement<'gcx>, + flow_state: &Self::FlowState) { + let summary = flow_state.summary(); + debug!("MirBorrowckCtxt::process_statement({:?}, {:?}): {}", location, stmt, summary); + let span = stmt.source_info.span; + match stmt.kind { + StatementKind::Assign(ref lhs, ref rhs) => { + self.mutate_lvalue(ContextKind::AssignLhs.new(location), + (lhs, span), JustWrite, flow_state); + self.consume_rvalue(ContextKind::AssignRhs.new(location), + (rhs, span), location, flow_state); + } + StatementKind::SetDiscriminant { ref lvalue, variant_index: _ } => { + self.mutate_lvalue(ContextKind::SetDiscrim.new(location), + (lvalue, span), JustWrite, flow_state); + } + StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => { + for (o, output) in asm.outputs.iter().zip(outputs) { + if o.is_indirect { + self.consume_lvalue(ContextKind::InlineAsm.new(location), + Consume, + (output, span), + flow_state); + } else { + self.mutate_lvalue(ContextKind::InlineAsm.new(location), + (output, span), + if o.is_rw { WriteAndRead } else { JustWrite }, + flow_state); + } + } + for input in inputs { + self.consume_operand(ContextKind::InlineAsm.new(location), + Consume, + (input, span), flow_state); + } + } + StatementKind::EndRegion(ref _rgn) => { + // ignored when consuming results (update to + // flow_state already handled). + } + StatementKind::Nop | + StatementKind::Validate(..) | + StatementKind::StorageLive(..) => { + // ignored by borrowck + } + + StatementKind::StorageDead(ref lvalue) => { + // causes non-drop values to be dropped. + self.consume_lvalue(ContextKind::StorageDead.new(location), + ConsumeKind::Consume, + (lvalue, span), + flow_state) + } + } + } + + fn visit_terminator_entry(&mut self, + location: Location, + term: &Terminator<'gcx>, + flow_state: &Self::FlowState) { + let loc = location; + let summary = flow_state.summary(); + debug!("MirBorrowckCtxt::process_terminator({:?}, {:?}): {}", location, term, summary); + let span = term.source_info.span; + match term.kind { + TerminatorKind::SwitchInt { ref discr, switch_ty: _, values: _, targets: _ } => { + self.consume_operand(ContextKind::SwitchInt.new(loc), + Consume, + (discr, span), flow_state); + } + TerminatorKind::Drop { location: ref drop_lvalue, target: _, unwind: _ } => { + self.consume_lvalue(ContextKind::Drop.new(loc), + ConsumeKind::Drop, + (drop_lvalue, span), flow_state); + } + TerminatorKind::DropAndReplace { location: ref drop_lvalue, + value: ref new_value, + target: _, + unwind: _ } => { + self.mutate_lvalue(ContextKind::DropAndReplace.new(loc), + (drop_lvalue, span), JustWrite, flow_state); + self.consume_operand(ContextKind::DropAndReplace.new(loc), + ConsumeKind::Drop, + (new_value, span), flow_state); + } + TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => { + self.consume_operand(ContextKind::CallOperator.new(loc), + Consume, + (func, span), flow_state); + for arg in args { + self.consume_operand(ContextKind::CallOperand.new(loc), + Consume, + (arg, span), flow_state); + } + if let Some((ref dest, _/*bb*/)) = *destination { + self.mutate_lvalue(ContextKind::CallDest.new(loc), + (dest, span), JustWrite, flow_state); + } + } + TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { + self.consume_operand(ContextKind::Assert.new(loc), + Consume, + (cond, span), flow_state); + match *msg { + AssertMessage::BoundsCheck { ref len, ref index } => { + self.consume_operand(ContextKind::Assert.new(loc), + Consume, + (len, span), flow_state); + self.consume_operand(ContextKind::Assert.new(loc), + Consume, + (index, span), flow_state); + } + AssertMessage::Math(_/*const_math_err*/) => {} + } + } + + TerminatorKind::Goto { target: _ } | + TerminatorKind::Resume | + TerminatorKind::Return | + TerminatorKind::Unreachable => { + // no data used, thus irrelevant to borrowck + } + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum MutateMode { JustWrite, WriteAndRead } + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum ConsumeKind { Drop, Consume } + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum Control { Continue, Break } + +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + fn mutate_lvalue(&mut self, + context: Context, + lvalue_span: (&Lvalue<'gcx>, Span), + mode: MutateMode, + flow_state: &InProgress<'b, 'gcx>) { + // Write of P[i] or *P, or WriteAndRead of any P, requires P init'd. + match mode { + MutateMode::WriteAndRead => { + self.check_if_path_is_moved(context, lvalue_span, flow_state); + } + MutateMode::JustWrite => { + self.check_if_assigned_path_is_moved(context, lvalue_span, flow_state); + } + } + + // check we don't invalidate any outstanding loans + self.each_borrow_involving_path(context, + lvalue_span.0, flow_state, |this, _index, _data| { + this.report_illegal_mutation_of_borrowed(context, + lvalue_span); + Control::Break + }); + + // check for reassignments to immutable local variables + self.check_if_reassignment_to_immutable_state(context, lvalue_span, flow_state); + } + + fn consume_rvalue(&mut self, + context: Context, + (rvalue, span): (&Rvalue<'gcx>, Span), + location: Location, + flow_state: &InProgress<'b, 'gcx>) { + match *rvalue { + Rvalue::Ref(_/*rgn*/, bk, ref lvalue) => { + self.borrow(context, location, bk, (lvalue, span), flow_state) + } + + Rvalue::Use(ref operand) | + Rvalue::Repeat(ref operand, _) | + Rvalue::UnaryOp(_/*un_op*/, ref operand) | + Rvalue::Cast(_/*cast_kind*/, ref operand, _/*ty*/) => { + self.consume_operand(context, Consume, (operand, span), flow_state) + } + + Rvalue::Len(ref lvalue) | + Rvalue::Discriminant(ref lvalue) => { + // len(_)/discriminant(_) merely read, not consume. + self.check_if_path_is_moved(context, (lvalue, span), flow_state); + } + + Rvalue::BinaryOp(_bin_op, ref operand1, ref operand2) | + Rvalue::CheckedBinaryOp(_bin_op, ref operand1, ref operand2) => { + self.consume_operand(context, Consume, (operand1, span), flow_state); + self.consume_operand(context, Consume, (operand2, span), flow_state); + } + + Rvalue::NullaryOp(_op, _ty) => { + // nullary ops take no dynamic input; no borrowck effect. + // + // FIXME: is above actually true? Do we want to track + // the fact that uninitialized data can be created via + // `NullOp::Box`? + } + + Rvalue::Aggregate(ref _aggregate_kind, ref operands) => { + for operand in operands { + self.consume_operand(context, Consume, (operand, span), flow_state); + } + } + } + } + + fn consume_operand(&mut self, + context: Context, + consume_via_drop: ConsumeKind, + (operand, span): (&Operand<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + match *operand { + Operand::Consume(ref lvalue) => + self.consume_lvalue(context, consume_via_drop, (lvalue, span), flow_state), + Operand::Constant(_) => {} + } + } + + fn consume_lvalue(&mut self, + context: Context, + consume_via_drop: ConsumeKind, + lvalue_span: (&Lvalue<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + let lvalue = lvalue_span.0; + let ty = lvalue.ty(self.mir, self.tcx).to_ty(self.tcx); + let moves_by_default = + self.fake_infer_ctxt.type_moves_by_default(self.param_env, ty, DUMMY_SP); + if moves_by_default { + // move of lvalue: check if this is move of already borrowed path + self.each_borrow_involving_path( + context, lvalue_span.0, flow_state, |this, _idx, borrow| { + if !borrow.compatible_with(BorrowKind::Mut) { + this.report_move_out_while_borrowed(context, lvalue_span); + Control::Break + } else { + Control::Continue + } + }); + } else { + // copy of lvalue: check if this is "copy of frozen path" (FIXME: see check_loans.rs) + self.each_borrow_involving_path( + context, lvalue_span.0, flow_state, |this, _idx, borrow| { + if !borrow.compatible_with(BorrowKind::Shared) { + this.report_use_while_mutably_borrowed(context, lvalue_span); + Control::Break + } else { + Control::Continue + } + }); + } + + // Finally, check if path was already moved. + match consume_via_drop { + ConsumeKind::Drop => { + // If path is merely being dropped, then we'll already + // check the drop flag to see if it is moved (thus we + // skip this check in that case). + } + ConsumeKind::Consume => { + self.check_if_path_is_moved(context, lvalue_span, flow_state); + } + } + } + + fn borrow(&mut self, + context: Context, + location: Location, + bk: BorrowKind, + lvalue_span: (&Lvalue<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + debug!("borrow location: {:?} lvalue: {:?} span: {:?}", + location, lvalue_span.0, lvalue_span.1); + self.check_if_path_is_moved(context, lvalue_span, flow_state); + self.check_for_conflicting_loans(context, location, bk, lvalue_span, flow_state); + } +} + +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + fn check_if_reassignment_to_immutable_state(&mut self, + context: Context, + (lvalue, span): (&Lvalue<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + let move_data = flow_state.inits.base_results.operator().move_data(); + + // determine if this path has a non-mut owner (and thus needs checking). + let mut l = lvalue; + loop { + match *l { + Lvalue::Projection(ref proj) => { + l = &proj.base; + continue; + } + Lvalue::Local(local) => { + match self.mir.local_decls[local].mutability { + Mutability::Not => break, // needs check + Mutability::Mut => return, + } + } + Lvalue::Static(_) => { + // mutation of non-mut static is always illegal, + // independent of dataflow. + self.report_assignment_to_static(context, (lvalue, span)); + return; + } + } + } + + if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) { + if flow_state.inits.curr_state.contains(&mpi) { + // may already be assigned before reaching this statement; + // report error. + self.report_illegal_reassignment(context, (lvalue, span)); + } + } + } + + fn check_if_path_is_moved(&mut self, + context: Context, + lvalue_span: (&Lvalue<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + // FIXME: analogous code in check_loans first maps `lvalue` to + // its base_path ... but is that what we want here? + let lvalue = self.base_path(lvalue_span.0); + + let maybe_uninits = &flow_state.uninits; + let move_data = maybe_uninits.base_results.operator().move_data(); + if let Some(mpi) = self.move_path_for_lvalue(context, move_data, lvalue) { + if maybe_uninits.curr_state.contains(&mpi) { + // find and report move(s) that could cause this to be uninitialized + self.report_use_of_moved(context, lvalue_span); + } else { + // sanity check: initialized on *some* path, right? + assert!(flow_state.inits.curr_state.contains(&mpi)); + } + } + } + + fn move_path_for_lvalue(&mut self, + _context: Context, + move_data: &MoveData<'gcx>, + lvalue: &Lvalue<'gcx>) + -> Option<MovePathIndex> + { + // If returns None, then there is no move path corresponding + // to a direct owner of `lvalue` (which means there is nothing + // that borrowck tracks for its analysis). + + match move_data.rev_lookup.find(lvalue) { + LookupResult::Parent(_) => None, + LookupResult::Exact(mpi) => Some(mpi), + } + } + + fn check_if_assigned_path_is_moved(&mut self, + context: Context, + (lvalue, span): (&Lvalue<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + // recur down lvalue; dispatch to check_if_path_is_moved when necessary + let mut lvalue = lvalue; + loop { + match *lvalue { + Lvalue::Local(_) | Lvalue::Static(_) => { + // assigning to `x` does not require `x` be initialized. + break; + } + Lvalue::Projection(ref proj) => { + let Projection { ref base, ref elem } = **proj; + match *elem { + ProjectionElem::Deref | + // assigning to *P requires `P` initialized. + ProjectionElem::Index(_/*operand*/) | + ProjectionElem::ConstantIndex { .. } | + // assigning to P[i] requires `P` initialized. + ProjectionElem::Downcast(_/*adt_def*/, _/*variant_idx*/) => + // assigning to (P->variant) is okay if assigning to `P` is okay + // + // FIXME: is this true even if P is a adt with a dtor? + { } + + ProjectionElem::Subslice { .. } => { + panic!("we dont allow assignments to subslices, context: {:?}", + context); + } + + ProjectionElem::Field(..) => { + // if type of `P` has a dtor, then + // assigning to `P.f` requires `P` itself + // be already initialized + let tcx = self.tcx; + match base.ty(self.mir, tcx).to_ty(tcx).sty { + ty::TyAdt(def, _) if def.has_dtor(tcx) => { + + // FIXME: analogous code in + // check_loans.rs first maps + // `base` to its base_path. + + self.check_if_path_is_moved(context, + (base, span), flow_state); + + // (base initialized; no need to + // recur further) + break; + } + _ => {} + } + } + } + + lvalue = base; + continue; + } + } + } + } + + fn check_for_conflicting_loans(&mut self, + context: Context, + _location: Location, + _bk: BorrowKind, + lvalue_span: (&Lvalue<'gcx>, Span), + flow_state: &InProgress<'b, 'gcx>) { + // NOTE FIXME: The analogous code in old borrowck + // check_loans.rs is careful to iterate over every *issued* + // loan, as opposed to just the in scope ones. + // + // (Or if you prefer, all the *other* iterations over loans + // only consider loans that are in scope of some given + // CodeExtent) + // + // The (currently skeletal) code here does not encode such a + // distinction, which means it is almost certainly over + // looking something. + // + // (It is probably going to reject code that should be + // accepted, I suspect, by treated issued-but-out-of-scope + // loans as issued-and-in-scope, and thus causing them to + // interfere with other loans.) + // + // However, I just want to get something running, especially + // since I am trying to move into new territory with NLL, so + // lets get this going first, and then address the issued vs + // in-scope distinction later. + + let state = &flow_state.borrows; + let data = &state.base_results.operator().borrows(); + + debug!("check_for_conflicting_loans location: {:?}", _location); + + // does any loan generated here conflict with a previously issued loan? + let mut loans_generated = 0; + for (g, gen) in state.elems_generated().map(|g| (g, &data[g])) { + loans_generated += 1; + for (i, issued) in state.elems_incoming().map(|i| (i, &data[i])) { + debug!("check_for_conflicting_loans gen: {:?} issued: {:?} conflicts: {}", + (g, gen, self.base_path(&gen.lvalue), + self.restrictions(&gen.lvalue).collect::<Vec<_>>()), + (i, issued, self.base_path(&issued.lvalue), + self.restrictions(&issued.lvalue).collect::<Vec<_>>()), + self.conflicts_with(gen, issued)); + if self.conflicts_with(gen, issued) { + self.report_conflicting_borrow(context, lvalue_span, gen, issued); + } + } + } + + // MIR statically ensures each statement gens *at most one* + // loan; mutual conflict (within a statement) can't arise. + // + // As safe-guard, assert that above property actually holds. + assert!(loans_generated <= 1); + } } + +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + fn each_borrow_involving_path<F>(&mut self, + _context: Context, + lvalue: &Lvalue<'gcx>, + flow_state: &InProgress<'b, 'gcx>, + mut op: F) + where F: FnMut(&mut Self, BorrowIndex, &BorrowData<'gcx>) -> Control + { + // FIXME: analogous code in check_loans first maps `lvalue` to + // its base_path. + + let domain = flow_state.borrows.base_results.operator(); + let data = domain.borrows(); + + // check for loan restricting path P being used. Accounts for + // borrows of P, P.a.b, etc. + for i in flow_state.borrows.elems_incoming() { + // FIXME: check_loans.rs filtered this to "in scope" + // loans; i.e. it took a scope S and checked that each + // restriction's kill_scope was a superscope of S. + let borrowed = &data[i]; + for restricted in self.restrictions(&borrowed.lvalue) { + if restricted == lvalue { + let ctrl = op(self, i, borrowed); + if ctrl == Control::Break { return; } + } + } + } + + // check for loans (not restrictions) on any base path. + // e.g. Rejects `{ let x = &mut a.b; let y = a.b.c; }`, + // since that moves out of borrowed path `a.b`. + // + // Limiting to loans (not restrictions) keeps this one + // working: `{ let x = &mut a.b; let y = a.c; }` + let mut cursor = lvalue; + loop { + // FIXME: check_loans.rs invoked `op` *before* cursor + // shift here. Might just work (and even avoid redundant + // errors?) given code above? But for now, I want to try + // doing what I think is more "natural" check. + for i in flow_state.borrows.elems_incoming() { + let borrowed = &data[i]; + if borrowed.lvalue == *cursor { + let ctrl = op(self, i, borrowed); + if ctrl == Control::Break { return; } + } + } + + match *cursor { + Lvalue::Local(_) | Lvalue::Static(_) => break, + Lvalue::Projection(ref proj) => cursor = &proj.base, + } + } + } +} + +mod restrictions { + use super::MirBorrowckCtxt; + + use rustc::hir; + use rustc::ty::{self, TyCtxt}; + use rustc::mir::{Lvalue, Mir, Operand, ProjectionElem}; + + pub(super) struct Restrictions<'c, 'tcx: 'c> { + mir: &'c Mir<'tcx>, + tcx: TyCtxt<'c, 'tcx, 'tcx>, + lvalue_stack: Vec<&'c Lvalue<'tcx>>, + } + + impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + pub(super) fn restrictions<'d>(&self, + lvalue: &'d Lvalue<'gcx>) + -> Restrictions<'d, 'gcx> where 'b: 'd + { + let lvalue_stack = if self.has_restrictions(lvalue) { vec![lvalue] } else { vec![] }; + Restrictions { lvalue_stack: lvalue_stack, mir: self.mir, tcx: self.tcx } + } + + fn has_restrictions(&self, lvalue: &Lvalue<'gcx>) -> bool { + let mut cursor = lvalue; + loop { + let proj = match *cursor { + Lvalue::Local(_) => return true, + Lvalue::Static(_) => return false, + Lvalue::Projection(ref proj) => proj, + }; + match proj.elem { + ProjectionElem::Index(..) | + ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Downcast(..) | + ProjectionElem::Subslice { .. } | + ProjectionElem::Field(_/*field*/, _/*ty*/) => { + cursor = &proj.base; + continue; + } + ProjectionElem::Deref => { + let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); + match ty.sty { + ty::TyRawPtr(_) => { + return false; + } + ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + // FIXME: do I need to check validity of + // region here though? (I think the original + // check_loans code did, like readme says) + return false; + } + ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { + cursor = &proj.base; + continue; + } + ty::TyAdt(..) if ty.is_box() => { + cursor = &proj.base; + continue; + } + _ => { + panic!("unknown type fed to Projection Deref."); + } + } + } + } + } + } + } + + impl<'c, 'tcx> Iterator for Restrictions<'c, 'tcx> { + type Item = &'c Lvalue<'tcx>; + fn next(&mut self) -> Option<Self::Item> { + 'pop: loop { + let lvalue = match self.lvalue_stack.pop() { + None => return None, + Some(lvalue) => lvalue, + }; + + // `lvalue` may not be a restriction itself, but may + // hold one further down (e.g. we never return + // downcasts here, but may return a base of a + // downcast). + // + // Also, we need to enqueue any additional + // subrestrictions that it implies, since we can only + // return from from this call alone. + + let mut cursor = lvalue; + 'cursor: loop { + let proj = match *cursor { + Lvalue::Local(_) => return Some(cursor), // search yielded this leaf + Lvalue::Static(_) => continue 'pop, // fruitless leaf; try next on stack + Lvalue::Projection(ref proj) => proj, + }; + + match proj.elem { + ProjectionElem::Field(_/*field*/, _/*ty*/) => { + // FIXME: add union handling + self.lvalue_stack.push(&proj.base); + return Some(cursor); + } + ProjectionElem::Downcast(..) | + ProjectionElem::Subslice { .. } | + ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Index(Operand::Constant(..)) => { + cursor = &proj.base; + continue 'cursor; + } + ProjectionElem::Index(Operand::Consume(ref index)) => { + self.lvalue_stack.push(index); // FIXME: did old borrowck do this? + cursor = &proj.base; + continue 'cursor; + } + ProjectionElem::Deref => { + // (handled below) + } + } + + assert_eq!(proj.elem, ProjectionElem::Deref); + + let ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); + match ty.sty { + ty::TyRawPtr(_) => { + // borrowck ignores raw ptrs; treat analogous to imm borrow + continue 'pop; + } + // R-Deref-Imm-Borrowed + ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) => { + // immutably-borrowed referents do not + // have recursively-implied restrictions + // (because preventing actions on `*LV` + // does nothing about aliases like `*LV1`) + + // FIXME: do I need to check validity of + // `_r` here though? (I think the original + // check_loans code did, like the readme + // says) + + // (And do I *really* not have to + // recursively process the `base` as a + // further search here? Leaving this `if + // false` here as a hint to look at this + // again later. + // + // Ah, it might be because the + // restrictions are distinct from the path + // substructure. Note that there is a + // separate loop over the path + // substructure in fn + // each_borrow_involving_path, for better + // or for worse. + + if false { + cursor = &proj.base; + continue 'cursor; + } else { + continue 'pop; + } + } + + // R-Deref-Mut-Borrowed + ty::TyRef(_/*rgn*/, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { + // mutably-borrowed referents are + // themselves restricted. + + // FIXME: do I need to check validity of + // `_r` here though? (I think the original + // check_loans code did, like the readme + // says) + + // schedule base for future iteration. + self.lvalue_stack.push(&proj.base); + return Some(cursor); // search yielded interior node + } + + // R-Deref-Send-Pointer + ty::TyAdt(..) if ty.is_box() => { + // borrowing interior of a box implies that + // its base can no longer be mutated (o/w box + // storage would be freed) + self.lvalue_stack.push(&proj.base); + return Some(cursor); // search yielded interior node + } + + _ => panic!("unknown type fed to Projection Deref."), + } + } + } + } + } +} + +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + fn report_use_of_moved(&mut self, + _context: Context, + (lvalue, span): (&Lvalue, Span)) { + let mut err = self.tcx.cannot_act_on_uninitialized_variable( + span, "use", &self.describe_lvalue(lvalue), Origin::Mir); + // FIXME: add span_label for use of uninitialized variable + err.emit(); + } + + fn report_move_out_while_borrowed(&mut self, + _context: Context, + (lvalue, span): (&Lvalue, Span)) { + let mut err = self.tcx.cannot_move_when_borrowed( + span, &self.describe_lvalue(lvalue), Origin::Mir); + // FIXME 1: add span_label for "borrow of `()` occurs here" + // FIXME 2: add span_label for "move out of `{}` occurs here" + err.emit(); + } + + fn report_use_while_mutably_borrowed(&mut self, + _context: Context, + (lvalue, span): (&Lvalue, Span)) { + let mut err = self.tcx.cannot_use_when_mutably_borrowed( + span, &self.describe_lvalue(lvalue), Origin::Mir); + // FIXME 1: add span_label for "borrow of `()` occurs here" + // FIXME 2: add span_label for "use of `{}` occurs here" + err.emit(); + } + + fn report_conflicting_borrow(&mut self, + _context: Context, + (lvalue, span): (&Lvalue, Span), + loan1: &BorrowData, + loan2: &BorrowData) { + // FIXME: obviously falsifiable. Generalize for non-eq lvalues later. + assert_eq!(loan1.lvalue, loan2.lvalue); + + // FIXME: supply non-"" `opt_via` when appropriate + let mut err = match (loan1.kind, "immutable", "mutable", + loan2.kind, "immutable", "mutable") { + (BorrowKind::Shared, lft, _, BorrowKind::Mut, _, rgt) | + (BorrowKind::Mut, _, lft, BorrowKind::Shared, rgt, _) | + (BorrowKind::Mut, _, lft, BorrowKind::Mut, _, rgt) => + self.tcx.cannot_reborrow_already_borrowed( + span, &self.describe_lvalue(lvalue), + "", lft, "it", rgt, "", Origin::Mir), + + _ => self.tcx.cannot_mutably_borrow_multiply( + span, &self.describe_lvalue(lvalue), "", Origin::Mir), + // FIXME: add span labels for first and second mutable borrows, as well as + // end point for first. + }; + err.emit(); + } + + fn report_illegal_mutation_of_borrowed(&mut self, _: Context, (lvalue, span): (&Lvalue, Span)) { + let mut err = self.tcx.cannot_assign_to_borrowed( + span, &self.describe_lvalue(lvalue), Origin::Mir); + // FIXME: add span labels for borrow and assignment points + err.emit(); + } + + fn report_illegal_reassignment(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) { + let mut err = self.tcx.cannot_reassign_immutable( + span, &self.describe_lvalue(lvalue), Origin::Mir); + // FIXME: add span labels for borrow and assignment points + err.emit(); + } + + fn report_assignment_to_static(&mut self, _context: Context, (lvalue, span): (&Lvalue, Span)) { + let mut err = self.tcx.cannot_assign_static( + span, &self.describe_lvalue(lvalue), Origin::Mir); + // FIXME: add span labels for borrow and assignment points + err.emit(); + } +} + +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + // End-user visible description of `lvalue` + fn describe_lvalue(&self, lvalue: &Lvalue) -> String { + let mut buf = String::new(); + self.append_lvalue_to_string(lvalue, &mut buf); + buf + } + + // Appends end-user visible description of `lvalue` to `buf`. + fn append_lvalue_to_string(&self, lvalue: &Lvalue, buf: &mut String) { + match *lvalue { + Lvalue::Local(local) => { + let local = &self.mir.local_decls[local]; + match local.name { + Some(name) => buf.push_str(&format!("{}", name)), + None => buf.push_str("_"), + } + } + Lvalue::Static(ref static_) => { + buf.push_str(&format!("{}", &self.tcx.item_name(static_.def_id))); + } + Lvalue::Projection(ref proj) => { + let (prefix, suffix, index_operand) = match proj.elem { + ProjectionElem::Deref => + ("(*", format!(")"), None), + ProjectionElem::Downcast(..) => + ("", format!(""), None), // (dont emit downcast info) + ProjectionElem::Field(field, _ty) => + ("", format!(".{}", field.index()), None), + ProjectionElem::Index(ref index) => + ("", format!(""), Some(index)), + ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => + ("", format!("[{} of {}]", offset, min_length), None), + ProjectionElem::ConstantIndex { offset, min_length, from_end: false } => + ("", format!("[-{} of {}]", offset, min_length), None), + ProjectionElem::Subslice { from, to: 0 } => + ("", format!("[{}:]", from), None), + ProjectionElem::Subslice { from: 0, to } => + ("", format!("[:-{}]", to), None), + ProjectionElem::Subslice { from, to } => + ("", format!("[{}:-{}]", from, to), None), + }; + buf.push_str(prefix); + self.append_lvalue_to_string(&proj.base, buf); + if let Some(index) = index_operand { + buf.push_str("["); + self.append_operand_to_string(index, buf); + buf.push_str("]"); + } else { + buf.push_str(&suffix); + } + + } + } + } + + fn append_operand_to_string(&self, operand: &Operand, buf: &mut String) { + match *operand { + Operand::Consume(ref lvalue) => { + self.append_lvalue_to_string(lvalue, buf); + } + Operand::Constant(ref constant) => { + buf.push_str(&format!("{:?}", constant)); + } + } + } +} + +impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { + // FIXME: needs to be able to express errors analogous to check_loans.rs + fn conflicts_with(&self, loan1: &BorrowData<'gcx>, loan2: &BorrowData<'gcx>) -> bool { + if loan1.compatible_with(loan2.kind) { return false; } + + let loan2_base_path = self.base_path(&loan2.lvalue); + for restricted in self.restrictions(&loan1.lvalue) { + if restricted != loan2_base_path { continue; } + return true; + } + + let loan1_base_path = self.base_path(&loan1.lvalue); + for restricted in self.restrictions(&loan2.lvalue) { + if restricted != loan1_base_path { continue; } + return true; + } + + return false; + } + + // FIXME (#16118): function intended to allow the borrow checker + // to be less precise in its handling of Box while still allowing + // moves out of a Box. They should be removed when/if we stop + // treating Box specially (e.g. when/if DerefMove is added...) + + fn base_path<'d>(&self, lvalue: &'d Lvalue<'gcx>) -> &'d Lvalue<'gcx> { + //! Returns the base of the leftmost (deepest) dereference of an + //! Box in `lvalue`. If there is no dereference of an Box + //! in `lvalue`, then it just returns `lvalue` itself. + + let mut cursor = lvalue; + let mut deepest = lvalue; + loop { + let proj = match *cursor { + Lvalue::Local(..) | Lvalue::Static(..) => return deepest, + Lvalue::Projection(ref proj) => proj, + }; + if proj.elem == ProjectionElem::Deref && + lvalue.ty(self.mir, self.tcx).to_ty(self.tcx).is_box() + { + deepest = &proj.base; + } + cursor = &proj.base; + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +struct Context { + kind: ContextKind, + loc: Location, +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum ContextKind { + AssignLhs, + AssignRhs, + SetDiscrim, + InlineAsm, + SwitchInt, + Drop, + DropAndReplace, + CallOperator, + CallOperand, + CallDest, + Assert, + StorageDead, +} + +impl ContextKind { + fn new(self, loc: Location) -> Context { Context { kind: self, loc: loc } } +} + +impl<'b, 'tcx: 'b> InProgress<'b, 'tcx> { + pub(super) fn new(borrows: DataflowResults<Borrows<'b, 'tcx>>, + inits: DataflowResults<MaybeInitializedLvals<'b, 'tcx>>, + uninits: DataflowResults<MaybeUninitializedLvals<'b, 'tcx>>) + -> Self { + InProgress { + borrows: FlowInProgress::new(borrows), + inits: FlowInProgress::new(inits), + uninits: FlowInProgress::new(uninits), + } + } + + fn each_flow<XB, XI, XU>(&mut self, + mut xform_borrows: XB, + mut xform_inits: XI, + mut xform_uninits: XU) where + XB: FnMut(&mut FlowInProgress<Borrows<'b, 'tcx>>), + XI: FnMut(&mut FlowInProgress<MaybeInitializedLvals<'b, 'tcx>>), + XU: FnMut(&mut FlowInProgress<MaybeUninitializedLvals<'b, 'tcx>>), + { + xform_borrows(&mut self.borrows); + xform_inits(&mut self.inits); + xform_uninits(&mut self.uninits); + } + + fn summary(&self) -> String { + let mut s = String::new(); + + s.push_str("borrows in effect: ["); + let mut saw_one = false; + self.borrows.each_state_bit(|borrow| { + if saw_one { s.push_str(", "); }; + saw_one = true; + let borrow_data = &self.borrows.base_results.operator().borrows()[borrow]; + s.push_str(&format!("{}", borrow_data)); + }); + s.push_str("] "); + + s.push_str("borrows generated: ["); + let mut saw_one = false; + self.borrows.each_gen_bit(|borrow| { + if saw_one { s.push_str(", "); }; + saw_one = true; + let borrow_data = &self.borrows.base_results.operator().borrows()[borrow]; + s.push_str(&format!("{}", borrow_data)); + }); + s.push_str("] "); + + s.push_str("inits: ["); + let mut saw_one = false; + self.inits.each_state_bit(|mpi_init| { + if saw_one { s.push_str(", "); }; + saw_one = true; + let move_path = + &self.inits.base_results.operator().move_data().move_paths[mpi_init]; + s.push_str(&format!("{}", move_path)); + }); + s.push_str("] "); + + s.push_str("uninits: ["); + let mut saw_one = false; + self.uninits.each_state_bit(|mpi_uninit| { + if saw_one { s.push_str(", "); }; + saw_one = true; + let move_path = + &self.uninits.base_results.operator().move_data().move_paths[mpi_uninit]; + s.push_str(&format!("{}", move_path)); + }); + s.push_str("]"); + + return s; + } +} + +impl<BD> FlowInProgress<BD> where BD: BitDenotation { + fn each_state_bit<F>(&self, f: F) where F: FnMut(BD::Idx) { + self.curr_state.each_bit(self.base_results.operator().bits_per_block(), f) + } + + fn each_gen_bit<F>(&self, f: F) where F: FnMut(BD::Idx) { + self.stmt_gen.each_bit(self.base_results.operator().bits_per_block(), f) + } + + fn new(results: DataflowResults<BD>) -> Self { + let bits_per_block = results.sets().bits_per_block(); + let curr_state = IdxSetBuf::new_empty(bits_per_block); + let stmt_gen = IdxSetBuf::new_empty(bits_per_block); + let stmt_kill = IdxSetBuf::new_empty(bits_per_block); + FlowInProgress { + base_results: results, + curr_state: curr_state, + stmt_gen: stmt_gen, + stmt_kill: stmt_kill, + } + } + + fn reset_to_entry_of(&mut self, bb: BasicBlock) { + (*self.curr_state).clone_from(self.base_results.sets().on_entry_set_for(bb.index())); + } + + fn reconstruct_statement_effect(&mut self, loc: Location) { + self.stmt_gen.reset_to_empty(); + self.stmt_kill.reset_to_empty(); + let mut ignored = IdxSetBuf::new_empty(0); + let mut sets = BlockSets { + on_entry: &mut ignored, gen_set: &mut self.stmt_gen, kill_set: &mut self.stmt_kill, + }; + self.base_results.operator().statement_effect(&mut sets, loc); + } + + fn reconstruct_terminator_effect(&mut self, loc: Location) { + self.stmt_gen.reset_to_empty(); + self.stmt_kill.reset_to_empty(); + let mut ignored = IdxSetBuf::new_empty(0); + let mut sets = BlockSets { + on_entry: &mut ignored, gen_set: &mut self.stmt_gen, kill_set: &mut self.stmt_kill, + }; + self.base_results.operator().terminator_effect(&mut sets, loc); + } + + fn apply_local_effect(&mut self) { + self.curr_state.union(&self.stmt_gen); + self.curr_state.subtract(&self.stmt_kill); + } + + fn elems_generated(&self) -> indexed_set::Elems<BD::Idx> { + let univ = self.base_results.sets().bits_per_block(); + self.stmt_gen.elems(univ) + } + + fn elems_incoming(&self) -> indexed_set::Elems<BD::Idx> { + let univ = self.base_results.sets().bits_per_block(); + self.curr_state.elems(univ) + } +} + +impl<'tcx> BorrowData<'tcx> { + fn compatible_with(&self, bk: BorrowKind) -> bool { + match (self.kind, bk) { + (BorrowKind::Shared, BorrowKind::Shared) => true, + + (BorrowKind::Mut, _) | + (BorrowKind::Unique, _) | + (_, BorrowKind::Mut) | + (_, BorrowKind::Unique) => false, + } + } +} diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index c20f8bde783..b390e2888f2 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -49,7 +49,7 @@ impl<'tcx> CFG<'tcx> { source_info: SourceInfo, extent: CodeExtent) { self.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::EndRegion(extent), }); } @@ -60,7 +60,7 @@ impl<'tcx> CFG<'tcx> { lvalue: &Lvalue<'tcx>, rvalue: Rvalue<'tcx>) { self.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::Assign(lvalue.clone(), rvalue) }); } @@ -93,8 +93,8 @@ impl<'tcx> CFG<'tcx> { block, self.block_data(block)); self.block_data_mut(block).terminator = Some(Terminator { - source_info: source_info, - kind: kind, + source_info, + kind, }); } } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index a625f4b0458..c74378bdadc 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -100,7 +100,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let Some(scope) = scope { // schedule a shallow free of that memory, lest we unwind: this.cfg.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::StorageLive(result.clone()) }); this.schedule_drop(expr_span, scope, &result, value.ty); diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index 9be306d2848..4f248ddb0e2 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -52,7 +52,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if !expr_ty.is_never() && temp_lifetime.is_some() { this.cfg.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::StorageLive(temp.clone()) }); } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 7ae5d6b0ec1..576b1059e59 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -240,8 +240,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let cleanup = this.diverge_cleanup(); this.cfg.terminate(block, source_info, TerminatorKind::Call { func: fun, - args: args, - cleanup: cleanup, + args, + cleanup, destination: if diverges { None } else { diff --git a/src/librustc_mir/build/expr/stmt.rs b/src/librustc_mir/build/expr/stmt.rs index 3120ac21908..0da722f72a1 100644 --- a/src/librustc_mir/build/expr/stmt.rs +++ b/src/librustc_mir/build/expr/stmt.rs @@ -127,11 +127,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { unpack!(block = this.as_local_operand(block, input)) }).collect(); this.cfg.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::InlineAsm { asm: box asm.clone(), - outputs: outputs, - inputs: inputs + outputs, + inputs, }, }); block.unit() diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index c0b54ce2a84..78805ba87ec 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -69,8 +69,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span: pattern.span, match_pairs: vec![MatchPair::new(discriminant_lvalue.clone(), pattern)], bindings: vec![], - guard: guard, - arm_index: arm_index, + guard, + arm_index, } }) .collect(); @@ -179,7 +179,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { var_scope = Some(this.new_visibility_scope(scope_span)); } let source_info = SourceInfo { - span: span, + span, scope: var_scope.unwrap() }; this.declare_binding(source_info, mutability, name, var, ty); @@ -193,7 +193,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let local_id = self.var_indices[&var]; let source_info = self.source_info(span); self.cfg.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::StorageLive(Lvalue::Local(local_id)) }); Lvalue::Local(local_id) @@ -708,10 +708,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { var_id, name, var_ty, source_info); let var = self.local_decls.push(LocalDecl::<'tcx> { - mutability: mutability, + mutability, ty: var_ty.clone(), name: Some(name), - source_info: source_info, + source_info, is_user_variable: true, }); self.var_indices.insert(var_id, var); diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index efddee2c933..6e3eef57352 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -71,8 +71,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Binding { name, mutability, mode, var, ty, ref subpattern } => { candidate.bindings.push(Binding { - name: name, - mutability: mutability, + name, + mutability, span: match_pair.pattern.span, source: match_pair.lvalue.clone(), var_id: var, diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 28386fa598c..dc15163ecc1 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -218,7 +218,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { discr: Operand::Consume(discr), switch_ty: discr_ty, values: From::from(values), - targets: targets + targets, }); target_blocks } @@ -249,9 +249,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ).collect(); (targets.clone(), TerminatorKind::SwitchInt { discr: Operand::Consume(lvalue.clone()), - switch_ty: switch_ty, + switch_ty, values: From::from(values), - targets: targets, + targets, }) }; self.cfg.terminate(block, source_info, terminator); @@ -315,7 +315,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }), args: vec![val, expect], destination: Some((eq_result.clone(), eq_block)), - cleanup: cleanup, + cleanup, }); // check the result diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index a013875b311..3e303865ac4 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { offset: idx as u32, - min_length: min_length, + min_length, from_end: false, }; let lvalue = lvalue.clone().elem(elem); @@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { .map(|(idx, subpattern)| { let elem = ProjectionElem::ConstantIndex { offset: (idx+1) as u32, - min_length: min_length, + min_length, from_end: true, }; let lvalue = lvalue.clone().elem(elem); @@ -80,8 +80,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { impl<'pat, 'tcx> MatchPair<'pat, 'tcx> { pub fn new(lvalue: Lvalue<'tcx>, pattern: &'pat Pattern<'tcx>) -> MatchPair<'pat, 'tcx> { MatchPair { - lvalue: lvalue, - pattern: pattern, + lvalue, + pattern, slice_len_checked: false, } } diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs index 6c93e073de6..0e4aac42991 100644 --- a/src/librustc_mir/build/misc.rs +++ b/src/librustc_mir/build/misc.rs @@ -41,9 +41,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { literal: Literal<'tcx>) -> Operand<'tcx> { let constant = box Constant { - span: span, - ty: ty, - literal: literal, + span, + ty, + literal, }; Operand::Constant(constant) } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 14392ae70e4..d7a295a1c3a 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -121,7 +121,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t // Convert the Mir to global types. let mut globalizer = GlobalizeMir { - tcx: tcx, + tcx, span: mir.span }; globalizer.visit_mir(&mut mir); @@ -179,7 +179,7 @@ fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Convert the Mir to global types. let tcx = infcx.tcx.global_tcx(); let mut globalizer = GlobalizeMir { - tcx: tcx, + tcx, span: mir.span }; globalizer.visit_mir(&mut mir); @@ -380,9 +380,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, }; let mut decl = UpvarDecl { debug_name: keywords::Invalid.name(), - by_ref: by_ref + by_ref, }; - if let Some(hir::map::NodeLocal(pat)) = tcx.hir.find(var_node_id) { + if let Some(hir::map::NodeBinding(pat)) = tcx.hir.find(var_node_id) { if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node { decl.debug_name = ident.node; } @@ -437,10 +437,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { return_ty: Ty<'tcx>) -> Builder<'a, 'gcx, 'tcx> { let mut builder = Builder { - hir: hir, + hir, cfg: CFG { basic_blocks: IndexVec::new() }, fn_span: span, - arg_count: arg_count, + arg_count, scopes: vec![], visibility_scopes: IndexVec::new(), visibility_scope: ARGUMENT_VISIBILITY_SCOPE, @@ -500,12 +500,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.local_decls.push(LocalDecl { mutability: Mutability::Not, - ty: ty, + ty, source_info: SourceInfo { scope: ARGUMENT_VISIBILITY_SCOPE, span: pattern.map_or(self.fn_span, |pat| pat.span) }, - name: name, + name, is_user_variable: false, }); } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index ce64f88d18e..c36da9410f3 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -89,7 +89,7 @@ should go to. use build::{BlockAnd, BlockAndExtension, Builder, CFG}; use rustc::middle::region::CodeExtent; -use rustc::ty::{Ty, TyCtxt}; +use rustc::ty::Ty; use rustc::mir::*; use rustc::mir::transform::MirSource; use syntax_pos::{Span}; @@ -213,7 +213,7 @@ impl<'tcx> Scope<'tcx> { /// Given a span and this scope's visibility scope, make a SourceInfo. fn source_info(&self, span: Span) -> SourceInfo { SourceInfo { - span: span, + span, scope: self.visibility_scope } } @@ -235,10 +235,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { { let extent = self.topmost_scope(); let scope = BreakableScope { - extent: extent, + extent, continue_block: loop_block, - break_block: break_block, - break_destination: break_destination, + break_block, + break_destination, }; self.breakable_scopes.push(scope); let res = f(self); @@ -386,7 +386,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let parent = self.visibility_scope; let scope = VisibilityScope::new(self.visibility_scopes.len()); self.visibility_scopes.push(VisibilityScopeData { - span: span, + span, parent_scope: Some(parent), }); scope @@ -411,7 +411,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { /// Given a span and the current visibility scope, make a SourceInfo. pub fn source_info(&self, span: Span) -> SourceInfo { SourceInfo { - span: span, + span, scope: self.visibility_scope } } @@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } assert!(!self.scopes.is_empty()); // or `any` above would be false - let Builder { ref mut hir, ref mut cfg, ref mut scopes, + let Builder { ref mut cfg, ref mut scopes, ref mut cached_resume_block, .. } = *self; // Build up the drops in **reverse** order. The end result will @@ -599,8 +599,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }; for scope in scopes.iter_mut() { - target = build_diverge_scope( - hir.tcx(), cfg, scope.extent_span, scope, target); + target = build_diverge_scope(cfg, scope.extent_span, scope, target); } Some(target) } @@ -619,7 +618,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let diverge_target = self.diverge_cleanup(); self.cfg.terminate(block, source_info, TerminatorKind::Drop { - location: location, + location, target: next_target, unwind: diverge_target, }); @@ -637,8 +636,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let diverge_target = self.diverge_cleanup(); self.cfg.terminate(block, source_info, TerminatorKind::DropAndReplace { - location: location, - value: value, + location, + value, target: next_target, unwind: diverge_target, }); @@ -661,11 +660,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.cfg.terminate(block, source_info, TerminatorKind::Assert { - cond: cond, - expected: expected, - msg: msg, + cond, + expected, + msg, target: success_block, - cleanup: cleanup + cleanup, }); success_block @@ -716,7 +715,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, match drop_data.location { Lvalue::Local(index) if index.index() > arg_count => { cfg.push(block, Statement { - source_info: source_info, + source_info, kind: StatementKind::StorageDead(drop_data.location.clone()) }); } @@ -726,8 +725,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>, block.unit() } -fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>, - cfg: &mut CFG<'tcx>, +fn build_diverge_scope<'a, 'gcx, 'tcx>(cfg: &mut CFG<'tcx>, span: Span, scope: &mut Scope<'tcx>, mut target: BasicBlock) @@ -748,7 +746,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>, let visibility_scope = scope.visibility_scope; let source_info = |span| SourceInfo { - span: span, + span, scope: visibility_scope }; @@ -776,7 +774,7 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>, cfg.terminate(block, source_info(drop_data.span), TerminatorKind::Drop { location: drop_data.location.clone(), - target: target, + target, unwind: None }); *cached_block = Some(block); diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index 890fe3c091a..bd41bce67da 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -8,84 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast::{self, MetaItem}; use syntax_pos::DUMMY_SP; - -use rustc::mir::{self, Mir, BasicBlock, Location}; -use rustc::session::Session; +use rustc::mir::{self, Mir, Location}; use rustc::ty::{self, TyCtxt}; use util::elaborate_drops::DropFlagState; -use rustc_data_structures::indexed_set::{IdxSet}; - -use std::fmt; -use super::{Dataflow, DataflowBuilder, DataflowAnalysis}; -use super::{BitDenotation, DataflowOperator, DataflowResults}; +use super::{MoveDataParamEnv}; use super::indexes::MovePathIndex; use super::move_paths::{MoveData, LookupResult}; -pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> { - for attr in attrs { - if attr.check_name("rustc_mir") { - let items = attr.meta_item_list(); - for item in items.iter().flat_map(|l| l.iter()) { - match item.meta_item() { - Some(mi) if mi.check_name(name) => return Some(mi.clone()), - _ => continue - } - } - } - } - return None; -} - -pub struct MoveDataParamEnv<'tcx> { - pub(crate) move_data: MoveData<'tcx>, - pub(crate) param_env: ty::ParamEnv<'tcx>, -} - -pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &Mir<'tcx>, - node_id: ast::NodeId, - attributes: &[ast::Attribute], - dead_unwinds: &IdxSet<BasicBlock>, - bd: BD, - p: P) - -> DataflowResults<BD> - where BD: BitDenotation<Idx=MovePathIndex> + DataflowOperator, - P: Fn(&BD, BD::Idx) -> &fmt::Debug -{ - let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> { - if let Some(item) = has_rustc_mir_with(attrs, name) { - if let Some(s) = item.value_str() { - return Some(s.to_string()) - } else { - sess.span_err( - item.span, - &format!("{} attribute requires a path", item.name())); - return None; - } - } - return None; - }; - - let print_preflow_to = - name_found(tcx.sess, attributes, "borrowck_graphviz_preflow"); - let print_postflow_to = - name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); - - let mut mbcx = DataflowBuilder { - node_id: node_id, - print_preflow_to: print_preflow_to, - print_postflow_to: print_postflow_to, - flow_state: DataflowAnalysis::new(tcx, mir, dead_unwinds, bd), - }; - - mbcx.dataflow(p); - mbcx.flow_state.results() -} - pub fn move_path_children_matching<'tcx, F>(move_data: &MoveData<'tcx>, path: MovePathIndex, mut cond: F) diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index e6d77aa2686..7ff4fbcf199 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -13,7 +13,6 @@ use syntax::ast::NodeId; use rustc::mir::{BasicBlock, Mir}; use rustc_data_structures::bitslice::bits_to_string; -use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; use dot; @@ -24,7 +23,6 @@ use std::fs::File; use std::io; use std::io::prelude::*; use std::marker::PhantomData; -use std::mem; use std::path::Path; use util; @@ -32,54 +30,6 @@ use util; use super::{BitDenotation, DataflowState}; use super::DataflowBuilder; -impl<O: BitDenotation> DataflowState<O> { - fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F) - where F: FnMut(O::Idx) { - //! Helper for iterating over the bits in a bitvector. - - let bits_per_block = self.operator.bits_per_block(); - let usize_bits: usize = mem::size_of::<usize>() * 8; - - for (word_index, &word) in words.words().iter().enumerate() { - if word != 0 { - let base_index = word_index * usize_bits; - for offset in 0..usize_bits { - let bit = 1 << offset; - if (word & bit) != 0 { - // NB: we round up the total number of bits - // that we store in any given bit set so that - // it is an even multiple of usize::BITS. This - // means that there may be some stray bits at - // the end that do not correspond to any - // actual value; that's why we first check - // that we are in range of bits_per_block. - let bit_index = base_index + offset as usize; - if bit_index >= bits_per_block { - return; - } else { - f(O::Idx::new(bit_index)); - } - } - } - } - } - } - - pub fn interpret_set<'c, P>(&self, - o: &'c O, - words: &IdxSet<O::Idx>, - render_idx: &P) - -> Vec<&'c Debug> - where P: Fn(&O, O::Idx) -> &Debug - { - let mut v = Vec::new(); - self.each_bit(words, |i| { - v.push(render_idx(o, i)); - }); - v - } -} - pub trait MirWithFlowState<'tcx> { type BD: BitDenotation; fn node_id(&self) -> NodeId; diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs new file mode 100644 index 00000000000..ab62342e607 --- /dev/null +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -0,0 +1,180 @@ +// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::mir::{self, Location, Mir}; +use rustc::mir::visit::Visitor; +use rustc::ty::{Region, TyCtxt}; +use rustc::ty::RegionKind::ReScope; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; + +use rustc_data_structures::bitslice::{BitwiseOperator}; +use rustc_data_structures::indexed_set::{IdxSet}; +use rustc_data_structures::indexed_vec::{IndexVec}; + +use dataflow::{BitDenotation, BlockSets, DataflowOperator}; +pub use dataflow::indexes::BorrowIndex; + +use std::fmt; + +// `Borrows` maps each dataflow bit to an `Rvalue::Ref`, which can be +// uniquely identified in the MIR by the `Location` of the assigment +// statement in which it appears on the right hand side. +pub struct Borrows<'a, 'tcx: 'a> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &'a Mir<'tcx>, + borrows: IndexVec<BorrowIndex, BorrowData<'tcx>>, + location_map: FxHashMap<Location, BorrowIndex>, + region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>, +} + +// temporarily allow some dead fields: `kind` and `region` will be +// needed by borrowck; `lvalue` will probably be a MovePathIndex when +// that is extended to include borrowed data paths. +#[allow(dead_code)] +#[derive(Debug)] +pub struct BorrowData<'tcx> { + pub(crate) location: Location, + pub(crate) kind: mir::BorrowKind, + pub(crate) region: Region<'tcx>, + pub(crate) lvalue: mir::Lvalue<'tcx>, +} + +impl<'tcx> fmt::Display for BorrowData<'tcx> { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + let kind = match self.kind { + mir::BorrowKind::Shared => "", + mir::BorrowKind::Unique => "uniq ", + mir::BorrowKind::Mut => "mut ", + }; + let region = format!("{}", self.region); + let region = if region.len() > 0 { format!("{} ", region) } else { region }; + write!(w, "&{}{}{:?}", region, kind, self.lvalue) + } +} + +impl<'a, 'tcx> Borrows<'a, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { + let mut visitor = GatherBorrows { idx_vec: IndexVec::new(), + location_map: FxHashMap(), + region_map: FxHashMap(), }; + visitor.visit_mir(mir); + return Borrows { tcx: tcx, + mir: mir, + borrows: visitor.idx_vec, + location_map: visitor.location_map, + region_map: visitor.region_map, }; + + struct GatherBorrows<'tcx> { + idx_vec: IndexVec<BorrowIndex, BorrowData<'tcx>>, + location_map: FxHashMap<Location, BorrowIndex>, + region_map: FxHashMap<Region<'tcx>, FxHashSet<BorrowIndex>>, + } + impl<'tcx> Visitor<'tcx> for GatherBorrows<'tcx> { + fn visit_rvalue(&mut self, + rvalue: &mir::Rvalue<'tcx>, + location: mir::Location) { + if let mir::Rvalue::Ref(region, kind, ref lvalue) = *rvalue { + let borrow = BorrowData { + location: location, kind: kind, region: region, lvalue: lvalue.clone(), + }; + let idx = self.idx_vec.push(borrow); + self.location_map.insert(location, idx); + let borrows = self.region_map.entry(region).or_insert(FxHashSet()); + borrows.insert(idx); + } + } + } + } + + pub fn borrows(&self) -> &IndexVec<BorrowIndex, BorrowData<'tcx>> { &self.borrows } + + pub fn location(&self, idx: BorrowIndex) -> &Location { + &self.borrows[idx].location + } +} + +impl<'a, 'tcx> BitDenotation for Borrows<'a, 'tcx> { + type Idx = BorrowIndex; + fn name() -> &'static str { "borrows" } + fn bits_per_block(&self) -> usize { + self.borrows.len() + } + fn start_block_effect(&self, _sets: &mut BlockSets<BorrowIndex>) { + // no borrows of code extents have been taken prior to + // function execution, so this method has no effect on + // `_sets`. + } + fn statement_effect(&self, + sets: &mut BlockSets<BorrowIndex>, + location: Location) { + let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { + panic!("could not find block at location {:?}", location); + }); + let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| { + panic!("could not find statement at location {:?}"); + }); + match stmt.kind { + mir::StatementKind::EndRegion(extent) => { + let borrow_indexes = self.region_map.get(&ReScope(extent)).unwrap_or_else(|| { + panic!("could not find BorrowIndexs for code-extent {:?}", extent); + }); + + for idx in borrow_indexes { sets.kill(&idx); } + } + + mir::StatementKind::Assign(_, ref rhs) => { + if let mir::Rvalue::Ref(region, _, _) = *rhs { + let index = self.location_map.get(&location).unwrap_or_else(|| { + panic!("could not find BorrowIndex for location {:?}", location); + }); + assert!(self.region_map.get(region).unwrap_or_else(|| { + panic!("could not find BorrowIndexs for region {:?}", region); + }).contains(&index)); + sets.gen(&index); + } + } + + mir::StatementKind::InlineAsm { .. } | + mir::StatementKind::SetDiscriminant { .. } | + mir::StatementKind::StorageLive(..) | + mir::StatementKind::StorageDead(..) | + mir::StatementKind::Validate(..) | + mir::StatementKind::Nop => {} + + } + } + fn terminator_effect(&self, + _sets: &mut BlockSets<BorrowIndex>, + _location: Location) { + // no terminators start nor end code extents. + } + + fn propagate_call_return(&self, + _in_out: &mut IdxSet<BorrowIndex>, + _call_bb: mir::BasicBlock, + _dest_bb: mir::BasicBlock, + _dest_lval: &mir::Lvalue) { + // there are no effects on the extents from method calls. + } +} + +impl<'a, 'tcx> BitwiseOperator for Borrows<'a, 'tcx> { + #[inline] + fn join(&self, pred1: usize, pred2: usize) -> usize { + pred1 | pred2 // union effects of preds when computing borrows + } +} + +impl<'a, 'tcx> DataflowOperator for Borrows<'a, 'tcx> { + #[inline] + fn bottom_value() -> bool { + false // bottom = no Rvalue::Refs are active by default + } +} diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 41019799e41..a4421b216c3 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,22 +14,22 @@ use rustc::ty::TyCtxt; use rustc::mir::{self, Mir, Location}; -use rustc_data_structures::bitslice::BitSlice; // adds set_bit/get_bit to &[usize] bitvector rep. use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; -use rustc_data_structures::indexed_vec::Idx; use super::MoveDataParamEnv; use util::elaborate_drops::DropFlagState; -use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex}; -use super::move_paths::LookupResult; +use super::move_paths::{HasMoveData, MoveData, MovePathIndex}; use super::{BitDenotation, BlockSets, DataflowOperator}; use super::drop_flag_effects_for_function_entry; use super::drop_flag_effects_for_location; use super::on_lookup_result_bits; +#[allow(dead_code)] +pub(super) mod borrows; + /// `MaybeInitializedLvals` tracks all l-values that might be /// initialized upon reaching a particular point in the control flow /// for a function. @@ -201,40 +201,6 @@ impl<'a, 'tcx: 'a> HasMoveData<'tcx> for DefinitelyInitializedLvals<'a, 'tcx> { fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } } -/// `MovingOutStatements` tracks the statements that perform moves out -/// of particular l-values. More precisely, it tracks whether the -/// *effect* of such moves (namely, the uninitialization of the -/// l-value in question) can reach some point in the control-flow of -/// the function, or if that effect is "killed" by some intervening -/// operation reinitializing that l-value. -/// -/// The resulting dataflow is a more enriched version of -/// `MaybeUninitializedLvals`. Both structures on their own only tell -/// you if an l-value *might* be uninitialized at a given point in the -/// control flow. But `MovingOutStatements` also includes the added -/// data of *which* particular statement causing the deinitialization -/// that the borrow checker's error message may need to report. -#[allow(dead_code)] -pub struct MovingOutStatements<'a, 'tcx: 'a> { - tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &'a Mir<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>, -} - -impl<'a, 'tcx: 'a> MovingOutStatements<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, - mir: &'a Mir<'tcx>, - mdpe: &'a MoveDataParamEnv<'tcx>) - -> Self - { - MovingOutStatements { tcx: tcx, mir: mir, mdpe: mdpe } - } -} - -impl<'a, 'tcx> HasMoveData<'tcx> for MovingOutStatements<'a, 'tcx> { - fn move_data(&self) -> &MoveData<'tcx> { &self.mdpe.move_data } -} - impl<'a, 'tcx> MaybeInitializedLvals<'a, 'tcx> { fn update_bits(sets: &mut BlockSets<MovePathIndex>, path: MovePathIndex, state: DropFlagState) @@ -287,24 +253,22 @@ impl<'a, 'tcx> BitDenotation for MaybeInitializedLvals<'a, 'tcx> { fn statement_effect(&self, sets: &mut BlockSets<MovePathIndex>, - bb: mir::BasicBlock, - idx: usize) + location: Location) { drop_flag_effects_for_location( self.tcx, self.mir, self.mdpe, - Location { block: bb, statement_index: idx }, + location, |path, s| Self::update_bits(sets, path, s) ) } fn terminator_effect(&self, sets: &mut BlockSets<MovePathIndex>, - bb: mir::BasicBlock, - statements_len: usize) + location: Location) { drop_flag_effects_for_location( self.tcx, self.mir, self.mdpe, - Location { block: bb, statement_index: statements_len }, + location, |path, s| Self::update_bits(sets, path, s) ) } @@ -344,24 +308,22 @@ impl<'a, 'tcx> BitDenotation for MaybeUninitializedLvals<'a, 'tcx> { fn statement_effect(&self, sets: &mut BlockSets<MovePathIndex>, - bb: mir::BasicBlock, - idx: usize) + location: Location) { drop_flag_effects_for_location( self.tcx, self.mir, self.mdpe, - Location { block: bb, statement_index: idx }, + location, |path, s| Self::update_bits(sets, path, s) ) } fn terminator_effect(&self, sets: &mut BlockSets<MovePathIndex>, - bb: mir::BasicBlock, - statements_len: usize) + location: Location) { drop_flag_effects_for_location( self.tcx, self.mir, self.mdpe, - Location { block: bb, statement_index: statements_len }, + location, |path, s| Self::update_bits(sets, path, s) ) } @@ -400,24 +362,22 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { fn statement_effect(&self, sets: &mut BlockSets<MovePathIndex>, - bb: mir::BasicBlock, - idx: usize) + location: Location) { drop_flag_effects_for_location( self.tcx, self.mir, self.mdpe, - Location { block: bb, statement_index: idx }, + location, |path, s| Self::update_bits(sets, path, s) ) } fn terminator_effect(&self, sets: &mut BlockSets<MovePathIndex>, - bb: mir::BasicBlock, - statements_len: usize) + location: Location) { drop_flag_effects_for_location( self.tcx, self.mir, self.mdpe, - Location { block: bb, statement_index: statements_len }, + location, |path, s| Self::update_bits(sets, path, s) ) } @@ -435,125 +395,6 @@ impl<'a, 'tcx> BitDenotation for DefinitelyInitializedLvals<'a, 'tcx> { } } -impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> { - type Idx = MoveOutIndex; - fn name() -> &'static str { "moving_out" } - fn bits_per_block(&self) -> usize { - self.move_data().moves.len() - } - - fn start_block_effect(&self, _sets: &mut BlockSets<MoveOutIndex>) { - // no move-statements have been executed prior to function - // execution, so this method has no effect on `_sets`. - } - fn statement_effect(&self, - sets: &mut BlockSets<MoveOutIndex>, - bb: mir::BasicBlock, - idx: usize) { - let (tcx, mir, move_data) = (self.tcx, self.mir, self.move_data()); - let stmt = &mir[bb].statements[idx]; - let loc_map = &move_data.loc_map; - let path_map = &move_data.path_map; - let rev_lookup = &move_data.rev_lookup; - - let loc = Location { block: bb, statement_index: idx }; - debug!("stmt {:?} at loc {:?} moves out of move_indexes {:?}", - stmt, loc, &loc_map[loc]); - for move_index in &loc_map[loc] { - // Every path deinitialized by a *particular move* - // has corresponding bit, "gen'ed" (i.e. set) - // here, in dataflow vector - zero_to_one(sets.gen_set.words_mut(), *move_index); - } - let bits_per_block = self.bits_per_block(); - match stmt.kind { - mir::StatementKind::SetDiscriminant { .. } => { - span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck"); - } - mir::StatementKind::Assign(ref lvalue, ref rvalue) => { - // assigning into this `lvalue` kills all - // MoveOuts from it, and *also* all MoveOuts - // for children and associated fragment sets. - match rvalue.initialization_state() { - mir::tcx::RvalueInitializationState::Shallow => { - if let LookupResult::Exact(mpi) = rev_lookup.find(lvalue) { - for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - sets.kill_set.add(&moi); - } - } - } - mir::tcx::RvalueInitializationState::Deep => { - on_lookup_result_bits(tcx, - mir, - move_data, - rev_lookup.find(lvalue), - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - sets.kill_set.add(&moi); - }); - } - } - } - mir::StatementKind::StorageLive(_) | - mir::StatementKind::StorageDead(_) | - mir::StatementKind::InlineAsm { .. } | - mir::StatementKind::EndRegion(_) | - mir::StatementKind::Validate(..) | - mir::StatementKind::Nop => {} - } - } - - fn terminator_effect(&self, - sets: &mut BlockSets<MoveOutIndex>, - bb: mir::BasicBlock, - statements_len: usize) - { - let (mir, move_data) = (self.mir, self.move_data()); - let term = mir[bb].terminator(); - let loc_map = &move_data.loc_map; - let loc = Location { block: bb, statement_index: statements_len }; - debug!("terminator {:?} at loc {:?} moves out of move_indexes {:?}", - term, loc, &loc_map[loc]); - let bits_per_block = self.bits_per_block(); - for move_index in &loc_map[loc] { - assert!(move_index.index() < bits_per_block); - zero_to_one(sets.gen_set.words_mut(), *move_index); - } - } - - fn propagate_call_return(&self, - in_out: &mut IdxSet<MoveOutIndex>, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_lval: &mir::Lvalue) { - let move_data = self.move_data(); - let bits_per_block = self.bits_per_block(); - - let path_map = &move_data.path_map; - on_lookup_result_bits(self.tcx, - self.mir, - move_data, - move_data.rev_lookup.find(dest_lval), - |mpi| for moi in &path_map[mpi] { - assert!(moi.index() < bits_per_block); - in_out.remove(&moi); - }); - } -} - -fn zero_to_one(bitvec: &mut [usize], move_index: MoveOutIndex) { - let retval = bitvec.set_bit(move_index.index()); - assert!(retval); -} - -impl<'a, 'tcx> BitwiseOperator for MovingOutStatements<'a, 'tcx> { - #[inline] - fn join(&self, pred1: usize, pred2: usize) -> usize { - pred1 | pred2 // moves from both preds are in scope - } -} - impl<'a, 'tcx> BitwiseOperator for MaybeInitializedLvals<'a, 'tcx> { #[inline] fn join(&self, pred1: usize, pred2: usize) -> usize { @@ -585,13 +426,6 @@ impl<'a, 'tcx> BitwiseOperator for DefinitelyInitializedLvals<'a, 'tcx> { // propagating, or you start at all-ones and then use Intersect as // your merge when propagating. -impl<'a, 'tcx> DataflowOperator for MovingOutStatements<'a, 'tcx> { - #[inline] - fn bottom_value() -> bool { - false // bottom = no loans in scope by default - } -} - impl<'a, 'tcx> DataflowOperator for MaybeInitializedLvals<'a, 'tcx> { #[inline] fn bottom_value() -> bool { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 7c0137b18c0..237795491b1 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -8,26 +8,29 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast; +use syntax::ast::{self, MetaItem}; use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::bitslice::{bitwise, BitwiseOperator}; -use rustc::ty::{TyCtxt}; -use rustc::mir::{self, Mir}; +use rustc::ty::{self, TyCtxt}; +use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; +use rustc::session::Session; -use std::fmt::Debug; +use std::fmt::{self, Debug}; use std::io; use std::mem; use std::path::PathBuf; use std::usize; pub use self::impls::{MaybeInitializedLvals, MaybeUninitializedLvals}; -pub use self::impls::{DefinitelyInitializedLvals, MovingOutStatements}; - +pub use self::impls::{DefinitelyInitializedLvals}; +pub use self::impls::borrows::{Borrows, BorrowData, BorrowIndex}; pub(crate) use self::drop_flag_effects::*; +use self::move_paths::MoveData; + mod drop_flag_effects; mod graphviz; mod impls; @@ -44,11 +47,22 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation } pub trait Dataflow<BD: BitDenotation> { - fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug; + /// Sets up and runs the dataflow problem, using `p` to render results if + /// implementation so chooses. + fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug { + let _ = p; // default implementation does not instrument process. + self.build_sets(); + self.propagate(); + } + + /// Sets up the entry, gen, and kill sets for this instance of a dataflow problem. + fn build_sets(&mut self); + + /// Finds a fixed-point solution to this instance of a dataflow problem. + fn propagate(&mut self); } -impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> - where BD: BitDenotation + DataflowOperator +impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation { fn dataflow<P>(&mut self, p: P) where P: Fn(&BD, BD::Idx) -> &Debug { self.flow_state.build_sets(); @@ -56,17 +70,79 @@ impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD> self.flow_state.propagate(); self.post_dataflow_instrumentation(|c,i| p(c,i)).unwrap(); } + + fn build_sets(&mut self) { self.flow_state.build_sets(); } + fn propagate(&mut self) { self.flow_state.propagate(); } +} + +pub(crate) fn has_rustc_mir_with(attrs: &[ast::Attribute], name: &str) -> Option<MetaItem> { + for attr in attrs { + if attr.check_name("rustc_mir") { + let items = attr.meta_item_list(); + for item in items.iter().flat_map(|l| l.iter()) { + match item.meta_item() { + Some(mi) if mi.check_name(name) => return Some(mi.clone()), + _ => continue + } + } + } + } + return None; +} + +pub struct MoveDataParamEnv<'tcx> { + pub(crate) move_data: MoveData<'tcx>, + pub(crate) param_env: ty::ParamEnv<'tcx>, +} + +pub(crate) fn do_dataflow<'a, 'tcx, BD, P>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + mir: &Mir<'tcx>, + node_id: ast::NodeId, + attributes: &[ast::Attribute], + dead_unwinds: &IdxSet<BasicBlock>, + bd: BD, + p: P) + -> DataflowResults<BD> + where BD: BitDenotation, + P: Fn(&BD, BD::Idx) -> &fmt::Debug +{ + let name_found = |sess: &Session, attrs: &[ast::Attribute], name| -> Option<String> { + if let Some(item) = has_rustc_mir_with(attrs, name) { + if let Some(s) = item.value_str() { + return Some(s.to_string()) + } else { + sess.span_err( + item.span, + &format!("{} attribute requires a path", item.name())); + return None; + } + } + return None; + }; + + let print_preflow_to = + name_found(tcx.sess, attributes, "borrowck_graphviz_preflow"); + let print_postflow_to = + name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); + + let mut mbcx = DataflowBuilder { + node_id, + print_preflow_to, + print_postflow_to, + flow_state: DataflowAnalysis::new(tcx, mir, dead_unwinds, bd), + }; + + mbcx.dataflow(p); + mbcx.flow_state.results() } -struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> - where O: 'b + BitDenotation +struct PropagationContext<'b, 'a: 'b, 'tcx: 'a, O> where O: 'b + BitDenotation { builder: &'b mut DataflowAnalysis<'a, 'tcx, O>, changed: bool, } -impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> - where BD: BitDenotation + DataflowOperator +impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation { fn propagate(&mut self) { let mut temp = IdxSetBuf::new_empty(self.flow_state.sets.bits_per_block); @@ -98,19 +174,19 @@ impl<'a, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> let sets = &mut self.flow_state.sets.for_block(bb.index()); for j_stmt in 0..statements.len() { - self.flow_state.operator.statement_effect(sets, bb, j_stmt); + let location = Location { block: bb, statement_index: j_stmt }; + self.flow_state.operator.statement_effect(sets, location); } if terminator.is_some() { - let stmts_len = statements.len(); - self.flow_state.operator.terminator_effect(sets, bb, stmts_len); + let location = Location { block: bb, statement_index: statements.len() }; + self.flow_state.operator.terminator_effect(sets, location); } } } } -impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> - where BD: BitDenotation + DataflowOperator +impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD> where BD: BitDenotation { fn reset(&mut self, bits: &mut IdxSet<BD::Idx>) { let e = if BD::bottom_value() {!0} else {0}; @@ -147,8 +223,7 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf { path } -impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> - where BD: BitDenotation +impl<'a, 'tcx: 'a, BD> DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation { fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()> where P: Fn(&BD, BD::Idx) -> &Debug @@ -189,16 +264,101 @@ impl<E:Idx> Bits<E> { } } -pub struct DataflowAnalysis<'a, 'tcx: 'a, O> - where O: BitDenotation +/// DataflowResultsConsumer abstracts over walking the MIR with some +/// already constructed dataflow results. +/// +/// It abstracts over the FlowState and also completely hides the +/// underlying flow analysis results, because it needs to handle cases +/// where we are combining the results of *multiple* flow analyses +/// (e.g. borrows + inits + uninits). +pub trait DataflowResultsConsumer<'a, 'tcx: 'a> { + type FlowState; + + // Observation Hooks: override (at least one of) these to get analysis feedback. + fn visit_block_entry(&mut self, + _bb: BasicBlock, + _flow_state: &Self::FlowState) {} + + fn visit_statement_entry(&mut self, + _loc: Location, + _stmt: &Statement<'tcx>, + _flow_state: &Self::FlowState) {} + + fn visit_terminator_entry(&mut self, + _loc: Location, + _term: &Terminator<'tcx>, + _flow_state: &Self::FlowState) {} + + // Main entry point: this drives the processing of results. + + fn analyze_results(&mut self, flow_uninit: &mut Self::FlowState) { + let flow = flow_uninit; + for bb in self.mir().basic_blocks().indices() { + self.reset_to_entry_of(bb, flow); + self.process_basic_block(bb, flow); + } + } + + fn process_basic_block(&mut self, bb: BasicBlock, flow_state: &mut Self::FlowState) { + let BasicBlockData { ref statements, ref terminator, is_cleanup: _ } = + self.mir()[bb]; + let mut location = Location { block: bb, statement_index: 0 }; + for stmt in statements.iter() { + self.reconstruct_statement_effect(location, flow_state); + self.visit_statement_entry(location, stmt, flow_state); + self.apply_local_effect(location, flow_state); + location.statement_index += 1; + } + + if let Some(ref term) = *terminator { + self.reconstruct_terminator_effect(location, flow_state); + self.visit_terminator_entry(location, term, flow_state); + + // We don't need to apply the effect of the terminator, + // since we are only visiting dataflow state on control + // flow entry to the various nodes. (But we still need to + // reconstruct the effect, because the visit method might + // inspect it.) + } + } + + // Delegated Hooks: Provide access to the MIR and process the flow state. + + fn mir(&self) -> &'a Mir<'tcx>; + + // reset the state bitvector to represent the entry to block `bb`. + fn reset_to_entry_of(&mut self, + bb: BasicBlock, + flow_state: &mut Self::FlowState); + + // build gen + kill sets for statement at `loc`. + fn reconstruct_statement_effect(&mut self, + loc: Location, + flow_state: &mut Self::FlowState); + + // build gen + kill sets for terminator for `loc`. + fn reconstruct_terminator_effect(&mut self, + loc: Location, + flow_state: &mut Self::FlowState); + + // apply current gen + kill sets to `flow_state`. + // + // (`bb` and `stmt_idx` parameters can be ignored if desired by + // client. For the terminator, the `stmt_idx` will be the number + // of statements in the block.) + fn apply_local_effect(&mut self, + loc: Location, + flow_state: &mut Self::FlowState); +} + +pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation { flow_state: DataflowState<O>, dead_unwinds: &'a IdxSet<mir::BasicBlock>, mir: &'a Mir<'tcx>, } -impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> - where O: BitDenotation +impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O> where O: BitDenotation { pub fn results(self) -> DataflowResults<O> { DataflowResults(self.flow_state) @@ -213,10 +373,14 @@ impl<O: BitDenotation> DataflowResults<O> { pub fn sets(&self) -> &AllSets<O::Idx> { &self.0.sets } + + pub fn operator(&self) -> &O { + &self.0.operator + } } -// FIXME: This type shouldn't be public, but the graphviz::MirWithFlowState trait -// references it in a method signature. Look into using `pub(crate)` to address this. +/// State of a dataflow analysis; couples a collection of bit sets +/// with operator used to initialize and merge bits during analysis. pub struct DataflowState<O: BitDenotation> { /// All the sets for the analysis. (Factored into its @@ -228,6 +392,28 @@ pub struct DataflowState<O: BitDenotation> pub(crate) operator: O, } +impl<O: BitDenotation> DataflowState<O> { + pub fn each_bit<F>(&self, words: &IdxSet<O::Idx>, f: F) where F: FnMut(O::Idx) + { + let bits_per_block = self.operator.bits_per_block(); + words.each_bit(bits_per_block, f) + } + + pub fn interpret_set<'c, P>(&self, + o: &'c O, + words: &IdxSet<O::Idx>, + render_idx: &P) + -> Vec<&'c Debug> + where P: Fn(&O, O::Idx) -> &Debug + { + let mut v = Vec::new(); + self.each_bit(words, |i| { + v.push(render_idx(o, i)); + }); + v + } +} + #[derive(Debug)] pub struct AllSets<E: Idx> { /// Analysis bitwidth for each block. @@ -251,9 +437,28 @@ pub struct AllSets<E: Idx> { on_entry_sets: Bits<E>, } +/// Triple of sets associated with a given block. +/// +/// Generally, one sets up `on_entry`, `gen_set`, and `kill_set` for +/// each block individually, and then runs the dataflow analysis which +/// iteratively modifies the various `on_entry` sets (but leaves the +/// other two sets unchanged, since they represent the effect of the +/// block, which should be invariant over the course of the analysis). +/// +/// It is best to ensure that the intersection of `gen_set` and +/// `kill_set` is empty; otherwise the results of the dataflow will +/// have a hidden dependency on what order the bits are generated and +/// killed during the iteration. (This is such a good idea that the +/// `fn gen` and `fn kill` methods that set their state enforce this +/// for you.) pub struct BlockSets<'a, E: Idx> { + /// Dataflow state immediately before control flow enters the given block. pub(crate) on_entry: &'a mut IdxSet<E>, + + /// Bits that are set to 1 by the time we exit the given block. pub(crate) gen_set: &'a mut IdxSet<E>, + + /// Bits that are set to 0 by the time we exit the given block. pub(crate) kill_set: &'a mut IdxSet<E>, } @@ -302,7 +507,7 @@ pub trait DataflowOperator: BitwiseOperator { fn bottom_value() -> bool; } -pub trait BitDenotation { +pub trait BitDenotation: DataflowOperator { /// Specifies what index type is used to access the bitvector. type Idx: Idx; @@ -341,8 +546,7 @@ pub trait BitDenotation { /// the MIR. fn statement_effect(&self, sets: &mut BlockSets<Self::Idx>, - bb: mir::BasicBlock, - idx_stmt: usize); + location: Location); /// Mutates the block-sets (the flow sets for the given /// basic block) according to the effects of evaluating @@ -356,8 +560,7 @@ pub trait BitDenotation { /// terminator took. fn terminator_effect(&self, sets: &mut BlockSets<Self::Idx>, - bb: mir::BasicBlock, - idx_term: usize); + location: Location); /// Mutates the block-sets according to the (flow-dependent) /// effect of a successful return from a Call terminator. @@ -385,8 +588,7 @@ pub trait BitDenotation { dest_lval: &mir::Lvalue); } -impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> - where D: BitDenotation + DataflowOperator +impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation { pub fn new(_tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &'a Mir<'tcx>, @@ -410,12 +612,12 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> }); DataflowAnalysis { - mir: mir, - dead_unwinds: dead_unwinds, + mir, + dead_unwinds, flow_state: DataflowState { sets: AllSets { - bits_per_block: bits_per_block, - words_per_block: words_per_block, + bits_per_block, + words_per_block, gen_sets: zeroes.clone(), kill_sets: zeroes, on_entry_sets: on_entry, @@ -427,8 +629,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> } } -impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> - where D: BitDenotation + DataflowOperator +impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation { /// Propagates the bits of `in_out` into all the successors of `bb`, /// using bitwise operator denoted by `self.operator`. diff --git a/src/librustc_mir/dataflow/move_paths/abs_domain.rs b/src/librustc_mir/dataflow/move_paths/abs_domain.rs index 1255209322b..173396f2245 100644 --- a/src/librustc_mir/dataflow/move_paths/abs_domain.rs +++ b/src/librustc_mir/dataflow/move_paths/abs_domain.rs @@ -58,9 +58,9 @@ impl<'tcx> Lift for LvalueElem<'tcx> { ProjectionElem::Subslice { from: from, to: to }, ProjectionElem::ConstantIndex {offset,min_length,from_end} => ProjectionElem::ConstantIndex { - offset: offset, - min_length: min_length, - from_end: from_end + offset, + min_length, + from_end, }, ProjectionElem::Downcast(a, u) => ProjectionElem::Downcast(a.clone(), u.clone()), diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs new file mode 100644 index 00000000000..c45c91011d9 --- /dev/null +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -0,0 +1,332 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::ty::{self, TyCtxt}; +use rustc::mir::*; +use rustc::mir::tcx::RvalueInitializationState; +use rustc::util::nodemap::FxHashMap; +use rustc_data_structures::indexed_vec::{IndexVec}; + +use syntax::codemap::DUMMY_SP; + +use std::collections::hash_map::Entry; +use std::mem; + +use super::abs_domain::Lift; + +use super::{LocationMap, MoveData, MovePath, MovePathLookup, MovePathIndex, MoveOut, MoveOutIndex}; + +pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> { + mir: &'a Mir<'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>, + data: MoveData<'tcx>, +} + +pub enum MovePathError { + IllegalMove, + UnionMove { path: MovePathIndex }, +} + +impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { + fn new(mir: &'a Mir<'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>) + -> Self { + let mut move_paths = IndexVec::new(); + let mut path_map = IndexVec::new(); + + MoveDataBuilder { + mir, + tcx, + param_env, + data: MoveData { + moves: IndexVec::new(), + loc_map: LocationMap::new(mir), + rev_lookup: MovePathLookup { + locals: mir.local_decls.indices().map(Lvalue::Local).map(|v| { + Self::new_move_path(&mut move_paths, &mut path_map, None, v) + }).collect(), + projections: FxHashMap(), + }, + move_paths, + path_map, + } + } + } + + fn new_move_path(move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>, + path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>, + parent: Option<MovePathIndex>, + lvalue: Lvalue<'tcx>) + -> MovePathIndex + { + let move_path = move_paths.push(MovePath { + next_sibling: None, + first_child: None, + parent, + lvalue, + }); + + if let Some(parent) = parent { + let next_sibling = + mem::replace(&mut move_paths[parent].first_child, Some(move_path)); + move_paths[move_path].next_sibling = next_sibling; + } + + let path_map_ent = path_map.push(vec![]); + assert_eq!(path_map_ent, move_path); + move_path + } + + /// This creates a MovePath for a given lvalue, returning an `MovePathError` + /// if that lvalue can't be moved from. + /// + /// NOTE: lvalues behind references *do not* get a move path, which is + /// problematic for borrowck. + /// + /// Maybe we should have separate "borrowck" and "moveck" modes. + fn move_path_for(&mut self, lval: &Lvalue<'tcx>) + -> Result<MovePathIndex, MovePathError> + { + debug!("lookup({:?})", lval); + match *lval { + Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]), + // error: can't move out of a static + Lvalue::Static(..) => Err(MovePathError::IllegalMove), + Lvalue::Projection(ref proj) => { + self.move_path_for_projection(lval, proj) + } + } + } + + fn create_move_path(&mut self, lval: &Lvalue<'tcx>) { + // This is an assignment, not a move, so this not being a valid + // move path is OK. + let _ = self.move_path_for(lval); + } + + fn move_path_for_projection(&mut self, + lval: &Lvalue<'tcx>, + proj: &LvalueProjection<'tcx>) + -> Result<MovePathIndex, MovePathError> + { + let base = try!(self.move_path_for(&proj.base)); + let lv_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); + match lv_ty.sty { + // error: can't move out of borrowed content + ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove), + // error: can't move out of struct with destructor + ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() => + return Err(MovePathError::IllegalMove), + // move out of union - always move the entire union + ty::TyAdt(adt, _) if adt.is_union() => + return Err(MovePathError::UnionMove { path: base }), + // error: can't move out of a slice + ty::TySlice(..) => + return Err(MovePathError::IllegalMove), + ty::TyArray(..) => match proj.elem { + // error: can't move out of an array + ProjectionElem::Index(..) => return Err(MovePathError::IllegalMove), + _ => { + // FIXME: still badly broken + } + }, + _ => {} + }; + match self.data.rev_lookup.projections.entry((base, proj.elem.lift())) { + Entry::Occupied(ent) => Ok(*ent.get()), + Entry::Vacant(ent) => { + let path = Self::new_move_path( + &mut self.data.move_paths, + &mut self.data.path_map, + Some(base), + lval.clone() + ); + ent.insert(path); + Ok(path) + } + } + } + + fn finalize(self) -> MoveData<'tcx> { + debug!("{}", { + debug!("moves for {:?}:", self.mir.span); + for (j, mo) in self.data.moves.iter_enumerated() { + debug!(" {:?} = {:?}", j, mo); + } + debug!("move paths for {:?}:", self.mir.span); + for (j, path) in self.data.move_paths.iter_enumerated() { + debug!(" {:?} = {:?}", j, path); + } + "done dumping moves" + }); + self.data + } +} + +pub(super) fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, + tcx: TyCtxt<'a, 'tcx, 'tcx>, + param_env: ty::ParamEnv<'tcx>) + -> MoveData<'tcx> { + let mut builder = MoveDataBuilder::new(mir, tcx, param_env); + + for (bb, block) in mir.basic_blocks().iter_enumerated() { + for (i, stmt) in block.statements.iter().enumerate() { + let source = Location { block: bb, statement_index: i }; + builder.gather_statement(source, stmt); + } + + let terminator_loc = Location { + block: bb, + statement_index: block.statements.len() + }; + builder.gather_terminator(terminator_loc, block.terminator()); + } + + builder.finalize() +} + +impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { + fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) { + debug!("gather_statement({:?}, {:?})", loc, stmt); + match stmt.kind { + StatementKind::Assign(ref lval, ref rval) => { + self.create_move_path(lval); + if let RvalueInitializationState::Shallow = rval.initialization_state() { + // Box starts out uninitialized - need to create a separate + // move-path for the interior so it will be separate from + // the exterior. + self.create_move_path(&lval.clone().deref()); + } + self.gather_rvalue(loc, rval); + } + StatementKind::StorageLive(_) | + StatementKind::StorageDead(_) => {} + StatementKind::SetDiscriminant{ .. } => { + span_bug!(stmt.source_info.span, + "SetDiscriminant should not exist during borrowck"); + } + StatementKind::InlineAsm { .. } | + StatementKind::EndRegion(_) | + StatementKind::Validate(..) | + StatementKind::Nop => {} + } + } + + fn gather_rvalue(&mut self, loc: Location, rvalue: &Rvalue<'tcx>) { + match *rvalue { + Rvalue::Use(ref operand) | + Rvalue::Repeat(ref operand, _) | + Rvalue::Cast(_, ref operand, _) | + Rvalue::UnaryOp(_, ref operand) => { + self.gather_operand(loc, operand) + } + Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) | + Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { + self.gather_operand(loc, lhs); + self.gather_operand(loc, rhs); + } + Rvalue::Aggregate(ref _kind, ref operands) => { + for operand in operands { + self.gather_operand(loc, operand); + } + } + Rvalue::Ref(..) | + Rvalue::Discriminant(..) | + Rvalue::Len(..) | + Rvalue::NullaryOp(NullOp::SizeOf, _) | + Rvalue::NullaryOp(NullOp::Box, _) => { + // This returns an rvalue with uninitialized contents. We can't + // move out of it here because it is an rvalue - assignments always + // completely initialize their lvalue. + // + // However, this does not matter - MIR building is careful to + // only emit a shallow free for the partially-initialized + // temporary. + // + // In any case, if we want to fix this, we have to register a + // special move and change the `statement_effect` functions. + } + } + } + + fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) { + debug!("gather_terminator({:?}, {:?})", loc, term); + match term.kind { + TerminatorKind::Goto { target: _ } | + TerminatorKind::Resume | + TerminatorKind::Unreachable => { } + + TerminatorKind::Return => { + self.gather_move(loc, &Lvalue::Local(RETURN_POINTER)); + } + + TerminatorKind::Assert { .. } | + TerminatorKind::SwitchInt { .. } => { + // branching terminators - these don't move anything + } + + TerminatorKind::Drop { ref location, target: _, unwind: _ } => { + self.gather_move(loc, location); + } + TerminatorKind::DropAndReplace { ref location, ref value, .. } => { + self.create_move_path(location); + self.gather_operand(loc, value); + } + TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => { + self.gather_operand(loc, func); + for arg in args { + self.gather_operand(loc, arg); + } + if let Some((ref destination, _bb)) = *destination { + self.create_move_path(destination); + } + } + } + } + + fn gather_operand(&mut self, loc: Location, operand: &Operand<'tcx>) { + match *operand { + Operand::Constant(..) => {} // not-a-move + Operand::Consume(ref lval) => { // a move + self.gather_move(loc, lval); + } + } + } + + fn gather_move(&mut self, loc: Location, lval: &Lvalue<'tcx>) { + debug!("gather_move({:?}, {:?})", loc, lval); + + let lv_ty = lval.ty(self.mir, self.tcx).to_ty(self.tcx); + if !lv_ty.moves_by_default(self.tcx, self.param_env, DUMMY_SP) { + debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", loc, lval, lv_ty); + return + } + + let path = match self.move_path_for(lval) { + Ok(path) | Err(MovePathError::UnionMove { path }) => path, + Err(MovePathError::IllegalMove) => { + // Moving out of a bad path. Eventually, this should be a MIR + // borrowck error instead of a bug. + span_bug!(self.mir.span, + "Broken MIR: moving out of lvalue {:?}: {:?} at {:?}", + lval, lv_ty, loc); + } + }; + let move_out = self.data.moves.push(MoveOut { path: path, source: loc }); + + debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}", + loc, lval, move_out, path); + + self.data.path_map[path].push(move_out); + self.data.loc_map[loc].push(move_out); + } +} diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 20a61418d85..d2d80649846 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -11,15 +11,10 @@ use rustc::ty::{self, TyCtxt}; use rustc::mir::*; -use rustc::mir::tcx::RvalueInitializationState; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{IndexVec}; -use syntax::codemap::DUMMY_SP; - -use std::collections::hash_map::Entry; use std::fmt; -use std::mem; use std::ops::{Index, IndexMut}; use self::abs_domain::{AbstractElem, Lift}; @@ -63,6 +58,9 @@ pub(crate) mod indexes { /// Index into MoveData.moves. new_index!(MoveOutIndex, "mo"); + + /// Index into Borrows.locations + new_index!(BorrowIndex, "bw"); } pub use self::indexes::MovePathIndex; @@ -110,6 +108,12 @@ impl<'tcx> fmt::Debug for MovePath<'tcx> { } } +impl<'tcx> fmt::Display for MovePath<'tcx> { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + write!(w, "{:?}", self.lvalue) + } +} + #[derive(Debug)] pub struct MoveData<'tcx> { pub move_paths: IndexVec<MovePathIndex, MovePath<'tcx>>, @@ -191,154 +195,7 @@ pub struct MovePathLookup<'tcx> { projections: FxHashMap<(MovePathIndex, AbstractElem<'tcx>), MovePathIndex> } -pub(super) struct MoveDataBuilder<'a, 'tcx: 'a> { - mir: &'a Mir<'tcx>, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - data: MoveData<'tcx>, -} - -pub enum MovePathError { - IllegalMove, - UnionMove { path: MovePathIndex }, -} - -impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { - fn new(mir: &'a Mir<'tcx>, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) - -> Self { - let mut move_paths = IndexVec::new(); - let mut path_map = IndexVec::new(); - - MoveDataBuilder { - mir: mir, - tcx: tcx, - param_env: param_env, - data: MoveData { - moves: IndexVec::new(), - loc_map: LocationMap::new(mir), - rev_lookup: MovePathLookup { - locals: mir.local_decls.indices().map(Lvalue::Local).map(|v| { - Self::new_move_path(&mut move_paths, &mut path_map, None, v) - }).collect(), - projections: FxHashMap(), - }, - move_paths: move_paths, - path_map: path_map, - } - } - } - - fn new_move_path(move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>, - path_map: &mut IndexVec<MovePathIndex, Vec<MoveOutIndex>>, - parent: Option<MovePathIndex>, - lvalue: Lvalue<'tcx>) - -> MovePathIndex - { - let move_path = move_paths.push(MovePath { - next_sibling: None, - first_child: None, - parent: parent, - lvalue: lvalue - }); - - if let Some(parent) = parent { - let next_sibling = - mem::replace(&mut move_paths[parent].first_child, Some(move_path)); - move_paths[move_path].next_sibling = next_sibling; - } - - let path_map_ent = path_map.push(vec![]); - assert_eq!(path_map_ent, move_path); - move_path - } - - /// This creates a MovePath for a given lvalue, returning an `MovePathError` - /// if that lvalue can't be moved from. - /// - /// NOTE: lvalues behind references *do not* get a move path, which is - /// problematic for borrowck. - /// - /// Maybe we should have separate "borrowck" and "moveck" modes. - fn move_path_for(&mut self, lval: &Lvalue<'tcx>) - -> Result<MovePathIndex, MovePathError> - { - debug!("lookup({:?})", lval); - match *lval { - Lvalue::Local(local) => Ok(self.data.rev_lookup.locals[local]), - // error: can't move out of a static - Lvalue::Static(..) => Err(MovePathError::IllegalMove), - Lvalue::Projection(ref proj) => { - self.move_path_for_projection(lval, proj) - } - } - } - - fn create_move_path(&mut self, lval: &Lvalue<'tcx>) { - // This is an assignment, not a move, so this not being a valid - // move path is OK. - let _ = self.move_path_for(lval); - } - - fn move_path_for_projection(&mut self, - lval: &Lvalue<'tcx>, - proj: &LvalueProjection<'tcx>) - -> Result<MovePathIndex, MovePathError> - { - let base = try!(self.move_path_for(&proj.base)); - let lv_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx); - match lv_ty.sty { - // error: can't move out of borrowed content - ty::TyRef(..) | ty::TyRawPtr(..) => return Err(MovePathError::IllegalMove), - // error: can't move out of struct with destructor - ty::TyAdt(adt, _) if adt.has_dtor(self.tcx) && !adt.is_box() => - return Err(MovePathError::IllegalMove), - // move out of union - always move the entire union - ty::TyAdt(adt, _) if adt.is_union() => - return Err(MovePathError::UnionMove { path: base }), - // error: can't move out of a slice - ty::TySlice(..) => - return Err(MovePathError::IllegalMove), - ty::TyArray(..) => match proj.elem { - // error: can't move out of an array - ProjectionElem::Index(..) => return Err(MovePathError::IllegalMove), - _ => { - // FIXME: still badly broken - } - }, - _ => {} - }; - match self.data.rev_lookup.projections.entry((base, proj.elem.lift())) { - Entry::Occupied(ent) => Ok(*ent.get()), - Entry::Vacant(ent) => { - let path = Self::new_move_path( - &mut self.data.move_paths, - &mut self.data.path_map, - Some(base), - lval.clone() - ); - ent.insert(path); - Ok(path) - } - } - } - - fn finalize(self) -> MoveData<'tcx> { - debug!("{}", { - debug!("moves for {:?}:", self.mir.span); - for (j, mo) in self.data.moves.iter_enumerated() { - debug!(" {:?} = {:?}", j, mo); - } - debug!("move paths for {:?}:", self.mir.span); - for (j, path) in self.data.move_paths.iter_enumerated() { - debug!(" {:?} = {:?}", j, path); - } - "done dumping moves" - }); - self.data - } -} +mod builder; #[derive(Copy, Clone, Debug)] pub enum LookupResult { @@ -375,165 +232,6 @@ impl<'a, 'tcx> MoveData<'tcx> { tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self { - gather_moves(mir, tcx, param_env) - } -} - -fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - param_env: ty::ParamEnv<'tcx>) - -> MoveData<'tcx> { - let mut builder = MoveDataBuilder::new(mir, tcx, param_env); - - for (bb, block) in mir.basic_blocks().iter_enumerated() { - for (i, stmt) in block.statements.iter().enumerate() { - let source = Location { block: bb, statement_index: i }; - builder.gather_statement(source, stmt); - } - - let terminator_loc = Location { - block: bb, - statement_index: block.statements.len() - }; - builder.gather_terminator(terminator_loc, block.terminator()); - } - - builder.finalize() -} - -impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> { - fn gather_statement(&mut self, loc: Location, stmt: &Statement<'tcx>) { - debug!("gather_statement({:?}, {:?})", loc, stmt); - match stmt.kind { - StatementKind::Assign(ref lval, ref rval) => { - self.create_move_path(lval); - if let RvalueInitializationState::Shallow = rval.initialization_state() { - // Box starts out uninitialized - need to create a separate - // move-path for the interior so it will be separate from - // the exterior. - self.create_move_path(&lval.clone().deref()); - } - self.gather_rvalue(loc, rval); - } - StatementKind::StorageLive(_) | - StatementKind::StorageDead(_) => {} - StatementKind::SetDiscriminant{ .. } => { - span_bug!(stmt.source_info.span, - "SetDiscriminant should not exist during borrowck"); - } - StatementKind::InlineAsm { .. } | - StatementKind::EndRegion(_) | - StatementKind::Validate(..) | - StatementKind::Nop => {} - } - } - - fn gather_rvalue(&mut self, loc: Location, rvalue: &Rvalue<'tcx>) { - match *rvalue { - Rvalue::Use(ref operand) | - Rvalue::Repeat(ref operand, _) | - Rvalue::Cast(_, ref operand, _) | - Rvalue::UnaryOp(_, ref operand) => { - self.gather_operand(loc, operand) - } - Rvalue::BinaryOp(ref _binop, ref lhs, ref rhs) | - Rvalue::CheckedBinaryOp(ref _binop, ref lhs, ref rhs) => { - self.gather_operand(loc, lhs); - self.gather_operand(loc, rhs); - } - Rvalue::Aggregate(ref _kind, ref operands) => { - for operand in operands { - self.gather_operand(loc, operand); - } - } - Rvalue::Ref(..) | - Rvalue::Discriminant(..) | - Rvalue::Len(..) | - Rvalue::NullaryOp(NullOp::SizeOf, _) | - Rvalue::NullaryOp(NullOp::Box, _) => { - // This returns an rvalue with uninitialized contents. We can't - // move out of it here because it is an rvalue - assignments always - // completely initialize their lvalue. - // - // However, this does not matter - MIR building is careful to - // only emit a shallow free for the partially-initialized - // temporary. - // - // In any case, if we want to fix this, we have to register a - // special move and change the `statement_effect` functions. - } - } - } - - fn gather_terminator(&mut self, loc: Location, term: &Terminator<'tcx>) { - debug!("gather_terminator({:?}, {:?})", loc, term); - match term.kind { - TerminatorKind::Goto { target: _ } | - TerminatorKind::Resume | - TerminatorKind::Unreachable => { } - - TerminatorKind::Return => { - self.gather_move(loc, &Lvalue::Local(RETURN_POINTER)); - } - - TerminatorKind::Assert { .. } | - TerminatorKind::SwitchInt { .. } => { - // branching terminators - these don't move anything - } - - TerminatorKind::Drop { ref location, target: _, unwind: _ } => { - self.gather_move(loc, location); - } - TerminatorKind::DropAndReplace { ref location, ref value, .. } => { - self.create_move_path(location); - self.gather_operand(loc, value); - } - TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => { - self.gather_operand(loc, func); - for arg in args { - self.gather_operand(loc, arg); - } - if let Some((ref destination, _bb)) = *destination { - self.create_move_path(destination); - } - } - } - } - - fn gather_operand(&mut self, loc: Location, operand: &Operand<'tcx>) { - match *operand { - Operand::Constant(..) => {} // not-a-move - Operand::Consume(ref lval) => { // a move - self.gather_move(loc, lval); - } - } - } - - fn gather_move(&mut self, loc: Location, lval: &Lvalue<'tcx>) { - debug!("gather_move({:?}, {:?})", loc, lval); - - let lv_ty = lval.ty(self.mir, self.tcx).to_ty(self.tcx); - if !lv_ty.moves_by_default(self.tcx, self.param_env, DUMMY_SP) { - debug!("gather_move({:?}, {:?}) - {:?} is Copy. skipping", loc, lval, lv_ty); - return - } - - let path = match self.move_path_for(lval) { - Ok(path) | Err(MovePathError::UnionMove { path }) => path, - Err(MovePathError::IllegalMove) => { - // Moving out of a bad path. Eventually, this should be a MIR - // borrowck error instead of a bug. - span_bug!(self.mir.span, - "Broken MIR: moving out of lvalue {:?}: {:?} at {:?}", - lval, lv_ty, loc); - } - }; - let move_out = self.data.moves.push(MoveOut { path: path, source: loc }); - - debug!("gather_move({:?}, {:?}): adding move {:?} of {:?}", - loc, lval, move_out, path); - - self.data.path_map[path].push(move_out); - self.data.loc_map[loc].push(move_out); + builder::gather_moves(mir, tcx, param_env) } } diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs index 34170a6609c..83a8ce34c69 100644 --- a/src/librustc_mir/diagnostics.rs +++ b/src/librustc_mir/diagnostics.rs @@ -195,6 +195,50 @@ instead of using a `const fn`, or refactoring the code to a functional style to avoid mutation if possible. "##, +E0381: r##" +It is not allowed to use or capture an uninitialized variable. For example: + +```compile_fail,E0381 +fn main() { + let x: i32; + let y = x; // error, use of possibly uninitialized variable +} +``` + +To fix this, ensure that any declared variables are initialized before being +used. Example: + +``` +fn main() { + let x: i32 = 0; + let y = x; // ok! +} +``` +"##, + +E0384: r##" +This error occurs when an attempt is made to reassign an immutable variable. +For example: + +```compile_fail,E0384 +fn main() { + let x = 3; + x = 5; // error, reassignment of immutable variable +} +``` + +By default, variables in Rust are immutable. To fix this error, add the keyword +`mut` after the keyword `let` when declaring the variable. For example: + +``` +fn main() { + let mut x = 3; + x = 5; +} +``` +"##, + + E0394: r##" A static was referred to by value by another static. @@ -438,9 +482,516 @@ static A : &'static u32 = &S.a; // ok! ``` "##, +E0499: r##" +A variable was borrowed as mutable more than once. Erroneous code example: + +```compile_fail,E0499 +let mut i = 0; +let mut x = &mut i; +let mut a = &mut i; +// error: cannot borrow `i` as mutable more than once at a time +``` + +Please note that in rust, you can either have many immutable references, or one +mutable reference. Take a look at +https://doc.rust-lang.org/stable/book/references-and-borrowing.html for more +information. Example: + + +``` +let mut i = 0; +let mut x = &mut i; // ok! + +// or: +let mut i = 0; +let a = &i; // ok! +let b = &i; // still ok! +let c = &i; // still ok! +``` +"##, + +E0500: r##" +A borrowed variable was used in another closure. Example of erroneous code: + +```compile_fail +fn you_know_nothing(jon_snow: &mut i32) { + let nights_watch = || { + *jon_snow = 2; + }; + let starks = || { + *jon_snow = 3; // error: closure requires unique access to `jon_snow` + // but it is already borrowed + }; +} +``` + +In here, `jon_snow` is already borrowed by the `nights_watch` closure, so it +cannot be borrowed by the `starks` closure at the same time. To fix this issue, +you can put the closure in its own scope: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + { + let nights_watch = || { + *jon_snow = 2; + }; + } // At this point, `jon_snow` is free. + let starks = || { + *jon_snow = 3; + }; +} +``` + +Or, if the type implements the `Clone` trait, you can clone it between +closures: + +``` +fn you_know_nothing(jon_snow: &mut i32) { + let mut jon_copy = jon_snow.clone(); + let nights_watch = || { + jon_copy = 2; + }; + let starks = || { + *jon_snow = 3; + }; +} +``` +"##, + +E0501: r##" +This error indicates that a mutable variable is being used while it is still +captured by a closure. Because the closure has borrowed the variable, it is not +available for use until the closure goes out of scope. + +Note that a capture will either move or borrow a variable, but in this +situation, the closure is borrowing the variable. Take a look at +http://rustbyexample.com/fn/closures/capture.html for more information about +capturing. + +Example of erroneous code: + +```compile_fail,E0501 +fn inside_closure(x: &mut i32) { + // Actions which require unique access +} + +fn outside_closure(x: &mut i32) { + // Actions which require unique access +} + +fn foo(a: &mut i32) { + let bar = || { + inside_closure(a) + }; + outside_closure(a); // error: cannot borrow `*a` as mutable because previous + // closure requires unique access. +} +``` + +To fix this error, you can place the closure in its own scope: + +``` +fn inside_closure(x: &mut i32) {} +fn outside_closure(x: &mut i32) {} + +fn foo(a: &mut i32) { + { + let bar = || { + inside_closure(a) + }; + } // borrow on `a` ends. + outside_closure(a); // ok! +} +``` + +Or you can pass the variable as a parameter to the closure: + +``` +fn inside_closure(x: &mut i32) {} +fn outside_closure(x: &mut i32) {} + +fn foo(a: &mut i32) { + let bar = |s: &mut i32| { + inside_closure(s) + }; + outside_closure(a); + bar(a); +} +``` + +It may be possible to define the closure later: + +``` +fn inside_closure(x: &mut i32) {} +fn outside_closure(x: &mut i32) {} + +fn foo(a: &mut i32) { + outside_closure(a); + let bar = || { + inside_closure(a) + }; +} +``` +"##, + +E0502: r##" +This error indicates that you are trying to borrow a variable as mutable when it +has already been borrowed as immutable. + +Example of erroneous code: + +```compile_fail,E0502 +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + let ref y = a; // a is borrowed as immutable. + bar(a); // error: cannot borrow `*a` as mutable because `a` is also borrowed + // as immutable +} +``` + +To fix this error, ensure that you don't have any other references to the +variable before trying to access it mutably: + +``` +fn bar(x: &mut i32) {} +fn foo(a: &mut i32) { + bar(a); + let ref y = a; // ok! +} +``` + +For more information on the rust ownership system, take a look at +https://doc.rust-lang.org/stable/book/references-and-borrowing.html. +"##, + +E0503: r##" +A value was used after it was mutably borrowed. + +Example of erroneous code: + +```compile_fail,E0503 +fn main() { + let mut value = 3; + // Create a mutable borrow of `value`. This borrow + // lives until the end of this function. + let _borrow = &mut value; + let _sum = value + 1; // error: cannot use `value` because + // it was mutably borrowed +} +``` + +In this example, `value` is mutably borrowed by `borrow` and cannot be +used to calculate `sum`. This is not possible because this would violate +Rust's mutability rules. + +You can fix this error by limiting the scope of the borrow: + +``` +fn main() { + let mut value = 3; + // By creating a new block, you can limit the scope + // of the reference. + { + let _borrow = &mut value; // Use `_borrow` inside this block. + } + // The block has ended and with it the borrow. + // You can now use `value` again. + let _sum = value + 1; +} +``` + +Or by cloning `value` before borrowing it: + +``` +fn main() { + let mut value = 3; + // We clone `value`, creating a copy. + let value_cloned = value.clone(); + // The mutable borrow is a reference to `value` and + // not to `value_cloned`... + let _borrow = &mut value; + // ... which means we can still use `value_cloned`, + let _sum = value_cloned + 1; + // even though the borrow only ends here. +} +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/stable/book/references-and-borrowing.html +"##, + +E0504: r##" +This error occurs when an attempt is made to move a borrowed variable into a +closure. + +Example of erroneous code: + +```compile_fail,E0504 +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + println!("child function: {}", fancy_num.num); + // error: cannot move `fancy_num` into closure because it is borrowed + }; + + x(); + println!("main function: {}", fancy_ref.num); +} +``` + +Here, `fancy_num` is borrowed by `fancy_ref` and so cannot be moved into +the closure `x`. There is no way to move a value into a closure while it is +borrowed, as that would invalidate the borrow. + +If the closure can't outlive the value being moved, try using a reference +rather than moving: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + + let x = move || { + // fancy_ref is usable here because it doesn't move `fancy_num` + println!("child function: {}", fancy_ref.num); + }; + + x(); + + println!("main function: {}", fancy_num.num); +} +``` + +If the value has to be borrowed and then moved, try limiting the lifetime of +the borrow using a scoped block: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_num = FancyNum { num: 5 }; + + { + let fancy_ref = &fancy_num; + println!("main function: {}", fancy_ref.num); + // `fancy_ref` goes out of scope here + } + + let x = move || { + // `fancy_num` can be moved now (no more references exist) + println!("child function: {}", fancy_num.num); + }; + + x(); +} +``` + +If the lifetime of a reference isn't enough, such as in the case of threading, +consider using an `Arc` to create a reference-counted value: + +``` +use std::sync::Arc; +use std::thread; + +struct FancyNum { + num: u8, +} + +fn main() { + let fancy_ref1 = Arc::new(FancyNum { num: 5 }); + let fancy_ref2 = fancy_ref1.clone(); + + let x = thread::spawn(move || { + // `fancy_ref1` can be moved and has a `'static` lifetime + println!("child thread: {}", fancy_ref1.num); + }); + + x.join().expect("child thread should finish"); + println!("main thread: {}", fancy_ref2.num); +} +``` +"##, + +E0505: r##" +A value was moved out while it was still borrowed. + +Erroneous code example: + +```compile_fail,E0505 +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(x); + } +} +``` + +Here, the function `eat` takes the ownership of `x`. However, +`x` cannot be moved because it was borrowed to `_ref_to_val`. +To fix that you can do few different things: + +* Try to avoid moving the variable. +* Release borrow before move. +* Implement the `Copy` trait on the type. + +Examples: + +``` +struct Value {} + +fn eat(val: &Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(&x); // pass by reference, if it's possible + } +} +``` + +Or: + +``` +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + } + eat(x); // release borrow and then move it. +} +``` + +Or: + +``` +#[derive(Clone, Copy)] // implement Copy trait +struct Value {} + +fn eat(val: Value) {} + +fn main() { + let x = Value{}; + { + let _ref_to_val: &Value = &x; + eat(x); // it will be copied here. + } +} +``` + +You can find more information about borrowing in the rust-book: +http://doc.rust-lang.org/stable/book/references-and-borrowing.html +"##, + +E0506: r##" +This error occurs when an attempt is made to assign to a borrowed value. + +Example of erroneous code: + +```compile_fail,E0506 +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + let fancy_ref = &fancy_num; + fancy_num = FancyNum { num: 6 }; + // error: cannot assign to `fancy_num` because it is borrowed + + println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num); +} +``` + +Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't +be assigned to a new value as it would invalidate the reference. + +Alternatively, we can move out of `fancy_num` into a second `fancy_num`: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + let moved_num = fancy_num; + fancy_num = FancyNum { num: 6 }; + + println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num); +} +``` + +If the value has to be borrowed, try limiting the lifetime of the borrow using +a scoped block: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + + { + let fancy_ref = &fancy_num; + println!("Ref: {}", fancy_ref.num); + } + + // Works because `fancy_ref` is no longer in scope + fancy_num = FancyNum { num: 6 }; + println!("Num: {}", fancy_num.num); +} +``` + +Or by moving the reference into a function: + +``` +struct FancyNum { + num: u8, +} + +fn main() { + let mut fancy_num = FancyNum { num: 5 }; + + print_fancy_ref(&fancy_num); + + // Works because function borrow has ended + fancy_num = FancyNum { num: 6 }; + println!("Num: {}", fancy_num.num); +} + +fn print_fancy_ref(fancy_ref: &FancyNum){ + println!("Ref: {}", fancy_ref.num); +} +``` +"##, + } register_diagnostics! { + E0524, // two closures require unique access to `..` at the same time E0526, // shuffle indices are not constant E0625, // thread-local statics cannot be accessed at compile-time } diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index fa54925c6e7..61d128fc847 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -22,16 +22,13 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { // We have to eagerly translate the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = mirror_stmts(cx, self.id, &*self.stmts); - let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id); - let opt_destruction_extent = opt_def_id.and_then(|def_id| { - cx.tcx.region_maps(def_id).opt_destruction_extent(self.id) - }); + let opt_destruction_extent = cx.region_maps.opt_destruction_extent(self.id); Block { targeted_by_break: self.targeted_by_break, extent: CodeExtent::Misc(self.id), - opt_destruction_extent: opt_destruction_extent, + opt_destruction_extent, span: self.span, - stmts: stmts, + stmts, expr: self.expr.to_ref(), } } @@ -42,11 +39,8 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, stmts: &'tcx [hir::Stmt]) -> Vec<StmtRef<'tcx>> { let mut result = vec![]; - let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id); for (index, stmt) in stmts.iter().enumerate() { - let opt_dxn_ext = opt_def_id.and_then(|def_id| { - cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id()) - }); + let opt_dxn_ext = cx.region_maps.opt_destruction_extent(stmt.node.id()); match stmt.node { hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { @@ -79,7 +73,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, kind: StmtKind::Let { remainder_scope: remainder_extent, init_scope: CodeExtent::Misc(id), - pattern: pattern, + pattern, initializer: local.init.to_ref(), }, opt_destruction_extent: opt_dxn_ext, @@ -99,7 +93,7 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let temp_lifetime = cx.region_maps.temporary_scope(block.id); let expr = Expr { ty: block_ty, - temp_lifetime: temp_lifetime, + temp_lifetime, span: block.span, kind: ExprKind::Block { body: block }, }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 617c3c77bbb..944fb8e8332 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -42,7 +42,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { // Next, wrap this up in the expr's scope. expr = Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: expr.ty, span: self.span, kind: ExprKind::Scope { @@ -54,11 +54,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { // Finally, create a destruction scope, if any. if let Some(extent) = cx.region_maps.opt_destruction_extent(self.id) { expr = Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: expr.ty, span: self.span, kind: ExprKind::Scope { - extent: extent, + extent, value: expr.to_ref(), }, }; @@ -136,7 +136,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }), span, kind: ExprKind::Borrow { - region: region, + region, borrow_kind: to_borrow_kind(m), arg: expr.to_ref(), }, @@ -173,7 +173,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), - args: args, + args, } } @@ -191,7 +191,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e)); let tupled_args = Expr { ty: cx.tcx.mk_tup(arg_tys, false), - temp_lifetime: temp_lifetime, + temp_lifetime, span: expr.span, kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() }, }; @@ -228,8 +228,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }) .collect(); ExprKind::Adt { - adt_def: adt_def, - substs: substs, + adt_def, + substs, variant_index: index, fields: field_refs, base: None, @@ -250,7 +250,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, _ => span_bug!(expr.span, "type of & not region"), }; ExprKind::Borrow { - region: region, + region, borrow_kind: to_borrow_kind(mutbl), arg: expr.to_ref(), } @@ -320,7 +320,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, _ => { let op = bin_op(op.node); ExprKind::Binary { - op: op, + op, lhs: lhs.to_ref(), rhs: rhs.to_ref(), } @@ -384,7 +384,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Adt { adt_def: adt, variant_index: 0, - substs: substs, + substs, fields: field_refs, base: base.as_ref().map(|base| { FruInfo { @@ -410,7 +410,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Adt { adt_def: adt, variant_index: index, - substs: substs, + substs, fields: field_refs, base: None, } @@ -446,8 +446,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); ExprKind::Closure { closure_id: def_id, - substs: substs, - upvars: upvars, + substs, + upvars, } } @@ -458,7 +458,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprInlineAsm(ref asm, ref outputs, ref inputs) => { ExprKind::InlineAsm { - asm: asm, + asm, outputs: outputs.to_ref(), inputs: inputs.to_ref(), } @@ -477,7 +477,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Repeat { value: v.to_ref(), - count: count, + count, } } hir::ExprRet(ref v) => ExprKind::Return { value: v.to_ref() }, @@ -570,10 +570,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: expr_ty, span: expr.span, - kind: kind, + kind, } } @@ -587,7 +587,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, cx.tables().node_substs(expr.hir_id)) }); Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: cx.tcx().mk_fn_def(def_id, substs), span: expr.span, kind: ExprKind::Literal { @@ -637,8 +637,8 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => ExprKind::Literal { literal: Literal::Item { - def_id: def_id, - substs: substs, + def_id, + substs, }, }, @@ -649,9 +649,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // We return a completely different ExprKind here to account for this special case. ty::TyAdt(adt_def, substs) => { ExprKind::Adt { - adt_def: adt_def, + adt_def, variant_index: adt_def.variant_index_with_id(def_id), - substs: substs, + substs, fields: vec![], base: None, } @@ -712,12 +712,12 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); Expr { ty: closure_ty, - temp_lifetime: temp_lifetime, + temp_lifetime, span: expr.span, kind: ExprKind::Deref { arg: Expr { ty: ref_closure_ty, - temp_lifetime: temp_lifetime, + temp_lifetime, span: expr.span, kind: ExprKind::SelfRef, } @@ -733,12 +733,12 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }); Expr { ty: closure_ty, - temp_lifetime: temp_lifetime, + temp_lifetime, span: expr.span, kind: ExprKind::Deref { arg: Expr { ty: ref_closure_ty, - temp_lifetime: temp_lifetime, + temp_lifetime, span: expr.span, kind: ExprKind::SelfRef, }.to_ref(), @@ -748,7 +748,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::ClosureKind::FnOnce => { Expr { ty: closure_ty, - temp_lifetime: temp_lifetime, + temp_lifetime, span: expr.span, kind: ExprKind::SelfRef, } @@ -772,7 +772,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::UpvarCapture::ByRef(borrow) => { ExprKind::Deref { arg: Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: cx.tcx.mk_ref(borrow.region, ty::TypeAndMut { ty: var_ty, @@ -857,7 +857,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let temp_lifetime = cx.region_maps.temporary_scope(expr.id); let fun = method_callee(cx, expr, custom_callee); let ref_expr = Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: ref_ty, span: expr.span, kind: ExprKind::Call { @@ -887,7 +887,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let var_ty = cx.tables() .node_id_to_type(cx.tcx.hir.node_to_hir_id(var_node_id)); let captured_var = Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: var_ty, span: closure_expr.span, kind: convert_var(cx, closure_expr, freevar.def), @@ -901,12 +901,12 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ty::BorrowKind::MutBorrow => BorrowKind::Mut, }; Expr { - temp_lifetime: temp_lifetime, + temp_lifetime, ty: freevar_ty, span: closure_expr.span, kind: ExprKind::Borrow { region: upvar_borrow.region, - borrow_kind: borrow_kind, + borrow_kind, arg: captured_var.to_ref(), }, }.to_ref() diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index ea8624930e5..dba625e98fd 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,9 +14,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! */ -#![crate_name = "rustc_mir"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![deny(warnings)] #![feature(box_patterns)] @@ -32,6 +29,7 @@ extern crate graphviz as dot; #[macro_use] extern crate rustc; extern crate rustc_data_structures; +extern crate rustc_errors; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -42,10 +40,11 @@ extern crate rustc_const_math; extern crate rustc_const_eval; extern crate core; // for NonZero -pub mod diagnostics; +mod diagnostics; +mod borrow_check; mod build; -pub mod dataflow; +mod dataflow; mod hair; mod shim; pub mod transform; @@ -54,6 +53,7 @@ pub mod util; use rustc::ty::maps::Providers; pub fn provide(providers: &mut Providers) { + borrow_check::provide(providers); shim::provide(providers); transform::provide(providers); } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 62e762be93a..6bee1ceff89 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -17,6 +17,7 @@ use rustc::mir::transform::MirSource; use rustc::ty::{self, Ty}; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::maps::Providers; +use rustc_const_math::{ConstInt, ConstUsize}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; @@ -98,14 +99,25 @@ fn make_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, ty::InstanceDef::DropGlue(def_id, ty) => { build_drop_shim(tcx, def_id, ty) } + ty::InstanceDef::CloneShim(def_id, ty) => { + let name = tcx.item_name(def_id).as_str(); + if name == "clone" { + build_clone_shim(tcx, def_id, ty) + } else if name == "clone_from" { + debug!("make_shim({:?}: using default trait implementation", instance); + return tcx.optimized_mir(def_id); + } else { + bug!("builtin clone shim {:?} not supported", instance) + } + } ty::InstanceDef::Intrinsic(_) => { bug!("creating shims from intrinsics ({:?}) is unsupported", instance) } }; - debug!("make_shim({:?}) = untransformed {:?}", instance, result); - no_landing_pads::no_landing_pads(tcx, &mut result); - simplify::simplify_cfg(&mut result); - add_call_guards::CriticalCallEdges.add_call_guards(&mut result); + debug!("make_shim({:?}) = untransformed {:?}", instance, result); + no_landing_pads::no_landing_pads(tcx, &mut result); + simplify::simplify_cfg(&mut result); + add_call_guards::CriticalCallEdges.add_call_guards(&mut result); debug!("make_shim({:?}) = {:?}", instance, result); tcx.alloc_mir(result) @@ -259,6 +271,374 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { } } +/// Build a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`. +fn build_clone_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + self_ty: ty::Ty<'tcx>) + -> Mir<'tcx> +{ + debug!("build_clone_shim(def_id={:?})", def_id); + + let mut builder = CloneShimBuilder::new(tcx, def_id); + let is_copy = !self_ty.moves_by_default(tcx, tcx.param_env(def_id), builder.span); + + match self_ty.sty { + _ if is_copy => builder.copy_shim(), + ty::TyArray(ty, len) => builder.array_shim(ty, len), + ty::TyTuple(tys, _) => builder.tuple_shim(tys), + _ => { + bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty); + } + }; + + builder.into_mir() +} + +struct CloneShimBuilder<'a, 'tcx: 'a> { + tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId, + local_decls: IndexVec<Local, LocalDecl<'tcx>>, + blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>, + span: Span, + sig: ty::FnSig<'tcx>, +} + +impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> { + fn new(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Self { + let sig = tcx.fn_sig(def_id); + let sig = tcx.erase_late_bound_regions(&sig); + let span = tcx.def_span(def_id); + + CloneShimBuilder { + tcx, + def_id, + local_decls: local_decls_for_sig(&sig, span), + blocks: IndexVec::new(), + span, + sig, + } + } + + fn into_mir(self) -> Mir<'tcx> { + Mir::new( + self.blocks, + IndexVec::from_elem_n( + VisibilityScopeData { span: self.span, parent_scope: None }, 1 + ), + IndexVec::new(), + self.sig.output(), + self.local_decls, + self.sig.inputs().len(), + vec![], + self.span + ) + } + + fn source_info(&self) -> SourceInfo { + SourceInfo { span: self.span, scope: ARGUMENT_VISIBILITY_SCOPE } + } + + fn block( + &mut self, + statements: Vec<Statement<'tcx>>, + kind: TerminatorKind<'tcx>, + is_cleanup: bool + ) -> BasicBlock { + let source_info = self.source_info(); + self.blocks.push(BasicBlockData { + statements, + terminator: Some(Terminator { source_info, kind }), + is_cleanup, + }) + } + + fn make_statement(&self, kind: StatementKind<'tcx>) -> Statement<'tcx> { + Statement { + source_info: self.source_info(), + kind, + } + } + + fn copy_shim(&mut self) { + let rcvr = Lvalue::Local(Local::new(1+0)).deref(); + let ret_statement = self.make_statement( + StatementKind::Assign( + Lvalue::Local(RETURN_POINTER), + Rvalue::Use(Operand::Consume(rcvr)) + ) + ); + self.block(vec![ret_statement], TerminatorKind::Return, false); + } + + fn make_lvalue(&mut self, mutability: Mutability, ty: ty::Ty<'tcx>) -> Lvalue<'tcx> { + let span = self.span; + Lvalue::Local( + self.local_decls.push(temp_decl(mutability, ty, span)) + ) + } + + fn make_clone_call( + &mut self, + ty: ty::Ty<'tcx>, + rcvr_field: Lvalue<'tcx>, + next: BasicBlock, + cleanup: BasicBlock + ) -> Lvalue<'tcx> { + let tcx = self.tcx; + + let substs = Substs::for_item( + tcx, + self.def_id, + |_, _| tcx.types.re_erased, + |_, _| ty + ); + + // `func == Clone::clone(&ty) -> ty` + let func = Operand::Constant(box Constant { + span: self.span, + ty: tcx.mk_fn_def(self.def_id, substs), + literal: Literal::Value { + value: ConstVal::Function(self.def_id, substs), + }, + }); + + let ref_loc = self.make_lvalue( + Mutability::Not, + tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut { + ty, + mutbl: hir::Mutability::MutImmutable, + }) + ); + + let loc = self.make_lvalue(Mutability::Not, ty); + + // `let ref_loc: &ty = &rcvr_field;` + let statement = self.make_statement( + StatementKind::Assign( + ref_loc.clone(), + Rvalue::Ref(tcx.types.re_erased, BorrowKind::Shared, rcvr_field) + ) + ); + + // `let loc = Clone::clone(ref_loc);` + self.block(vec![statement], TerminatorKind::Call { + func, + args: vec![Operand::Consume(ref_loc)], + destination: Some((loc.clone(), next)), + cleanup: Some(cleanup), + }, false); + + loc + } + + fn loop_header( + &mut self, + beg: Lvalue<'tcx>, + end: Lvalue<'tcx>, + loop_body: BasicBlock, + loop_end: BasicBlock, + is_cleanup: bool + ) { + let tcx = self.tcx; + + let cond = self.make_lvalue(Mutability::Mut, tcx.types.bool); + let compute_cond = self.make_statement( + StatementKind::Assign( + cond.clone(), + Rvalue::BinaryOp(BinOp::Ne, Operand::Consume(end), Operand::Consume(beg)) + ) + ); + + // `if end != beg { goto loop_body; } else { goto loop_end; }` + self.block( + vec![compute_cond], + TerminatorKind::if_(tcx, Operand::Consume(cond), loop_body, loop_end), + is_cleanup + ); + } + + fn make_usize(&self, value: usize) -> Box<Constant<'tcx>> { + let value = ConstUsize::new(value as u64, self.tcx.sess.target.uint_type).unwrap(); + box Constant { + span: self.span, + ty: self.tcx.types.usize, + literal: Literal::Value { + value: ConstVal::Integral(ConstInt::Usize(value)) + } + } + } + + fn array_shim(&mut self, ty: ty::Ty<'tcx>, len: usize) { + let tcx = self.tcx; + let rcvr = Lvalue::Local(Local::new(1+0)).deref(); + + let beg = self.make_lvalue(Mutability::Mut, tcx.types.usize); + let end = self.make_lvalue(Mutability::Not, tcx.types.usize); + let ret = self.make_lvalue(Mutability::Mut, tcx.mk_array(ty, len)); + + // BB #0 + // `let mut beg = 0;` + // `let end = len;` + // `goto #1;` + let inits = vec![ + self.make_statement( + StatementKind::Assign( + beg.clone(), + Rvalue::Use(Operand::Constant(self.make_usize(0))) + ) + ), + self.make_statement( + StatementKind::Assign( + end.clone(), + Rvalue::Use(Operand::Constant(self.make_usize(len))) + ) + ) + ]; + self.block(inits, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); + + // BB #1: loop { + // BB #2; + // BB #3; + // } + // BB #4; + self.loop_header(beg.clone(), end, BasicBlock::new(2), BasicBlock::new(4), false); + + // BB #2 + // `let cloned = Clone::clone(rcvr[beg])`; + // Goto #3 if ok, #5 if unwinding happens. + let rcvr_field = rcvr.clone().index(Operand::Consume(beg.clone())); + let cloned = self.make_clone_call(ty, rcvr_field, BasicBlock::new(3), BasicBlock::new(5)); + + // BB #3 + // `ret[beg] = cloned;` + // `beg = beg + 1;` + // `goto #1`; + let ret_field = ret.clone().index(Operand::Consume(beg.clone())); + let statements = vec![ + self.make_statement( + StatementKind::Assign( + ret_field, + Rvalue::Use(Operand::Consume(cloned)) + ) + ), + self.make_statement( + StatementKind::Assign( + beg.clone(), + Rvalue::BinaryOp( + BinOp::Add, + Operand::Consume(beg.clone()), + Operand::Constant(self.make_usize(1)) + ) + ) + ) + ]; + self.block(statements, TerminatorKind::Goto { target: BasicBlock::new(1) }, false); + + // BB #4 + // `return ret;` + let ret_statement = self.make_statement( + StatementKind::Assign( + Lvalue::Local(RETURN_POINTER), + Rvalue::Use(Operand::Consume(ret.clone())), + ) + ); + self.block(vec![ret_statement], TerminatorKind::Return, false); + + // BB #5 (cleanup) + // `let end = beg;` + // `let mut beg = 0;` + // goto #6; + let end = beg; + let beg = self.make_lvalue(Mutability::Mut, tcx.types.usize); + let init = self.make_statement( + StatementKind::Assign( + beg.clone(), + Rvalue::Use(Operand::Constant(self.make_usize(0))) + ) + ); + self.block(vec![init], TerminatorKind::Goto { target: BasicBlock::new(6) }, true); + + // BB #6 (cleanup): loop { + // BB #7; + // BB #8; + // } + // BB #9; + self.loop_header(beg.clone(), end, BasicBlock::new(7), BasicBlock::new(9), true); + + // BB #7 (cleanup) + // `drop(ret[beg])`; + self.block(vec![], TerminatorKind::Drop { + location: ret.index(Operand::Consume(beg.clone())), + target: BasicBlock::new(8), + unwind: None, + }, true); + + // BB #8 (cleanup) + // `beg = beg + 1;` + // `goto #6;` + let statement = self.make_statement( + StatementKind::Assign( + beg.clone(), + Rvalue::BinaryOp( + BinOp::Add, + Operand::Consume(beg.clone()), + Operand::Constant(self.make_usize(1)) + ) + ) + ); + self.block(vec![statement], TerminatorKind::Goto { target: BasicBlock::new(6) }, true); + + // BB #9 (resume) + self.block(vec![], TerminatorKind::Resume, true); + } + + fn tuple_shim(&mut self, tys: &ty::Slice<ty::Ty<'tcx>>) { + let rcvr = Lvalue::Local(Local::new(1+0)).deref(); + + let mut returns = Vec::new(); + for (i, ity) in tys.iter().enumerate() { + let rcvr_field = rcvr.clone().field(Field::new(i), *ity); + + // BB #(2i) + // `returns[i] = Clone::clone(&rcvr.i);` + // Goto #(2i + 2) if ok, #(2i + 1) if unwinding happens. + returns.push( + self.make_clone_call( + *ity, + rcvr_field, + BasicBlock::new(2 * i + 2), + BasicBlock::new(2 * i + 1), + ) + ); + + // BB #(2i + 1) (cleanup) + if i == 0 { + // Nothing to drop, just resume. + self.block(vec![], TerminatorKind::Resume, true); + } else { + // Drop previous field and goto previous cleanup block. + self.block(vec![], TerminatorKind::Drop { + location: returns[i - 1].clone(), + target: BasicBlock::new(2 * i - 1), + unwind: None, + }, true); + } + } + + // `return (returns[0], returns[1], ..., returns[tys.len() - 1]);` + let ret_statement = self.make_statement( + StatementKind::Assign( + Lvalue::Local(RETURN_POINTER), + Rvalue::Aggregate( + box AggregateKind::Tuple, + returns.into_iter().map(Operand::Consume).collect() + ) + ) + ); + self.block(vec![ret_statement], TerminatorKind::Return, false); + } +} + /// Build a "call" shim for `def_id`. The shim calls the /// function specified by `call_kind`, first adjusting its first /// argument according to `rcvr_adjustment`. @@ -303,7 +683,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, span )); statements.push(Statement { - source_info: source_info, + source_info, kind: StatementKind::Assign( Lvalue::Local(ref_rcvr), Rvalue::Ref(tcx.types.re_erased, BorrowKind::Mut, rcvr_l) @@ -317,7 +697,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, CallKind::Indirect => (rcvr, vec![]), CallKind::Direct(def_id) => ( Operand::Constant(box Constant { - span: span, + span, ty: tcx.type_of(def_id), literal: Literal::Value { value: ConstVal::Function(def_id, @@ -351,7 +731,7 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, // BB #0 block(&mut blocks, statements, TerminatorKind::Call { func: callee, - args: args, + args, destination: Some((Lvalue::Local(RETURN_POINTER), BasicBlock::new(1))), cleanup: if let Adjustment::RefMut = rcvr_adjustment { @@ -423,7 +803,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo { - span: span, + span, scope: ARGUMENT_VISIBILITY_SCOPE }; @@ -436,7 +816,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, // return = ADT(arg0, arg1, ...); return let start_block = BasicBlockData { statements: vec![Statement { - source_info: source_info, + source_info, kind: StatementKind::Assign( Lvalue::Local(RETURN_POINTER), Rvalue::Aggregate( @@ -448,7 +828,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, ) }], terminator: Some(Terminator { - source_info: source_info, + source_info, kind: TerminatorKind::Return, }), is_cleanup: false diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index 23a9c4c57ca..3f14a6be8b2 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -75,7 +75,7 @@ impl AddCallGuards { statements: vec![], is_cleanup: block.is_cleanup, terminator: Some(Terminator { - source_info: source_info, + source_info, kind: TerminatorKind::Goto { target: *destination } }) }; diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index dec0717e9e3..59b81f7e77c 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -299,8 +299,8 @@ impl<'tcx> ConstantPropagationVisitor<'tcx> { fn new(dest_local: Local, constant: Constant<'tcx>) -> ConstantPropagationVisitor<'tcx> { ConstantPropagationVisitor { - dest_local: dest_local, - constant: constant, + dest_local, + constant, uses_replaced: 0, } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index b158cb43ce7..97391452e59 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -50,8 +50,8 @@ impl MirPass for ElaborateDrops { let elaborate_patch = { let mir = &*mir; let env = MoveDataParamEnv { - move_data: move_data, - param_env: param_env + move_data, + param_env, }; let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); let flow_inits = @@ -64,11 +64,11 @@ impl MirPass for ElaborateDrops { |bd, p| &bd.move_data().move_paths[p]); ElaborateDropsCtxt { - tcx: tcx, - mir: mir, + tcx, + mir, env: &env, - flow_inits: flow_inits, - flow_uninits: flow_uninits, + flow_inits, + flow_uninits, drop_flags: FxHashMap(), patch: MirPatch::new(mir), }.elaborate() @@ -510,7 +510,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { debug!("elaborate_drop_and_replace({:?}) - untracked {:?}", terminator, parent); self.patch.patch_terminator(bb, TerminatorKind::Drop { location: location.clone(), - target: target, + target, unwind: Some(unwind) }); } @@ -519,7 +519,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { - span: span, + span, ty: self.tcx.types.bool, literal: Literal::Value { value: ConstVal::Bool(val) } }))) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 89de847231c..fa51cd91be1 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -28,7 +28,7 @@ struct EraseRegionsVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { EraseRegionsVisitor { - tcx: tcx, + tcx, in_validation_statement: false, } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index d3fee8045e6..53b46dd2683 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -90,8 +90,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { if let ty::TyFnDef(callee_def_id, substs) = f.ty.sty { callsites.push_back(CallSite { callee: callee_def_id, - substs: substs, - bb: bb, + substs, + bb, location: terminator.source_info }); } @@ -115,8 +115,13 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => { callee_mir.subst(self.tcx, callsite.substs) } + Ok(_) => continue, - _ => continue, + Err(mut bug) => { + // FIXME(#43542) shouldn't have to cancel an error + bug.cancel(); + continue + } }; let start = caller_mir.basic_blocks().len(); @@ -136,8 +141,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { if callsite.callee != callee_def_id { callsites.push_back(CallSite { callee: callee_def_id, - substs: substs, - bb: bb, + substs, + bb, location: terminator.source_info }); } @@ -433,12 +438,12 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let mut integrator = Integrator { block_idx: bb_len, args: &args, - local_map: local_map, - scope_map: scope_map, - promoted_map: promoted_map, + local_map, + scope_map, + promoted_map, _callsite: callsite, destination: dest, - return_block: return_block, + return_block, cleanup_block: cleanup, in_cleanup_block: false }; @@ -461,7 +466,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { kind => { caller_mir[callsite.bb].terminator = Some(Terminator { source_info: terminator.source_info, - kind: kind + kind, }); false } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 88a368077d4..6ccc886577a 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -76,8 +76,8 @@ struct OptimizationFinder<'b, 'a, 'tcx:'a+'b> { impl<'b, 'a, 'tcx:'b> OptimizationFinder<'b, 'a, 'tcx> { fn new(mir: &'b Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> OptimizationFinder<'b, 'a, 'tcx> { OptimizationFinder { - mir: mir, - tcx: tcx, + mir, + tcx, optimizations: OptimizationList::default(), } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index a247ce2231e..d8dffa03662 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -93,7 +93,7 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) } } tcx.hir.krate().visit_all_item_likes(&mut GatherCtors { - tcx: tcx, + tcx, set: &mut set, }.as_deep_visitor()); @@ -122,8 +122,9 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx } fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Mir<'tcx> { - // Borrowck uses `mir_validated`, so we have to force it to + // (Mir-)Borrowck uses `mir_validated`, so we have to force it to // execute before we can steal. + ty::queries::mir_borrowck::force(tcx, DUMMY_SP, def_id); ty::queries::borrowck::force(tcx, DUMMY_SP, def_id); let mut mir = tcx.mir_validated(def_id).steal(); @@ -148,6 +149,14 @@ fn run_suite<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pass.run_pass(tcx, source, mir); + for (index, promoted_mir) in mir.promoted.iter_enumerated_mut() { + let promoted_source = MirSource::Promoted(source.item_id(), index); + pass.run_pass(tcx, promoted_source, promoted_mir); + + // Let's make sure we don't miss any nested instances + assert!(promoted_mir.promoted.is_empty()); + } + for hook in tcx.mir_passes.hooks() { hook.on_mir_pass(tcx, suite, pass_num, &pass.name(), source, &mir, true); } diff --git a/src/librustc_mir/transform/nll.rs b/src/librustc_mir/transform/nll.rs index fb4764c4962..bd02788df16 100644 --- a/src/librustc_mir/transform/nll.rs +++ b/src/librustc_mir/transform/nll.rs @@ -27,7 +27,7 @@ struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self { NLLVisitor { - infcx: infcx, + infcx, lookup_map: HashMap::new(), } } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index e1c4602b045..1665cb2f15e 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -107,7 +107,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> { LvalueContext::Store | LvalueContext::Call => { *temp = TempState::Defined { - location: location, + location, uses: 0 }; return; @@ -140,7 +140,7 @@ pub fn collect_temps(mir: &Mir, rpo: &mut ReversePostorder) -> IndexVec<Local, T let mut collector = TempCollector { temps: IndexVec::from_elem(TempState::Undefined, &mir.local_decls), span: mir.span, - mir: mir, + mir, }; for (bb, data) in rpo { collector.visit_basic_block_data(bb, data); @@ -165,7 +165,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { statements: vec![], terminator: Some(Terminator { source_info: SourceInfo { - span: span, + span, scope: ARGUMENT_VISIBILITY_SCOPE }, kind: TerminatorKind::Return @@ -179,7 +179,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let data = &mut self.promoted[last]; data.statements.push(Statement { source_info: SourceInfo { - span: span, + span, scope: ARGUMENT_VISIBILITY_SCOPE }, kind: StatementKind::Assign(Lvalue::Local(dest), rvalue) @@ -251,7 +251,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Terminator { source_info: terminator.source_info, kind: mem::replace(&mut terminator.kind, TerminatorKind::Goto { - target: target + target, }) } }; @@ -268,8 +268,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { *self.promoted[last].terminator_mut() = Terminator { kind: TerminatorKind::Call { - func: func, - args: args, + func, + args, cleanup: None, destination: Some((Lvalue::Local(new_temp), new_target)) }, @@ -289,7 +289,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { fn promote_candidate(mut self, candidate: Candidate) { let span = self.promoted.span; let new_operand = Operand::Constant(box Constant { - span: span, + span, ty: self.promoted.return_ty, literal: Literal::Promoted { index: Promoted::new(self.source.promoted.len()) @@ -387,7 +387,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, promoted: Mir::new( IndexVec::new(), Some(VisibilityScopeData { - span: span, + span, parent_scope: None }).into_iter().collect(), IndexVec::new(), @@ -423,7 +423,7 @@ pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>, TerminatorKind::Drop { location: Lvalue::Local(index), target, .. } => { if promoted(index) { terminator.kind = TerminatorKind::Goto { - target: target + target, }; } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 2ecffdf9fdf..ee99bb7d9d5 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -135,13 +135,13 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { let temps = promote_consts::collect_temps(mir, &mut rpo); rpo.reset(); Qualifier { - mode: mode, + mode, span: mir.span, - def_id: def_id, - mir: mir, - rpo: rpo, - tcx: tcx, - param_env: param_env, + def_id, + mir, + rpo, + tcx, + param_env, temp_qualif: IndexVec::from_elem(None, &mir.local_decls), return_qualif: None, qualif: Qualif::empty(), diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 268e7a4c185..ceff52409b2 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -13,7 +13,7 @@ use syntax::ast; use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; -use rustc::mir::{self, Mir}; +use rustc::mir::{self, Mir, Location}; use rustc::mir::transform::{MirPass, MirSource}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; @@ -202,7 +202,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // reset GEN and KILL sets before emulating their effect. for e in sets.gen_set.words_mut() { *e = 0; } for e in sets.kill_set.words_mut() { *e = 0; } - results.0.operator.statement_effect(&mut sets, bb, j); + results.0.operator.statement_effect(&mut sets, Location { block: bb, statement_index: j }); sets.on_entry.union(sets.gen_set); sets.on_entry.subtract(sets.kill_set); } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index a1d56ccd874..070250cda4d 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -99,8 +99,8 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { let basic_blocks = mir.basic_blocks_mut(); CfgSimplifier { - basic_blocks: basic_blocks, - pred_count: pred_count + basic_blocks, + pred_count, } } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index f3a82b54063..72092042f8d 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -108,8 +108,8 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { fn new(cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self { TypeVerifier { - cx: cx, - mir: mir, + cx, + mir, last_span: mir.span, errors_reported: false } @@ -235,8 +235,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } } else { LvalueTy::Downcast { - adt_def: adt_def, - substs: substs, + adt_def, + substs, variant_index: index } } @@ -333,7 +333,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { param_env: ty::ParamEnv<'gcx>) -> Self { TypeChecker { - infcx: infcx, + infcx, fulfillment_cx: traits::FulfillmentContext::new(), last_span: DUMMY_SP, body_id, @@ -740,12 +740,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { pub struct TypeckMir; -impl TypeckMir { - pub fn new() -> Self { - TypeckMir - } -} - impl MirPass for TypeckMir { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs new file mode 100644 index 00000000000..9de30726586 --- /dev/null +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -0,0 +1,192 @@ +// 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 rustc::ty::{self, TyCtxt}; +use rustc_errors::DiagnosticBuilder; +use syntax_pos::{MultiSpan, Span}; + +use std::fmt; + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Origin { Ast, Mir } + +impl fmt::Display for Origin { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + match *self { + Origin::Mir => write!(w, " (Mir)"), + Origin::Ast => ty::tls::with_opt(|opt_tcx| { + // If user passed `-Z borrowck-mir`, then include an + // AST origin as part of the error report + if let Some(tcx) = opt_tcx { + if tcx.sess.opts.debugging_opts.borrowck_mir { + return write!(w, " (Ast)"); + } + } + // otherwise, do not include the origin (i.e., print + // nothing at all) + Ok(()) + }), + } + } +} + +pub trait BorrowckErrors { + fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self, + sp: S, + msg: &str, + code: &str) + -> DiagnosticBuilder<'a>; + + fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'a>; + + fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0505, + "cannot move out of `{}` because it is borrowed{OGN}", + desc, OGN=o) + } + + fn cannot_use_when_mutably_borrowed(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0503, + "cannot use `{}` because it was mutably borrowed{OGN}", + desc, OGN=o) + } + + fn cannot_act_on_uninitialized_variable(&self, + span: Span, + verb: &str, + desc: &str, + o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0381, + "{} of possibly uninitialized variable: `{}`{OGN}", + verb, desc, OGN=o) + } + + fn cannot_mutably_borrow_multiply(&self, + span: Span, + desc: &str, + opt_via: &str, + o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0499, + "cannot borrow `{}`{} as mutable more than once at a time{OGN}", + desc, opt_via, OGN=o) + } + + fn cannot_uniquely_borrow_by_two_closures(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0524, + "two closures require unique access to `{}` at the same time{OGN}", + desc, OGN=o) + } + + fn cannot_uniquely_borrow_by_one_closure(&self, + span: Span, + desc_new: &str, + noun_old: &str, + msg_old: &str, + o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0500, + "closure requires unique access to `{}` but {} is already borrowed{}{OGN}", + desc_new, noun_old, msg_old, OGN=o) + } + + fn cannot_reborrow_already_uniquely_borrowed(&self, + span: Span, + desc_new: &str, + msg_new: &str, + kind_new: &str, + o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0501, + "cannot borrow `{}`{} as {} because previous closure \ + requires unique access{OGN}", + desc_new, msg_new, kind_new, OGN=o) + } + + fn cannot_reborrow_already_borrowed(&self, + span: Span, + desc_new: &str, + msg_new: &str, + kind_new: &str, + noun_old: &str, + kind_old: &str, + msg_old: &str, + o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0502, + "cannot borrow `{}`{} as {} because {} is also borrowed as {}{}{OGN}", + desc_new, msg_new, kind_new, noun_old, kind_old, msg_old, OGN=o) + } + + fn cannot_assign_to_borrowed(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0506, + "cannot assign to `{}` because it is borrowed{OGN}", + desc, OGN=o) + } + + fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0504, + "cannot move `{}` into closure because it is borrowed{OGN}", + desc, OGN=o) + } + + fn cannot_reassign_immutable(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + struct_span_err!(self, span, E0384, + "re-assignment of immutable variable `{}`{OGN}", + desc, OGN=o) + } + + fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin) + -> DiagnosticBuilder + { + self.struct_span_err(span, &format!("cannot assign to immutable static item {}{OGN}", + desc, OGN=o)) + } +} + +impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> { + fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self, + sp: S, + msg: &str, + code: &str) + -> DiagnosticBuilder<'a> + { + self.sess.struct_span_err_with_code(sp, msg, code) + } + + fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self, + sp: S, + msg: &str) + -> DiagnosticBuilder<'a> + { + self.sess.struct_span_err(sp, msg) + } +} diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index d20d50c5611..8263e149d84 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -50,10 +50,6 @@ impl<'tcx> DefUseAnalysis<'tcx> { &self.info[local] } - pub fn local_info_mut(&mut self, local: Local) -> &mut Info<'tcx> { - &mut self.info[local] - } - fn mutate_defs_and_uses<F>(&self, local: Local, mir: &mut Mir<'tcx>, mut callback: F) where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, @@ -97,8 +93,8 @@ impl<'tcx> Visitor<'tcx> for DefUseFinder<'tcx> { location: Location) { if let Some(ref mut info) = self.lvalue_mut_info(lvalue) { info.defs_and_uses.push(Use { - context: context, - location: location, + context, + location, }) } self.super_lvalue(lvalue, context, location) @@ -140,8 +136,8 @@ impl<'tcx, F> MutateUseVisitor<'tcx, F> { -> MutateUseVisitor<'tcx, F> where F: for<'a> FnMut(&'a mut Lvalue<'tcx>, LvalueContext<'tcx>, Location) { MutateUseVisitor { - query: query, - callback: callback, + query, + callback, phantom: PhantomData, } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index da7e218439c..d8a061f4b19 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -521,7 +521,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let substs = tcx.mk_substs(iter::once(Kind::from(ty))); let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut { - ty: ty, + ty, mutbl: hir::Mutability::MutMutable }); let ref_lvalue = self.new_temp(ref_ty); @@ -860,7 +860,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> fn drop_block<'a>(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock { let block = TerminatorKind::Drop { location: self.lvalue.clone(), - target: target, + target, unwind: unwind.into_option() }; self.new_block(unwind, block) diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 4386bab38c0..f0d837e1362 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +pub mod borrowck_errors; pub mod elaborate_drops; pub mod def_use; pub mod patch; diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index ac121131eb9..1af0b6c67f2 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -156,7 +156,7 @@ impl<'tcx> MirPatch<'tcx> { ); mir[loc.block].statements.insert( loc.statement_index, Statement { - source_info: source_info, + source_info, kind: stmt }); delta += 1; diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index b22f8112d7a..ffe444933a3 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -140,14 +140,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ExprKind::Continue(Some(ident)) => { self.check_label(ident.node, ident.span); } - ExprKind::MethodCall(ref segment, ..) => { - if let Some(ref params) = segment.parameters { - if let PathParameters::Parenthesized(..) = **params { - self.err_handler().span_err(expr.span, - "parenthesized parameters cannot be used on method calls"); - } - } - } _ => {} } diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 9185f73974c..763f885b4d0 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -470,7 +470,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { tcx.hir.krate().visit_all_item_likes(&mut CheckCrateVisitor { - tcx: tcx, + tcx, tables: &ty::TypeckTables::empty(None), in_fn: false, promotable: false, diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index ed5ea69d04e..28b99e1185b 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_passes"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -36,13 +33,13 @@ extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; -pub mod diagnostics; +mod diagnostics; pub mod ast_validation; pub mod consts; pub mod hir_stats; pub mod loops; -pub mod mir_stats; +mod mir_stats; pub mod no_asm; pub mod static_recursion; diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 21a4c007fb1..1b2a07cd1a7 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -51,7 +51,7 @@ struct CheckLoopVisitor<'a, 'hir: 'a> { pub fn check_crate(sess: &Session, map: &Map) { let krate = map.krate(); krate.visit_all_item_likes(&mut CheckLoopVisitor { - sess: sess, + sess, hir_map: map, cx: Normal, }.as_deep_visitor()); diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index d5e477ff0c7..9975082c551 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -13,7 +13,6 @@ // completely accurate (some things might be counted twice, others missed). use rustc_const_math::{ConstUsize}; -use rustc::hir::def_id::LOCAL_CRATE; use rustc::middle::const_val::{ConstVal}; use rustc::mir::{AggregateKind, AssertMessage, BasicBlock, BasicBlockData}; use rustc::mir::{Constant, Literal, Location, LocalDecl}; @@ -22,9 +21,7 @@ use rustc::mir::{Mir, Operand, ProjectionElem}; use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData}; use rustc::mir::visit as mir_visit; -use rustc::mir::visit::Visitor; use rustc::ty::{ClosureSubsts, TyCtxt}; -use rustc::util::common::to_readable_str; use rustc::util::nodemap::{FxHashMap}; struct NodeData { @@ -37,21 +34,6 @@ struct StatCollector<'a, 'tcx: 'a> { data: FxHashMap<&'static str, NodeData>, } -pub fn print_mir_stats<'tcx, 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, title: &str) { - let mut collector = StatCollector { - _tcx: tcx, - data: FxHashMap(), - }; - // For debugging instrumentation like this, we don't need to worry - // about maintaining the dep graph. - let _ignore = tcx.dep_graph.in_ignore(); - for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() { - let mir = tcx.optimized_mir(def_id); - collector.visit_mir(&mir); - } - collector.print(title); -} - impl<'a, 'tcx> StatCollector<'a, 'tcx> { fn record_with_size(&mut self, label: &'static str, node_size: usize) { @@ -67,27 +49,6 @@ impl<'a, 'tcx> StatCollector<'a, 'tcx> { fn record<T>(&mut self, label: &'static str, node: &T) { self.record_with_size(label, ::std::mem::size_of_val(node)); } - - fn print(&self, title: &str) { - let mut stats: Vec<_> = self.data.iter().collect(); - - stats.sort_by_key(|&(_, ref d)| d.count * d.size); - - println!("\n{}\n", title); - - println!("{:<32}{:>18}{:>14}{:>14}", - "Name", "Accumulated Size", "Count", "Item Size"); - println!("------------------------------------------------------------------------------"); - - for (label, data) in stats { - println!("{:<32}{:>18}{:>14}{:>14}", - label, - to_readable_str(data.count * data.size), - to_readable_str(data.count), - to_readable_str(data.size)); - } - println!("------------------------------------------------------------------------------"); - } } impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs index 0dbb2d1d4d0..987243b5234 100644 --- a/src/librustc_passes/static_recursion.rs +++ b/src/librustc_passes/static_recursion.rs @@ -91,8 +91,8 @@ pub fn check_crate<'hir>(sess: &Session, hir_map: &hir_map::Map<'hir>) -> Result<(), ErrorReported> { let mut visitor = CheckCrateVisitor { - sess: sess, - hir_map: hir_map, + sess, + hir_map, discriminant_map: NodeMap(), detected_recursive_ids: NodeSet(), }; diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index ef1d9093df2..4cc65ee28e8 100644 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_platform_intrinsics"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![deny(warnings)] #![allow(bad_style)] diff --git a/src/librustc_platform_intrinsics/powerpc.rs b/src/librustc_platform_intrinsics/powerpc.rs index b38369665f8..1a2e8e9c5d8 100644 --- a/src/librustc_platform_intrinsics/powerpc.rs +++ b/src/librustc_platform_intrinsics/powerpc.rs @@ -282,6 +282,61 @@ pub fn find(name: &str) -> Option<Intrinsic> { output: &::U32x4, definition: Named("llvm.ppc.altivec.vavguw") }, + "_vec_packssh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::I8x16, + definition: Named("llvm.ppc.altivec.vpkshss") + }, + "_vec_packsuh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U16x8, &::U16x8]; &INPUTS }, + output: &::U8x16, + definition: Named("llvm.ppc.altivec.vpkuhus") + }, + "_vec_packssw" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vpkswss") + }, + "_vec_packsuw" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::U32x4, &::U32x4]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vpkuwus") + }, + "_vec_packsush" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I16x8, &::I16x8]; &INPUTS }, + output: &::U8x16, + definition: Named("llvm.ppc.altivec.vpkshus") + }, + "_vec_packsusw" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::U16x8, + definition: Named("llvm.ppc.altivec.vpkswus") + }, + "_vec_packpx" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 2] = [&::I32x4, &::I32x4]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vpkpx") + }, + "_vec_unpacklsb" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vupklsb") + }, + "_vec_unpacklsh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vupklsh") + }, + "_vec_unpackhsb" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 1] = [&::I8x16]; &INPUTS }, + output: &::I16x8, + definition: Named("llvm.ppc.altivec.vupkhsb") + }, + "_vec_unpackhsh" => Intrinsic { + inputs: { static INPUTS: [&'static Type; 1] = [&::I16x8]; &INPUTS }, + output: &::I32x4, + definition: Named("llvm.ppc.altivec.vupkhsh") + }, _ => return None, }) } diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index e17a3c82b50..a2a6d183e9c 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -60,15 +60,13 @@ //! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of //! the Unstable Book for more examples. -#![crate_name = "rustc_plugin"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] #![deny(warnings)] #![feature(rustc_diagnostic_macros)] +#![feature(staged_api)] #[macro_use] extern crate syntax; @@ -80,7 +78,7 @@ extern crate rustc_errors as errors; pub use self::registry::Registry; -pub mod diagnostics; +mod diagnostics; pub mod registry; pub mod load; pub mod build; diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index ed49e8a14c8..aba56788928 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -91,7 +91,7 @@ pub fn load_plugins(sess: &Session, impl<'a> PluginLoader<'a> { fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self { PluginLoader { - sess: sess, + sess, reader: CrateLoader::new(sess, cstore, crate_name), plugins: vec![], } @@ -104,8 +104,8 @@ impl<'a> PluginLoader<'a> { let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index); let fun = self.dylink_registrar(span, lib, symbol); self.plugins.push(PluginRegistrar { - fun: fun, - args: args, + fun, + args, }); } } diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index aac21f2af0d..3f74093241d 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -67,9 +67,9 @@ impl<'a> Registry<'a> { #[doc(hidden)] pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> { Registry { - sess: sess, + sess, args_hidden: None, - krate_span: krate_span, + krate_span, syntax_exts: vec![], early_lint_passes: vec![], late_lint_passes: vec![], diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 983f478e07d..772b16bbecf 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_privacy"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -41,7 +38,7 @@ use std::cmp; use std::mem::replace; use std::rc::Rc; -pub mod diagnostics; +mod diagnostics; //////////////////////////////////////////////////////////////////////////////// /// Visitor used to determine if pub(restricted) is used anywhere in the crate. @@ -1496,9 +1493,9 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { item_def_id: self.tcx.hir.local_def_id(item_id), span: self.tcx.hir.span(item_id), min_visibility: ty::Visibility::Public, - required_visibility: required_visibility, + required_visibility, has_pub_restricted: self.has_pub_restricted, - has_old_errors: has_old_errors, + has_old_errors, } } } @@ -1660,7 +1657,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check privacy of names not checked in previous compilation stages. let mut visitor = NamePrivacyVisitor { - tcx: tcx, + tcx, tables: &empty_tables, current_item: CRATE_NODE_ID, empty_tables: &empty_tables, @@ -1670,7 +1667,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check privacy of explicitly written types and traits as well as // inferred types of expressions and patterns. let mut visitor = TypePrivacyVisitor { - tcx: tcx, + tcx, tables: &empty_tables, current_item: DefId::local(CRATE_DEF_INDEX), span: krate.span, @@ -1681,7 +1678,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Build up a set of all exported items in the AST. This is a set of all // items which are reachable from external crates based on visibility. let mut visitor = EmbargoVisitor { - tcx: tcx, + tcx, access_levels: Default::default(), prev_level: Some(AccessLevel::Public), changed: false, @@ -1698,7 +1695,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, { let mut visitor = ObsoleteVisiblePrivateTypesVisitor { - tcx: tcx, + tcx, access_levels: &visitor.access_levels, in_variant: false, old_error_set: NodeSet(), @@ -1708,7 +1705,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let has_pub_restricted = { let mut pub_restricted_visitor = PubRestrictedVisitor { - tcx: tcx, + tcx, has_pub_restricted: false }; intravisit::walk_crate(&mut pub_restricted_visitor, krate); @@ -1717,8 +1714,8 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Check for private types and traits in public interfaces let mut visitor = PrivateItemsInPublicInterfacesVisitor { - tcx: tcx, - has_pub_restricted: has_pub_restricted, + tcx, + has_pub_restricted, old_error_set: &visitor.old_error_set, inner_visibility: ty::Visibility::Public, }; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a061484b5c4..47fa5357abf 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -172,7 +172,7 @@ impl<'a> Resolver<'a> { let subclass = SingleImport { target: binding, - source: source, + source, result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), type_ns_only: false, }; @@ -229,7 +229,7 @@ impl<'a> Resolver<'a> { target: rename, source: ident.node, result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), - type_ns_only: type_ns_only, + type_ns_only, }; let id = source_item.node.id; self.add_import_directive( @@ -239,7 +239,7 @@ impl<'a> Resolver<'a> { } ViewPathGlob(_) => { let subclass = GlobImport { - is_prelude: is_prelude, + is_prelude, max_vis: Cell::new(ty::Visibility::Invisible), }; self.add_import_directive( @@ -262,13 +262,13 @@ impl<'a> Resolver<'a> { (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.arenas); let directive = self.arenas.alloc_import_directive(ImportDirective { id: item.id, - parent: parent, + parent, imported_module: Cell::new(Some(module)), subclass: ImportDirectiveSubclass::ExternCrate, span: item.span, module_path: Vec::new(), vis: Cell::new(vis), - expansion: expansion, + expansion, used: Cell::new(used), }); self.potentially_unused_imports.push(directive); @@ -618,10 +618,10 @@ impl<'a> Resolver<'a> { parent: graph_root, imported_module: Cell::new(Some(module)), subclass: ImportDirectiveSubclass::MacroUse, - span: span, + span, module_path: Vec::new(), vis: Cell::new(ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX))), - expansion: expansion, + expansion, used: Cell::new(false), }); diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index a8bb6619bbd..a66d1ce0859 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -121,9 +121,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { directive.vis.get() == ty::Visibility::Public || directive.span.source_equal(&DUMMY_SP) => {} ImportDirectiveSubclass::ExternCrate => { - let lint = lint::builtin::UNUSED_EXTERN_CRATES; - let msg = "unused extern crate"; - ; resolver.session.buffer_lint(lint, directive.id, directive.span, msg) + resolver.maybe_unused_extern_crates.push((directive.id, directive.span)); } ImportDirectiveSubclass::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; @@ -135,7 +133,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { } let mut visitor = UnusedImportCheckVisitor { - resolver: resolver, + resolver, unused_imports: NodeMap(), }; visit::walk_crate(&mut visitor, krate); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index da170e7fe22..a83ac9bb633 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_resolve"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -581,6 +578,55 @@ impl<T> ::std::ops::IndexMut<Namespace> for PerNS<T> { } } +struct UsePlacementFinder { + target_module: NodeId, + span: Option<Span>, + found_use: bool, +} + +impl<'tcx> Visitor<'tcx> for UsePlacementFinder { + fn visit_mod( + &mut self, + module: &'tcx ast::Mod, + _: Span, + _: &[ast::Attribute], + node_id: NodeId, + ) { + if self.span.is_some() { + return; + } + if node_id != self.target_module { + visit::walk_mod(self, module); + return; + } + // find a use statement + for item in &module.items { + match item.node { + ItemKind::Use(..) => { + // don't suggest placing a use before the prelude + // import or other generated ones + if item.span == DUMMY_SP { + let mut span = item.span; + span.hi = span.lo; + self.span = Some(span); + self.found_use = true; + return; + } + }, + // don't place use before extern crate + ItemKind::ExternCrate(_) => {} + // but place them before the first other item + _ => if self.span.map_or(true, |span| item.span < span ) { + let mut span = item.span; + span.hi = span.lo; + self.span = Some(span); + }, + } + } + assert!(self.span.is_some(), "a file can't have no items and emit suggestions"); + } +} + impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { fn visit_item(&mut self, item: &'tcx Item) { self.resolve_item(item); @@ -733,8 +779,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> { } } -pub type ErrorMessage = Option<(Span, String)>; - #[derive(Copy, Clone)] enum TypeParameters<'a, 'b> { NoTypeParameters, @@ -793,7 +837,7 @@ impl<'a> Rib<'a> { fn new(kind: RibKind<'a>) -> Rib<'a> { Rib { bindings: FxHashMap(), - kind: kind, + kind, } } } @@ -866,7 +910,7 @@ pub struct ModuleData<'a> { expansion: Mark, } -pub type Module<'a> = &'a ModuleData<'a>; +type Module<'a> = &'a ModuleData<'a>; impl<'a> ModuleData<'a> { fn new(parent: Option<Module<'a>>, @@ -875,9 +919,9 @@ impl<'a> ModuleData<'a> { expansion: Mark, span: Span) -> Self { ModuleData { - parent: parent, - kind: kind, - normal_ancestor_id: normal_ancestor_id, + parent, + kind, + normal_ancestor_id, resolutions: RefCell::new(FxHashMap()), legacy_macro_resolutions: RefCell::new(Vec::new()), macro_resolutions: RefCell::new(Vec::new()), @@ -887,8 +931,8 @@ impl<'a> ModuleData<'a> { globs: RefCell::new((Vec::new())), traits: RefCell::new(None), populated: Cell::new(normal_ancestor_id.is_local()), - span: span, - expansion: expansion, + span, + expansion, } } @@ -990,6 +1034,16 @@ enum NameBindingKind<'a> { struct PrivacyError<'a>(Span, Name, &'a NameBinding<'a>); +struct UseError<'a> { + err: DiagnosticBuilder<'a>, + /// Attach `use` statements for these candidates + candidates: Vec<ImportSuggestion>, + /// The node id of the module to place the use statements in + node_id: NodeId, + /// Whether the diagnostic should state that it's "better" + better: bool, +} + struct AmbiguityError<'a> { span: Span, name: Name, @@ -1190,15 +1244,21 @@ pub struct Resolver<'a> { extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, pub make_glob_map: bool, - // Maps imports to the names of items actually imported (this actually maps - // all imports, but only glob imports are actually interesting). + /// Maps imports to the names of items actually imported (this actually maps + /// all imports, but only glob imports are actually interesting). pub glob_map: GlobMap, used_imports: FxHashSet<(NodeId, Namespace)>, pub maybe_unused_trait_imports: NodeSet, + pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, + /// privacy errors are delayed until the end in order to deduplicate them privacy_errors: Vec<PrivacyError<'a>>, + /// ambiguity errors are delayed for deduplication ambiguity_errors: Vec<AmbiguityError<'a>>, + /// `use` injections are delayed for better placement and deduplication + use_injections: Vec<UseError<'a>>, + gated_errors: FxHashSet<Span>, disallowed_shadowing: Vec<&'a LegacyBinding<'a>>, @@ -1356,13 +1416,13 @@ impl<'a> Resolver<'a> { macro_defs.insert(Mark::root(), root_def_id); Resolver { - session: session, + session, - definitions: definitions, + definitions, // The outermost module has def ID 0; this is not reflected in the // AST. - graph_root: graph_root, + graph_root, prelude: None, has_self: FxHashSet(), @@ -1389,7 +1449,7 @@ impl<'a> Resolver<'a> { freevars_seen: NodeMap(), export_map: NodeMap(), trait_map: NodeMap(), - module_map: module_map, + module_map, block_map: NodeMap(), extern_module_map: FxHashMap(), @@ -1398,13 +1458,15 @@ impl<'a> Resolver<'a> { used_imports: FxHashSet(), maybe_unused_trait_imports: NodeSet(), + maybe_unused_extern_crates: Vec::new(), privacy_errors: Vec::new(), ambiguity_errors: Vec::new(), + use_injections: Vec::new(), gated_errors: FxHashSet(), disallowed_shadowing: Vec::new(), - arenas: arenas, + arenas, dummy_binding: arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Def(Def::Err), expansion: Mark::root(), @@ -1416,14 +1478,14 @@ impl<'a> Resolver<'a> { use_extern_macros: features.use_extern_macros || features.proc_macro || features.decl_macro, - crate_loader: crate_loader, + crate_loader, macro_names: FxHashSet(), global_macros: FxHashMap(), lexical_macro_resolutions: Vec::new(), macro_map: FxHashMap(), macro_exports: Vec::new(), - invocations: invocations, - macro_defs: macro_defs, + invocations, + macro_defs, local_macro_def_scopes: FxHashMap(), name_already_seen: FxHashMap(), whitelisted_legacy_custom_derives: Vec::new(), @@ -1465,10 +1527,11 @@ impl<'a> Resolver<'a> { ImportResolver { resolver: self }.finalize_imports(); self.current_module = self.graph_root; self.finalize_current_module_macro_resolutions(); + visit::walk_crate(self, krate); check_unused::check_crate(self, krate); - self.report_errors(); + self.report_errors(krate); self.crate_loader.postprocess(krate); } @@ -1502,7 +1565,7 @@ impl<'a> Resolver<'a> { NameBindingKind::Import { .. } => false, NameBindingKind::Ambiguity { b1, b2, legacy } => { self.ambiguity_errors.push(AmbiguityError { - span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy: legacy, + span: span, name: ident.name, lexical: false, b1: b1, b2: b2, legacy, }); if legacy { self.record_use(ident, ns, b1, span); @@ -2413,25 +2476,20 @@ impl<'a> Resolver<'a> { __diagnostic_used!(E0411); err.code("E0411".into()); err.span_label(span, "`Self` is only available in traits and impls"); - return err; + return (err, Vec::new()); } if is_self_value(path, ns) { __diagnostic_used!(E0424); err.code("E0424".into()); err.span_label(span, format!("`self` value is only available in \ methods with `self` parameter")); - return err; + return (err, Vec::new()); } // Try to lookup the name in more relaxed fashion for better error reporting. let ident = *path.last().unwrap(); let candidates = this.lookup_import_candidates(ident.node.name, ns, is_expected); - if !candidates.is_empty() { - let mut module_span = this.current_module.span; - module_span.hi = module_span.lo; - // Report import candidates as help and proceed searching for labels. - show_candidates(&mut err, module_span, &candidates, def.is_some()); - } else if is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { + if candidates.is_empty() && is_expected(Def::Enum(DefId::local(CRATE_DEF_INDEX))) { let enum_candidates = this.lookup_import_candidates(ident.node.name, ns, is_enum_variant); let mut enum_candidates = enum_candidates.iter() @@ -2471,7 +2529,7 @@ impl<'a> Resolver<'a> { format!("Self::{}", path_str)); } } - return err; + return (err, candidates); } } @@ -2488,22 +2546,22 @@ impl<'a> Resolver<'a> { match (def, source) { (Def::Macro(..), _) => { err.span_label(span, format!("did you mean `{}!(...)`?", path_str)); - return err; + return (err, candidates); } (Def::TyAlias(..), PathSource::Trait) => { err.span_label(span, "type aliases cannot be used for traits"); - return err; + return (err, candidates); } (Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node { ExprKind::Field(_, ident) => { err.span_label(parent.span, format!("did you mean `{}::{}`?", path_str, ident.node)); - return err; + return (err, candidates); } ExprKind::MethodCall(ref segment, ..) => { err.span_label(parent.span, format!("did you mean `{}::{}(...)`?", path_str, segment.identifier)); - return err; + return (err, candidates); } _ => {} }, @@ -2519,7 +2577,7 @@ impl<'a> Resolver<'a> { } err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?", path_str)); - return err; + return (err, candidates); } _ => {} } @@ -2530,10 +2588,14 @@ impl<'a> Resolver<'a> { err.span_label(base_span, fallback_label); this.type_ascription_suggestion(&mut err, base_span); } - err + (err, candidates) }; let report_errors = |this: &mut Self, def: Option<Def>| { - report_errors(this, def).emit(); + let (err, candidates) = report_errors(this, def); + let def_id = this.current_module.normal_ancestor_id; + let node_id = this.definitions.as_local_node_id(def_id).unwrap(); + let better = def.is_some(); + this.use_injections.push(UseError { err, candidates, node_id, better }); err_path_resolution() }; @@ -2915,7 +2977,7 @@ impl<'a> Resolver<'a> { if record_used { vec.push(Freevar { def: prev_def, - span: span, + span, }); seen.insert(node_id, depth); } @@ -2966,31 +3028,6 @@ impl<'a> Resolver<'a> { return def; } - // Calls `f` with a `Resolver` whose current lexical scope is `module`'s lexical scope, - // i.e. the module's items and the prelude (unless the module is `#[no_implicit_prelude]`). - // FIXME #34673: This needs testing. - pub fn with_module_lexical_scope<T, F>(&mut self, module: Module<'a>, f: F) -> T - where F: FnOnce(&mut Resolver<'a>) -> T, - { - self.with_empty_ribs(|this| { - this.ribs[ValueNS].push(Rib::new(ModuleRibKind(module))); - this.ribs[TypeNS].push(Rib::new(ModuleRibKind(module))); - f(this) - }) - } - - fn with_empty_ribs<T, F>(&mut self, f: F) -> T - where F: FnOnce(&mut Resolver<'a>) -> T, - { - let ribs = replace(&mut self.ribs, PerNS::<Vec<Rib>>::default()); - let label_ribs = replace(&mut self.label_ribs, Vec::new()); - - let result = f(self); - self.ribs = ribs; - self.label_ribs = label_ribs; - result - } - fn lookup_assoc_candidate<FilterFn>(&mut self, ident: Ident, ns: Namespace, @@ -3458,8 +3495,9 @@ impl<'a> Resolver<'a> { vis.is_accessible_from(module.normal_ancestor_id, self) } - fn report_errors(&mut self) { + fn report_errors(&mut self, krate: &Crate) { self.report_shadowing_errors(); + self.report_with_use_injections(krate); let mut reported_spans = FxHashSet(); for &AmbiguityError { span, name, b1, b2, lexical, legacy } in &self.ambiguity_errors { @@ -3507,6 +3545,22 @@ impl<'a> Resolver<'a> { } } + fn report_with_use_injections(&mut self, krate: &Crate) { + for UseError { mut err, candidates, node_id, better } in self.use_injections.drain(..) { + let mut finder = UsePlacementFinder { + target_module: node_id, + span: None, + found_use: false, + }; + visit::walk_crate(&mut finder, krate); + if !candidates.is_empty() { + let span = finder.span.expect("did not find module"); + show_candidates(&mut err, span, &candidates, better, finder.found_use); + } + err.emit(); + } + } + fn report_shadowing_errors(&mut self) { for (ident, scope) in replace(&mut self.lexical_macro_resolutions, Vec::new()) { self.resolve_legacy_scope(scope, ident, true); @@ -3697,7 +3751,8 @@ fn import_candidate_to_paths(suggestion: &ImportSuggestion) -> (Span, String, St fn show_candidates(err: &mut DiagnosticBuilder, span: Span, candidates: &[ImportSuggestion], - better: bool) { + better: bool, + found_use: bool) { // we want consistent results across executions, but candidates are produced // by iterating through a hash map, so make sure they are ordered: @@ -3713,7 +3768,14 @@ fn show_candidates(err: &mut DiagnosticBuilder, let msg = format!("possible {}candidate{} into scope", better, msg_diff); for candidate in &mut path_strings { - *candidate = format!("use {};\n", candidate); + // produce an additional newline to separate the new use statement + // from the directly following item. + let additional_newline = if found_use { + "" + } else { + "\n" + }; + *candidate = format!("use {};\n{}", candidate, additional_newline); } err.span_suggestions(span, &msg, path_strings); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 7572c4aa680..f8dc341653e 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -273,7 +273,7 @@ impl<'a> base::Resolver for Resolver<'a> { id: attr::mk_attr_id(), style: ast::AttrStyle::Outer, is_sugared_doc: false, - span: span, + span, }); } } @@ -491,7 +491,7 @@ impl<'a> Resolver<'a> { let name = ident.name; self.ambiguity_errors.push(AmbiguityError { span: path_span, - name: name, + name, b1: shadower, b2: binding, lexical: true, diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 26c398379dc..5616971e9d1 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -165,7 +165,7 @@ impl<'a> Resolver<'a> { binding.def() != shadowed_glob.def() { self.ambiguity_errors.push(AmbiguityError { span: path_span, - name: name, + name, lexical: false, b1: binding, b2: shadowed_glob, @@ -265,13 +265,13 @@ impl<'a> Resolver<'a> { let current_module = self.current_module; let directive = self.arenas.alloc_import_directive(ImportDirective { parent: current_module, - module_path: module_path, + module_path, imported_module: Cell::new(None), - subclass: subclass, - span: span, - id: id, + subclass, + span, + id, vis: Cell::new(vis), - expansion: expansion, + expansion, used: Cell::new(false), }); @@ -311,13 +311,13 @@ impl<'a> Resolver<'a> { self.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Import { - binding: binding, - directive: directive, + binding, + directive, used: Cell::new(false), legacy_self_import: false, }, span: directive.span, - vis: vis, + vis, expansion: directive.expansion, }) } @@ -661,8 +661,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { legacy_self_import = Some(directive); let binding = this.arenas.alloc_name_binding(NameBinding { kind: NameBindingKind::Import { - binding: binding, - directive: directive, + binding, + directive, used: Cell::new(false), legacy_self_import: true, }, diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 658b6dbc4e3..619ebbc5422 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -83,8 +83,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { let span_utils = SpanUtils::new(&save_ctxt.tcx.sess); DumpVisitor { tcx: save_ctxt.tcx, - save_ctxt: save_ctxt, - dumper: dumper, + save_ctxt, + dumper, span: span_utils.clone(), cur_scope: CRATE_NODE_ID, // mac_defs: HashSet::new(), @@ -1351,7 +1351,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc self.span_from_span(sub_span.expect("No span found for var ref")); self.dumper.dump_ref(Ref { kind: RefKind::Variable, - span: span, + span, ref_id: ::id_from_def_id(def.struct_variant().fields[idx.node].did), }); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c3d071d27d6..9b74df865d7 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustc_save_analysis"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -51,7 +48,7 @@ use std::env; use std::fs::File; use std::path::{Path, PathBuf}; -use syntax::ast::{self, NodeId, PatKind, Attribute, CRATE_NODE_ID}; +use syntax::ast::{self, NodeId, PatKind, Attribute}; use syntax::parse::lexer::comments::strip_doc_comment_decoration; use syntax::parse::token; use syntax::print::pprust; @@ -80,8 +77,6 @@ pub struct SaveContext<'l, 'tcx: 'l> { #[derive(Debug)] pub enum Data { - /// Data about a macro use. - MacroUseData(MacroRef), RefData(Ref), DefData(Def), RelationData(Relation), @@ -591,7 +586,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { self.tables.qpath_def(qpath, hir_id) } - Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { + Node::NodeBinding(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => { HirDef::Local(def_id) } @@ -759,11 +754,6 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } - #[inline] - pub fn enclosing_scope(&self, id: NodeId) -> NodeId { - self.tcx.hir.get_enclosing_scope(id).unwrap_or(CRATE_NODE_ID) - } - fn docs_for_attrs(&self, attrs: &[Attribute]) -> String { let mut result = String::new(); @@ -881,7 +871,7 @@ pub struct DumpHandler<'a> { impl<'a> DumpHandler<'a> { pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> { DumpHandler { - odir: odir, + odir, cratename: cratename.to_owned() } } @@ -976,9 +966,9 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(tcx: TyCtxt<'l, 'tcx, 'tcx>, info!("Dumping crate {}", cratename); let save_ctxt = SaveContext { - tcx: tcx, + tcx, tables: &ty::TypeckTables::empty(None), - analysis: analysis, + analysis, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), }; @@ -1048,7 +1038,7 @@ fn lower_attributes(attrs: Vec<Attribute>, scx: &SaveContext) -> Vec<rls_data::A let value = value[2..value.len()-1].to_string(); rls_data::Attribute { - value: value, + value, span: scx.span_from_span(attr.span), } }).collect() diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 6ef499694aa..c7e00245d63 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -149,7 +149,7 @@ fn merge_sigs(text: String, sigs: Vec<Signature>) -> Signature { fn text_sig(text: String) -> Signature { Signature { - text: text, + text, defs: vec![], refs: vec![], } @@ -706,8 +706,8 @@ impl Sig for ast::Variant_ { text.push('}'); Ok(Signature { text, - defs: defs, - refs: refs, + defs, + refs, }) } ast::VariantData::Tuple(ref fields, id) => { @@ -729,8 +729,8 @@ impl Sig for ast::Variant_ { text.push(')'); Ok(Signature { text, - defs: defs, - refs: refs, + defs, + refs, }) } ast::VariantData::Unit(id) => { diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 631907b28f8..36e4d09c963 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -32,7 +32,7 @@ pub struct SpanUtils<'a> { impl<'a> SpanUtils<'a> { pub fn new(sess: &'a Session) -> SpanUtils<'a> { SpanUtils { - sess: sess, + sess, err_count: Cell::new(0), } } diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 144b484d7e8..5e50696b560 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -433,7 +433,7 @@ impl<'a, 'tcx> ArgType<'tcx> { fn new(layout: TyLayout<'tcx>) -> ArgType<'tcx> { ArgType { kind: ArgKind::Direct, - layout: layout, + layout, cast: None, pad: None, attrs: ArgAttributes::default() @@ -808,10 +808,10 @@ impl<'a, 'tcx> FnType<'tcx> { } FnType { - args: args, - ret: ret, + args, + ret, variadic: sig.variadic, - cconv: cconv + cconv, } } diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index cbad43066e4..8863d4ea5ea 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -47,7 +47,7 @@ pub fn unwind(val: ValueRef, can_unwind: bool) { Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind); } -/// Tell LLVM whether it should optimise function for size. +/// Tell LLVM whether it should optimize function for size. #[inline] #[allow(dead_code)] // possibly useful function pub fn set_optimize_for_size(val: ValueRef, optimize: bool) { diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs index 6ec40bd689c..0d39db9e10a 100644 --- a/src/librustc_trans/back/archive.rs +++ b/src/librustc_trans/back/archive.rs @@ -10,7 +10,7 @@ //! A helper class for dealing with static archives -use std::ffi::{CString, CStr, OsString}; +use std::ffi::{CString, CStr}; use std::io; use std::mem; use std::path::{Path, PathBuf}; @@ -28,8 +28,6 @@ pub struct ArchiveConfig<'a> { pub dst: PathBuf, pub src: Option<PathBuf>, pub lib_search_paths: Vec<PathBuf>, - pub ar_prog: String, - pub command_path: OsString, } /// Helper for adding many files to an archive with a single invocation of @@ -89,7 +87,7 @@ impl<'a> ArchiveBuilder<'a> { /// by `config`. pub fn new(config: ArchiveConfig<'a>) -> ArchiveBuilder<'a> { ArchiveBuilder { - config: config, + config, removals: Vec::new(), additions: Vec::new(), should_update_symbols: false, @@ -190,7 +188,7 @@ impl<'a> ArchiveBuilder<'a> { Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), }; self.additions.push(Addition::Archive { - archive: archive, + archive, skip: Box::new(skip), }); Ok(()) diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index a9bd8ea9010..4e211d83cff 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -138,12 +138,6 @@ pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)> (Command::new("link.exe"), vec![]) } -pub fn get_ar_prog(sess: &Session) -> String { - sess.opts.cg.ar.clone().unwrap_or_else(|| { - sess.target.target.options.ar.clone() - }) -} - fn command_path(sess: &Session) -> OsString { // The compiler's sysroot often has some bundled tools, so add it to the // PATH for the child. @@ -379,12 +373,10 @@ fn archive_config<'a>(sess: &'a Session, output: &Path, input: Option<&Path>) -> ArchiveConfig<'a> { ArchiveConfig { - sess: sess, + sess, dst: output.to_path_buf(), src: input.map(|p| p.to_path_buf()), lib_search_paths: archive_search_paths(sess), - ar_prog: get_ar_prog(sess), - command_path: command_path(sess), } } @@ -910,7 +902,7 @@ fn link_args(cmd: &mut Linker, let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); if get_reloc_model(sess) == llvm::RelocMode::PIC - && !args.any(|x| *x == "-static") { + && !sess.crt_static() && !args.any(|x| *x == "-static") { cmd.position_independent_executable(); } } @@ -974,11 +966,13 @@ fn link_args(cmd: &mut Linker, add_upstream_rust_crates(cmd, sess, crate_type, tmpdir); add_upstream_native_libraries(cmd, sess, crate_type); - // # Telling the linker what we're doing - + // Tell the linker what we're doing. if crate_type != config::CrateTypeExecutable { cmd.build_dylib(out_filename); } + if crate_type == config::CrateTypeExecutable && sess.crt_static() { + cmd.build_static_executable(); + } // FIXME (#2397): At some point we want to rpath our guesses as to // where extern libraries might live, based on the diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index b364f92f104..9b0a5e3f4a5 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -49,22 +49,22 @@ impl<'a, 'tcx> LinkerInfo { match sess.linker_flavor() { LinkerFlavor::Msvc => { Box::new(MsvcLinker { - cmd: cmd, - sess: sess, + cmd, + sess, info: self }) as Box<Linker> } LinkerFlavor::Em => { Box::new(EmLinker { - cmd: cmd, - sess: sess, + cmd, + sess, info: self }) as Box<Linker> } LinkerFlavor::Gcc => { Box::new(GccLinker { - cmd: cmd, - sess: sess, + cmd, + sess, info: self, hinted_static: false, is_ld: false, @@ -72,8 +72,8 @@ impl<'a, 'tcx> LinkerInfo { } LinkerFlavor::Ld => { Box::new(GccLinker { - cmd: cmd, - sess: sess, + cmd, + sess, info: self, hinted_static: false, is_ld: true, @@ -110,6 +110,7 @@ pub trait Linker { fn debuginfo(&mut self); fn no_default_libraries(&mut self); fn build_dylib(&mut self, out_filename: &Path); + fn build_static_executable(&mut self); fn args(&mut self, args: &[String]); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); fn subsystem(&mut self, subsystem: &str); @@ -179,6 +180,7 @@ impl<'a> Linker for GccLinker<'a> { fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); } fn partial_relro(&mut self) { self.linker_arg("-z,relro"); } fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); } + fn build_static_executable(&mut self) { self.cmd.arg("-static"); } fn args(&mut self, args: &[String]) { self.cmd.args(args); } fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { @@ -396,6 +398,10 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg(arg); } + fn build_static_executable(&mut self) { + // noop + } + fn gc_sections(&mut self, _keep_metadata: bool) { // MSVC's ICF (Identical COMDAT Folding) link optimization is // slow for Rust and thus we disable it by default when not in @@ -683,6 +689,10 @@ impl<'a> Linker for EmLinker<'a> { bug!("building dynamic library is unsupported on Emscripten") } + fn build_static_executable(&mut self) { + // noop + } + fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) { let symbols = &self.info.exports[&crate_type]; diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 94cae37761f..3f9b28d3d61 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -237,7 +237,7 @@ impl ModuleConfig { fn new(sess: &Session, passes: Vec<String>) -> ModuleConfig { ModuleConfig { tm: create_target_machine(sess), - passes: passes, + passes, opt_level: None, opt_size: None, @@ -426,8 +426,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, let tm = config.tm; let fv = HandlerFreeVars { - cgcx: cgcx, - diag_handler: diag_handler, + cgcx, + diag_handler, }; let fv = &fv as *const HandlerFreeVars as *mut c_void; @@ -785,8 +785,6 @@ pub fn start_async_translation(sess: &Session, crate_name, link, metadata, - exported_symbols, - no_builtins, windows_subsystem, linker_info, no_integrated_as, @@ -1012,9 +1010,9 @@ fn build_work_item(mtrans: ModuleTranslation, -> WorkItem { WorkItem { - mtrans: mtrans, - config: config, - output_names: output_names + mtrans, + config, + output_names, } } @@ -1136,17 +1134,17 @@ fn start_executing_work(sess: &Session, let cgcx = CodegenContext { crate_types: sess.crate_types.borrow().clone(), - each_linked_rlib_for_lto: each_linked_rlib_for_lto, + each_linked_rlib_for_lto, lto: sess.lto(), no_landing_pads: sess.no_landing_pads(), opts: Arc::new(sess.opts.clone()), time_passes: sess.time_passes(), - exported_symbols: exported_symbols, + exported_symbols, plugin_passes: sess.plugin_llvm_passes.borrow().clone(), remark: sess.opts.cg.remark.clone(), worker: 0, incr_comp_session_dir: sess.incr_comp_session_dir_opt().map(|r| r.clone()), - coordinator_send: coordinator_send, + coordinator_send, diag_emitter: shared_emitter.clone(), time_graph, }; @@ -1801,8 +1799,6 @@ pub struct OngoingCrateTranslation { crate_name: Symbol, link: LinkMeta, metadata: EncodedMetadata, - exported_symbols: Arc<ExportedSymbols>, - no_builtins: bool, windows_subsystem: Option<String>, linker_info: LinkerInfo, no_integrated_as: bool, @@ -1852,13 +1848,10 @@ impl OngoingCrateTranslation { crate_name: self.crate_name, link: self.link, metadata: self.metadata, - exported_symbols: self.exported_symbols, - no_builtins: self.no_builtins, windows_subsystem: self.windows_subsystem, linker_info: self.linker_info, modules: compiled_modules.modules, - metadata_module: compiled_modules.metadata_module, allocator_module: compiled_modules.allocator_module, }; diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index b4a2891f94c..e4b090471d7 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -99,9 +99,9 @@ impl<'a, 'tcx> StatRecorder<'a, 'tcx> { pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> { let istart = ccx.stats().n_llvm_insns.get(); StatRecorder { - ccx: ccx, + ccx, name: Some(name), - istart: istart, + istart, } } } @@ -664,7 +664,7 @@ fn check_for_rustc_errors_attr(tcx: TyCtxt) { } } -/// Create the `main` function which will initialise the rust runtime and call +/// Create the `main` function which will initialize the rust runtime and call /// users main function. fn maybe_create_entry_wrapper(ccx: &CrateContext) { let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() { @@ -1058,8 +1058,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (llcx, llmod) = context::create_context_and_module(tcx.sess, "allocator"); let modules = ModuleLlvm { - llmod: llmod, - llcx: llcx, + llmod, + llcx, }; time(tcx.sess.time_passes(), "write allocator module", || { allocator::trans(tcx, &modules, kind) diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 5103ca5c5e1..8a585e72f59 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -70,8 +70,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { llvm::LLVMCreateBuilderInContext(ccx.llcx()) }; Builder { - llbuilder: llbuilder, - ccx: ccx, + llbuilder, + ccx, } } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index b31295f4022..c5de3a4ffb0 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -331,8 +331,8 @@ fn collect_roots<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, { let mut visitor = RootCollector { - scx: scx, - mode: mode, + scx, + mode, exported_symbols, output: &mut roots, }; @@ -699,7 +699,8 @@ fn visit_instance_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, } ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Item(..) | - ty::InstanceDef::FnPtrShim(..) => { + ty::InstanceDef::FnPtrShim(..) | + ty::InstanceDef::CloneShim(..) => { output.push(create_fn_trans_item(instance)); } } @@ -716,7 +717,8 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan ty::InstanceDef::Virtual(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | - ty::InstanceDef::Intrinsic(_) => return true + ty::InstanceDef::Intrinsic(_) | + ty::InstanceDef::CloneShim(..) => return true }; match tcx.hir.get_if_local(def_id) { Some(hir_map::NodeForeignItem(..)) => { @@ -1035,9 +1037,9 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let mir = scx.tcx().instance_mir(instance.def); let mut visitor = MirNeighborCollector { - scx: scx, + scx, mir: &mir, - output: output, + output, param_substs: instance.substs, const_context, }; diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 0cc499577bb..09aa3d2335a 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -177,7 +177,7 @@ pub struct Funclet { impl Funclet { pub fn new(cleanuppad: ValueRef) -> Funclet { Funclet { - cleanuppad: cleanuppad, + cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]), } } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index bec39e3cde6..f2b07cf6a58 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -27,10 +27,9 @@ use type_::Type; use rustc_data_structures::base_n; use rustc::session::config::{self, NoDebugInfo, OutputFilenames}; use rustc::session::Session; -use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout}; -use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::ffi::{CStr, CString}; use std::cell::{Cell, RefCell}; @@ -39,7 +38,6 @@ use std::iter; use std::str; use std::sync::Arc; use std::marker::PhantomData; -use syntax::ast; use syntax::symbol::InternedString; use syntax_pos::DUMMY_SP; use abi::Abi; @@ -124,12 +122,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> { /// Cache of emitted const globals (value -> global) const_globals: RefCell<FxHashMap<ValueRef, ValueRef>>, - /// Cache of emitted const values - const_values: RefCell<FxHashMap<(ast::NodeId, &'tcx Substs<'tcx>), ValueRef>>, - - /// Cache of external const values - extern_const_values: RefCell<DefIdMap<ValueRef>>, - /// Mapping from static definitions to their DefId's. statics: RefCell<FxHashMap<ValueRef, DefId>>, @@ -144,7 +136,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> { used_statics: RefCell<Vec<ValueRef>>, lltypes: RefCell<FxHashMap<Ty<'tcx>, Type>>, - type_hashcodes: RefCell<FxHashMap<Ty<'tcx>, String>>, int_type: Type, opaque_vec_type: Type, str_slice_type: Type, @@ -157,9 +148,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> { intrinsics: RefCell<FxHashMap<&'static str, ValueRef>>, - /// Depth of the current type-of computation - used to bail out - type_of_depth: Cell<usize>, - /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell<usize>, @@ -323,10 +311,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc; SharedCrateContext { - tcx: tcx, - check_overflow: check_overflow, - use_dll_storage_attrs: use_dll_storage_attrs, - output_filenames: output_filenames, + tcx, + check_overflow, + use_dll_storage_attrs, + output_filenames, } } @@ -395,10 +383,10 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { }; let local_ccx = LocalCrateContext { - llmod: llmod, - llcx: llcx, + llmod, + llcx, stats: Stats::default(), - codegen_unit: codegen_unit, + codegen_unit, crate_trans_items, exported_symbols, instances: RefCell::new(FxHashMap()), @@ -406,22 +394,18 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { const_cstr_cache: RefCell::new(FxHashMap()), const_unsized: RefCell::new(FxHashMap()), const_globals: RefCell::new(FxHashMap()), - const_values: RefCell::new(FxHashMap()), - extern_const_values: RefCell::new(DefIdMap()), statics: RefCell::new(FxHashMap()), statics_to_rauw: RefCell::new(Vec::new()), used_statics: RefCell::new(Vec::new()), lltypes: RefCell::new(FxHashMap()), - type_hashcodes: RefCell::new(FxHashMap()), int_type: Type::from_ref(ptr::null_mut()), opaque_vec_type: Type::from_ref(ptr::null_mut()), str_slice_type: Type::from_ref(ptr::null_mut()), - dbg_cx: dbg_cx, + dbg_cx, eh_personality: Cell::new(None), eh_unwind_resume: Cell::new(None), rust_try_fn: Cell::new(None), intrinsics: RefCell::new(FxHashMap()), - type_of_depth: Cell::new(0), local_gen_sym_counter: Cell::new(0), placeholder: PhantomData, }; @@ -462,7 +446,7 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { -> CrateContext<'a, 'tcx> { assert!(local_ccxs.len() == 1); CrateContext { - shared: shared, + shared, local_ccx: &local_ccxs[0] } } @@ -545,15 +529,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().const_globals } - pub fn const_values<'a>(&'a self) -> &'a RefCell<FxHashMap<(ast::NodeId, &'tcx Substs<'tcx>), - ValueRef>> { - &self.local().const_values - } - - pub fn extern_const_values<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> { - &self.local().extern_const_values - } - pub fn statics<'a>(&'a self) -> &'a RefCell<FxHashMap<ValueRef, DefId>> { &self.local().statics } @@ -570,10 +545,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().lltypes } - pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FxHashMap<Ty<'tcx>, String>> { - &self.local().type_hashcodes - } - pub fn stats<'a>(&'a self) -> &'a Stats { &self.local().stats } @@ -582,10 +553,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.local().int_type } - pub fn opaque_vec_type(&self) -> Type { - self.local().opaque_vec_type - } - pub fn str_slice_type(&self) -> Type { self.local().str_slice_type } @@ -602,27 +569,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().intrinsics } - pub fn obj_size_bound(&self) -> u64 { - self.tcx().data_layout.obj_size_bound() - } - - pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! { - self.sess().fatal( - &format!("the type `{:?}` is too big for the current architecture", - obj)) - } - - pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> { - let current_depth = self.local().type_of_depth.get(); - debug!("enter_type_of({:?}) at depth {:?}", ty, current_depth); - if current_depth > self.sess().recursion_limit.get() { - self.sess().fatal( - &format!("overflow representing the type `{}`", ty)) - } - self.local().type_of_depth.set(current_depth + 1); - TypeOfDepthLock(self.local()) - } - pub fn check_overflow(&self) -> bool { self.shared.check_overflow } @@ -631,12 +577,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { self.shared.use_dll_storage_attrs() } - /// Given the def-id of some item that has no type parameters, make - /// a suitable "empty substs" for it. - pub fn empty_substs_for_def_id(&self, item_def_id: DefId) -> &'tcx Substs<'tcx> { - self.tcx().empty_substs_for_def_id(item_def_id) - } - /// Generate a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. pub fn generate_local_symbol_name(&self, prefix: &str) -> String { @@ -776,14 +716,6 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> { } } -pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'a, 'tcx>); - -impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> { - fn drop(&mut self) { - self.0.type_of_depth.set(self.0.type_of_depth.get() - 1); - } -} - /// Declare any llvm intrinsics that you might need fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> { macro_rules! ifn { diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs index ae618c7e170..95f13ea8716 100644 --- a/src/librustc_trans/debuginfo/create_scope_map.rs +++ b/src/librustc_trans/debuginfo/create_scope_map.rs @@ -129,7 +129,7 @@ fn make_mir_scope(ccx: &CrateContext, loc.col.to_usize() as c_uint) }; scopes[scope] = MirDebugScope { - scope_metadata: scope_metadata, + scope_metadata, file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, }; diff --git a/src/librustc_trans/debuginfo/doc.rs b/src/librustc_trans/debuginfo/doc.rs index 7a739071506..93dca03e1ff 100644 --- a/src/librustc_trans/debuginfo/doc.rs +++ b/src/librustc_trans/debuginfo/doc.rs @@ -92,7 +92,7 @@ //! encounters a recursive reference, it will hit the cache and does not try to //! describe the type anew. //! -//! This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, +//! This behavior is encapsulated in the 'RecursiveTypeDescription' enum, //! which represents a kind of continuation, storing all state needed to //! continue traversal at the type members after the type has been registered //! with the cache. (This implementation approach might be a tad over- @@ -156,13 +156,13 @@ //! (2) Structs, enums and traits have a multipart identifier //! //! (1) The first part is the SVH (strict version hash) of the crate they -//! wereoriginally defined in +//! were originally defined in //! //! (2) The second part is the ast::NodeId of the definition in their -//! originalcrate +//! original crate //! //! (3) The final part is a concatenation of the type IDs of their concrete -//! typearguments if they are generic types. +//! type arguments if they are generic types. //! //! (3) Tuple-, pointer and function types are structurally identified, which //! means that they are equivalent if their component types are equivalent diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 61204b88e13..9aba075a20c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -205,11 +205,11 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>( type_map.register_type_with_metadata(unfinished_type, metadata_stub); UnfinishedMetadata { - unfinished_type: unfinished_type, - unique_type_id: unique_type_id, - metadata_stub: metadata_stub, - llvm_type: llvm_type, - member_description_factory: member_description_factory, + unfinished_type, + unique_type_id, + metadata_stub, + llvm_type, + member_description_factory, } } @@ -847,8 +847,8 @@ struct MetadataCreationResult { impl MetadataCreationResult { fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult { MetadataCreationResult { - metadata: metadata, - already_stored_in_typemap: already_stored_in_typemap + metadata, + already_stored_in_typemap, } } } @@ -947,10 +947,10 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { let offset = FixedMemberOffset { bytes: offsets[i].bytes() as usize}; MemberDescription { - name: name, + name, llvm_type: type_of::in_memory_type_of(cx, fty), type_metadata: type_metadata(cx, fty, self.span), - offset: offset, + offset, flags: DIFlags::FlagZero, } }).collect() @@ -987,9 +987,9 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, struct_llvm_type, StructMDF(StructMemberDescriptionFactory { ty: struct_type, - variant: variant, - substs: substs, - span: span, + variant, + substs, + span, }) ) } @@ -1052,7 +1052,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, TupleMDF(TupleMemberDescriptionFactory { ty: tuple_type, component_types: component_types.to_vec(), - span: span, + span, }) ) } @@ -1111,9 +1111,9 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, union_metadata_stub, union_llvm_type, UnionMDF(UnionMemberDescriptionFactory { - variant: variant, - substs: substs, - span: span, + variant, + substs, + span, }) ) } @@ -1462,14 +1462,14 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { offsets: &struct_def.offsets[..], - args: args, + args, discriminant_type_metadata: match discriminant_info { RegularDiscriminant(discriminant_type_metadata) => { Some(discriminant_type_metadata) } _ => None }, - span: span, + span, }); (metadata_stub, variant_llvm_type, member_description_factory) @@ -1590,12 +1590,12 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, enum_metadata, enum_llvm_type, EnumMDF(EnumMemberDescriptionFactory { - enum_type: enum_type, + enum_type, type_rep: type_rep.layout, - discriminant_type_metadata: discriminant_type_metadata, - containing_scope: containing_scope, - file_metadata: file_metadata, - span: span, + discriminant_type_metadata, + containing_scope, + file_metadata, + span, }), ); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 68432c22f81..83366c13453 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -87,9 +87,9 @@ impl<'tcx> CrateDebugContext<'tcx> { // DIBuilder inherits context from the module, so we'd better use the same one let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) }; CrateDebugContext { - llcontext: llcontext, - llmod: llmod, - builder: builder, + llcontext, + llmod, + builder, created_files: RefCell::new(FxHashMap()), created_enum_disr_types: RefCell::new(FxHashMap()), type_map: RefCell::new(TypeMap::new()), @@ -292,7 +292,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // Initialize fn debug context (including scope map and namespace map) let fn_debug_context = FunctionDebugContextData { - fn_metadata: fn_metadata, + fn_metadata, source_locations_enabled: Cell::new(false), defining_crate: def_id.krate, }; diff --git a/src/librustc_trans/debuginfo/source_loc.rs b/src/librustc_trans/debuginfo/source_loc.rs index e99e26261a3..7393802294a 100644 --- a/src/librustc_trans/debuginfo/source_loc.rs +++ b/src/librustc_trans/debuginfo/source_loc.rs @@ -72,9 +72,9 @@ pub enum InternalDebugLocation { impl InternalDebugLocation { pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation { KnownLocation { - scope: scope, - line: line, - col: col, + scope, + line, + col, } } } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 5a4a5b95cf9..1758e331129 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_trans"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -36,7 +33,6 @@ use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; -use std::sync::Arc; extern crate flate2; extern crate libc; @@ -46,7 +42,7 @@ extern crate rustc_allocator; extern crate rustc_back; extern crate rustc_data_structures; extern crate rustc_incremental; -pub extern crate rustc_llvm as llvm; +extern crate rustc_llvm as llvm; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_const_math; #[macro_use] @@ -78,7 +74,7 @@ pub mod back { pub(crate) mod symbol_export; pub(crate) mod symbol_names; pub mod write; - pub mod rpath; + mod rpath; } mod diagnostics; @@ -138,8 +134,8 @@ pub struct ModuleTranslation { /// unique amongst **all** crates. Therefore, it should contain /// something unique to this crate (e.g., a module path) as well /// as the crate name and disambiguator. - pub name: String, - pub symbol_name_hash: u64, + name: String, + symbol_name_hash: u64, pub source: ModuleSource, pub kind: ModuleKind, } @@ -206,7 +202,7 @@ pub enum ModuleSource { #[derive(Copy, Clone, Debug)] pub struct ModuleLlvm { - pub llcx: llvm::ContextRef, + llcx: llvm::ContextRef, pub llmod: llvm::ModuleRef, } @@ -216,14 +212,11 @@ unsafe impl Sync for ModuleTranslation { } pub struct CrateTranslation { pub crate_name: Symbol, pub modules: Vec<CompiledModule>, - pub metadata_module: CompiledModule, - pub allocator_module: Option<CompiledModule>, + allocator_module: Option<CompiledModule>, pub link: rustc::middle::cstore::LinkMeta, pub metadata: rustc::middle::cstore::EncodedMetadata, - pub exported_symbols: Arc<back::symbol_export::ExportedSymbols>, - pub no_builtins: bool, - pub windows_subsystem: Option<String>, - pub linker_info: back::linker::LinkerInfo + windows_subsystem: Option<String>, + linker_info: back::linker::LinkerInfo } __build_diagnostic_array! { librustc_trans, DIAGNOSTICS } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 9bb29c340d9..28fe1044e74 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -673,8 +673,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { Ref(ptr, align) }; let op = OperandRef { - val: val, - ty: ty + val, + ty, }; self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def); } @@ -697,7 +697,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // If the tuple is immediate, the elements are as well let op = OperandRef { val: Immediate(elem), - ty: ty + ty, }; self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def); } @@ -713,7 +713,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { // Pair is always made up of immediates let op = OperandRef { val: Immediate(elem), - ty: ty + ty, }; self.trans_argument(bcx, op, llargs, fn_ty, next_idx, llfn, def); } diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index 53469689bc7..293e6462de2 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -57,8 +57,8 @@ pub struct Const<'tcx> { impl<'tcx> Const<'tcx> { pub fn new(llval: ValueRef, ty: Ty<'tcx>) -> Const<'tcx> { Const { - llval: llval, - ty: ty + llval, + ty, } } @@ -158,7 +158,7 @@ impl<'tcx> Const<'tcx> { }; OperandRef { - val: val, + val, ty: self.ty } } @@ -247,9 +247,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { args: IndexVec<mir::Local, Result<Const<'tcx>, ConstEvalErr<'tcx>>>) -> MirConstContext<'a, 'tcx> { let mut context = MirConstContext { - ccx: ccx, - mir: mir, - substs: substs, + ccx, + mir, + substs, locals: (0..mir.local_decls.len()).map(|_| None).collect(), }; for (i, arg) in args.into_iter().enumerate() { @@ -491,7 +491,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> { }; ConstLvalue { base: projected, - llextra: llextra, + llextra, ty: projected_ty } } diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index af8976967a1..89c76ccdd27 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -380,7 +380,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { }; LvalueRef { llval: llprojected, - llextra: llextra, + llextra, ty: projected_ty, alignment: align, } diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs index d0f7f27d5a8..a67fa070324 100644 --- a/src/librustc_trans/mir/mod.rs +++ b/src/librustc_trans/mir/mod.rs @@ -228,19 +228,19 @@ pub fn trans_mir<'a, 'tcx: 'a>( let (landing_pads, funclets) = create_funclets(&bcx, &cleanup_kinds, &block_bcxs); let mut mircx = MirContext { - mir: mir, - llfn: llfn, - fn_ty: fn_ty, - ccx: ccx, + mir, + llfn, + fn_ty, + ccx, llpersonalityslot: None, blocks: block_bcxs, unreachable_block: None, - cleanup_kinds: cleanup_kinds, - landing_pads: landing_pads, + cleanup_kinds, + landing_pads, funclets: &funclets, - scopes: scopes, + scopes, locals: IndexVec::new(), - debug_context: debug_context, + debug_context, param_substs: { assert!(!instance.substs.needs_infer()); instance.substs @@ -486,7 +486,7 @@ fn arg_local_refs<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, OperandValue::Immediate(llarg) }; let operand = OperandRef { - val: val, + val, ty: arg_ty }; return LocalRef::Operand(Some(operand.unpack_if_pair(bcx))); diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs index 1b8a05b6f6c..9ce1749190b 100644 --- a/src/librustc_trans/mir/operand.rs +++ b/src/librustc_trans/mir/operand.rs @@ -98,8 +98,8 @@ impl<'a, 'tcx> OperandRef<'tcx> { OperandValue::Immediate(C_null(llty)) }; OperandRef { - val: val, - ty: ty + val, + ty, } } @@ -122,7 +122,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { }; LvalueRef { llval: llptr, - llextra: llextra, + llextra, ty: LvalueTy::from_ty(projected_ty), alignment: Alignment::AbiAligned, } diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index a23e1a0684b..096f43e44ab 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -29,7 +29,7 @@ use type_of; use tvec; use value::Value; -use super::MirContext; +use super::{MirContext, LocalRef}; use super::constant::const_scalar_checked_binop; use super::operand::{OperandRef, OperandValue}; use super::lvalue::LvalueRef; @@ -148,9 +148,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { dest.llval, dest.ty, dest.alignment); let field_index = active_field_index.unwrap_or(i); val.ty = LvalueTy::Downcast { - adt_def: adt_def, + adt_def, substs: self.monomorphize(&substs), - variant_index: variant_index, + variant_index, }; let (lldest_i, align) = val.trans_field_ptr(&bcx, field_index); self.store_operand(&bcx, lldest_i, align.to_align(), op); @@ -348,7 +348,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } }; let operand = OperandRef { - val: val, + val, ty: cast_ty }; (bcx, operand) @@ -381,9 +381,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } mir::Rvalue::Len(ref lvalue) => { - let tr_lvalue = self.trans_lvalue(&bcx, lvalue); + let size = self.evaluate_array_len(&bcx, lvalue); let operand = OperandRef { - val: OperandValue::Immediate(tr_lvalue.len(bcx.ccx)), + val: OperandValue::Immediate(size), ty: bcx.tcx().types.usize, }; (bcx, operand) @@ -512,6 +512,26 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> { } } + fn evaluate_array_len(&mut self, + bcx: &Builder<'a, 'tcx>, + lvalue: &mir::Lvalue<'tcx>) -> ValueRef + { + // ZST are passed as operands and require special handling + // because trans_lvalue() panics if Local is operand. + if let mir::Lvalue::Local(index) = *lvalue { + if let LocalRef::Operand(Some(op)) = self.locals[index] { + if common::type_is_zero_size(bcx.ccx, op.ty) { + if let ty::TyArray(_, n) = op.ty.sty { + return common::C_uint(bcx.ccx, n); + } + } + } + } + // use common size calculation for non zero-sized types + let tr_value = self.trans_lvalue(&bcx, lvalue); + return tr_value.len(bcx.ccx); + } + pub fn trans_scalar_binop(&mut self, bcx: &Builder<'a, 'tcx>, op: mir::BinOp, diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs index 1f6a262162d..b0d8be23b0d 100644 --- a/src/librustc_trans/monomorphize.rs +++ b/src/librustc_trans/monomorphize.rs @@ -143,6 +143,12 @@ fn resolve_associated_item<'a, 'tcx>( substs: rcvr_substs } } + traits::VtableBuiltin(..) if Some(trait_id) == tcx.lang_items.clone_trait() => { + Instance { + def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), + substs: rcvr_substs + } + } _ => { bug!("static call to invalid vtable: {:?}", vtbl) } diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs index 63c7b18e8d2..26256fa78dd 100644 --- a/src/librustc_trans/partitioning.rs +++ b/src/librustc_trans/partitioning.rs @@ -361,7 +361,8 @@ fn place_root_translation_items<'a, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>, InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | InstanceDef::ClosureOnceShim { .. } | - InstanceDef::DropGlue(..) => { + InstanceDef::DropGlue(..) | + InstanceDef::CloneShim(..) => { bug!("partitioning: Encountered unexpected root translation item: {:?}", trans_item) @@ -603,7 +604,8 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 't ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::DropGlue(..) | - ty::InstanceDef::Virtual(..) => return None + ty::InstanceDef::Virtual(..) | + ty::InstanceDef::CloneShim(..) => return None }; // If this is a method, we want to put it into the same module as diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index b94fd13c3a4..38232ed1d11 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -384,9 +384,9 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { omit_local_crate_name: bool) -> Self { DefPathBasedNames { - tcx: tcx, - omit_disambiguators: omit_disambiguators, - omit_local_crate_name: omit_local_crate_name, + tcx, + omit_disambiguators, + omit_local_crate_name, } } diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs index d70afc0cce5..b8a8068d36a 100644 --- a/src/librustc_trans/type_.rs +++ b/src/librustc_trans/type_.rs @@ -237,19 +237,6 @@ impl Type { ty!(llvm::LLVMPointerType(self.to_ref(), 0)) } - pub fn is_aggregate(&self) -> bool { - match self.kind() { - TypeKind::Struct | TypeKind::Array => true, - _ => false - } - } - - pub fn is_packed(&self) -> bool { - unsafe { - llvm::LLVMIsPackedStruct(self.to_ref()) == True - } - } - pub fn element_type(&self) -> Type { unsafe { Type::from_ref(llvm::LLVMGetElementType(self.to_ref())) @@ -263,12 +250,6 @@ impl Type { } } - pub fn array_length(&self) -> usize { - unsafe { - llvm::LLVMGetArrayLength(self.to_ref()) as usize - } - } - pub fn field_types(&self) -> Vec<Type> { unsafe { let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as usize; @@ -282,10 +263,6 @@ impl Type { } } - pub fn return_type(&self) -> Type { - ty!(llvm::LLVMGetReturnType(self.to_ref())) - } - pub fn func_params(&self) -> Vec<Type> { unsafe { let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize; @@ -324,13 +301,4 @@ impl Type { I128 => Type::i128(cx), } } - - pub fn from_primitive(ccx: &CrateContext, p: layout::Primitive) -> Type { - match p { - layout::Int(i) => Type::from_integer(ccx, i), - layout::F32 => Type::f32(ccx), - layout::F64 => Type::f64(ccx), - layout::Pointer => bug!("It is not possible to convert Pointer directly to Type.") - } - } } diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index 81e83076f8c..90e17906328 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -12,9 +12,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "rustc_trans_utils"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs index 264158f0de9..aa8637fabe8 100644 --- a/src/librustc_trans_utils/link.rs +++ b/src/librustc_trans_utils/link.rs @@ -123,8 +123,11 @@ pub fn invalid_output_for_target(sess: &Session, match (sess.target.target.options.dynamic_linking, sess.target.target.options.executables, crate_type) { (false, _, config::CrateTypeCdylib) | - (false, _, config::CrateTypeProcMacro) | - (false, _, config::CrateTypeDylib) => true, + (false, _, config::CrateTypeDylib) | + (false, _, config::CrateTypeProcMacro) => true, + (true, _, config::CrateTypeCdylib) | + (true, _, config::CrateTypeDylib) => sess.crt_static() && + !sess.target.target.options.crt_static_allows_dylibs, (_, false, config::CrateTypeExecutable) => true, _ => false } diff --git a/src/librustc_tsan/Cargo.toml b/src/librustc_tsan/Cargo.toml index 97c1181e3a2..7b83985ba67 100644 --- a/src/librustc_tsan/Cargo.toml +++ b/src/librustc_tsan/Cargo.toml @@ -14,5 +14,6 @@ build_helper = { path = "../build_helper" } cmake = "0.1.18" [dependencies] +alloc = { path = "../liballoc" } alloc_system = { path = "../liballoc_system" } core = { path = "../libcore" } diff --git a/src/librustc_tsan/lib.rs b/src/librustc_tsan/lib.rs index 54941362e84..3429e3bda0f 100644 --- a/src/librustc_tsan/lib.rs +++ b/src/librustc_tsan/lib.rs @@ -9,8 +9,10 @@ // except according to those terms. #![sanitizer_runtime] -#![feature(sanitizer_runtime)] #![feature(alloc_system)] +#![feature(allocator_api)] +#![feature(global_allocator)] +#![feature(sanitizer_runtime)] #![feature(staged_api)] #![no_std] #![unstable(feature = "sanitizer_runtime_lib", @@ -18,3 +20,8 @@ issue = "0")] extern crate alloc_system; + +use alloc_system::System; + +#[global_allocator] +static ALLOC: System = System; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 2910d25486e..ee1e6bd950f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -22,16 +22,14 @@ use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; -use rustc::lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES; use rustc_back::slice; use require_c_abi_if_variadic; -use util::common::{ErrorReported, FN_OUTPUT_NAME}; +use util::common::ErrorReported; use util::nodemap::FxHashSet; use std::iter; use syntax::{abi, ast}; use syntax::feature_gate::{GateIssue, emit_feature_err}; -use syntax::symbol::Symbol; use syntax_pos::Span; pub trait AstConv<'gcx, 'tcx> { @@ -117,8 +115,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let name = tcx.hir.name(id); tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir.local_def_id(id), - index: index, - name: name + index, + name, })) } @@ -152,21 +150,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { item_segment: &hir::PathSegment) -> &'tcx Substs<'tcx> { - let tcx = self.tcx(); - - match item_segment.parameters { - hir::AngleBracketedParameters(_) => {} - hir::ParenthesizedParameters(..) => { - self.prohibit_parenthesized_params(item_segment, true); - - return Substs::for_item(tcx, def_id, |_, _| { - tcx.types.re_static - }, |_, _| { - tcx.types.err - }); - } - } - let (substs, assoc_bindings) = self.create_substs_for_ast_path(span, def_id, @@ -196,19 +179,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { parameters={:?})", def_id, self_ty, parameters); - let (lifetimes, num_types_provided, infer_types) = match *parameters { - hir::AngleBracketedParameters(ref data) => { - (&data.lifetimes[..], data.types.len(), data.infer_types) - } - hir::ParenthesizedParameters(_) => (&[][..], 1, false) - }; - // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). let decl_generics = tcx.generics_of(def_id); + let num_types_provided = parameters.types.len(); let expected_num_region_params = decl_generics.regions.len(); - let supplied_num_region_params = lifetimes.len(); + let supplied_num_region_params = parameters.lifetimes.len(); if expected_num_region_params != supplied_num_region_params { report_lifetime_number_error(tcx, span, supplied_num_region_params, @@ -220,7 +197,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // Check the number of type parameters supplied by the user. let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..]; - if !infer_types || num_types_provided > ty_param_defs.len() { + if !parameters.infer_types || num_types_provided > ty_param_defs.len() { check_type_argument_count(tcx, span, num_types_provided, ty_param_defs); } @@ -237,10 +214,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { false }; - let mut output_assoc_binding = None; let substs = Substs::for_item(tcx, def_id, |def, _| { let i = def.index as usize - self_ty.is_some() as usize; - if let Some(lifetime) = lifetimes.get(i) { + if let Some(lifetime) = parameters.lifetimes.get(i) { self.ast_region_to_region(lifetime, Some(def)) } else { tcx.types.re_static @@ -256,18 +232,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let i = i - self_ty.is_some() as usize - decl_generics.regions.len(); if i < num_types_provided { // A provided type parameter. - match *parameters { - hir::AngleBracketedParameters(ref data) => { - self.ast_ty_to_ty(&data.types[i]) - } - hir::ParenthesizedParameters(ref data) => { - assert_eq!(i, 0); - let (ty, assoc) = self.convert_parenthesized_parameters(data); - output_assoc_binding = Some(assoc); - ty - } - } - } else if infer_types { + self.ast_ty_to_ty(¶meters.types[i]) + } else if parameters.infer_types { // No type parameters were provided, we can infer all. let ty_var = if !default_needs_object_self(def) { self.ty_infer_for_def(def, substs, span) @@ -306,24 +272,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } }); - let assoc_bindings = match *parameters { - hir::AngleBracketedParameters(ref data) => { - data.bindings.iter().map(|b| { - ConvertedBinding { - item_name: b.name, - ty: self.ast_ty_to_ty(&b.ty), - span: b.span - } - }).collect() - } - hir::ParenthesizedParameters(ref data) => { - vec![output_assoc_binding.unwrap_or_else(|| { - // This is an error condition, but we should - // get the associated type binding anyway. - self.convert_parenthesized_parameters(data).1 - })] + let assoc_bindings = parameters.bindings.iter().map(|binding| { + ConvertedBinding { + item_name: binding.name, + ty: self.ast_ty_to_ty(&binding.ty), + span: binding.span, } - }; + }).collect(); debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}", decl_generics, self_ty, substs); @@ -331,32 +286,6 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { (substs, assoc_bindings) } - fn convert_parenthesized_parameters(&self, - data: &hir::ParenthesizedParameterData) - -> (Ty<'tcx>, ConvertedBinding<'tcx>) - { - let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| { - self.ast_ty_to_ty(a_t) - })); - - let (output, output_span) = match data.output { - Some(ref output_ty) => { - (self.ast_ty_to_ty(output_ty), output_ty.span) - } - None => { - (self.tcx().mk_nil(), data.span) - } - }; - - let output_binding = ConvertedBinding { - item_name: Symbol::intern(FN_OUTPUT_NAME), - ty: output, - span: output_span - }; - - (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding) - } - /// Instantiates the path for the given trait reference, assuming that it's /// bound to a valid trait type. Returns the def_id for the defining trait. /// Fails if the type is a type other than a trait type. @@ -453,29 +382,17 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def = self.tcx().trait_def(trait_def_id); - match trait_segment.parameters { - hir::AngleBracketedParameters(_) => { - // For now, require that parenthetical notation be used - // only with `Fn()` etc. - if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar { - emit_feature_err(&self.tcx().sess.parse_sess, - "unboxed_closures", span, GateIssue::Language, - "\ - the precise format of `Fn`-family traits' \ - type parameters is subject to change. \ - Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"); - } - } - hir::ParenthesizedParameters(_) => { - // For now, require that parenthetical notation be used - // only with `Fn()` etc. - if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar { - emit_feature_err(&self.tcx().sess.parse_sess, - "unboxed_closures", span, GateIssue::Language, - "\ - parenthetical notation is only stable when used with `Fn`-family traits"); - } - } + if !self.tcx().sess.features.borrow().unboxed_closures && + trait_segment.parameters.parenthesized != trait_def.paren_sugar { + // For now, require that parenthetical notation be used only with `Fn()` etc. + let msg = if trait_def.paren_sugar { + "the precise format of `Fn`-family traits' type parameters is subject to change. \ + Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead" + } else { + "parenthetical notation is only stable when used with `Fn`-family traits" + }; + emit_feature_err(&self.tcx().sess.parse_sess, "unboxed_closures", + span, GateIssue::Language, msg); } self.create_substs_for_ast_path(span, @@ -951,18 +868,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) { for segment in segments { - if let hir::ParenthesizedParameters(_) = segment.parameters { - self.prohibit_parenthesized_params(segment, false); - break; - } - for typ in segment.parameters.types() { + for typ in &segment.parameters.types { struct_span_err!(self.tcx().sess, typ.span, E0109, "type parameters are not allowed on this type") .span_label(typ.span, "type parameter not allowed") .emit(); break; } - for lifetime in segment.parameters.lifetimes() { + for lifetime in &segment.parameters.lifetimes { struct_span_err!(self.tcx().sess, lifetime.span, E0110, "lifetime parameters are not allowed on this type") .span_label(lifetime.span, @@ -970,28 +883,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); break; } - for binding in segment.parameters.bindings() { + for binding in &segment.parameters.bindings { self.prohibit_projection(binding.span); break; } } } - pub fn prohibit_parenthesized_params(&self, segment: &hir::PathSegment, emit_error: bool) { - if let hir::ParenthesizedParameters(ref data) = segment.parameters { - if emit_error { - struct_span_err!(self.tcx().sess, data.span, E0214, - "parenthesized parameters may only be used with a trait") - .span_label(data.span, "only traits may use parentheses") - .emit(); - } else { - let msg = "parenthesized parameters may only be used with a trait"; - self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES, - ast::CRATE_NODE_ID, data.span, msg); - } - } - } - pub fn prohibit_projection(&self, span: Span) { let mut err = struct_span_err!(self.tcx().sess, span, E0229, "associated type bindings are not allowed here"); @@ -1392,13 +1290,13 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, Some(trait_did) == tcx.lang_items.sync_trait() { let segments = &bound.trait_ref.path.segments; let parameters = &segments[segments.len() - 1].parameters; - if !parameters.types().is_empty() { + if !parameters.types.is_empty() { check_type_argument_count(tcx, bound.trait_ref.path.span, - parameters.types().len(), &[]); + parameters.types.len(), &[]); } - if !parameters.lifetimes().is_empty() { + if !parameters.lifetimes.is_empty() { report_lifetime_number_error(tcx, bound.trait_ref.path.span, - parameters.lifetimes().len(), 0); + parameters.lifetimes.len(), 0); } true } else { diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 6aac9dc42ee..e0e946a9c63 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -217,7 +217,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { cur_ty: self.resolve_type_vars_if_possible(&base_ty), obligations: vec![], at_start: true, - span: span, + span, } } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index b18b11f3d90..9c6cacb9d25 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -136,12 +136,12 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { span: Span) -> Result<CastCheck<'tcx>, ErrorReported> { let check = CastCheck { - expr: expr, - expr_ty: expr_ty, - expr_diverges: expr_diverges, - cast_ty: cast_ty, - cast_span: cast_span, - span: span, + expr, + expr_ty, + expr_diverges, + cast_ty, + cast_span, + span, }; // For better error messages, check for some obviously unsized diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 53f3d811fae..e406ce845a6 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -128,8 +128,8 @@ fn success<'tcx>(adj: Vec<Adjustment<'tcx>>, 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, + fcx, + cause, use_lub: false, } } @@ -807,8 +807,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let lub_ty = self.commit_if_ok(|_| { self.at(cause, self.param_env) .lub(prev_ty, new_ty) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); + }).map(|ok| self.register_infer_ok_obligations(ok)); if lub_ty.is_ok() { // We have a LUB of prev_ty and new_ty, just return it. @@ -884,8 +883,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return self.commit_if_ok(|_| { self.at(cause, self.param_env) .lub(prev_ty, new_ty) - .map(|ok| self.register_infer_ok_obligations(ok)) - }); + }).map(|ok| self.register_infer_ok_obligations(ok)); } } @@ -898,8 +896,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.commit_if_ok(|_| { self.at(cause, self.param_env) .lub(prev_ty, new_ty) - .map(|ok| self.register_infer_ok_obligations(ok)) - }) + }).map(|ok| self.register_infer_ok_obligations(ok)) } } Ok(ok) => { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 355e6cdbbe0..db383b6305b 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -69,10 +69,10 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { call_expr: &'gcx hir::Expr) -> ConfirmContext<'a, 'gcx, 'tcx> { ConfirmContext { - fcx: fcx, - span: span, - self_expr: self_expr, - call_expr: call_expr, + fcx, + span, + self_expr, + call_expr, } } @@ -311,17 +311,14 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. - let (supplied_types, supplied_lifetimes) = match segment.parameters { - hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes), - _ => bug!("unexpected generic arguments: {:?}", segment.parameters), - }; assert_eq!(method_generics.parent_count(), parent_substs.len()); + let provided = &segment.parameters; Substs::for_item(self.tcx, pick.item.def_id, |def, _| { let i = def.index as usize; if i < parent_substs.len() { parent_substs.region_at(i) - } else if let Some(lifetime) = - supplied_lifetimes.get(i - parent_substs.len()) { + } else if let Some(lifetime) + = provided.lifetimes.get(i - parent_substs.len()) { AstConv::ast_region_to_region(self.fcx, lifetime, Some(def)) } else { self.region_var_for_def(self.span, def) @@ -330,8 +327,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { let i = def.index as usize; if i < parent_substs.len() { parent_substs.type_at(i) - } else if let Some(ast_ty) = - supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) { + } else if let Some(ast_ty) + = provided.types.get(i - parent_substs.len() - method_generics.regions.len()) { self.to_ty(ast_ty) } else { self.type_var_for_def(self.span, def, cur_substs) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index a1c987f22e0..819f48a1b57 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -27,8 +27,6 @@ use rustc::hir; pub use self::MethodError::*; pub use self::CandidateSource::*; -pub use self::suggest::AllTraitsVec; - mod confirm; pub mod probe; mod suggest; @@ -83,10 +81,10 @@ impl<'tcx> NoMatchData<'tcx> { mode: probe::Mode) -> Self { NoMatchData { - static_candidates: static_candidates, - unsatisfied_predicates: unsatisfied_predicates, - out_of_scope_traits: out_of_scope_traits, - mode: mode, + static_candidates, + unsatisfied_predicates, + out_of_scope_traits, + mode, } } } @@ -331,7 +329,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Predicate::WellFormed(method_ty))); let callee = MethodCallee { - def_id: def_id, + def_id, substs: trait_ref.substs, sig: fn_sig, }; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5de4a35bdc7..096b778cab2 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -253,7 +253,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } else { vec![CandidateStep { - self_ty: self_ty, + self_ty, autoderefs: 0, unsize: false, }] @@ -361,15 +361,15 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>) -> ProbeContext<'a, 'gcx, 'tcx> { ProbeContext { - fcx: fcx, - span: span, - mode: mode, - looking_for: looking_for, + fcx, + span, + mode, + looking_for, inherent_candidates: Vec::new(), extension_candidates: Vec::new(), impl_dups: FxHashSet(), steps: Rc::new(steps), - opt_simplified_steps: opt_simplified_steps, + opt_simplified_steps, static_candidates: Vec::new(), private_candidate: None, unsatisfied_predicates: Vec::new(), @@ -719,6 +719,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { continue; } + self.assemble_builtin_candidates(import_id, trait_def_id, item.clone()); + self.assemble_extension_candidates_for_trait_impls(import_id, trait_def_id, item.clone()); @@ -732,6 +734,49 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { Ok(()) } + fn assemble_builtin_candidates(&mut self, + import_id: Option<ast::NodeId>, + trait_def_id: DefId, + item: ty::AssociatedItem) { + if Some(trait_def_id) == self.tcx.lang_items.clone_trait() { + self.assemble_builtin_clone_candidates(import_id, trait_def_id, item); + } + } + + fn assemble_builtin_clone_candidates(&mut self, + import_id: Option<ast::NodeId>, + trait_def_id: DefId, + item: ty::AssociatedItem) { + for step in Rc::clone(&self.steps).iter() { + match step.self_ty.sty { + ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) | + ty::TyUint(_) | ty::TyInt(_) | ty::TyBool | ty::TyFloat(_) | + ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyChar | + ty::TyRawPtr(..) | ty::TyError | ty::TyNever | + ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutImmutable }) | + ty::TyArray(..) | ty::TyTuple(..) => { + () + } + + _ => continue, + }; + + let substs = Substs::for_item(self.tcx, + trait_def_id, + |def, _| self.region_var_for_def(self.span, def), + |def, substs| { + if def.index == 0 { + step.self_ty + } else { + self.type_var_for_def(self.span, def, substs) + } + }); + + let xform_self_ty = self.xform_self_ty(&item, step.self_ty, substs); + self.push_inherent_candidate(xform_self_ty, item, TraitCandidate, import_id); + } + } + fn assemble_extension_candidates_for_trait_impls(&mut self, import_id: Option<ast::NodeId>, trait_def_id: DefId, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 56eacc3194d..c8b828f3a43 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -260,6 +260,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !static_sources.is_empty() { err.note("found the following associated functions; to be used as methods, \ functions must have a `self` parameter"); + err.help(&format!("try with `{}::{}`", self.ty_to_string(actual), item_name)); report_candidates(&mut err, static_sources); } @@ -584,7 +585,7 @@ pub fn all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> AllTraits<'a> let borrow = tcx.all_traits.borrow(); assert!(borrow.is_some()); AllTraits { - borrow: borrow, + borrow, idx: 0, } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1b56044710b..955171203e1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -393,8 +393,8 @@ impl UnsafetyState { hir::DefaultBlock => (unsafety, self.def, self.unsafe_push_count), }; - UnsafetyState{ def: def, - unsafety: unsafety, + UnsafetyState{ def, + unsafety, unsafe_push_count: count, from_fn: false } } @@ -609,7 +609,7 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { tables: MaybeInProgressTables { maybe_tables: infcx.in_progress_tables, }, - infcx: infcx, + infcx, fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()), locals: RefCell::new(NodeMap()), deferred_call_resolutions: RefCell::new(DefIdMap()), @@ -1646,11 +1646,10 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>) -> Ty<'tcx> { - let item = self.tcx().associated_item(item_def_id); let (trait_ref, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::LateBoundRegionConversionTime::AssocTypeProjection(item.name), + infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id), &poly_trait_ref); self.tcx().mk_projection(item_def_id, trait_ref.substs) @@ -1697,7 +1696,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { body_id: ast::NodeId) -> FnCtxt<'a, 'gcx, 'tcx> { FnCtxt { - body_id: body_id, + body_id, param_env, err_count_on_creation: inh.tcx.sess.err_count(), ret_coercion: None, @@ -1709,7 +1708,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { stack: Vec::new(), by_id: NodeMap(), }), - inh: inh, + inh, } } @@ -2968,8 +2967,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { type_error_struct!(self.tcx().sess, field.span, expr_t, E0615, "attempted to take value of method `{}` on type `{}`", field.node, expr_t) - .help("maybe a `()` to call it is missing? \ - If not, try an anonymous function") + .help("maybe a `()` to call it is missing?") .emit(); self.tcx().types.err } else { @@ -3783,7 +3781,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; let ctxt = BreakableCtxt { - coerce: coerce, + coerce, may_break: false, // will get updated if/when we find a `break` }; @@ -4622,11 +4620,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { i -= fn_start; fn_segment }; - let lifetimes = match segment.map(|(s, _)| &s.parameters) { - Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..], - Some(&hir::ParenthesizedParameters(_)) => bug!(), - None => &[] - }; + let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]); if let Some(lifetime) = lifetimes.get(i) { AstConv::ast_region_to_region(self, lifetime, Some(def)) @@ -4649,13 +4643,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { i -= fn_start; fn_segment }; - let (types, infer_types) = match segment.map(|(s, _)| &s.parameters) { - Some(&hir::AngleBracketedParameters(ref data)) => { - (&data.types[..], data.infer_types) - } - Some(&hir::ParenthesizedParameters(_)) => bug!(), - None => (&[][..], true) - }; + let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| { + (&s.parameters.types[..], s.parameters.infer_types) + }); // Skip over the lifetimes in the same segment. if let Some((_, generics)) = segment { @@ -4729,19 +4719,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, segment: &mut Option<(&hir::PathSegment, &ty::Generics)>, is_method_call: bool) { - let (lifetimes, types, infer_types, bindings) = { - match segment.map(|(s, _)| &s.parameters) { - Some(&hir::AngleBracketedParameters(ref data)) => { - (&data.lifetimes[..], &data.types[..], data.infer_types, &data.bindings[..]) - } - Some(&hir::ParenthesizedParameters(_)) => { - AstConv::prohibit_parenthesized_params(self, &segment.as_ref().unwrap().0, - false); - (&[][..], &[][..], true, &[][..]) - } - None => (&[][..], &[][..], true, &[][..]) - } - }; + let (lifetimes, types, infer_types, bindings) = segment.map_or( + (&[][..], &[][..], true, &[][..]), + |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..], + s.parameters.infer_types, &s.parameters.bindings[..])); let infer_lifetimes = lifetimes.len() == 0; let count_lifetime_params = |n| { @@ -4787,9 +4768,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } if !bindings.is_empty() { - span_err!(self.tcx.sess, bindings[0].span, E0182, - "unexpected binding of associated item in expression path \ - (only allowed in type paths)"); + AstConv::prohibit_projection(self, bindings[0].span); } // Check provided lifetime parameters. diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b187075a36d..fdbdf925e4c 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -232,8 +232,8 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { Subject(subject): Subject) -> RegionCtxt<'a, 'gcx, 'tcx> { let region_maps = fcx.tcx.region_maps(subject); RegionCtxt { - fcx: fcx, - region_maps: region_maps, + fcx, + region_maps, repeating_scope: initial_repeating_scope, body_id: initial_body_id, call_site_scope: None, @@ -1805,8 +1805,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let (outlives, _) = self.replace_late_bound_regions_with_fresh_var( span, - infer::AssocTypeProjection( - self.tcx.associated_item(projection_ty.item_def_id).name), + infer::AssocTypeProjection(projection_ty.item_def_id), &outlives); debug!("projection_bounds: outlives={:?} (3)", @@ -1815,12 +1814,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // check whether this predicate applies to our current projection let cause = self.fcx.misc(span); match self.at(&cause, self.fcx.param_env).eq(outlives.0, ty) { - Ok(ok) => { - self.register_infer_ok_obligations(ok); - Ok(outlives.1) - } - Err(_) => { Err(()) } + Ok(ok) => Ok((ok, outlives.1)), + Err(_) => Err(()) } + }).map(|(ok, result)| { + self.register_infer_ok_obligations(ok); + result }); debug!("projection_bounds: region_result={:?}", diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 31e14a6b630..69f045ab4e9 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -54,7 +54,7 @@ impl<'a, 'gcx, 'tcx> CheckWfFcxBuilder<'a, 'gcx, 'tcx> { let fcx = FnCtxt::new(&inh, param_env, id); let wf_tys = f(&fcx, &mut CheckTypeWellFormedVisitor { tcx: fcx.tcx.global_tcx(), - code: code + code, }); fcx.select_all_obligations_or_error(); fcx.regionck_item(id, span, &wf_tys); @@ -66,7 +66,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { pub fn new(tcx: TyCtxt<'a, 'gcx, 'gcx>) -> CheckTypeWellFormedVisitor<'a, 'gcx> { CheckTypeWellFormedVisitor { - tcx: tcx, + tcx, code: ObligationCauseCode::MiscObligation } } @@ -211,8 +211,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { CheckWfFcxBuilder { inherited: Inherited::build(self.tcx, def_id), code: self.code.clone(), - id: id, - span: span, + id, + span, param_env: self.tcx.param_env(def_id), } } @@ -233,7 +233,10 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), traits::ObligationCause::new(field.span, fcx.body_id, - traits::FieldSized)); + traits::FieldSized(match item.node.adt_kind() { + Some(i) => i, + None => bug!(), + }))); } // All field types must be well-formed. @@ -471,7 +474,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { ExplicitSelf::ByReference(region, mutbl) => { fcx.tcx.mk_ref(region, ty::TypeAndMut { ty: self_ty, - mutbl: mutbl + mutbl, }) } ExplicitSelf::ByBox => fcx.tcx.mk_box(self_ty) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index a363e47a14f..36c72fc4b19 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -80,9 +80,9 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { let owner = fcx.tcx.hir.definitions().node_to_hir_id(body.id().node_id); WritebackCx { - fcx: fcx, + fcx, tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))), - body: body + body, } } @@ -445,8 +445,8 @@ impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> { Resolver { tcx: fcx.tcx, infcx: fcx, - span: span, - body: body, + span, + body, } } diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index e95d49f00bf..3da154e0689 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -72,4 +72,15 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { let mut visitor = CheckVisitor { tcx, used_trait_imports }; tcx.hir.krate().visit_all_item_likes(&mut visitor); + + for &(id, span) in &tcx.maybe_unused_extern_crates { + let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id(); + if !tcx.is_compiler_builtins(cnum) + && !tcx.is_panic_runtime(cnum) + && !tcx.has_global_allocator(cnum) { + let lint = lint::builtin::UNUSED_EXTERN_CRATES; + let msg = "unused extern crate"; + tcx.lint_node(lint, id, span, msg); + } + } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 91b41eb33a1..ea86c570c82 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -185,8 +185,8 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, item_def_id: DefId) -> ItemCtxt<'a,'tcx> { ItemCtxt { - tcx: tcx, - item_def_id: item_def_id, + tcx, + item_def_id, } } } @@ -630,10 +630,10 @@ fn convert_struct_variant<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }).collect(); ty::VariantDef { - did: did, - name: name, - discr: discr, - fields: fields, + did, + name, + discr, + fields, ctor_kind: CtorKind::from_hir(def), } } @@ -1028,7 +1028,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, types.extend(fv.iter().enumerate().map(|(i, _)| ty::TypeParameterDef { index: type_start + i as u32, name: Symbol::intern("<upvar>"), - def_id: def_id, + def_id, has_default: false, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, @@ -1043,11 +1043,11 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.alloc_generics(ty::Generics { parent: parent_def_id, - parent_regions: parent_regions, - parent_types: parent_types, - regions: regions, - types: types, - type_param_to_index: type_param_to_index, + parent_regions, + parent_types, + regions, + types, + type_param_to_index, has_self: has_self || parent_has_self, has_late_bound_regions: has_late_bound_regions(tcx, node), }) @@ -1382,7 +1382,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ItemTrait(_, ref generics, .., ref items) => { is_trait = Some((ty::TraitRef { - def_id: def_id, + def_id, substs: Substs::identity_for_item(tcx, def_id) }, items)); generics @@ -1441,7 +1441,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, for param in early_bound_lifetimes_from_generics(tcx, ast_generics) { let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir.local_def_id(param.lifetime.id), - index: index, + index, name: param.lifetime.name })); index += 1; @@ -1560,7 +1560,7 @@ fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::GenericPredicates { parent: generics.parent, - predicates: predicates + predicates, } } @@ -1611,10 +1611,10 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, }; Bounds { - region_bounds: region_bounds, - implicitly_sized: implicitly_sized, - trait_bounds: trait_bounds, - projection_bounds: projection_bounds, + region_bounds, + implicitly_sized, + trait_bounds, + projection_bounds, } } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 37cb1f9280b..09c7487e635 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -48,7 +48,7 @@ pub fn parameters_for<'tcx, T>(t: &T, let mut collector = ParameterCollector { parameters: vec![], - include_nonconstraining: include_nonconstraining + include_nonconstraining, }; t.visit_with(&mut collector); collector.parameters diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index c74dc24ddc3..cb430efd950 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1636,45 +1636,6 @@ fn bar(foo: Foo) -> u32 { ``` "##, -E0182: r##" -You bound an associated type in an expression path which is not -allowed. - -Erroneous code example: - -```compile_fail,E0182 -trait Foo { - type A; - fn bar() -> isize; -} - -impl Foo for isize { - type A = usize; - fn bar() -> isize { 42 } -} - -// error: unexpected binding of associated item in expression path -let x: isize = Foo::<A=usize>::bar(); -``` - -To give a concrete type when using the Universal Function Call Syntax, -use "Type as Trait". Example: - -``` -trait Foo { - type A; - fn bar() -> isize; -} - -impl Foo for isize { - type A = usize; - fn bar() -> isize { 42 } -} - -let x: isize = <isize as Foo>::bar(); // ok! -``` -"##, - E0184: r##" Explicitly implementing both Drop and Copy for a type is currently disallowed. This feature can make some sense in theory, but the current implementation is @@ -2359,21 +2320,6 @@ impl Foo { "##, */ -E0214: r##" -A generic type was described using parentheses rather than angle brackets. For -example: - -```compile_fail,E0214 -fn main() { - let v: Vec(&str) = vec!["foo"]; -} -``` - -This is not currently supported: `v` should be defined as `Vec<&str>`. -Parentheses are currently only used with generic types when defining parameters -for `Fn`-family traits. -"##, - E0220: r##" You used an associated type which isn't defined in the trait. Erroneous code example: @@ -4721,6 +4667,7 @@ register_diagnostics! { // E0172, // non-trait found in a type sum, moved to resolve // E0173, // manual implementations of unboxed closure traits are experimental // E0174, +// E0182, // merged into E0229 E0183, // E0187, // can't infer the kind of the closure // E0188, // can not cast an immutable reference to a mutable pointer diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9b829e6e3ff..86feea13b17 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -63,9 +63,6 @@ This API is completely unstable and subject to change. */ -#![crate_name = "rustc_typeck"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -95,12 +92,11 @@ extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_errors as errors; -pub use rustc::dep_graph; -pub use rustc::hir; -pub use rustc::lint; -pub use rustc::middle; -pub use rustc::session; -pub use rustc::util; +use rustc::hir; +use rustc::lint; +use rustc::middle; +use rustc::session; +use rustc::util; use hir::map as hir_map; use rustc::infer::InferOk; @@ -118,7 +114,7 @@ use syntax_pos::Span; use std::iter; // NB: This module needs to be declared first so diagnostics are // registered before they are used. -pub mod diagnostics; +mod diagnostics; mod check; mod check_unused; @@ -130,8 +126,8 @@ mod coherence; mod variance; pub struct TypeAndSubsts<'tcx> { - pub substs: &'tcx Substs<'tcx>, - pub ty: Ty<'tcx>, + substs: &'tcx Substs<'tcx>, + ty: Ty<'tcx>, } fn require_c_abi_if_variadic(tcx: TyCtxt, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 4b0db749964..40474a7933f 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -73,11 +73,11 @@ pub fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>) let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant)); let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant)); let mut constraint_cx = ConstraintContext { - terms_cx: terms_cx, - covariant: covariant, - contravariant: contravariant, - invariant: invariant, - bivariant: bivariant, + terms_cx, + covariant, + contravariant, + invariant, + bivariant, constraints: Vec::new(), dependencies: TransitiveRelation::new(), }; @@ -213,7 +213,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { debug!("add_constraint(index={}, variance={:?})", index, variance); self.constraints.push(Constraint { inferred: InferredIndex(current.inferred_start.0 + index as usize), - variance: variance, + variance, }); } diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index 38457146a97..c624b11c5ec 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -79,8 +79,8 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx> arena: &'a mut TypedArena<VarianceTerm<'a>>) -> TermsContext<'a, 'tcx> { let mut terms_cx = TermsContext { - tcx: tcx, - arena: arena, + tcx, + arena, inferred_starts: NodeMap(), inferred_terms: vec![], diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 9b4c4e479d0..5d39d1d27f4 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -102,7 +102,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name) source: cx.tcx.def_span(did).clean(cx), name: Some(name.clean(cx)), attrs: load_attrs(cx, did), - inner: inner, + inner, visibility: Some(clean::Public), stability: cx.tcx.lookup_stability(did).clean(cx), deprecation: cx.tcx.lookup_deprecation(did).clean(cx), @@ -142,7 +142,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait { let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); clean::Trait { unsafety: cx.tcx.trait_def(did).unsafety, - generics: generics, + generics, items: trait_items, bounds: supertrait_bounds, } @@ -162,7 +162,7 @@ fn build_external_function(cx: &DocContext, did: DefId) -> clean::Function { decl: (did, sig).clean(cx), generics: (cx.tcx.generics_of(did), &predicates).clean(cx), unsafety: sig.unsafety(), - constness: constness, + constness, abi: sig.abi(), } } @@ -302,7 +302,7 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) { }), source: tcx.def_span(did).clean(cx), name: None, - attrs: attrs, + attrs, visibility: Some(clean::Inherited), stability: tcx.lookup_stability(did).clean(cx), deprecation: tcx.lookup_deprecation(did).clean(cx), @@ -359,11 +359,11 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) { }; clean::MethodItem(clean::Method { - unsafety: unsafety, - constness: constness, - decl: decl, - generics: generics, - abi: abi + unsafety, + constness, + decl, + generics, + abi, }) } ref r => panic!("not a tymethod: {:?}", r), @@ -414,15 +414,15 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) { inner: clean::ImplItem(clean::Impl { unsafety: hir::Unsafety::Normal, // FIXME: this should be decoded provided_trait_methods: provided, - trait_: trait_, - for_: for_, + trait_, + for_, generics: (tcx.generics_of(did), &predicates).clean(cx), items: trait_items, polarity: Some(polarity.clean(cx)), }), source: tcx.def_span(did).clean(cx), name: None, - attrs: attrs, + attrs, visibility: Some(clean::Inherited), stability: tcx.lookup_stability(did).clean(cx), deprecation: tcx.lookup_deprecation(did).clean(cx), @@ -434,7 +434,7 @@ fn build_module(cx: &DocContext, did: DefId) -> clean::Module { let mut items = Vec::new(); fill_in(cx, did, &mut items); return clean::Module { - items: items, + items, is_crate: false, }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 57e72c3a40b..7d6ad5286d1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -156,7 +156,7 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> { visibility: Some(Public), stability: get_stability(cx, def_id), deprecation: get_deprecation(cx, def_id), - def_id: def_id, + def_id, inner: PrimitiveItem(prim), } })); @@ -166,11 +166,11 @@ impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> { let mut external_traits = cx.external_traits.borrow_mut(); Crate { - name: name, - src: src, + name, + src, module: Some(module), - externs: externs, - primitives: primitives, + externs, + primitives, access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())), external_traits: mem::replace(&mut external_traits, Default::default()), } @@ -252,7 +252,7 @@ impl Clean<ExternalCrate> for CrateNum { name: cx.tcx.crate_name(*self).to_string(), src: PathBuf::from(krate_src), attrs: cx.tcx.get_attrs(root).clean(cx), - primitives: primitives, + primitives, } } } @@ -323,6 +323,10 @@ impl Item { pub fn is_union(&self) -> bool { self.type_() == ItemType::Union } + pub fn is_import(&self) -> bool { + self.type_() == ItemType::Import + } + pub fn is_stripped(&self) -> bool { match self.inner { StrippedItem(..) => true, _ => false } } @@ -474,7 +478,7 @@ impl Clean<Item> for doctree::Module { def_id: cx.tcx.hir.local_def_id(self.id), inner: ModuleItem(Module { is_crate: self.is_crate, - items: items + items, }) } } @@ -519,7 +523,7 @@ impl AttributesExt for [ast::Attribute] { ListAttributesIter { attrs: self.iter(), current_list: Vec::new().into_iter(), - name: name + name, } } } @@ -673,9 +677,9 @@ impl TyParamBound { inline::record_extern_fqn(cx, did, TypeKind::Trait); TraitBound(PolyTrait { trait_: ResolvedPath { - path: path, + path, typarams: None, - did: did, + did, is_generic: false, }, lifetimes: vec![] @@ -715,9 +719,9 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(), _ => { return PathParameters::AngleBracketed { - lifetimes: lifetimes, + lifetimes, types: types.clean(cx), - bindings: bindings + bindings, } } }; @@ -728,15 +732,15 @@ fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: boo // _ => Some(types[1].clean(cx)) // }; PathParameters::Parenthesized { - inputs: inputs, - output: output + inputs, + output, } }, _ => { PathParameters::AngleBracketed { - lifetimes: lifetimes, + lifetimes, types: types.clean(cx), - bindings: bindings + bindings, } } } @@ -784,7 +788,7 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> { TraitBound( PolyTrait { trait_: ResolvedPath { - path: path, + path, typarams: None, did: self.def_id, is_generic: false, @@ -1181,7 +1185,7 @@ impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) { name = "_".to_string(); } Argument { - name: name, + name, type_: ty.clean(cx), } }).collect() @@ -1359,7 +1363,7 @@ impl Clean<Item> for hir::TraitItem { visibility: None, stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), - inner: inner + inner, } } } @@ -1391,7 +1395,7 @@ impl Clean<Item> for hir::ImplItem { visibility: self.vis.clean(cx), stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), - inner: inner + inner, } } } @@ -1438,8 +1442,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem { if provided { MethodItem(Method { unsafety: sig.unsafety(), - generics: generics, - decl: decl, + generics, + decl, abi: sig.abi(), // trait methods cannot (currently, at least) be const @@ -1448,8 +1452,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem { } else { TyMethodItem(TyMethod { unsafety: sig.unsafety(), - generics: generics, - decl: decl, + generics, + decl, abi: sig.abi(), }) } @@ -1515,7 +1519,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem { def_id: self.def_id, attrs: inline::load_attrs(cx, self.def_id), source: cx.tcx.def_span(self.def_id).clean(cx), - inner: inner, + inner, } } } @@ -1794,16 +1798,14 @@ impl Clean<Type> for hir::Ty { let mut lt_substs = FxHashMap(); for (i, ty_param) in generics.ty_params.iter().enumerate() { let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); - if let Some(ty) = provided_params.types().get(i).cloned() - .cloned() { + if let Some(ty) = provided_params.types.get(i).cloned() { ty_substs.insert(ty_param_def, ty.unwrap().clean(cx)); } else if let Some(default) = ty_param.default.clone() { ty_substs.insert(ty_param_def, default.unwrap().clean(cx)); } } for (i, lt_param) in generics.lifetimes.iter().enumerate() { - if let Some(lt) = provided_params.lifetimes().get(i).cloned() - .cloned() { + if let Some(lt) = provided_params.lifetimes.get(i).cloned() { if !lt.is_elided() { lt_substs.insert(lt_param.lifetime.id, lt.clean(cx)); } @@ -1835,7 +1837,7 @@ impl Clean<Type> for hir::Ty { } let trait_path = hir::Path { span: self.span, - def: def, + def, segments: vec![].into(), }; Type::QPath { @@ -1854,10 +1856,10 @@ impl Clean<Type> for hir::Ty { bounds.push(RegionBound(lifetime.clean(cx))); } ResolvedPath { - path: path, + path, typarams: Some(bounds), - did: did, - is_generic: is_generic, + did, + is_generic, } } _ => Infer // shouldn't happen @@ -1915,9 +1917,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> { let path = external_path(cx, &cx.tcx.item_name(did).as_str(), None, false, vec![], substs); ResolvedPath { - path: path, + path, typarams: None, - did: did, + did, is_generic: false, } } @@ -1935,9 +1937,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> { inline::record_extern_fqn(cx, did, TypeKind::Trait); let bound = TraitBound(PolyTrait { trait_: ResolvedPath { - path: path, + path, typarams: None, - did: did, + did, is_generic: false, }, lifetimes: vec![] @@ -1956,9 +1958,9 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> { let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, bindings, principal.0.substs); ResolvedPath { - path: path, + path, typarams: Some(typarams), - did: did, + did, is_generic: false, } } else { @@ -2274,7 +2276,7 @@ impl Path { global: false, def: Def::Err, segments: vec![PathSegment { - name: name, + name, params: PathParameters::AngleBracketed { lifetimes: Vec::new(), types: Vec::new(), @@ -2314,24 +2316,21 @@ pub enum PathParameters { impl Clean<PathParameters> for hir::PathParameters { fn clean(&self, cx: &DocContext) -> PathParameters { - match *self { - hir::AngleBracketedParameters(ref data) => { - PathParameters::AngleBracketed { - lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) { - vec![] - } else { - data.lifetimes.clean(cx) - }, - types: data.types.clean(cx), - bindings: data.bindings.clean(cx), - } + if self.parenthesized { + let output = self.bindings[0].ty.clean(cx); + PathParameters::Parenthesized { + inputs: self.inputs().clean(cx), + output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None } } - - hir::ParenthesizedParameters(ref data) => { - PathParameters::Parenthesized { - inputs: data.inputs.clean(cx), - output: data.output.clean(cx), - } + } else { + PathParameters::AngleBracketed { + lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) { + vec![] + } else { + self.lifetimes.clean(cx) + }, + types: self.types.clean(cx), + bindings: self.bindings.clean(cx), } } } @@ -2549,9 +2548,9 @@ impl Clean<Vec<Item>> for doctree::Impl { unsafety: self.unsafety, generics: self.generics.clean(cx), provided_trait_methods: provided, - trait_: trait_, + trait_, for_: self.for_.clean(cx), - items: items, + items, polarity: Some(self.polarity.clean(cx)), }), }); @@ -2745,7 +2744,7 @@ impl Clean<Item> for hir::ForeignItem { visibility: self.vis.clean(cx), stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), - inner: inner, + inner, } } } @@ -2871,7 +2870,7 @@ fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource { } else { Some(register_def(cx, path.def)) }, - path: path, + path, } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9bb7e4e3a09..58de0e1caec 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -121,18 +121,18 @@ pub fn run_core(search_paths: SearchPaths, let warning_lint = lint::builtin::WARNINGS.name_lower(); let sessopts = config::Options { - maybe_sysroot: maybe_sysroot, - search_paths: search_paths, + maybe_sysroot, + search_paths, crate_types: vec![config::CrateTypeRlib], lint_opts: if !allow_warnings { vec![(warning_lint, lint::Allow)] } else { vec![] }, lint_cap: Some(lint::Allow), - externs: externs, + externs, target_triple: triple.unwrap_or(config::host_triple().to_string()), // Ensure that rustdoc works even if rustc is feature-staged unstable_features: UnstableFeatures::Allow, actually_rustdoc: true, debugging_opts: config::DebuggingOptions { - force_unstable_if_unmarked: force_unstable_if_unmarked, + force_unstable_if_unmarked, ..config::basic_debugging_options() }, ..config::basic_options().clone() @@ -203,7 +203,7 @@ pub fn run_core(search_paths: SearchPaths, }; let ctxt = DocContext { - tcx: tcx, + tcx, populated_all_crate_impls: Cell::new(false), access_levels: RefCell::new(access_levels), external_traits: Default::default(), diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index e269d940bfa..54c57c9ac6e 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -97,9 +97,8 @@ pub trait DocFolder : Sized { _ => self.fold_inner_recur(inner), }; - Some(Item { attrs: attrs, name: name, source: source, inner: inner, - visibility: visibility, stability: stability, deprecation: deprecation, - def_id: def_id }) + Some(Item { attrs, name, source, inner, visibility, + stability, deprecation, def_id }) } fn fold_mod(&mut self, m: Module) -> Module { diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 89a40b0db96..eb27fa3abfa 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -106,7 +106,7 @@ pub enum Class { } /// Trait that controls writing the output of syntax highlighting. Users should -/// implement this trait to customise writing output. +/// implement this trait to customize writing output. /// /// The classifier will call into the `Writer` implementation as it finds spans /// of text to highlight. Exactly how that text should be highlighted is up to @@ -164,8 +164,8 @@ impl<U: Write> Writer for U { impl<'a> Classifier<'a> { pub fn new(lexer: lexer::StringReader<'a>, codemap: &'a CodeMap) -> Classifier<'a> { Classifier { - lexer: lexer, - codemap: codemap, + lexer, + codemap, in_attribute: false, in_macro: false, in_macro_nonterminal: false, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 82c252ae4d7..2d14c02bf8a 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -241,7 +241,7 @@ impl<'a, 'b, I: Iterator<Item = Event<'a>>> HeadingLinks<'a, 'b, I> { fn new(iter: I, toc: Option<&'b mut TocBuilder>) -> Self { HeadingLinks { inner: iter, - toc: toc, + toc, buf: VecDeque::new(), } } @@ -1121,15 +1121,15 @@ mod tests { should_panic: bool, no_run: bool, ignore: bool, rust: bool, test_harness: bool, compile_fail: bool, allow_fail: bool, error_codes: Vec<String>) { assert_eq!(LangString::parse(s), LangString { - should_panic: should_panic, - no_run: no_run, - ignore: ignore, - rust: rust, - test_harness: test_harness, - compile_fail: compile_fail, - error_codes: error_codes, + should_panic, + no_run, + ignore, + rust, + test_harness, + compile_fail, + error_codes, original: s.to_owned(), - allow_fail: allow_fail, + allow_fail, }) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4e3181759f9..5457f69cb6d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -443,8 +443,8 @@ pub fn run(mut krate: clean::Crate, None => PathBuf::new(), }; let mut scx = SharedContext { - src_root: src_root, - passes: passes, + src_root, + passes, include_sources: true, local_sources: FxHashMap(), issue_tracker_base_url: None, @@ -496,10 +496,10 @@ pub fn run(mut krate: clean::Crate, krate = render_sources(&dst, &mut scx, krate)?; let cx = Context { current: Vec::new(), - dst: dst, + dst, render_redirect_pages: false, shared: Arc::new(scx), - render_type: render_type, + render_type, }; // Crawl the crate to build various caches used for the output @@ -518,7 +518,7 @@ pub fn run(mut krate: clean::Crate, let mut cache = Cache { impls: FxHashMap(), - external_paths: external_paths, + external_paths, paths: FxHashMap(), implementors: FxHashMap(), stack: Vec::new(), @@ -531,9 +531,9 @@ pub fn run(mut krate: clean::Crate, access_levels: krate.access_levels.clone(), orphan_impl_items: Vec::new(), traits: mem::replace(&mut krate.external_traits, FxHashMap()), - deref_trait_did: deref_trait_did, - deref_mut_trait_did: deref_mut_trait_did, - owned_box_did: owned_box_did, + deref_trait_did, + deref_mut_trait_did, + owned_box_did, typarams: external_typarams, }; @@ -823,8 +823,8 @@ fn render_sources(dst: &Path, scx: &mut SharedContext, let dst = dst.join("src").join(&krate.name); try_err!(fs::create_dir_all(&dst), &dst); let mut folder = SourceCollector { - dst: dst, - scx: scx, + dst, + scx, }; Ok(folder.fold_crate(krate)) } @@ -1068,7 +1068,7 @@ impl DocFolder for Cache { name: s.to_string(), path: path.join("::").to_string(), desc: plain_summary_line(item.doc_value()), - parent: parent, + parent, parent_idx: None, search_type: get_index_search_type(&item), }); @@ -1764,6 +1764,37 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context, } indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2)); + // This call is to remove reexport duplicates in cases such as: + // + // ``` + // pub mod foo { + // pub mod bar { + // pub trait Double { fn foo(); } + // } + // } + // + // pub use foo::bar::*; + // pub use foo::*; + // ``` + // + // `Double` will appear twice in the generated docs. + // + // FIXME: This code is quite ugly and could be improved. Small issue: DefId + // can be identical even if the elements are different (mostly in imports). + // So in case this is an import, we keep everything by adding a "unique id" + // (which is the position in the vector). + indices.dedup_by_key(|i| (items[*i].def_id, + if items[*i].name.as_ref().is_some() { + Some(full_path(cx, &items[*i]).clone()) + } else { + None + }, + items[*i].type_(), + if items[*i].is_import() { + *i + } else { + 0 + })); debug!("{:?}", indices); let mut curty = None; @@ -2038,7 +2069,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true }, decl = Method { decl: &f.decl, - name_len: name_len, + name_len, indent: 0, })?; document(w, cx, it) @@ -2406,12 +2437,12 @@ fn render_assoc_item(w: &mut fmt::Formatter, decl = Method { decl: d, name_len: head_len, - indent: indent, + indent, }, where_clause = WhereClause { gens: g, - indent: indent, - end_newline: end_newline, + indent, + end_newline, }) } match item.inner { @@ -2925,7 +2956,13 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl, fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink, render_mode: RenderMode, outer_version: Option<&str>) -> fmt::Result { if render_mode == RenderMode::Normal { - write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?; + let id = derive_id(match i.inner_impl().trait_ { + Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))), + None => "impl".to_string(), + }); + write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>", + id, i.inner_impl())?; + write!(w, "<a href='#{}' class='anchor'></a>", id)?; write!(w, "</span><span class='out-of-band'>")?; let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]); if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index ee94f0baeb9..4a3286b421a 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -126,6 +126,10 @@ p { margin: 0 0 .6em 0; } +summary { + outline: none; +} + code, pre { font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace; white-space: pre-wrap; @@ -441,6 +445,10 @@ a { .small-section-header:hover > .anchor { display: initial; } + +.in-band:hover > .anchor { + display: initial; +} .anchor { display: none; } diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css index 08bf5a10fe9..c5f4272b932 100644 --- a/src/librustdoc/html/static/styles/main.css +++ b/src/librustdoc/html/static/styles/main.css @@ -26,6 +26,7 @@ h1.fqn { h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) { border-bottom-color: #DDDDDD; } + .in-band { background-color: white; } @@ -83,6 +84,11 @@ pre { } :target { background: #FDFFD3; } + +:target > .in-band { + background: #FDFFD3; +} + .content .highlighted { color: #000 !important; background-color: #ccc; diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index a7da1c5cca4..f3379b33155 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -95,7 +95,7 @@ impl TocBuilder { /// self.top_level, D is in C.children, and C, E, F, G are in /// self.chain. /// - /// When we attempt to push H, we realise that first G is not the + /// When we attempt to push H, we realize that first G is not the /// parent (level is too high) so it is popped from chain and put /// into F.children, then F isn't the parent (level is equal, aka /// sibling), so it's also popped and put into E.children. @@ -161,10 +161,10 @@ impl TocBuilder { } self.chain.push(TocEntry { - level: level, - name: name, - sec_number: sec_number, - id: id, + level, + name, + sec_number, + id, children: Toc { entries: Vec::new() } }); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 9264015ed9e..61a8165d26a 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,9 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![crate_name = "rustdoc"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/", @@ -400,7 +397,7 @@ pub fn main_args(args: &[String]) -> isize { }) } -/// Prints an uniformised error message on the standard error output +/// Prints an uniformized error message on the standard error output fn print_error<T>(error_message: T) where T: Display { writeln!( &mut io::stderr(), diff --git a/src/librustdoc/plugins.rs b/src/librustdoc/plugins.rs index a38ef2b2518..4fc5159588d 100644 --- a/src/librustdoc/plugins.rs +++ b/src/librustdoc/plugins.rs @@ -35,7 +35,7 @@ impl PluginManager { PluginManager { dylibs: Vec::new(), callbacks: Vec::new(), - prefix: prefix, + prefix, } } diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index b1fb343b8bb..47e8d63f80a 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -194,7 +194,7 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec<String>, libs search_paths: libs, crate_types: vec![config::CrateTypeExecutable], output_types: outputs, - externs: externs, + externs, cg: config::CodegenOptions { prefer_dynamic: true, .. config::basic_codegen_options() @@ -416,19 +416,19 @@ impl Collector { tests: Vec::new(), old_tests: HashMap::new(), names: Vec::new(), - cfgs: cfgs, - libs: libs, - externs: externs, + cfgs, + libs, + externs, cnt: 0, - use_headers: use_headers, + use_headers, current_header: None, - cratename: cratename, - opts: opts, - maybe_sysroot: maybe_sysroot, + cratename, + opts, + maybe_sysroot, position: DUMMY_SP, - codemap: codemap, - filename: filename, - render_type: render_type, + codemap, + filename, + render_type, } } @@ -499,7 +499,7 @@ impl Collector { ignore: should_ignore, // compiler failures are test failures should_panic: testing::ShouldPanic::No, - allow_fail: allow_fail, + allow_fail, }, testfn: testing::DynTestFn(box move |()| { let panic = io::set_panic(None); diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 657aab958bb..e3426fba1bc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { RustdocVisitor { module: Module::new(None), attrs: hir::HirVec::new(), - cx: cx, + cx, view_item_stack: stack, inlining: false, inside_public_path: true, @@ -99,8 +99,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let struct_type = struct_type_from_def(&*sd); Struct { id: item.id, - struct_type: struct_type, - name: name, + struct_type, + name, vis: item.vis.clone(), stab: self.stability(item.id), depr: self.deprecation(item.id), @@ -118,8 +118,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let struct_type = struct_type_from_def(&*sd); Union { id: item.id, - struct_type: struct_type, - name: name, + struct_type, + name, vis: item.vis.clone(), stab: self.stability(item.id), depr: self.deprecation(item.id), @@ -135,7 +135,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { params: &hir::Generics) -> Enum { debug!("Visiting enum"); Enum { - name: name, + name, variants: def.variants.iter().map(|v| Variant { name: v.node.name, attrs: v.node.attrs.clone(), @@ -169,13 +169,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { depr: self.deprecation(item.id), attrs: item.attrs.clone(), decl: fd.clone(), - name: name, + name, whence: item.span, generics: gen.clone(), unsafety: *unsafety, - constness: constness, + constness, abi: *abi, - body: body, + body, } } @@ -221,11 +221,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; om.macros.push(Macro { - def_id: def_id, + def_id, attrs: def.attrs.clone().into(), name: def.ident.name, whence: def.span, - matchers: matchers, + matchers, stab: self.stability(def.id), depr: self.deprecation(def.id), imported_from: Some(imported_from), @@ -374,7 +374,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.extern_crates.push(ExternCrate { cnum: cstore.extern_mod_stmt_cnum(item.id) .unwrap_or(LOCAL_CRATE), - name: name, + name, path: p.map(|x|x.to_string()), vis: item.vis.clone(), attrs: item.attrs.clone(), @@ -408,7 +408,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } om.imports.push(Import { - name: name, + name, id: item.id, vis: item.vis.clone(), attrs: item.attrs.clone(), @@ -438,7 +438,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let t = Typedef { ty: ty.clone(), gen: gen.clone(), - name: name, + name, id: item.id, attrs: item.attrs.clone(), whence: item.span, @@ -454,7 +454,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { mutability: mut_.clone(), expr: exp.clone(), id: item.id, - name: name, + name, attrs: item.attrs.clone(), whence: item.span, vis: item.vis.clone(), @@ -468,7 +468,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { type_: ty.clone(), expr: exp.clone(), id: item.id, - name: name, + name, attrs: item.attrs.clone(), whence: item.span, vis: item.vis.clone(), @@ -482,9 +482,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { .map(|ti| self.cx.tcx.hir.trait_item(ti.id).clone()) .collect(); let t = Trait { - unsafety: unsafety, - name: name, - items: items, + unsafety, + name, + items, generics: gen.clone(), bounds: b.iter().cloned().collect(), id: item.id, @@ -511,13 +511,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { .map(|ii| self.cx.tcx.hir.impl_item(ii.id).clone()) .collect(); let i = Impl { - unsafety: unsafety, - polarity: polarity, - defaultness: defaultness, + unsafety, + polarity, + defaultness, generics: gen.clone(), trait_: tr.clone(), for_: ty.clone(), - items: items, + items, attrs: item.attrs.clone(), id: item.id, whence: item.span, @@ -532,7 +532,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // See comment above about ItemImpl. if !self.inlining { let i = DefaultImpl { - unsafety: unsafety, + unsafety, trait_: trait_ref.clone(), id: item.id, attrs: item.attrs.clone(), @@ -555,7 +555,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { attrs: def.attrs.clone(), name: def.name, whence: def.span, - matchers: matchers, + matchers, stab: self.stability(def.id), depr: self.deprecation(def.id), imported_from: None, diff --git a/src/librustdoc/visit_lib.rs b/src/librustdoc/visit_lib.rs index 5518d854348..7b5b27c5565 100644 --- a/src/librustdoc/visit_lib.rs +++ b/src/librustdoc/visit_lib.rs @@ -37,7 +37,7 @@ pub struct LibEmbargoVisitor<'a, 'b: 'a, 'tcx: 'b> { impl<'a, 'b, 'tcx> LibEmbargoVisitor<'a, 'b, 'tcx> { pub fn new(cx: &'a ::core::DocContext<'b, 'tcx>) -> LibEmbargoVisitor<'a, 'b, 'tcx> { LibEmbargoVisitor { - cx: cx, + cx, cstore: &*cx.sess().cstore, access_levels: cx.access_levels.borrow_mut(), prev_level: Some(AccessLevel::Public), diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index dae0b5f0123..5e1c09641e1 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -717,7 +717,7 @@ impl<'a> PrettyEncoder<'a> { /// Creates a new encoder whose output will be written to the specified writer pub fn new(writer: &'a mut fmt::Write) -> PrettyEncoder<'a> { PrettyEncoder { - writer: writer, + writer, curr_indent: 0, indent: 2, is_emitting_map_key: false, @@ -1451,7 +1451,7 @@ impl<T: Iterator<Item=char>> Parser<T> { /// Creates the JSON parser. pub fn new(rdr: T) -> Parser<T> { let mut p = Parser { - rdr: rdr, + rdr, ch: Some('\x00'), line: 1, col: 0, diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index c3107d1f190..2e354252c15 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -14,9 +14,6 @@ Core encoding and decoding interfaces. */ -#![crate_name = "serialize"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs index 9c3db64d4d8..f3475bd18ce 100644 --- a/src/libserialize/opaque.rs +++ b/src/libserialize/opaque.rs @@ -153,8 +153,8 @@ pub struct Decoder<'a> { impl<'a> Decoder<'a> { pub fn new(data: &'a [u8], position: usize) -> Decoder<'a> { Decoder { - data: data, - position: position, + data, + position, } } diff --git a/src/libstd/build.rs b/src/libstd/build.rs index 0b5c2db171d..f57dec98b79 100644 --- a/src/libstd/build.rs +++ b/src/libstd/build.rs @@ -21,7 +21,7 @@ fn main() { let target = env::var("TARGET").expect("TARGET was not set"); let host = env::var("HOST").expect("HOST was not set"); if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") && - !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") { + !target.contains("emscripten") && !target.contains("fuchsia") { let _ = build_libbacktrace(&host, &target); } @@ -30,7 +30,7 @@ fn main() { println!("cargo:rustc-link-lib=dl"); println!("cargo:rustc-link-lib=log"); println!("cargo:rustc-link-lib=gcc"); - } else if !target.contains("musl") || target.contains("mips") { + } else if !target.contains("musl") { println!("cargo:rustc-link-lib=dl"); println!("cargo:rustc-link-lib=rt"); println!("cargo:rustc-link-lib=pthread"); diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 7e2229a8f84..16b0c709986 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -419,7 +419,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter Empty(bucket) => { // Found a hole! return InternalEntry::Vacant { - hash: hash, + hash, elem: NoElem(bucket, displacement), }; } @@ -433,7 +433,7 @@ fn search_hashed<K, V, M, F>(table: M, hash: SafeHash, mut is_match: F) -> Inter // We can finish the search early if we hit any bucket // with a lower distance to initial bucket than we've probed. return InternalEntry::Vacant { - hash: hash, + hash, elem: NeqElem(full, probe_displacement), }; } @@ -646,7 +646,7 @@ impl<K, V, S> HashMap<K, V, S> #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> { HashMap { - hash_builder: hash_builder, + hash_builder, resize_policy: DefaultResizePolicy::new(), table: RawTable::new(0), } @@ -679,8 +679,8 @@ impl<K, V, S> HashMap<K, V, S> let resize_policy = DefaultResizePolicy::new(); let raw_cap = resize_policy.raw_capacity(capacity); HashMap { - hash_builder: hash_builder, - resize_policy: resize_policy, + hash_builder, + resize_policy, table: RawTable::new(raw_cap), } } @@ -1496,14 +1496,14 @@ impl<'a, K, V> InternalEntry<K, V, &'a mut RawTable<K, V>> { InternalEntry::Occupied { elem } => { Some(Occupied(OccupiedEntry { key: Some(key), - elem: elem, + elem, })) } InternalEntry::Vacant { hash, elem } => { Some(Vacant(VacantEntry { - hash: hash, - key: key, - elem: elem, + hash, + key, + elem, })) } InternalEntry::TableIsEmpty => None, diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 80a223c7d74..9771363d545 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -337,7 +337,7 @@ impl<T, S> HashSet<T, S> pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> { Difference { iter: self.iter(), - other: other, + other, } } @@ -391,7 +391,7 @@ impl<T, S> HashSet<T, S> pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> { Intersection { iter: self.iter(), - other: other, + other, } } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 6f7c5a5de42..f1e8ff66af1 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -353,14 +353,14 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> Bucket<K, V, M> { let ib_index = ib_index & table.capacity_mask; Bucket { raw: table.raw_bucket_at(ib_index), - table: table, + table, } } pub fn first(table: M) -> Bucket<K, V, M> { Bucket { raw: table.raw_bucket_at(0), - table: table, + table, } } @@ -455,7 +455,7 @@ impl<K, V, M: Deref<Target = RawTable<K, V>>> EmptyBucket<K, V, M> { match self.next().peek() { Full(bucket) => { Ok(GapThenFull { - gap: gap, + gap, full: bucket, }) } @@ -860,8 +860,8 @@ impl<K, V> RawTable<K, V> { // Replace the marker regardless of lifetime bounds on parameters. IntoIter { iter: RawBuckets { - raw: raw, - elems_left: elems_left, + raw, + elems_left, marker: marker::PhantomData, }, table: self, @@ -873,8 +873,8 @@ impl<K, V> RawTable<K, V> { // Replace the marker regardless of lifetime bounds on parameters. Drain { iter: RawBuckets { - raw: raw, - elems_left: elems_left, + raw, + elems_left, marker: marker::PhantomData, }, table: Shared::from(self), diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index db64d41011c..7392a153e3b 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -830,7 +830,7 @@ impl CStr { /// /// It is your responsibility to make sure that the underlying memory is not /// freed too early. For example, the following code will cause undefined - /// behaviour when `ptr` is used inside the `unsafe` block: + /// behavior when `ptr` is used inside the `unsafe` block: /// /// ```no_run /// use std::ffi::{CString}; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index d62e3e905e3..a40a9329ed9 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -123,7 +123,7 @@ impl OsString { /// Creates a new `OsString` with the given capacity. /// - /// The string will be able to hold exactly `capacity` lenth units of other + /// The string will be able to hold exactly `capacity` length units of other /// OS strings without reallocating. If `capacity` is 0, the string will not /// allocate. /// diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 1e692abaff2..a438b4afdd0 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -916,7 +916,7 @@ impl AsInner<fs_imp::FileAttr> for Metadata { } impl Permissions { - /// Returns whether these permissions describe a readonly file. + /// Returns whether these permissions describe a readonly (unwritable) file. /// /// # Examples /// @@ -934,7 +934,11 @@ impl Permissions { #[stable(feature = "rust1", since = "1.0.0")] pub fn readonly(&self) -> bool { self.0.readonly() } - /// Modifies the readonly flag for this set of permissions. + /// Modifies the readonly flag for this set of permissions. If the + /// `readonly` argument is `true`, using the resulting `Permission` will + /// update file permissions to forbid writing. Conversely, if it's `false`, + /// using the resulting `Permission` will update file permissions to allow + /// writing. /// /// This operation does **not** modify the filesystem. To modify the /// filesystem use the `fs::set_permissions` function. diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index d765dd227be..4ebd3554fd1 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -97,7 +97,7 @@ impl<R: Read> BufReader<R> { buffer.set_len(cap); inner.initializer().initialize(&mut buffer); BufReader { - inner: inner, + inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0, diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index d986021a18b..32a92145aaf 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -69,7 +69,7 @@ use io::{self, Initializer, SeekFrom, Error, ErrorKind}; /// // now let's write a test /// #[test] /// fn test_writes_bytes() { -/// // setting up a real File is much more slow than an in-memory buffer, +/// // setting up a real File is much slower than an in-memory buffer, /// // let's use a cursor instead /// use std::io::Cursor; /// let mut buff = Cursor::new(vec![0; 15]); diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 68f55221a6c..bb9383d3d6e 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -252,8 +252,8 @@ impl Error { fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error { Error { repr: Repr::Custom(Box::new(Custom { - kind: kind, - error: error, + kind, + error, })) } } diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs index ce205c3b11c..9cef4e3cdf1 100644 --- a/src/libstd/io/lazy.rs +++ b/src/libstd/io/lazy.rs @@ -27,7 +27,7 @@ impl<T: Send + Sync + 'static> Lazy<T> { Lazy { lock: Mutex::new(), ptr: Cell::new(ptr::null_mut()), - init: init + init, } } diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index f486493f98b..074ab3ebd8f 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -401,28 +401,29 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> /// /// Implementors of the `Read` trait are called 'readers'. /// -/// Readers are defined by one required method, `read()`. Each call to `read` +/// Readers are defined by one required method, [`read()`]. Each call to [`read()`] /// will attempt to pull bytes from this source into a provided buffer. A -/// number of other methods are implemented in terms of `read()`, giving +/// number of other methods are implemented in terms of [`read()`], giving /// implementors a number of ways to read bytes while only needing to implement /// a single method. /// /// Readers are intended to be composable with one another. Many implementors -/// throughout `std::io` take and provide types which implement the `Read` +/// throughout [`std::io`] take and provide types which implement the `Read` /// trait. /// -/// Please note that each call to `read` may involve a system call, and -/// therefore, using something that implements [`BufRead`][bufread], such as -/// [`BufReader`][bufreader], will be more efficient. -/// -/// [bufread]: trait.BufRead.html -/// [bufreader]: struct.BufReader.html +/// Please note that each call to [`read()`] may involve a system call, and +/// therefore, using something that implements [`BufRead`], such as +/// [`BufReader`], will be more efficient. /// /// # Examples /// -/// [`File`][file]s implement `Read`: +/// [`File`]s implement `Read`: /// -/// [file]: ../fs/struct.File.html +/// [`read()`]: trait.Read.html#tymethod.read +/// [`std::io`]: ../../std/io/index.html +/// [`File`]: ../fs/struct.File.html +/// [`BufRead`]: trait.BufRead.html +/// [`BufReader`]: struct.BufReader.html /// /// ``` /// use std::io; @@ -455,9 +456,9 @@ pub trait Read { /// /// This function does not provide any guarantees about whether it blocks /// waiting for data, but if an object needs to block for a read but cannot - /// it will typically signal this via an `Err` return value. + /// it will typically signal this via an [`Err`] return value. /// - /// If the return value of this method is `Ok(n)`, then it must be + /// If the return value of this method is [`Ok(n)`], then it must be /// guaranteed that `0 <= n <= buf.len()`. A nonzero `n` value indicates /// that the buffer `buf` has been filled in with `n` bytes of data from this /// source. If `n` is `0`, then it can indicate one of two scenarios: @@ -478,14 +479,17 @@ pub trait Read { /// variant will be returned. If an error is returned then it must be /// guaranteed that no bytes were read. /// - /// An error of the `ErrorKind::Interrupted` kind is non-fatal and the read + /// An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read /// operation should be retried if there is nothing else to do. /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`Ok(n)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`File`]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -511,18 +515,21 @@ pub trait Read { /// buffers. /// /// If a `Read`er guarantees that it can work properly with uninitialized - /// memory, it should call `Initializer::nop()`. See the documentation for - /// `Initializer` for details. + /// memory, it should call [`Initializer::nop()`]. See the documentation for + /// [`Initializer`] for details. /// /// The behavior of this method must be independent of the state of the /// `Read`er - the method only takes `&self` so that it can be used through /// trait objects. /// - /// # Unsafety + /// # Safety /// /// This method is unsafe because a `Read`er could otherwise return a /// non-zeroing `Initializer` from another `Read` type without an `unsafe` /// block. + /// + /// [`Initializer::nop()`]: ../../std/io/struct.Initializer.html#method.nop + /// [`Initializer`]: ../../std/io/struct.Initializer.html #[unstable(feature = "read_initializer", issue = "42788")] #[inline] unsafe fn initializer(&self) -> Initializer { @@ -532,16 +539,16 @@ pub trait Read { /// Read all bytes until EOF in this source, placing them into `buf`. /// /// All bytes read from this source will be appended to the specified buffer - /// `buf`. This function will continuously call `read` to append more data to - /// `buf` until `read` returns either `Ok(0)` or an error of - /// non-`ErrorKind::Interrupted` kind. + /// `buf`. This function will continuously call [`read()`] to append more data to + /// `buf` until [`read()`] returns either [`Ok(0)`] or an error of + /// non-[`ErrorKind::Interrupted`] kind. /// /// If successful, this function will return the total number of bytes read. /// /// # Errors /// /// If this function encounters an error of the kind - /// `ErrorKind::Interrupted` then the error is ignored and the operation + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If any other read error is encountered then this function immediately @@ -550,9 +557,12 @@ pub trait Read { /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`read()`]: trait.Read.html#tymethod.read + /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`File`]: ../fs/struct.File.html /// /// ``` /// use std::io; @@ -633,11 +643,11 @@ pub trait Read { /// # Errors /// /// If this function encounters an error of the kind - /// `ErrorKind::Interrupted` then the error is ignored and the operation + /// [`ErrorKind::Interrupted`] then the error is ignored and the operation /// will continue. /// /// If this function encounters an "end of file" before completely filling - /// the buffer, it returns an error of the kind `ErrorKind::UnexpectedEof`. + /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`]. /// The contents of `buf` are unspecified in this case. /// /// If any other read error is encountered then this function immediately @@ -649,9 +659,11 @@ pub trait Read { /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`File`]: ../fs/struct.File.html + /// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted + /// [`ErrorKind::UnexpectedEof`]: ../../std/io/enum.ErrorKind.html#variant.UnexpectedEof /// /// ``` /// use std::io; @@ -722,11 +734,11 @@ pub trait Read { #[stable(feature = "rust1", since = "1.0.0")] fn by_ref(&mut self) -> &mut Self where Self: Sized { self } - /// Transforms this `Read` instance to an `Iterator` over its bytes. + /// Transforms this `Read` instance to an [`Iterator`] over its bytes. /// - /// The returned type implements `Iterator` where the `Item` is `Result<u8, - /// R::Err>`. The yielded item is `Ok` if a byte was successfully read and - /// `Err` otherwise for I/O errors. EOF is mapped to returning `None` from + /// The returned type implements [`Iterator`] where the `Item` is [`Result`]`<`[`u8`]`, + /// R::Err>`. The yielded item is [`Ok`] if a byte was successfully read and + /// [`Err`] otherwise for I/O errors. EOF is mapped to returning [`None`] from /// this iterator. /// /// # Examples @@ -734,6 +746,12 @@ pub trait Read { /// [`File`][file]s implement `Read`: /// /// [file]: ../fs/struct.File.html + /// [`Iterator`]: ../../std/iter/trait.Iterator.html + /// [`Result`]: ../../std/result/enum.Result.html + /// [`u8`]: ../../std/primitive.u8.html + /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok + /// [`Err`]: ../../std/result/enum.Result.html#variant.Err + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// ``` /// use std::io; @@ -754,12 +772,12 @@ pub trait Read { Bytes { inner: self } } - /// Transforms this `Read` instance to an `Iterator` over `char`s. + /// Transforms this `Read` instance to an [`Iterator`] over [`char`]s. /// /// This adaptor will attempt to interpret this reader as a UTF-8 encoded - /// sequence of characters. The returned iterator will return `None` once + /// sequence of characters. The returned iterator will return [`None`] once /// EOF is reached for this reader. Otherwise each element yielded will be a - /// `Result<char, E>` where `E` may contain information about what I/O error + /// [`Result`]`<`[`char`]`, E>` where `E` may contain information about what I/O error /// occurred or where decoding failed. /// /// Currently this adaptor will discard intermediate data read, and should @@ -767,9 +785,13 @@ pub trait Read { /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`File`]: ../fs/struct.File.html + /// [`Iterator`]: ../../std/iter/trait.Iterator.html + /// [`Result`]: ../../std/result/enum.Result.html + /// [`char`]: ../../std/primitive.char.html + /// [`None`]: ../../std/option/enum.Option.html#variant.None /// /// ``` /// #![feature(io)] @@ -832,15 +854,17 @@ pub trait Read { /// Creates an adaptor which will read at most `limit` bytes from it. /// /// This function returns a new instance of `Read` which will read at most - /// `limit` bytes, after which it will always return EOF (`Ok(0)`). Any + /// `limit` bytes, after which it will always return EOF ([`Ok(0)`]). Any /// read errors will not count towards the number of bytes read and future - /// calls to `read` may succeed. + /// calls to [`read()`] may succeed. /// /// # Examples /// - /// [`File`][file]s implement `Read`: + /// [`File`]s implement `Read`: /// - /// [file]: ../fs/struct.File.html + /// [`File`]: ../fs/struct.File.html + /// [`Ok(0)`]: ../../std/result/enum.Result.html#variant.Ok + /// [`read()`]: trait.Read.html#tymethod.read /// /// ``` /// use std::io; @@ -879,7 +903,7 @@ impl Initializer { /// Returns a new `Initializer` which will not zero out buffers. /// - /// # Unsafety + /// # Safety /// /// This may only be called by `Read`ers which guarantee that they will not /// read from buffers passed to `Read` methods, and that the return value of diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 880caa2ade5..b57067e35e9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -81,7 +81,7 @@ //! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also //! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually //! calls to methods on [`str`] and [`[T]`][slice] respectively, via [deref -//! coercions]. +//! coercions][deref-coercions]. //! //! Third, the standard library defines [The Rust Prelude], a small collection //! of items - mostly traits - that are imported into every module of every @@ -203,16 +203,13 @@ //! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use //! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules //! [crates.io]: https://crates.io -//! [deref coercions]: ../book/first-edition/deref-coercions.html +//! [deref-coercions]: ../book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods //! [files]: fs/struct.File.html //! [multithreading]: thread/index.html //! [other]: #what-is-in-the-standard-library-documentation //! [primitive types]: ../book/first-edition/primitive-types.html -#![crate_name = "std"] #![stable(feature = "rust1", since = "1.0.0")] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -361,6 +358,7 @@ extern crate std_unicode; extern crate libc; // We always need an unwinder currently for backtraces +#[allow(unused_extern_crates)] extern crate unwind; // compiler-rt intrinsics diff --git a/src/libstd/memchr.rs b/src/libstd/memchr.rs index 98642f86f4d..240e82069ff 100644 --- a/src/libstd/memchr.rs +++ b/src/libstd/memchr.rs @@ -20,7 +20,7 @@ /// magnitude faster than `haystack.iter().position(|&b| b == needle)`. /// (See benchmarks.) /// -/// # Example +/// # Examples /// /// This shows how to find the first position of a byte in a byte string. /// @@ -40,7 +40,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> { /// Returns the index corresponding to the last occurrence of `needle` in /// `haystack`, or `None` if one is not found. /// -/// # Example +/// # Examples /// /// This shows how to find the last position of a byte in a byte string. /// diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 99567bd08bb..739dc4163fe 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -453,7 +453,7 @@ pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> { let mut any_data = 0; let mut any_vtable = 0; let mut data = Data { - f: f, + f, }; let r = __rust_maybe_catch_panic(do_call::<F, R>, diff --git a/src/libstd/path.rs b/src/libstd/path.rs index c90a0c78527..830b9dc475d 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -323,6 +323,11 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { mem::transmute(s) } +// Detect scheme on Redox +fn has_redox_scheme(s: &[u8]) -> bool { + cfg!(target_os = "redox") && s.split(|b| *b == b'/').next().unwrap_or(b"").contains(&b':') +} + //////////////////////////////////////////////////////////////////////////////// // Cross-platform, iterator-independent parsing //////////////////////////////////////////////////////////////////////////////// @@ -1685,8 +1690,12 @@ impl Path { #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] pub fn is_absolute(&self) -> bool { - // FIXME: Remove target_os = "redox" and allow Redox prefixes - self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some()) + if !cfg!(target_os = "redox") { + self.has_root() && (cfg!(unix) || self.prefix().is_some()) + } else { + // FIXME: Allow Redox prefixes + has_redox_scheme(self.as_u8_slice()) + } } /// Returns `true` if the `Path` is relative, i.e. not absolute. @@ -2049,8 +2058,9 @@ impl Path { let prefix = parse_prefix(self.as_os_str()); Components { path: self.as_u8_slice(), - prefix: prefix, - has_physical_root: has_physical_root(self.as_u8_slice(), prefix), + prefix, + has_physical_root: has_physical_root(self.as_u8_slice(), prefix) || + has_redox_scheme(self.as_u8_slice()), front: State::Prefix, back: State::Body, } @@ -3953,4 +3963,10 @@ mod tests { assert_eq!(path, path_buf); assert!(path_buf.into_os_string().capacity() >= 15); } + + #[test] + fn display_format_flags() { + assert_eq!(format!("a{:#<5}b", Path::new("").display()), "a#####b"); + assert_eq!(format!("a{:#<5}b", Path::new("a").display()), "aa####b"); + } } diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs index 49cdba21a1d..538753d8692 100644 --- a/src/libstd/prelude/mod.rs +++ b/src/libstd/prelude/mod.rs @@ -23,6 +23,7 @@ //! On a technical level, Rust inserts //! //! ``` +//! # #[allow(unused_extern_crates)] //! extern crate std; //! ``` //! diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index c52899db437..76ef36cc9a7 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -103,26 +103,31 @@ mod prim_bool { } /// [`String`]: string/struct.String.html /// /// As always, remember that a human intuition for 'character' may not map to -/// Unicode's definitions. For example, emoji symbols such as '❤️' can be more -/// than one Unicode code point; this ❤️ in particular is two: +/// Unicode's definitions. For example, despite looking similar, the 'é' +/// character is one Unicode code point while 'é' is two Unicode code points: /// /// ``` -/// let s = String::from("❤️"); +/// let mut chars = "é".chars(); +/// // U+00e9: 'latin small letter e with acute' +/// assert_eq!(Some('\u{00e9}'), chars.next()); +/// assert_eq!(None, chars.next()); /// -/// // we get two chars out of a single ❤️ -/// let mut iter = s.chars(); -/// assert_eq!(Some('\u{2764}'), iter.next()); -/// assert_eq!(Some('\u{fe0f}'), iter.next()); -/// assert_eq!(None, iter.next()); +/// let mut chars = "é".chars(); +/// // U+0065: 'latin small letter e' +/// assert_eq!(Some('\u{0065}'), chars.next()); +/// // U+0301: 'combining acute accent' +/// assert_eq!(Some('\u{0301}'), chars.next()); +/// assert_eq!(None, chars.next()); /// ``` /// -/// This means it won't fit into a `char`. Trying to create a literal with -/// `let heart = '❤️';` gives an error: +/// This means that the contents of the first string above _will_ fit into a +/// `char` while the contents of the second string _will not_. Trying to create +/// a `char` literal with the contents of the second string gives an error: /// /// ```text -/// error: character literal may only contain one codepoint: '❤ -/// let heart = '❤️'; -/// ^~ +/// error: character literal may only contain one codepoint: 'é' +/// let c = 'é'; +/// ^^^^ /// ``` /// /// Another implication of the 4-byte fixed size of a `char` is that @@ -183,9 +188,10 @@ mod prim_unit { } /// Working with raw pointers in Rust is uncommon, /// typically limited to a few patterns. /// -/// Use the [`null`] function to create null pointers, and the [`is_null`] method -/// of the `*const T` type to check for null. The `*const T` type also defines -/// the [`offset`] method, for pointer math. +/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the +/// [`is_null`] method of the `*const T` and `*mut T` types to check for null. +/// The `*const T` and `*mut T` types also define the [`offset`] method, for +/// pointer math. /// /// # Common ways to create raw pointers /// @@ -256,6 +262,7 @@ mod prim_unit { } /// *[See also the `std::ptr` module](ptr/index.html).* /// /// [`null`]: ../std/ptr/fn.null.html +/// [`null_mut`]: ../std/ptr/fn.null_mut.html /// [`is_null`]: ../std/primitive.pointer.html#method.is_null /// [`offset`]: ../std/primitive.pointer.html#method.offset /// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw diff --git a/src/libstd/process.rs b/src/libstd/process.rs index a872e7eee06..a3a7e91dd80 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -126,7 +126,7 @@ impl AsInner<imp::Process> for Child { impl FromInner<(imp::Process, imp::StdioPipes)> for Child { fn from_inner((handle, io): (imp::Process, imp::StdioPipes)) -> Child { Child { - handle: handle, + handle, stdin: io.stdin.map(ChildStdin::from_inner), stdout: io.stdout.map(ChildStdout::from_inner), stderr: io.stderr.map(ChildStderr::from_inner), @@ -1035,9 +1035,9 @@ impl Child { let status = self.wait()?; Ok(Output { - status: status, - stdout: stdout, - stderr: stderr, + status, + stdout, + stderr, }) } } diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index 0f9ef6fabb0..c08bd6d133d 100644 --- a/src/libstd/sync/mpsc/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -46,7 +46,7 @@ pub fn tokens() -> (WaitToken, SignalToken) { inner: inner.clone(), }; let signal_token = SignalToken { - inner: inner + inner, }; (wait_token, signal_token) } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 8b4da532af6..e49f4cff024 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -148,12 +148,12 @@ impl Select { let id = self.next_id.get(); self.next_id.set(id + 1); Handle { - id: id, + id, selector: self.inner.get(), next: ptr::null_mut(), prev: ptr::null_mut(), added: false, - rx: rx, + rx, packet: rx, } } diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 1d16e002a2b..90f12c826d6 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -177,7 +177,7 @@ impl<T> Packet<T> { lock: Mutex::new(State { disconnected: false, blocker: NoneBlocked, - cap: cap, + cap, canceled: None, queue: Queue { head: ptr::null_mut(), diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index bb18fe95a9d..403685a4b8e 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -387,7 +387,7 @@ impl Drop for Finish { impl OnceState { /// Returns whether the associated [`Once`] has been poisoned. /// - /// Once an initalization routine for a [`Once`] has panicked it will forever + /// Once an initialization routine for a [`Once`] has panicked it will forever /// indicate to future forced initialization routines that it is poisoned. /// /// [`Once`]: struct.Once.html diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs index 6e44ad705fe..59ae2a74a6d 100644 --- a/src/libstd/sys/redox/args.rs +++ b/src/libstd/sys/redox/args.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Global initialization and retreival of command line arguments. +//! Global initialization and retrieval of command line arguments. //! //! On some platforms these are stored during runtime startup, //! and on some they are retrieved from the system on demand. diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs deleted file mode 100644 index 6cafe3e69ba..00000000000 --- a/src/libstd/sys/redox/backtrace.rs +++ /dev/null @@ -1,32 +0,0 @@ -// 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. - -use io; -use sys_common::backtrace::Frame; - -pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; -pub struct BacktraceContext; - -#[inline(never)] -pub fn unwind_backtrace(_frames: &mut [Frame]) - -> io::Result<(usize, BacktraceContext)> -{ - Ok((0, BacktraceContext)) -} - -pub mod gnu { - use io; - use fs; - use libc::c_char; - - pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> { - Err(io::Error::new(io::ErrorKind::Other, "Not implemented")) - } -} diff --git a/src/libstd/sys/redox/backtrace/mod.rs b/src/libstd/sys/redox/backtrace/mod.rs new file mode 100644 index 00000000000..40b957d847b --- /dev/null +++ b/src/libstd/sys/redox/backtrace/mod.rs @@ -0,0 +1,42 @@ +// 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. + +/// See sys/unix/backtrace/mod.rs for an explanation of the method used here. + +pub use self::tracing::unwind_backtrace; +pub use self::printing::{foreach_symbol_fileline, resolve_symname}; + +// tracing impls: +mod tracing; +// symbol resolvers: +mod printing; + +pub mod gnu { + use io; + use fs; + use libc::c_char; + use vec::Vec; + use ffi::OsStr; + use os::unix::ffi::OsStrExt; + use io::Read; + + pub fn get_executable_filename() -> io::Result<(Vec<c_char>, fs::File)> { + let mut exefile = fs::File::open("sys:exe")?; + let mut exename = Vec::new(); + exefile.read_to_end(&mut exename)?; + if exename.last() == Some(&b'\n') { + exename.pop(); + } + let file = fs::File::open(OsStr::from_bytes(&exename))?; + Ok((exename.into_iter().map(|c| c as c_char).collect(), file)) + } +} + +pub struct BacktraceContext; diff --git a/src/libstd/sys/redox/backtrace/printing.rs b/src/libstd/sys/redox/backtrace/printing.rs new file mode 100644 index 00000000000..3e937dbe623 --- /dev/null +++ b/src/libstd/sys/redox/backtrace/printing.rs @@ -0,0 +1,11 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub use sys_common::gnu::libbacktrace::{foreach_symbol_fileline, resolve_symname}; diff --git a/src/libstd/sys/redox/backtrace/tracing.rs b/src/libstd/sys/redox/backtrace/tracing.rs new file mode 100644 index 00000000000..cfeabaddda9 --- /dev/null +++ b/src/libstd/sys/redox/backtrace/tracing.rs @@ -0,0 +1,106 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use error::Error; +use io; +use libc; +use sys::backtrace::BacktraceContext; +use sys_common::backtrace::Frame; + +use unwind as uw; + +struct Context<'a> { + idx: usize, + frames: &'a mut [Frame], +} + +#[derive(Debug)] +struct UnwindError(uw::_Unwind_Reason_Code); + +impl Error for UnwindError { + fn description(&self) -> &'static str { + "unexpected return value while unwinding" + } +} + +impl ::fmt::Display for UnwindError { + fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result { + write!(f, "{}: {:?}", self.description(), self.0) + } +} + +#[inline(never)] // if we know this is a function call, we can skip it when + // tracing +pub fn unwind_backtrace(frames: &mut [Frame]) + -> io::Result<(usize, BacktraceContext)> +{ + let mut cx = Context { + idx: 0, + frames: frames, + }; + let result_unwind = unsafe { + uw::_Unwind_Backtrace(trace_fn, + &mut cx as *mut Context + as *mut libc::c_void) + }; + // See libunwind:src/unwind/Backtrace.c for the return values. + // No, there is no doc. + match result_unwind { + // These return codes seem to be benign and need to be ignored for backtraces + // to show up properly on all tested platforms. + uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => { + Ok((cx.idx, BacktraceContext)) + } + _ => { + Err(io::Error::new(io::ErrorKind::Other, + UnwindError(result_unwind))) + } + } +} + +extern fn trace_fn(ctx: *mut uw::_Unwind_Context, + arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code { + let cx = unsafe { &mut *(arg as *mut Context) }; + let mut ip_before_insn = 0; + let mut ip = unsafe { + uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void + }; + if !ip.is_null() && ip_before_insn == 0 { + // this is a non-signaling frame, so `ip` refers to the address + // after the calling instruction. account for that. + ip = (ip as usize - 1) as *mut _; + } + + // dladdr() on osx gets whiny when we use FindEnclosingFunction, and + // it appears to work fine without it, so we only use + // FindEnclosingFunction on non-osx platforms. In doing so, we get a + // slightly more accurate stack trace in the process. + // + // This is often because panic involves the last instruction of a + // function being "call std::rt::begin_unwind", with no ret + // instructions after it. This means that the return instruction + // pointer points *outside* of the calling function, and by + // unwinding it we go back to the original function. + let symaddr = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { + ip + } else { + unsafe { uw::_Unwind_FindEnclosingFunction(ip) } + }; + + if cx.idx < cx.frames.len() { + cx.frames[cx.idx] = Frame { + symbol_addr: symaddr, + exact_position: ip, + }; + cx.idx += 1; + } + + uw::_URC_NO_REASON +} diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs index 259cda5bcb3..9fd8d6c9186 100644 --- a/src/libstd/sys/redox/ext/mod.rs +++ b/src/libstd/sys/redox/ext/mod.rs @@ -13,7 +13,7 @@ //! For now, this module is limited to extracting file descriptors, //! but its functionality will grow over time. //! -//! # Example +//! # Examples //! //! ```no_run //! use std::fs::File; diff --git a/src/libstd/sys/redox/net/dns/mod.rs b/src/libstd/sys/redox/net/dns/mod.rs index 49cde89dc05..1a26257e4a7 100644 --- a/src/libstd/sys/redox/net/dns/mod.rs +++ b/src/libstd/sys/redox/net/dns/mod.rs @@ -206,10 +206,10 @@ impl Dns { } Ok(Dns { - transaction_id: transaction_id, - flags: flags, - queries: queries, - answers: answers, + transaction_id, + flags, + queries, + answers, }) } } diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs index 17fa07b99ae..d87364b8121 100644 --- a/src/libstd/sys/redox/process.rs +++ b/src/libstd/sys/redox/process.rs @@ -336,7 +336,7 @@ impl Command { panic!("return from exec without err"); } } else { - io::Error::new(io::ErrorKind::NotFound, "") + io::Error::from_raw_os_error(syscall::ENOENT) } } diff --git a/src/libstd/sys/unix/args.rs b/src/libstd/sys/unix/args.rs index bbdcb5d3616..810d2d40c05 100644 --- a/src/libstd/sys/unix/args.rs +++ b/src/libstd/sys/unix/args.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Global initialization and retreival of command line arguments. +//! Global initialization and retrieval of command line arguments. //! //! On some platforms these are stored during runtime startup, //! and on some they are retrieved from the system on demand. diff --git a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs index cfeabaddda9..e3ffbe88acd 100644 --- a/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs +++ b/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs @@ -43,7 +43,7 @@ pub fn unwind_backtrace(frames: &mut [Frame]) { let mut cx = Context { idx: 0, - frames: frames, + frames, }; let result_unwind = unsafe { uw::_Unwind_Backtrace(trace_fn, diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs index a94585723a1..f44b9aa9615 100644 --- a/src/libstd/sys/unix/ext/fs.rs +++ b/src/libstd/sys/unix/ext/fs.rs @@ -154,8 +154,6 @@ pub trait OpenOptionsExt { /// # Examples /// /// ```no_run - /// # #![feature(libc)] - /// extern crate libc; /// use std::fs::OpenOptions; /// use std::os::unix::fs::OpenOptionsExt; /// diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs index a0323d933d6..c9fe3590a64 100644 --- a/src/libstd/sys/unix/ext/io.rs +++ b/src/libstd/sys/unix/ext/io.rs @@ -13,11 +13,10 @@ #![stable(feature = "rust1", since = "1.0.0")] use fs; -use net; use os::raw; use sys; use io; -use sys_common::{self, AsInner, FromInner, IntoInner}; +use sys_common::{AsInner, FromInner, IntoInner}; use libc; /// Raw file descriptors. @@ -93,19 +92,6 @@ impl IntoRawFd for fs::File { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for net::TcpStream { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for net::TcpListener { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl AsRawFd for net::UdpSocket { - fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } -} - #[stable(feature = "asraw_stdio", since = "1.21.0")] impl AsRawFd for io::Stdin { fn as_raw_fd(&self) -> RawFd { libc::STDIN_FILENO } @@ -120,44 +106,3 @@ impl AsRawFd for io::Stdout { impl AsRawFd for io::Stderr { fn as_raw_fd(&self) -> RawFd { libc::STDERR_FILENO } } - -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawFd for net::TcpStream { - unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { - let socket = sys::net::Socket::from_inner(fd); - net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) - } -} -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawFd for net::TcpListener { - unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { - let socket = sys::net::Socket::from_inner(fd); - net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) - } -} -#[stable(feature = "from_raw_os", since = "1.1.0")] -impl FromRawFd for net::UdpSocket { - unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { - let socket = sys::net::Socket::from_inner(fd); - net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) - } -} - -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for net::TcpStream { - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for net::TcpListener { - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } -} -#[stable(feature = "into_raw_os", since = "1.4.0")] -impl IntoRawFd for net::UdpSocket { - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner() - } -} diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs index 67fe46cc9c7..98bc90dd4e1 100644 --- a/src/libstd/sys/unix/ext/mod.rs +++ b/src/libstd/sys/unix/ext/mod.rs @@ -13,7 +13,7 @@ //! For now, this module is limited to extracting file descriptors, //! but its functionality will grow over time. //! -//! # Example +//! # Examples //! //! ```no_run //! use std::fs::File; diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 27853427128..86b0f35be92 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -30,14 +30,14 @@ use ffi::OsStr; use fmt; use io::{self, Initializer}; use mem; -use net::Shutdown; +use net::{self, Shutdown}; use os::unix::ffi::OsStrExt; use os::unix::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd}; use path::Path; use time::Duration; -use sys::cvt; +use sys::{self, cvt}; use sys::net::Socket; -use sys_common::{AsInner, FromInner, IntoInner}; +use sys_common::{self, AsInner, FromInner, IntoInner}; #[cfg(any(target_os = "linux", target_os = "android", target_os = "dragonfly", target_os = "freebsd", @@ -141,8 +141,8 @@ impl SocketAddr { } Ok(SocketAddr { - addr: addr, - len: len, + addr, + len, }) } @@ -588,6 +588,64 @@ impl IntoRawFd for UnixStream { } } +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::TcpStream { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::TcpListener { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for net::UdpSocket { + fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::TcpStream { + unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream { + let socket = sys::net::Socket::from_inner(fd); + net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket)) + } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::TcpListener { + unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener { + let socket = sys::net::Socket::from_inner(fd); + net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket)) + } +} + +#[stable(feature = "from_raw_os", since = "1.1.0")] +impl FromRawFd for net::UdpSocket { + unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket { + let socket = sys::net::Socket::from_inner(fd); + net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket)) + } +} + +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::TcpStream { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::TcpListener { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} +#[stable(feature = "into_raw_os", since = "1.4.0")] +impl IntoRawFd for net::UdpSocket { + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner() + } +} + /// A structure representing a Unix domain socket server. /// /// # Examples diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 4e6fde5c29d..cb0f687e072 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -170,11 +170,17 @@ impl AsInner<stat64> for FileAttr { } impl FilePermissions { - pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 } + pub fn readonly(&self) -> bool { + // check if any class (owner, group, others) has write permission + self.mode & 0o222 == 0 + } + pub fn set_readonly(&mut self, readonly: bool) { if readonly { + // remove write permission for all classes; equivalent to `chmod a-w <file>` self.mode &= !0o222; } else { + // add write permission for all classes; equivalent to `chmod a+w <file>` self.mode |= 0o222; } } diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs index ab609126cdb..bc20a74f114 100644 --- a/src/libstd/sys/unix/process/magenta.rs +++ b/src/libstd/sys/unix/process/magenta.rs @@ -61,7 +61,7 @@ pub struct Handle { impl Handle { pub fn new(raw: mx_handle_t) -> Handle { Handle { - raw: raw, + raw, } } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 839e2d88d6a..689ccd78524 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -94,14 +94,14 @@ impl Command { let program = os2c(program, &mut saw_nul); Command { argv: vec![program.as_ptr(), ptr::null()], - program: program, + program, args: Vec::new(), env: None, envp: None, cwd: None, uid: None, gid: None, - saw_nul: saw_nul, + saw_nul, closures: Vec::new(), stdin: None, stdout: None, diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 15747746611..40f1d6a6db1 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -168,7 +168,8 @@ impl Thread { unsafe { let ret = libc::pthread_join(self.id, ptr::null_mut()); mem::forget(self); - debug_assert_eq!(ret, 0); + assert!(ret == 0, + "failed to join thread: {}", io::Error::from_raw_os_error(ret)); } } diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs index 99ab8741159..18944be58ee 100644 --- a/src/libstd/sys/unix/weak.rs +++ b/src/libstd/sys/unix/weak.rs @@ -49,7 +49,7 @@ pub struct Weak<F> { impl<F> Weak<F> { pub const fn new(name: &'static str) -> Weak<F> { Weak { - name: name, + name, addr: AtomicUsize::new(1), _marker: marker::PhantomData, } diff --git a/src/libstd/sys/windows/backtrace/mod.rs b/src/libstd/sys/windows/backtrace/mod.rs index 3c3fd8d3e4a..26b4cb90e0a 100644 --- a/src/libstd/sys/windows/backtrace/mod.rs +++ b/src/libstd/sys/windows/backtrace/mod.rs @@ -68,8 +68,8 @@ pub fn unwind_backtrace(frames: &mut [Frame]) let backtrace_context = BacktraceContext { handle: process, - SymCleanup: SymCleanup, - dbghelp: dbghelp, + SymCleanup, + dbghelp, }; // Initialize this process's symbols diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index ba54ca6ea18..7dfcc996e18 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -273,6 +273,7 @@ pub const FILE_END: DWORD = 2; pub const WAIT_OBJECT_0: DWORD = 0x00000000; pub const WAIT_TIMEOUT: DWORD = 258; +pub const WAIT_FAILED: DWORD = 0xFFFFFFFF; #[cfg(target_env = "msvc")] pub const MAX_SYM_NAME: usize = 2000; diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs index be7482c4bb1..452d720ce59 100644 --- a/src/libstd/sys/windows/pipe.rs +++ b/src/libstd/sys/windows/pipe.rs @@ -239,10 +239,10 @@ impl<'a> AsyncPipe<'a> { }; overlapped.hEvent = event.raw(); Ok(AsyncPipe { - pipe: pipe, - overlapped: overlapped, - event: event, - dst: dst, + pipe, + overlapped, + event, + dst, state: State::NotReading, }) } diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs index 5a376a867ee..2cdd86e88b0 100644 --- a/src/libstd/sys/windows/thread.rs +++ b/src/libstd/sys/windows/thread.rs @@ -61,7 +61,11 @@ impl Thread { } pub fn join(self) { - unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE); } + let rc = unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE) }; + if rc == c::WAIT_FAILED { + panic!("failed to join on thread: {}", + io::Error::last_os_error()); + } } pub fn yield_now() { diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs index ad57f87dc1f..7ae9ed917bd 100644 --- a/src/libstd/sys/windows/thread_local.rs +++ b/src/libstd/sys/windows/thread_local.rs @@ -122,8 +122,8 @@ struct Node { unsafe fn register_dtor(key: Key, dtor: Dtor) { let mut node = Box::new(Node { - key: key, - dtor: dtor, + key, + dtor, next: ptr::null_mut(), }); diff --git a/src/libstd/sys_common/thread_info.rs b/src/libstd/sys_common/thread_info.rs index 2abb8afa828..7970042b1d6 100644 --- a/src/libstd/sys_common/thread_info.rs +++ b/src/libstd/sys_common/thread_info.rs @@ -45,7 +45,7 @@ pub fn stack_guard() -> Option<usize> { pub fn set(stack_guard: Option<usize>, thread: Thread) { THREAD_INFO.with(|c| assert!(c.borrow().is_none())); THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{ - stack_guard: stack_guard, - thread: thread, + stack_guard, + thread, })); } diff --git a/src/libstd/sys_common/thread_local.rs b/src/libstd/sys_common/thread_local.rs index 1f889c70707..87ffd304e1a 100644 --- a/src/libstd/sys_common/thread_local.rs +++ b/src/libstd/sys_common/thread_local.rs @@ -128,7 +128,7 @@ impl StaticKey { pub const fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> StaticKey { StaticKey { key: atomic::AtomicUsize::new(0), - dtor: dtor + dtor, } } diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 4e4a6e77d12..b89a73cd28a 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -452,10 +452,14 @@ impl fmt::Display for Wtf8 { pos = surrogate_pos + 3; }, None => { - formatter.write_str(unsafe { + let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) - })?; - return Ok(()); + }; + if pos == 0 { + return s.fmt(formatter) + } else { + return formatter.write_str(s) + } } } } diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 48f611a3439..7a9b642350f 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -258,8 +258,8 @@ impl<T: 'static> LocalKey<T> { pub const unsafe fn new(inner: unsafe fn() -> Option<&'static UnsafeCell<Option<T>>>, init: fn() -> T) -> LocalKey<T> { LocalKey { - inner: inner, - init: init, + inner, + init, } } diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 3cd9cf7727c..4912ff93abd 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -374,7 +374,7 @@ impl Builder { { let Builder { name, stack_size } = self; - let stack_size = stack_size.unwrap_or(util::min_stack()); + let stack_size = stack_size.unwrap_or_else(util::min_stack); let my_thread = Thread::new(name); let their_thread = my_thread.clone(); @@ -560,7 +560,7 @@ pub fn current() -> Thread { /// implementing low-level shared resources or synchronization primitives. /// /// However programmers will usually prefer to use, [`channel`]s, [`Condvar`]s, -/// [`Mutex`]es or [`join`] for their synchronisation routines, as they avoid +/// [`Mutex`]es or [`join`] for their synchronization routines, as they avoid /// thinking about thread scheduling. /// /// Note that [`channel`]s for example are implemented using this primitive. @@ -807,7 +807,7 @@ pub fn park_timeout_ms(ms: u32) { /// Platforms which do not support nanosecond precision for sleeping will have /// `dur` rounded up to the nearest granularity of time they can sleep for. /// -/// # Example +/// # Examples /// /// Waiting for the complete expiration of the timeout: /// @@ -1230,6 +1230,11 @@ impl<T> JoinHandle<T> { /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// [`panic`]: ../../std/macro.panic.html /// + /// # Panics + /// + /// This function may panic on some platforms if a thread attempts to join + /// itself or otherwise may create a deadlock with joining threads. + /// /// # Examples /// /// ``` diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs index 48819adb23e..d715a0d740b 100644 --- a/src/libstd/time/duration.rs +++ b/src/libstd/time/duration.rs @@ -197,8 +197,8 @@ impl Duration { } debug_assert!(nanos < NANOS_PER_SEC); Some(Duration { - secs: secs, - nanos: nanos, + secs, + nanos, }) } else { None @@ -268,8 +268,8 @@ impl Duration { .and_then(|s| s.checked_add(extra_secs)) { debug_assert!(nanos < NANOS_PER_SEC); Some(Duration { - secs: secs, - nanos: nanos, + secs, + nanos, }) } else { None diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs index e8eb4abaa40..5b893505b34 100644 --- a/src/libstd/time/mod.rs +++ b/src/libstd/time/mod.rs @@ -112,7 +112,7 @@ pub struct Instant(time::Instant); /// println!("{}", elapsed.as_secs()); /// } /// Err(e) => { -/// // an error occured! +/// // an error occurred! /// println!("Error: {:?}", e); /// } /// } diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index 698210e83f3..e5a114caed0 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -20,9 +20,7 @@ //! provide for basic string-related manipulations. This crate does not //! (yet) aim to provide a full set of Unicode tables. -#![crate_name = "std_unicode"] #![unstable(feature = "unicode", issue = "27783")] -#![crate_type = "rlib"] #![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/", @@ -34,7 +32,6 @@ #![feature(core_char_ext)] #![feature(str_internals)] -#![feature(core_intrinsics)] #![feature(decode_utf8)] #![feature(fused)] #![feature(fn_traits)] diff --git a/src/libstd_unicode/lossy.rs b/src/libstd_unicode/lossy.rs index b914cbcf4b8..253dcb6a159 100644 --- a/src/libstd_unicode/lossy.rs +++ b/src/libstd_unicode/lossy.rs @@ -12,7 +12,7 @@ use core::str as core_str; use core::fmt; use core::fmt::Write; use char; -use core::intrinsics; +use core::mem; /// Lossy UTF-8 string. @@ -27,7 +27,7 @@ impl Utf8Lossy { } pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { - unsafe { intrinsics::transmute(bytes) } + unsafe { mem::transmute(bytes) } } pub fn chunks(&self) -> Utf8LossyChunksIter { @@ -153,7 +153,21 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { impl fmt::Display for Utf8Lossy { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + // If we're the empty string then our iterator won't actually yield + // anything, so perform the formatting manually + if self.bytes.len() == 0 { + return "".fmt(f) + } + for Utf8LossyChunk { valid, broken } in self.chunks() { + // If we successfully decoded the whole chunk as a valid string then + // we can return a direct formatting of the string which will also + // respect various formatting flags if possible. + if valid.len() == self.bytes.len() { + assert!(broken.is_empty()); + return valid.fmt(f) + } + f.write_str(valid)?; if !broken.is_empty() { f.write_char(char::REPLACEMENT_CHARACTER)?; diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs index 54a5288a57c..1274b062587 100644 --- a/src/libstd_unicode/u_str.rs +++ b/src/libstd_unicode/u_str.rs @@ -87,7 +87,7 @@ impl<I> Utf16Encoder<I> { where I: Iterator<Item = char> { Utf16Encoder { - chars: chars, + chars, extra: 0, } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 38ef79822c7..fa4df2196a3 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -135,7 +135,7 @@ impl PathSegment { pub fn crate_root(span: Span) -> Self { PathSegment { identifier: Ident { ctxt: span.ctxt, ..keywords::CrateRoot.ident() }, - span: span, + span, parameters: None, } } @@ -844,6 +844,32 @@ pub struct Expr { pub attrs: ThinVec<Attribute> } +impl Expr { + /// Wether this expression would be valid somewhere that expects a value, for example, an `if` + /// condition. + pub fn returns(&self) -> bool { + if let ExprKind::Block(ref block) = self.node { + match block.stmts.last().map(|last_stmt| &last_stmt.node) { + // implicit return + Some(&StmtKind::Expr(_)) => true, + Some(&StmtKind::Semi(ref expr)) => { + if let ExprKind::Ret(_) = expr.node { + // last statement is explicit return + true + } else { + false + } + } + // This is a block that doesn't end in either an implicit or explicit return + _ => false, + } + } else { + // This is not a block, it is a value + true + } + } +} + impl fmt::Debug for Expr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self)) @@ -1492,15 +1518,15 @@ impl Arg { let infer_ty = P(Ty { id: DUMMY_NODE_ID, node: TyKind::ImplicitSelf, - span: span, + span, }); let arg = |mutbl, ty| Arg { pat: P(Pat { id: DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None), - span: span, + span, }), - ty: ty, + ty, id: DUMMY_NODE_ID, }; match eself.node { @@ -1509,7 +1535,7 @@ impl Arg { SelfKind::Region(lt, mutbl) => arg(Mutability::Immutable, P(Ty { id: DUMMY_NODE_ID, node: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl: mutbl }), - span: span, + span, })), } } @@ -1738,7 +1764,7 @@ impl PolyTraitRef { PolyTraitRef { bound_lifetimes: lifetimes, trait_ref: TraitRef { path: path, ref_id: DUMMY_NODE_ID }, - span: span, + span, } } } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index d5caf458fd7..ca87c807103 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -438,7 +438,7 @@ pub fn mk_attr_inner(span: Span, id: AttrId, item: MetaItem) -> Attribute { /// Returns an inner attribute with the given value and span. pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute { Attribute { - id: id, + id, style: ast::AttrStyle::Inner, path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)), tokens: item.node.tokens(item.span), @@ -456,7 +456,7 @@ pub fn mk_attr_outer(span: Span, id: AttrId, item: MetaItem) -> Attribute { /// Returns an outer attribute with the given value and span. pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute { Attribute { - id: id, + id, style: ast::AttrStyle::Outer, path: ast::Path::from_ident(item.span, ast::Ident::with_empty_ctxt(item.name)), tokens: item.node.tokens(item.span), @@ -469,12 +469,12 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { let style = doc_comment_style(&text.as_str()); let lit = respan(span, LitKind::Str(text, ast::StrStyle::Cooked)); Attribute { - id: id, - style: style, + id, + style, path: ast::Path::from_ident(span, ast::Ident::from_str("doc")), tokens: MetaItemKind::NameValue(lit).tokens(span), is_sugared_doc: true, - span: span, + span, } } @@ -718,8 +718,8 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, match (since, reason) { (Some(since), Some(reason)) => { rustc_depr = Some(RustcDeprecation { - since: since, - reason: reason, + since, + reason, }) } (None, _) => { @@ -763,7 +763,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, (Some(feature), reason, Some(issue)) => { stab = Some(Stability { level: Unstable { - reason: reason, + reason, issue: { if let Ok(issue) = issue.as_str().parse() { issue @@ -774,7 +774,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } } }, - feature: feature, + feature, rustc_depr: None, }) } @@ -817,9 +817,9 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, (Some(feature), Some(since)) => { stab = Some(Stability { level: Stable { - since: since, + since, }, - feature: feature, + feature, rustc_depr: None, }) } @@ -1064,26 +1064,21 @@ impl MetaItem { }, _ => return None, }; + let list_closing_paren_pos = tokens.peek().map(|tt| tt.span().hi); let node = match MetaItemKind::from_tokens(tokens) { Some(node) => node, _ => return None, }; - if let Some(last_span) = node.last_span() { - span.hi = last_span.hi; - } + span.hi = match node { + MetaItemKind::NameValue(ref lit) => lit.span.hi, + MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(span.hi), + _ => span.hi, + }; Some(MetaItem { name: name, span: span, node: node }) } } impl MetaItemKind { - fn last_span(&self) -> Option<Span> { - match *self { - MetaItemKind::Word => None, - MetaItemKind::List(ref list) => list.last().map(NestedMetaItem::span), - MetaItemKind::NameValue(ref lit) => Some(lit.span), - } - } - pub fn tokens(&self, span: Span) -> TokenStream { match *self { MetaItemKind::Word => TokenStream::empty(), @@ -1130,7 +1125,7 @@ impl MetaItemKind { let mut result = Vec::new(); while let Some(..) = tokens.peek() { match NestedMetaItemKind::from_tokens(&mut tokens) { - Some(item) => result.push(Spanned { span: item.span(), node: item }), + Some(item) => result.push(respan(item.span(), item)), None => return None, } match tokens.next() { @@ -1163,7 +1158,7 @@ impl NestedMetaItemKind { if let Some(TokenTree::Token(span, token)) = tokens.peek().cloned() { if let Some(node) = LitKind::from_token(token) { tokens.next(); - return Some(NestedMetaItemKind::Literal(Spanned { node: node, span: span })); + return Some(NestedMetaItemKind::Literal(respan(span, node))); } } @@ -1256,7 +1251,7 @@ pub trait HasAttrs: Sized { impl<T: HasAttrs> HasAttrs for Spanned<T> { fn attrs(&self) -> &[ast::Attribute] { self.node.attrs() } fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self { - Spanned { node: self.node.map_attrs(f), span: self.span } + respan(self.span, self.node.map_attrs(f)) } } diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 6c48b4cadd8..30ae7df9353 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -115,7 +115,7 @@ impl CodeMap { CodeMap { files: RefCell::new(Vec::new()), file_loader: Box::new(RealFileLoader), - path_mapping: path_mapping, + path_mapping, } } @@ -124,8 +124,8 @@ impl CodeMap { -> CodeMap { CodeMap { files: RefCell::new(Vec::new()), - file_loader: file_loader, - path_mapping: path_mapping, + file_loader, + path_mapping, } } @@ -215,13 +215,13 @@ impl CodeMap { let filemap = Rc::new(FileMap { name: filename, - name_was_remapped: name_was_remapped, - crate_of_origin: crate_of_origin, + name_was_remapped, + crate_of_origin, src: None, - src_hash: src_hash, + src_hash, external_src: RefCell::new(ExternalSource::AbsentOk), - start_pos: start_pos, - end_pos: end_pos, + start_pos, + end_pos, lines: RefCell::new(file_local_lines), multibyte_chars: RefCell::new(file_local_multibyte_chars), }); @@ -255,7 +255,7 @@ impl CodeMap { assert!(chpos >= linechpos); Loc { file: f, - line: line, + line, col: chpos - linechpos, } } @@ -385,15 +385,15 @@ impl CodeMap { let line_len = lo.file.get_line(line_index) .map(|s| s.chars().count()) .unwrap_or(0); - lines.push(LineInfo { line_index: line_index, - start_col: start_col, + lines.push(LineInfo { line_index, + start_col, end_col: CharPos::from_usize(line_len) }); start_col = CharPos::from_usize(0); } // For the last line, it extends from `start_col` to `hi.col`: lines.push(LineInfo { line_index: hi.line - 1, - start_col: start_col, + start_col, end_col: hi.col }); Ok(FileLines {file: lo.file, lines: lines}) @@ -426,7 +426,7 @@ impl CodeMap { return Err(SpanSnippetError::MalformedForCodemap( MalformedCodemapPositions { name: local_begin.fm.name.clone(), - source_len: source_len, + source_len, begin_pos: local_begin.pos, end_pos: local_end.pos, })); @@ -581,7 +581,7 @@ impl FilePathMapping { pub fn new(mapping: Vec<(String, String)>) -> FilePathMapping { FilePathMapping { - mapping: mapping + mapping, } } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 54e6dde41e6..14f1f8fbf8c 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -32,8 +32,8 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool) let features; { let mut strip_unconfigured = StripUnconfigured { - should_test: should_test, - sess: sess, + should_test, + sess, features: None, }; @@ -105,10 +105,10 @@ impl<'a> StripUnconfigured<'a> { self.process_cfg_attr(ast::Attribute { id: attr::mk_attr_id(), style: attr.style, - path: path, - tokens: tokens, + path, + tokens, is_sugared_doc: false, - span: span, + span, }) } else { None diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 855f4cd3557..5224f52c496 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -133,7 +133,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, // Add the error to the map. with_registered_diagnostics(|diagnostics| { let info = ErrorInfo { - description: description, + description, use_site: None }; if diagnostics.insert(code.name, info).is_some() { @@ -235,7 +235,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, expr, ), vis: ast::Visibility::Public, - span: span, + span, tokens: None, }) ])) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 72b2552f64f..e57d9c6fe89 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -677,10 +677,10 @@ impl<'a> ExtCtxt<'a> { resolver: &'a mut Resolver) -> ExtCtxt<'a> { ExtCtxt { - parse_sess: parse_sess, - ecfg: ecfg, + parse_sess, + ecfg, crate_root: None, - resolver: resolver, + resolver, resolve_err_count: 0, current_expansion: ExpansionData { mark: Mark::root(), diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index de0538e38b3..cbdd0013593 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -366,7 +366,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { path.segments.push(ast::PathSegment { identifier: ident.node, span: ident.span, - parameters: parameters, + parameters, }); (ast::QSelf { @@ -377,15 +377,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy { ast::MutTy { - ty: ty, - mutbl: mutbl + ty, + mutbl, } } fn ty(&self, span: Span, ty: ast::TyKind) -> P<ast::Ty> { P(ast::Ty { id: ast::DUMMY_NODE_ID, - span: span, + span, node: ty }) } @@ -444,15 +444,15 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ident: id, id: ast::DUMMY_NODE_ID, attrs: attrs.into(), - bounds: bounds, - default: default, - span: span + bounds, + default, + span, } } fn trait_ref(&self, path: ast::Path) -> ast::TraitRef { ast::TraitRef { - path: path, + path, ref_id: ast::DUMMY_NODE_ID, } } @@ -461,7 +461,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::PolyTraitRef { bound_lifetimes: Vec::new(), trait_ref: self.trait_ref(path), - span: span, + span, } } @@ -482,7 +482,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::LifetimeDef { attrs: attrs.into(), lifetime: self.lifetime(span, ident), - bounds: bounds + bounds, } } @@ -511,7 +511,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat_ident(sp, ident) }; let local = P(ast::Local { - pat: pat, + pat, ty: None, init: Some(ex), id: ast::DUMMY_NODE_ID, @@ -539,7 +539,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { self.pat_ident(sp, ident) }; let local = P(ast::Local { - pat: pat, + pat, ty: Some(typ), init: Some(ex), id: ast::DUMMY_NODE_ID, @@ -560,13 +560,13 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ty: Some(ty), init: None, id: ast::DUMMY_NODE_ID, - span: span, + span, attrs: ast::ThinVec::new(), }); ast::Stmt { id: ast::DUMMY_NODE_ID, node: ast::StmtKind::Local(local), - span: span, + span, } } @@ -587,18 +587,18 @@ impl<'a> AstBuilder for ExtCtxt<'a> { } fn block(&self, span: Span, stmts: Vec<ast::Stmt>) -> P<ast::Block> { P(ast::Block { - stmts: stmts, + stmts, id: ast::DUMMY_NODE_ID, rules: BlockCheckMode::Default, - span: span, + span, }) } fn expr(&self, span: Span, node: ast::ExprKind) -> P<ast::Expr> { P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: node, - span: span, + node, + span, attrs: ast::ThinVec::new(), }) } @@ -672,7 +672,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ast::Field { ident: respan(span, name), expr: e, - span: span, + span, is_shorthand: false, attrs: ast::ThinVec::new(), } @@ -876,7 +876,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn arm(&self, _span: Span, pats: Vec<P<ast::Pat>>, expr: P<ast::Expr>) -> ast::Arm { ast::Arm { attrs: vec![], - pats: pats, + pats, guard: None, body: expr } @@ -954,7 +954,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg { let arg_pat = self.pat_ident(span, ident); ast::Arg { - ty: ty, + ty, pat: arg_pat, id: ast::DUMMY_NODE_ID } @@ -963,7 +963,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { // FIXME unused self fn fn_decl(&self, inputs: Vec<ast::Arg>, output: P<ast::Ty>) -> P<ast::FnDecl> { P(ast::FnDecl { - inputs: inputs, + inputs, output: ast::FunctionRetTy::Ty(output), variadic: false }) @@ -975,11 +975,11 @@ impl<'a> AstBuilder for ExtCtxt<'a> { // Rust coding conventions P(ast::Item { ident: name, - attrs: attrs, + attrs, id: ast::DUMMY_NODE_ID, - node: node, + node, vis: ast::Visibility::Inherited, - span: span, + span, tokens: None, }) } @@ -1022,7 +1022,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { let fields: Vec<_> = tys.into_iter().map(|ty| { ast::StructField { span: ty.span, - ty: ty, + ty, ident: None, vis: ast::Visibility::Inherited, attrs: Vec::new(), @@ -1038,7 +1038,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { respan(span, ast::Variant_ { - name: name, + name, attrs: Vec::new(), data: vdata, disr_expr: None, @@ -1081,7 +1081,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { attrs, ast::ItemKind::Mod(ast::Mod { inner: inner_span, - items: items, + items, }) ) } @@ -1147,7 +1147,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> { ident: keywords::Invalid.ident(), attrs: vec![], node: ast::ItemKind::Use(vp), - vis: vis, + vis, span: sp, tokens: None, }) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9625602fa4a..d1172b1b2ce 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -303,7 +303,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind: InvocationKind::Derive { path: path.clone(), item: item }, expansion_kind: invoc.expansion_kind, expansion_data: ExpansionData { - mark: mark, + mark, ..invoc.expansion_data.clone() }, }); @@ -579,7 +579,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let pretty_name = Symbol::intern(&format!("derive({})", path)); let span = path.span; let attr = ast::Attribute { - path: path, tokens: TokenStream::empty(), span: span, + path, span, + tokens: TokenStream::empty(), // irrelevant: id: ast::AttrId(0), style: ast::AttrStyle::Outer, is_sugared_doc: false, }; @@ -714,10 +715,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn collect(&mut self, expansion_kind: ExpansionKind, kind: InvocationKind) -> Expansion { let mark = Mark::fresh(self.cx.current_expansion.mark); self.invocations.push(Invocation { - kind: kind, - expansion_kind: expansion_kind, + kind, + expansion_kind, expansion_data: ExpansionData { - mark: mark, + mark, depth: self.cx.current_expansion.depth + 1, ..self.cx.current_expansion.clone() }, @@ -876,7 +877,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { item.and_then(|item| match item.node { ItemKind::Mac(mac) => { self.collect(ExpansionKind::Items, InvocationKind::Bang { - mac: mac, + mac, ident: Some(item.ident), span: item.span, }).make_items() @@ -1035,7 +1036,7 @@ macro_rules! feature_tests { impl<'feat> ExpansionConfig<'feat> { pub fn default(crate_name: String) -> ExpansionConfig<'static> { ExpansionConfig { - crate_name: crate_name, + crate_name, features: None, recursion_limit: 1024, trace_mac: false, diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index e3377c1d8de..4fc2b92d3cd 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -35,7 +35,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { let vis = ast::Visibility::Inherited; let span = DUMMY_SP; let expr_placeholder = || P(ast::Expr { - id: id, span: span, + id, span, attrs: ast::ThinVec::new(), node: ast::ExprKind::Mac(mac_placeholder()), }); @@ -44,30 +44,30 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion { ExpansionKind::Expr => Expansion::Expr(expr_placeholder()), ExpansionKind::OptExpr => Expansion::OptExpr(Some(expr_placeholder())), ExpansionKind::Items => Expansion::Items(SmallVector::one(P(ast::Item { - id: id, span: span, ident: ident, vis: vis, attrs: attrs, + id, span, ident, vis, attrs, node: ast::ItemKind::Mac(mac_placeholder()), tokens: None, }))), ExpansionKind::TraitItems => Expansion::TraitItems(SmallVector::one(ast::TraitItem { - id: id, span: span, ident: ident, attrs: attrs, + id, span, ident, attrs, node: ast::TraitItemKind::Macro(mac_placeholder()), tokens: None, })), ExpansionKind::ImplItems => Expansion::ImplItems(SmallVector::one(ast::ImplItem { - id: id, span: span, ident: ident, vis: vis, attrs: attrs, + id, span, ident, vis, attrs, node: ast::ImplItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, })), ExpansionKind::Pat => Expansion::Pat(P(ast::Pat { - id: id, span: span, node: ast::PatKind::Mac(mac_placeholder()), + id, span, node: ast::PatKind::Mac(mac_placeholder()), })), ExpansionKind::Ty => Expansion::Ty(P(ast::Ty { - id: id, span: span, node: ast::TyKind::Mac(mac_placeholder()), + id, span, node: ast::TyKind::Mac(mac_placeholder()), })), ExpansionKind::Stmts => Expansion::Stmts(SmallVector::one({ let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::ThinVec::new())); - ast::Stmt { id: id, span: span, node: ast::StmtKind::Mac(mac) } + ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) } })), } } @@ -81,9 +81,9 @@ pub struct PlaceholderExpander<'a, 'b: 'a> { impl<'a, 'b> PlaceholderExpander<'a, 'b> { pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { PlaceholderExpander { - cx: cx, + cx, expansions: HashMap::new(), - monotonic: monotonic, + monotonic, } } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 9907dfe341e..c3f3a59c302 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -383,7 +383,7 @@ pub fn unflatten(tts: Vec<TokenTree>) -> Vec<TokenTree> { } TokenTree::Token(span, token::CloseDelim(delim)) => { let tree = TokenTree::Delimited(span, Delimited { - delim: delim, + delim, tts: result.into_iter().map(TokenStream::from).collect::<TokenStream>().into(), }); result = results.pop().unwrap(); diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 146bd5d9856..405d06dafbf 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -178,7 +178,7 @@ fn initial_matcher_pos(ms: Vec<TokenTree>, lo: BytePos) -> Box<MatcherPos> { sep: None, idx: 0, up: None, - matches: matches, + matches, match_lo: 0, match_cur: 0, match_hi: match_idx_hi, @@ -374,7 +374,7 @@ fn inner_parse_loop(sess: &ParseSess, stack: vec![], sep: seq.separator.clone(), idx: 0, - matches: matches, + matches, match_lo: item.match_cur, match_cur: item.match_cur, match_hi: item.match_cur + seq.num_captures, @@ -400,7 +400,7 @@ fn inner_parse_loop(sess: &ParseSess, let idx = item.idx; item.stack.push(MatcherTtFrame { elts: lower_elts, - idx: idx, + idx, }); item.idx = 0; cur_items.push(item); @@ -599,9 +599,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { panic!(FatalError) } }, - "path" => { - token::NtPath(panictry!(p.parse_path(PathStyle::Type))) - }, + "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))), "meta" => token::NtMeta(panictry!(p.parse_meta_item())), "vis" => token::NtVis(panictry!(p.parse_visibility(true))), // this is not supposed to happen, since it has been checked diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 7b3fe2bd993..983b19c5bf0 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -271,9 +271,9 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item) let expander: Box<_> = Box::new(MacroRulesMacroExpander { name: def.ident, - lhses: lhses, - rhses: rhses, - valid: valid, + lhses, + rhses, + valid, }); if body.legacy { diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index 6fdcadd1dde..012d4a54b36 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -191,8 +191,8 @@ fn parse_tree<I>(tree: tokenstream::TokenTree, let name_captures = macro_parser::count_names(&sequence); TokenTree::Sequence(span, Rc::new(SequenceRepetition { tts: sequence, - separator: separator, - op: op, + separator, + op, num_captures: name_captures, })) } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2b8a733b852..09574d5ba12 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -112,8 +112,8 @@ macro_rules! declare_features { // was set. This is most important for knowing when a particular feature became // stable (active). // -// NB: The featureck.py script parses this information directly out of the source -// so take care when modifying it. +// NB: tools/tidy/src/features.rs parses this information directly out of the +// source, so take care when modifying it. declare_features! ( (active, asm, "1.0.0", Some(29722)), @@ -345,9 +345,6 @@ declare_features! ( // Allows `repr(align(u16))` struct attribute (RFC 1358) (active, repr_align, "1.17.0", Some(33626)), - // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work. - (active, rvalue_static_promotion, "1.15.1", Some(38865)), - // Used to preserve symbols (see llvm.used) (active, used, "1.18.0", Some(40289)), @@ -375,6 +372,9 @@ declare_features! ( // #[doc(cfg(...))] (active, doc_cfg, "1.21.0", Some(43781)), + + // allow `#[must_use]` on functions (RFC 1940) + (active, fn_must_use, "1.21.0", Some(43302)), ); declare_features! ( @@ -457,6 +457,8 @@ declare_features! ( (accepted, associated_consts, "1.20.0", Some(29646)), // Usage of the `compile_error!` macro (accepted, compile_error, "1.20.0", Some(40872)), + // See rust-lang/rfcs#1414. Allows code like `let x: &'static u32 = &42` to work. + (accepted, rvalue_static_promotion, "1.21.0", Some(38865)), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -916,20 +918,27 @@ struct Context<'a> { } macro_rules! gate_feature_fn { - ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{ - let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain); + ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{ + let (cx, has_feature, span, + name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); let has_feature: bool = has_feature(&$cx.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); if !has_feature && !span.allows_unstable() { - emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain); + leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) + .emit(); } }} } macro_rules! gate_feature { ($cx: expr, $feature: ident, $span: expr, $explain: expr) => { - gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain) - } + gate_feature_fn!($cx, |x:&Features| x.$feature, $span, + stringify!($feature), $explain, GateStrength::Hard) + }; + ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { + gate_feature_fn!($cx, |x:&Features| x.$feature, $span, + stringify!($feature), $explain, $level) + }; } impl<'a> Context<'a> { @@ -939,7 +948,7 @@ impl<'a> Context<'a> { for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES { if name == n { if let Gated(_, name, desc, ref has_feature) = *gateage { - gate_feature_fn!(self, has_feature, attr.span, name, desc); + gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard); } debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage); return; @@ -1009,13 +1018,26 @@ pub enum GateIssue { Library(Option<u32>) } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum GateStrength { + /// A hard error. (Most feature gates should use this.) + Hard, + /// Only a warning. (Use this only as backwards-compatibility demands.) + Soft, +} + pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue, explain: &str) { feature_err(sess, feature, span, issue, explain).emit(); } pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue, - explain: &str) -> DiagnosticBuilder<'a> { + explain: &str) -> DiagnosticBuilder<'a> { + leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard) +} + +fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue, + explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> { let diag = &sess.span_diagnostic; let issue = match issue { @@ -1023,10 +1045,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga GateIssue::Library(lib) => lib, }; - let mut err = if let Some(n) = issue { - diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n)) + let explanation = if let Some(n) = issue { + format!("{} (see issue #{})", explain, n) } else { - diag.struct_span_err(span, explain) + explain.to_owned() + }; + + let mut err = match level { + GateStrength::Hard => diag.struct_span_err(span, &explanation), + GateStrength::Soft => diag.struct_span_warn(span, &explanation), }; // #23973: do not suggest `#![feature(...)]` if we are in beta/stable @@ -1036,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga feature)); } + // If we're on stable and only emitting a "soft" warning, add a note to + // clarify that the feature isn't "on" (rather than being on but + // warning-worthy). + if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft { + err.help("a nightly build of the compiler is required to enable this feature"); + } + err + } const EXPLAIN_BOX_SYNTAX: &'static str = @@ -1093,6 +1128,12 @@ macro_rules! gate_feature_post { if !span.allows_unstable() { gate_feature!(cx.context, $feature, span, $explain) } + }}; + ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ + let (cx, span) = ($cx, $span); + if !span.allows_unstable() { + gate_feature!(cx.context, $feature, span, $explain, $level) + } }} } @@ -1235,6 +1276,11 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { function may change over time, for now \ a top-level `fn main()` is required"); } + if attr::contains_name(&i.attrs[..], "must_use") { + gate_feature_post!(&self, fn_must_use, i.span, + "`#[must_use]` on functions is experimental", + GateStrength::Soft); + } } ast::ItemKind::Struct(..) => { @@ -1272,7 +1318,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { and possibly buggy"); } - ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => { + ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => { if polarity == ast::ImplPolarity::Negative { gate_feature_post!(&self, optin_builtin_traits, i.span, @@ -1285,6 +1331,16 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { i.span, "specialization is unstable"); } + + for impl_item in impl_items { + if let ast::ImplItemKind::Method(..) = impl_item.node { + if attr::contains_name(&impl_item.attrs[..], "must_use") { + gate_feature_post!(&self, fn_must_use, impl_item.span, + "`#[must_use]` on methods is experimental", + GateStrength::Soft); + } + } + } } ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { @@ -1576,9 +1632,9 @@ pub fn check_crate(krate: &ast::Crate, unstable: UnstableFeatures) { maybe_stage_features(&sess.span_diagnostic, krate, unstable); let ctx = Context { - features: features, + features, parse_sess: sess, - plugin_attributes: plugin_attributes, + plugin_attributes, }; visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate); } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index a54e2573af4..6fd0a2eab42 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -375,8 +375,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { TyKind::BareFn(f) => { TyKind::BareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy { lifetimes: fld.fold_lifetime_defs(lifetimes), - unsafety: unsafety, - abi: abi, + unsafety, + abi, decl: fld.fold_fn_decl(decl) })) } @@ -387,7 +387,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { let qself = qself.map(|QSelf { ty, position }| { QSelf { ty: fld.fold_ty(ty), - position: position + position, } }); TyKind::Path(qself, fld.fold_path(path)) @@ -415,7 +415,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> { pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod, fld: &mut T) -> ForeignMod { ForeignMod { - abi: abi, + abi, items: items.move_map(|x| fld.fold_foreign_item(x)), } } @@ -658,7 +658,7 @@ pub fn noop_fold_fn_decl<T: Folder>(decl: P<FnDecl>, fld: &mut T) -> P<FnDecl> { FunctionRetTy::Ty(ty) => FunctionRetTy::Ty(fld.fold_ty(ty)), FunctionRetTy::Default(span) => FunctionRetTy::Default(fld.new_span(span)), }, - variadic: variadic + variadic, }) } @@ -745,7 +745,7 @@ pub fn noop_fold_where_clause<T: Folder>( predicates: predicates.move_map(|predicate| { fld.fold_where_predicate(predicate) }), - span: span, + span, } } @@ -846,7 +846,7 @@ pub fn noop_fold_field<T: Folder>(f: Field, folder: &mut T) -> Field { pub fn noop_fold_mt<T: Folder>(MutTy {ty, mutbl}: MutTy, folder: &mut T) -> MutTy { MutTy { ty: folder.fold_ty(ty), - mutbl: mutbl, + mutbl, } } @@ -864,7 +864,7 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> { b.map(|Block {id, stmts, rules, span}| Block { id: folder.new_id(id), stmts: stmts.move_flat_map(|s| folder.fold_stmt(s).into_iter()), - rules: rules, + rules, span: folder.new_span(span), }) } @@ -998,10 +998,10 @@ 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(), - attrs: attrs, + attrs, id: ast::DUMMY_NODE_ID, vis: ast::Visibility::Public, - span: span, + span, node: ast::ItemKind::Mod(module), tokens: None, })).into_iter(); @@ -1024,9 +1024,9 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate, }; Crate { - module: module, - attrs: attrs, - span: span, + module, + attrs, + span, } } @@ -1048,7 +1048,7 @@ pub fn noop_fold_item_simple<T: Folder>(Item {id, ident, attrs, node, vis, span, // FIXME: if this is replaced with a call to `folder.fold_tts` it causes // an ICE during resolve... odd! - tokens: tokens, + tokens, } } @@ -1264,7 +1264,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu let qself = qself.map(|QSelf { ty, position }| { QSelf { ty: folder.fold_ty(ty), - position: position + position, } }); ExprKind::Path(qself, folder.fold_path(path)) diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 695c740f405..37a59411c16 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -11,7 +11,7 @@ //! A JSON emitter for errors. //! //! This works by converting errors to a simplified structural format (see the -//! structs at the start of the file) and then serialising them. These should +//! structs at the start of the file) and then serializing them. These should //! contain as much information about the error as possible. //! //! The format of the JSON output should be considered *unstable*. For now the @@ -42,7 +42,7 @@ impl JsonEmitter { code_map: Rc<CodeMap>) -> JsonEmitter { JsonEmitter { dst: Box::new(io::stderr()), - registry: registry, + registry, cm: code_map, } } @@ -56,8 +56,8 @@ impl JsonEmitter { registry: Option<Registry>, code_map: Rc<CodeMap>) -> JsonEmitter { JsonEmitter { - dst: dst, - registry: registry, + dst, + registry, cm: code_map, } } @@ -251,7 +251,7 @@ impl DiagnosticSpan { Box::new(DiagnosticSpanMacroExpansion { span: call_site, macro_decl_name: bt.macro_decl_name, - def_site_span: def_site_span, + def_site_span, }) }); DiagnosticSpan { @@ -262,11 +262,11 @@ impl DiagnosticSpan { line_end: end.line, column_start: start.col.0 + 1, column_end: end.col.0 + 1, - is_primary: is_primary, + is_primary, text: DiagnosticSpanLine::from_span(span, je), suggested_replacement: suggestion.cloned(), expansion: backtrace_step, - label: label, + label, } } @@ -351,7 +351,7 @@ impl DiagnosticCode { DiagnosticCode { code: s, - explanation: explanation, + explanation, } }) } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 43345b02bf6..e3c9f0a9345 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "syntax"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/", diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index c99a09ab24e..48c92873e14 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -141,11 +141,11 @@ impl<'a> Parser<'a> { Ok(ast::Attribute { id: attr::mk_attr_id(), - style: style, - path: path, - tokens: tokens, + style, + path, + tokens, is_sugared_doc: false, - span: span, + span, }) } @@ -244,10 +244,9 @@ impl<'a> Parser<'a> { pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> { Ok(if self.eat(&token::Eq) { ast::MetaItemKind::NameValue(self.parse_unsuffixed_lit()?) - } else if self.token == token::OpenDelim(token::Paren) { + } else if self.eat(&token::OpenDelim(token::Paren)) { ast::MetaItemKind::List(self.parse_meta_seq()?) } else { - self.eat(&token::OpenDelim(token::Paren)); ast::MetaItemKind::Word }) } @@ -277,9 +276,8 @@ impl<'a> Parser<'a> { /// matches meta_seq = ( COMMASEP(meta_item_inner) ) fn parse_meta_seq(&mut self) -> PResult<'a, Vec<ast::NestedMetaItem>> { - self.parse_unspanned_seq(&token::OpenDelim(token::Paren), - &token::CloseDelim(token::Paren), - SeqSep::trailing_allowed(token::Comma), - |p: &mut Parser<'a>| p.parse_meta_item_inner()) + self.parse_seq_to_end(&token::CloseDelim(token::Paren), + SeqSep::trailing_allowed(token::Comma), + |p: &mut Parser<'a>| p.parse_meta_item_inner()) } } diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index 8b545d3b909..f65fffebe33 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -192,7 +192,7 @@ fn read_line_comments(rdr: &mut StringReader, if !lines.is_empty() { comments.push(Comment { style: if code_to_the_left { Trailing } else { Isolated }, - lines: lines, + lines, pos: p, }); } @@ -306,8 +306,8 @@ fn read_block_comment(rdr: &mut StringReader, } debug!("<<< block comment"); comments.push(Comment { - style: style, - lines: lines, + style, + lines, pos: p, }); } diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 09cdf26bf1f..527d2e41396 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -160,18 +160,18 @@ impl<'a> StringReader<'a> { let source_text = (*filemap.src.as_ref().unwrap()).clone(); StringReader { - sess: sess, + sess, next_pos: filemap.start_pos, pos: filemap.start_pos, col: CharPos(0), ch: Some('\n'), - filemap: filemap, + filemap, terminator: None, save_new_lines_and_multibyte: true, // dummy values; not read peek_tok: token::Eof, peek_span: syntax_pos::DUMMY_SP, - source_text: source_text, + source_text, fatal_errs: Vec::new(), token: token::Eof, span: syntax_pos::DUMMY_SP, @@ -546,7 +546,7 @@ impl<'a> StringReader<'a> { }; Some(TokenAndSpan { - tok: tok, + tok, sp: self.mk_sp(start_bpos, self.pos), }) }) @@ -675,7 +675,7 @@ impl<'a> StringReader<'a> { }; Some(TokenAndSpan { - tok: tok, + tok, sp: self.mk_sp(start_bpos, self.pos), }) }) diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index 63a396c14db..ad389ab510a 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -114,7 +114,7 @@ impl<'a> StringReader<'a> { } Ok(TokenTree::Delimited(span, Delimited { - delim: delim, + delim, tts: tts.into(), })) }, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 957164bab79..67b4954a8f1 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -69,7 +69,7 @@ impl ParseSess { config: HashSet::new(), missing_fragment_specifiers: RefCell::new(HashSet::new()), included_mod_stack: RefCell::new(vec![]), - code_map: code_map + code_map, } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 15f05df58b5..90a635fdf44 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -84,7 +84,7 @@ pub enum PathStyle { Expr, /// In other contexts, notably in types, no ambiguity exists and paths can be written /// without the disambiguator, e.g. `x<y>` - unambiguously a path. - /// Paths with disambiguators are rejected for now, but may be allowed in the future. + /// Paths with disambiguators are still accepted, `x::<Y>` - unambiguously a path too. Type, /// A path with generic arguments disallowed, e.g. `foo::bar::Baz`, used in imports, /// visibilities or attributes. @@ -465,17 +465,17 @@ impl From<P<Expr>> for LhsExpr { /// Create a placeholder argument. fn dummy_arg(span: Span) -> Arg { let spanned = Spanned { - span: span, + span, node: keywords::Invalid.ident() }; let pat = P(Pat { id: ast::DUMMY_NODE_ID, node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), spanned, None), - span: span + span, }); let ty = Ty { node: TyKind::Err, - span: span, + span, id: ast::DUMMY_NODE_ID }; Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID } @@ -489,7 +489,7 @@ impl<'a> Parser<'a> { desugar_doc_comments: bool) -> Self { let mut parser = Parser { - sess: sess, + sess, token: token::Underscore, span: syntax_pos::DUMMY_SP, prev_span: syntax_pos::DUMMY_SP, @@ -497,7 +497,7 @@ impl<'a> Parser<'a> { prev_token_kind: PrevTokenKind::Other, restrictions: Restrictions::empty(), obsolete_set: HashSet::new(), - recurse_into_file_modules: recurse_into_file_modules, + recurse_into_file_modules, directory: Directory { path: PathBuf::new(), ownership: DirectoryOwnership::Owned }, root_module_name: None, expected_tokens: Vec::new(), @@ -508,7 +508,7 @@ impl<'a> Parser<'a> { }), stack: Vec::new(), }, - desugar_doc_comments: desugar_doc_comments, + desugar_doc_comments, cfg_mods: true, }; @@ -1216,15 +1216,15 @@ impl<'a> Parser<'a> { let (inputs, variadic) = self.parse_fn_args(false, true)?; let ret_ty = self.parse_ret_ty()?; let decl = P(FnDecl { - inputs: inputs, + inputs, output: ret_ty, - variadic: variadic + variadic, }); Ok(TyKind::BareFn(P(BareFnTy { - abi: abi, - unsafety: unsafety, + abi, + unsafety, lifetimes: lifetime_defs, - decl: decl + decl, }))) } @@ -1312,11 +1312,11 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; let sig = ast::MethodSig { - unsafety: unsafety, - constness: constness, + unsafety, + constness, decl: d, - generics: generics, - abi: abi, + generics, + abi, }; let body = match self.token { @@ -1344,8 +1344,8 @@ impl<'a> Parser<'a> { Ok(TraitItem { id: ast::DUMMY_NODE_ID, ident: name, - attrs: attrs, - node: node, + attrs, + node, span: lo.to(self.prev_span), tokens: None, }) @@ -1625,7 +1625,7 @@ impl<'a> Parser<'a> { Ok(Arg { ty: t, - pat: pat, + pat, id: ast::DUMMY_NODE_ID, }) } @@ -1649,7 +1649,7 @@ impl<'a> Parser<'a> { }; Ok(Arg { ty: t, - pat: pat, + pat, id: ast::DUMMY_NODE_ID }) } @@ -1755,7 +1755,7 @@ impl<'a> Parser<'a> { self.expect(&token::ModSep)?; let qself = QSelf { ty, position: path.segments.len() }; - self.parse_path_segments(&mut path.segments, style)?; + self.parse_path_segments(&mut path.segments, style, true)?; Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) })) } @@ -1770,16 +1770,26 @@ impl<'a> Parser<'a> { /// `a::b::C::<D>` (with disambiguator) /// `Fn(Args)` (without disambiguator) /// `Fn::(Args)` (with disambiguator) - pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> - { - maybe_whole!(self, NtPath, |x| x); + pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { + self.parse_path_common(style, true) + } + + pub fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool) + -> PResult<'a, ast::Path> { + maybe_whole!(self, NtPath, |path| { + if style == PathStyle::Mod && + path.segments.iter().any(|segment| segment.parameters.is_some()) { + self.diagnostic().span_err(path.span, "unexpected generic arguments in path"); + } + path + }); let lo = self.meta_var_span.unwrap_or(self.span); let mut segments = Vec::new(); if self.eat(&token::ModSep) { segments.push(PathSegment::crate_root(lo)); } - self.parse_path_segments(&mut segments, style)?; + self.parse_path_segments(&mut segments, style, enable_warning)?; Ok(ast::Path { segments, span: lo.to(self.prev_span) }) } @@ -1804,10 +1814,10 @@ impl<'a> Parser<'a> { self.parse_path(style) } - fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle) - -> PResult<'a, ()> { + fn parse_path_segments(&mut self, segments: &mut Vec<PathSegment>, style: PathStyle, + enable_warning: bool) -> PResult<'a, ()> { loop { - segments.push(self.parse_path_segment(style)?); + segments.push(self.parse_path_segment(style, enable_warning)?); if self.is_import_coupler() || !self.eat(&token::ModSep) { return Ok(()); @@ -1815,7 +1825,8 @@ impl<'a> Parser<'a> { } } - fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> { + fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool) + -> PResult<'a, PathSegment> { let ident_span = self.span; let ident = self.parse_path_segment_ident()?; @@ -1835,17 +1846,9 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| is_args_start(t)) { // Generic arguments are found - `<`, `(`, `::<` or `::(`. let lo = self.span; - if self.eat(&token::ModSep) { - // These errors are not strictly necessary and may be removed in the future. - if style == PathStyle::Type { - let mut err = self.diagnostic().struct_span_err(self.prev_span, - "unnecessary path disambiguator"); - err.span_label(self.prev_span, "try removing `::`"); - err.emit(); - } else if self.token == token::OpenDelim(token::Paren) { - self.diagnostic().span_err(self.prev_span, - "`::` is not supported before parenthesized generic arguments") - } + if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning { + self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator") + .span_label(self.prev_span, "try removing `::`").emit(); } let parameters = if self.eat_lt() { @@ -1934,8 +1937,8 @@ impl<'a> Parser<'a> { Ok(ast::Field { ident: respan(lo.to(hi), fieldname), span: lo.to(expr.span), - expr: expr, - is_shorthand: is_shorthand, + expr, + is_shorthand, attrs: attrs.into(), }) } @@ -1943,8 +1946,8 @@ impl<'a> Parser<'a> { pub fn mk_expr(&mut self, span: Span, node: ExprKind, attrs: ThinVec<Attribute>) -> P<Expr> { P(Expr { id: ast::DUMMY_NODE_ID, - node: node, - span: span, + node, + span, attrs: attrs.into(), }) } @@ -1990,8 +1993,8 @@ impl<'a> Parser<'a> { P(Expr { id: ast::DUMMY_NODE_ID, node: ExprKind::Mac(codemap::Spanned {node: m, span: span}), - span: span, - attrs: attrs, + span, + attrs, }) } @@ -2006,7 +2009,7 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, node: ExprKind::Lit(lv_lit), span: *span, - attrs: attrs, + attrs, }) } @@ -2382,7 +2385,7 @@ impl<'a> Parser<'a> { // Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> { - let segment = self.parse_path_segment(PathStyle::Expr)?; + let segment = self.parse_path_segment(PathStyle::Expr, true)?; Ok(match self.token { token::OpenDelim(token::Paren) => { // Method call `expr.f()` @@ -2968,6 +2971,18 @@ impl<'a> Parser<'a> { } let lo = self.prev_span; let cond = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL, None)?; + + // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then + // verify that the last statement is either an implicit return (no `;`) or an explicit + // return. This won't catch blocks with an explicit `return`, but that would be caught by + // the dead code lint. + if self.eat_keyword(keywords::Else) || !cond.returns() { + let sp = lo.next_point(); + let mut err = self.diagnostic() + .struct_span_err(sp, "missing condition for `if` statemement"); + err.span_label(sp, "expected if condition here"); + return Err(err) + } let thn = self.parse_block()?; let mut els: Option<P<Expr>> = None; let mut hi = thn.span; @@ -3153,9 +3168,9 @@ impl<'a> Parser<'a> { } Ok(ast::Arm { - attrs: attrs, - pats: pats, - guard: guard, + attrs, + pats, + guard, body: expr, }) } @@ -3361,7 +3376,7 @@ impl<'a> Parser<'a> { node: ast::FieldPat { ident: fieldname, pat: subpat, - is_shorthand: is_shorthand, + is_shorthand, attrs: attrs.into(), } }); @@ -3597,12 +3612,12 @@ impl<'a> Parser<'a> { }; let init = self.parse_initializer()?; Ok(P(ast::Local { - ty: ty, - pat: pat, - init: init, + ty, + pat, + init, id: ast::DUMMY_NODE_ID, span: lo.to(self.prev_span), - attrs: attrs, + attrs, })) } @@ -3618,10 +3633,10 @@ impl<'a> Parser<'a> { Ok(StructField { span: lo.to(self.prev_span), ident: Some(name), - vis: vis, + vis, id: ast::DUMMY_NODE_ID, - ty: ty, - attrs: attrs, + ty, + attrs, }) } @@ -3929,7 +3944,7 @@ impl<'a> Parser<'a> { Stmt { id: ast::DUMMY_NODE_ID, span: lo.to(hi), - node: node, + node, } } else { // if it has a special ident, it's definitely an item @@ -3946,7 +3961,7 @@ impl<'a> Parser<'a> { let span = lo.to(hi); Stmt { id: ast::DUMMY_NODE_ID, - span: span, + span, node: StmtKind::Item({ self.mk_item( span, id /*id is good here*/, @@ -4083,7 +4098,7 @@ impl<'a> Parser<'a> { } Ok(P(ast::Block { - stmts: stmts, + stmts, id: ast::DUMMY_NODE_ID, rules: s, span: lo.to(self.prev_span), @@ -4227,11 +4242,11 @@ impl<'a> Parser<'a> { Ok(TyParam { attrs: preceding_attrs.into(), - ident: ident, + ident, id: ast::DUMMY_NODE_ID, - bounds: bounds, - default: default, - span: span, + bounds, + default, + span, }) } @@ -4253,8 +4268,8 @@ impl<'a> Parser<'a> { }; lifetime_defs.push(LifetimeDef { attrs: attrs.into(), - lifetime: lifetime, - bounds: bounds, + lifetime, + bounds, }); if seen_ty_param { self.span_err(self.prev_span, @@ -4297,7 +4312,7 @@ impl<'a> Parser<'a> { self.expect_gt()?; Ok(ast::Generics { lifetimes: lifetime_defs, - ty_params: ty_params, + ty_params, where_clause: WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), @@ -4334,8 +4349,8 @@ impl<'a> Parser<'a> { let ty = self.parse_ty()?; bindings.push(TypeBinding { id: ast::DUMMY_NODE_ID, - ident: ident, - ty: ty, + ident, + ty, span: lo.to(self.prev_span), }); seen_binding = true; @@ -4404,8 +4419,8 @@ impl<'a> Parser<'a> { where_clause.predicates.push(ast::WherePredicate::RegionPredicate( ast::WhereRegionPredicate { span: lo.to(self.prev_span), - lifetime: lifetime, - bounds: bounds, + lifetime, + bounds, } )); } else if self.check_type() { @@ -4427,7 +4442,7 @@ impl<'a> Parser<'a> { span: lo.to(self.prev_span), bound_lifetimes: lifetime_defs, bounded_ty: ty, - bounds: bounds, + bounds, } )); // FIXME: Decide what should be used here, `=` or `==`. @@ -4437,7 +4452,7 @@ impl<'a> Parser<'a> { ast::WhereEqPredicate { span: lo.to(self.prev_span), lhs_ty: ty, - rhs_ty: rhs_ty, + rhs_ty, id: ast::DUMMY_NODE_ID, } )); @@ -4518,7 +4533,7 @@ impl<'a> Parser<'a> { Ok(P(FnDecl { inputs: args, output: ret_ty, - variadic: variadic + variadic, })) } @@ -4679,7 +4694,7 @@ impl<'a> Parser<'a> { Ok(P(FnDecl { inputs: inputs_captures, - output: output, + output, variadic: false })) } @@ -4694,12 +4709,12 @@ impl<'a> Parser<'a> { fn mk_item(&mut self, span: Span, ident: Ident, node: ItemKind, vis: Visibility, attrs: Vec<Attribute>) -> P<Item> { P(Item { - ident: ident, - attrs: attrs, + ident, + attrs, id: ast::DUMMY_NODE_ID, - node: node, - vis: vis, - span: span, + node, + vis, + span, tokens: None, }) } @@ -4799,10 +4814,10 @@ impl<'a> Parser<'a> { id: ast::DUMMY_NODE_ID, span: lo.to(self.prev_span), ident: name, - vis: vis, - defaultness: defaultness, - attrs: attrs, - node: node, + vis, + defaultness, + attrs, + node, tokens: None, }) } @@ -4896,11 +4911,11 @@ impl<'a> Parser<'a> { *at_end = true; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; Ok((ident, inner_attrs, ast::ImplItemKind::Method(ast::MethodSig { - generics: generics, - abi: abi, - unsafety: unsafety, - constness: constness, - decl: decl + generics, + abi, + unsafety, + constness, + decl, }, body))) } } @@ -5151,11 +5166,11 @@ impl<'a> Parser<'a> { let ty = p.parse_ty()?; Ok(StructField { span: lo.to(p.span), - vis: vis, + vis, ident: None, id: ast::DUMMY_NODE_ID, - ty: ty, - attrs: attrs, + ty, + attrs, }) })?; @@ -5281,7 +5296,7 @@ impl<'a> Parser<'a> { Ok(ast::Mod { inner: inner_lo.to(hi), - items: items + items, }) } @@ -5403,7 +5418,7 @@ impl<'a> Parser<'a> { ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, - result: result, + result, } } @@ -5418,7 +5433,7 @@ impl<'a> Parser<'a> { Some("mod.rs") => DirectoryOwnership::Owned, _ => DirectoryOwnership::UnownedViaMod(true), }, - path: path, + path, warn: false, }); } @@ -5509,12 +5524,12 @@ impl<'a> Parser<'a> { let hi = self.span; self.expect(&token::Semi)?; Ok(ast::ForeignItem { - ident: ident, - attrs: attrs, + ident, + attrs, node: ForeignItemKind::Fn(decl, generics), id: ast::DUMMY_NODE_ID, span: lo.to(hi), - vis: vis + vis, }) } @@ -5529,12 +5544,12 @@ impl<'a> Parser<'a> { let hi = self.span; self.expect(&token::Semi)?; Ok(ForeignItem { - ident: ident, - attrs: attrs, + ident, + attrs, node: ForeignItemKind::Static(ty, mutbl), id: ast::DUMMY_NODE_ID, span: lo.to(hi), - vis: vis + vis, }) } @@ -5596,7 +5611,7 @@ impl<'a> Parser<'a> { let prev_span = self.prev_span; let m = ast::ForeignMod { - abi: abi, + abi, items: foreign_items }; let invalid = keywords::Invalid.ident(); @@ -5647,7 +5662,7 @@ impl<'a> Parser<'a> { name: ident, attrs: variant_attrs, data: struct_def, - disr_expr: disr_expr, + disr_expr, }; variants.push(respan(vlo.to(self.prev_span), vr)); @@ -6162,7 +6177,7 @@ impl<'a> Parser<'a> { let rename = this.parse_rename()?; let node = ast::PathListItem_ { name: ident, - rename: rename, + rename, id: ast::DUMMY_NODE_ID }; Ok(respan(lo.to(this.prev_span), node)) diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 3ce9e9d07b3..5c4bf47a6db 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -246,7 +246,7 @@ pub fn mk_printer<'a>(out: Box<io::Write+'a>, linewidth: usize) -> Printer<'a> { let n: usize = 55 * linewidth; debug!("mk_printer {}", linewidth); Printer { - out: out, + out, buf_len: n, margin: linewidth as isize, space: linewidth as isize, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e9d11e73837..3be831e828c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -72,7 +72,7 @@ fn rust_printer<'a>(writer: Box<Write+'a>, ann: &'a PpAnn) -> State<'a> { literals: vec![].into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), - ann: ann, + ann, } } @@ -145,11 +145,11 @@ impl<'a> State<'a> { State { s: pp::mk_printer(out, DEFAULT_COLUMNS), cm: Some(cm), - comments: comments, + comments, literals: literals.unwrap_or_default().into_iter().peekable(), cur_cmnt: 0, boxes: Vec::new(), - ann: ann, + ann, } } } diff --git a/src/libsyntax/show_span.rs b/src/libsyntax/show_span.rs index 263a4f13c1b..8ab2ba71ec1 100644 --- a/src/libsyntax/show_span.rs +++ b/src/libsyntax/show_span.rs @@ -79,8 +79,8 @@ pub fn run(span_diagnostic: &errors::Handler, None => return }; let mut v = ShowSpanVisitor { - span_diagnostic: span_diagnostic, - mode: mode, + span_diagnostic, + mode, }; visit::walk_crate(&mut v, krate); } diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 430976e7d3c..8977d701e5a 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -72,18 +72,18 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin tokens: TokenStream::empty(), id: attr::mk_attr_id(), is_sugared_doc: false, - span: span, + span, }], 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::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP) }).collect(), - span: span, + span, })))), id: ast::DUMMY_NODE_ID, ident: keywords::Invalid.ident(), - span: span, + span, tokens: None, })); diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index c05e166e013..35dc9819529 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -56,13 +56,12 @@ struct Test { } struct TestCtxt<'a> { - sess: &'a ParseSess, span_diagnostic: &'a errors::Handler, path: Vec<Ident>, ext_cx: ExtCtxt<'a>, testfns: Vec<Test>, reexport_test_harness_main: Option<Symbol>, - is_test_crate: bool, + is_libtest: bool, ctxt: SyntaxContext, // top-level re-export submodule, filled out after folding is finished @@ -202,18 +201,18 @@ impl fold::Folder for EntryPointCleaner { allow_dead_code_item); ast::Item { - id: id, - ident: ident, + id, + ident, attrs: attrs.into_iter() .filter(|attr| { !attr.check_name("main") && !attr.check_name("start") }) .chain(iter::once(allow_dead_code)) .collect(), - node: node, - vis: vis, - span: span, - tokens: tokens, + node, + vis, + span, + tokens, } }), EntryPointType::None | @@ -243,7 +242,7 @@ fn mk_reexport_mod(cx: &mut TestCtxt, let reexport_mod = ast::Mod { inner: DUMMY_SP, - items: items, + items, }; let sym = Ident::with_empty_ctxt(Symbol::gensym("__test_reexports")); @@ -272,14 +271,15 @@ fn generate_test_harness(sess: &ParseSess, let krate = cleaner.fold_crate(krate); let mark = Mark::fresh(Mark::root()); + let mut cx: TestCtxt = TestCtxt { - sess: sess, span_diagnostic: sd, ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver), path: Vec::new(), testfns: Vec::new(), - reexport_test_harness_main: reexport_test_harness_main, - is_test_crate: is_test_crate(&krate), + reexport_test_harness_main, + // NB: doesn't consider the value of `--crate-name` passed on the command line. + is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false), toplevel_reexport: None, ctxt: SyntaxContext::empty().apply_mark(mark), }; @@ -296,7 +296,7 @@ fn generate_test_harness(sess: &ParseSess, }); TestHarnessGenerator { - cx: cx, + cx, tests: Vec::new(), tested_submods: Vec::new(), }.fold_crate(krate) @@ -454,7 +454,7 @@ mod __test { fn mk_std(cx: &TestCtxt) -> P<ast::Item> { let id_test = Ident::from_str("test"); let sp = ignored_span(cx, DUMMY_SP); - let (vi, vis, ident) = if cx.is_test_crate { + let (vi, vis, ident) = if cx.is_libtest { (ast::ItemKind::Use( P(nospan(ast::ViewPathSimple(id_test, path_node(vec![id_test]))))), @@ -464,10 +464,10 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> { }; P(ast::Item { id: ast::DUMMY_NODE_ID, - ident: ident, + ident, node: vi, attrs: vec![], - vis: vis, + vis, span: sp, tokens: None, }) @@ -608,13 +608,6 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> { test_descs) } -fn is_test_crate(krate: &ast::Crate) -> bool { - match attr::find_crate_name(&krate.attrs) { - Some(s) if "test" == s.as_str() => true, - _ => false - } -} - fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> { debug!("building test vector from {} tests", cx.testfns.len()); diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index bdcec26cb83..1c470240288 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -10,7 +10,6 @@ crate-type = ["dylib"] [dependencies] fmt_macros = { path = "../libfmt_macros" } -log = "0.3" proc_macro = { path = "../libproc_macro" } rustc_errors = { path = "../librustc_errors" } syntax = { path = "../libsyntax" } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 923e8072f43..3742fb8c804 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -152,8 +152,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, outputs.push(ast::InlineAsmOutput { constraint: output.unwrap_or(constraint), expr: out, - is_rw: is_rw, - is_indirect: is_indirect, + is_rw, + is_indirect, }); } } @@ -242,14 +242,14 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, node: ast::ExprKind::InlineAsm(P(ast::InlineAsm { - asm: asm, + asm, asm_str_style: asm_str_style.unwrap(), - outputs: outputs, - inputs: inputs, + outputs, + inputs, clobbers: clobs, - volatile: volatile, - alignstack: alignstack, - dialect: dialect, + volatile, + alignstack, + dialect, ctxt: cx.backtrace(), })), span: sp, diff --git a/src/libsyntax_ext/deriving/bounds.rs b/src/libsyntax_ext/deriving/bounds.rs index efb2fe5eb3b..0bc802283fb 100644 --- a/src/libsyntax_ext/deriving/bounds.rs +++ b/src/libsyntax_ext/deriving/bounds.rs @@ -34,9 +34,9 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt, let path = Path::new(v); let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), - path: path, + path, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 35a2a2513f4..71dd7abfab0 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -77,7 +77,7 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt, let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: path_std!(cx, core::clone::Clone), additional_bounds: bounds, diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index eef21492deb..0b57beeae85 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -28,7 +28,7 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt, let doc = cx.meta_list(span, Symbol::intern("doc"), vec![hidden]); let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)]; let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: path_std!(cx, core::cmp::Eq), additional_bounds: Vec::new(), diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 9fc3d997585..9b057aacece 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -26,7 +26,7 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt, let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: path_std!(cx, core::cmp::Ord), additional_bounds: Vec::new(), diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index f2a050ce971..e635c6bebcd 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -91,14 +91,14 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt, } let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: path_std!(cx, core::cmp::PartialEq), additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, supports_unions: false, - methods: methods, + methods, associated_types: Vec::new(), }; trait_def.expand(cx, mitem, item, push) diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index ce4d549d696..e7e1c108760 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -59,7 +59,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, generics: LifetimeBounds::empty(), explicit_self: borrowed_explicit_self(), args: vec![borrowed_self()], - ret_ty: ret_ty, + ret_ty, attributes: attrs, is_unsafe: false, unify_fieldless_variants: true, @@ -82,14 +82,14 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt, }; let trait_def = TraitDef { - span: span, + span, attributes: vec![], path: path_std!(cx, core::cmp::PartialOrd), additional_bounds: vec![], generics: LifetimeBounds::empty(), is_unsafe: false, supports_unions: false, - methods: methods, + methods, associated_types: Vec::new(), }; trait_def.expand(cx, mitem, item, push) diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 38ed596098b..54d71dd4b48 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -28,7 +28,7 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt, Borrowed(None, ast::Mutability::Mutable)); let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: path_std!(cx, core::fmt::Debug), additional_bounds: Vec::new(), diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index 498f2348b80..517221af1d4 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -57,7 +57,7 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt, let typaram = &*deriving::hygienic_type_parameter(item, "__D"); let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: Path::new_(vec![krate, "Decodable"], None, vec![], true), additional_bounds: Vec::new(), diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index 69391f48c22..0c8e3c39395 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -26,7 +26,7 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, let inline = cx.meta_word(span, Symbol::intern("inline")); let attrs = vec![cx.attribute(span, inline)]; let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: path_std!(cx, core::default::Default), additional_bounds: Vec::new(), diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 1e19cd99419..c2c862f043f 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -138,7 +138,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt, let typaram = &*deriving::hygienic_type_parameter(item, "__S"); let trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), path: Path::new_(vec![krate, "Encodable"], None, vec![], true), additional_bounds: Vec::new(), diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 3cbc7938bde..a0dd2975ca0 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -23,7 +23,7 @@ //! and lifetimes for methods.) //! - Additional bounds on the type parameters (`TraitDef.additional_bounds`) //! -//! The most important thing for implementers is the `Substructure` and +//! The most important thing for implementors is the `Substructure` and //! `SubstructureFields` objects. The latter groups 5 possibilities of the //! arguments: //! @@ -381,10 +381,10 @@ fn find_type_parameters(ty: &ast::Ty, } let mut visitor = Visitor { - ty_param_names: ty_param_names, + ty_param_names, types: Vec::new(), - span: span, - cx: cx, + span, + cx, }; visit::Visitor::visit_ty(&mut visitor, ty); @@ -499,7 +499,7 @@ impl<'a> TraitDef<'a> { ast::ImplItem { id: ast::DUMMY_NODE_ID, span: self.span, - ident: ident, + ident, vis: ast::Visibility::Inherited, defaultness: ast::Defaultness::Final, attrs: Vec::new(), @@ -596,7 +596,7 @@ impl<'a> TraitDef<'a> { span: self.span, bound_lifetimes: vec![], bounded_ty: ty, - bounds: bounds, + bounds, }; let predicate = ast::WherePredicate::BoundPredicate(predicate); @@ -606,10 +606,10 @@ impl<'a> TraitDef<'a> { } let trait_generics = Generics { - lifetimes: lifetimes, - ty_params: ty_params, - where_clause: where_clause, - span: span, + lifetimes, + ty_params, + where_clause, + span, }; // Create the reference to the trait. @@ -807,11 +807,11 @@ impl<'a> MethodDef<'a> { fields: &SubstructureFields) -> P<Expr> { let substructure = Substructure { - type_ident: type_ident, + type_ident, method_ident: cx.ident_of(self.name), - self_args: self_args, - nonself_args: nonself_args, - fields: fields, + self_args, + nonself_args, + fields, }; let mut f = self.combine_substructure.borrow_mut(); let f: &mut CombineSubstructureFunc = &mut *f; @@ -924,8 +924,8 @@ impl<'a> MethodDef<'a> { ident: method_ident, node: ast::ImplItemKind::Method(ast::MethodSig { generics: fn_generics, - abi: abi, - unsafety: unsafety, + abi, + unsafety, constness: dummy_spanned(ast::Constness::NotConst), decl: fn_decl, @@ -985,7 +985,7 @@ impl<'a> MethodDef<'a> { let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect(); first_field.map(|(span, opt_id, field, attrs)| { FieldInfo { - span: span, + span, name: opt_id, self_: field, other: other_fields.iter_mut() @@ -995,7 +995,7 @@ impl<'a> MethodDef<'a> { } }) .collect(), - attrs: attrs, + attrs, } }) .collect() @@ -1246,7 +1246,7 @@ impl<'a> MethodDef<'a> { name: opt_ident, self_: self_getter_expr, other: others, - attrs: attrs, + attrs, } }).collect::<Vec<FieldInfo>>(); @@ -1553,7 +1553,7 @@ impl<'a> TraitDef<'a> { span: Span { ctxt: self.span.ctxt, ..pat.span }, node: ast::FieldPat { ident: ident.unwrap(), - pat: pat, + pat, is_shorthand: false, attrs: ast::ThinVec::new(), }, diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index f5ac1743920..47b5f40832a 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -55,10 +55,10 @@ impl<'a> Path<'a> { global: bool) -> Path<'r> { Path { - path: path, - lifetime: lifetime, - params: params, - global: global, + path, + lifetime, + params, + global, } } @@ -211,14 +211,14 @@ fn mk_ty_param(cx: &ExtCtxt, fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>, span: Span) -> Generics { Generics { - lifetimes: lifetimes, - ty_params: ty_params, + lifetimes, + ty_params, where_clause: ast::WhereClause { id: ast::DUMMY_NODE_ID, predicates: Vec::new(), - span: span, + span, }, - span: span, + span, } } diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index a341c21d0a1..6c78eea186d 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -30,9 +30,9 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt, let arg = Path::new_local(typaram); let hash_trait_def = TraitDef { - span: span, + span, attributes: Vec::new(), - path: path, + path, additional_bounds: Vec::new(), generics: LifetimeBounds::empty(), is_unsafe: false, diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 00dcfc7a587..cd706f14a68 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -173,6 +173,6 @@ fn call_intrinsic(cx: &ExtCtxt, stmts: vec![cx.stmt_expr(call)], id: ast::DUMMY_NODE_ID, rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated), - span: span, + span, })) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 16b06424c92..764cedfcf20 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -709,11 +709,11 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, }; let mut cx = Context { - ecx: ecx, - args: args, - arg_types: arg_types, - arg_unique_types: arg_unique_types, - names: names, + ecx, + args, + arg_types, + arg_unique_types, + names, curarg: 0, arg_index_map: Vec::new(), count_args: Vec::new(), @@ -724,7 +724,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, pieces: Vec::new(), str_pieces: Vec::new(), all_pieces_simple: true, - macsp: macsp, + macsp, fmtsp: fmt.span, }; diff --git a/src/libsyntax_ext/format_foreign.rs b/src/libsyntax_ext/format_foreign.rs index 3c802e8334d..99dae29d606 100644 --- a/src/libsyntax_ext/format_foreign.rs +++ b/src/libsyntax_ext/format_foreign.rs @@ -265,7 +265,7 @@ pub mod printf { /// Returns an iterator over all substitutions in a given string. pub fn iter_subs(s: &str) -> Substitutions { Substitutions { - s: s, + s, } } @@ -553,12 +553,12 @@ pub mod printf { let f = Format { span: start.slice_between(end).unwrap(), - parameter: parameter, - flags: flags, - width: width, - precision: precision, - length: length, - type_: type_, + parameter, + flags, + width, + precision, + length, + type_, }; Some((Substitution::Format(f), end.slice_after())) } @@ -776,7 +776,7 @@ pub mod shell { /// Returns an iterator over all substitutions in a given string. pub fn iter_subs(s: &str) -> Substitutions { Substitutions { - s: s, + s, } } @@ -933,7 +933,7 @@ mod strcursor { impl<'a> StrCursor<'a> { pub fn new_at_start(s: &'a str) -> StrCursor<'a> { StrCursor { - s: s, + s, at: 0, } } diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 8b0bb8cb891..81226ba599a 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -56,7 +56,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt, attrs: Vec::new(), id: ast::DUMMY_NODE_ID, node: ast::ItemKind::GlobalAsm(P(ast::GlobalAsm { - asm: asm, + asm, ctxt: cx.backtrace(), })), vis: ast::Visibility::Inherited, diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 439538a8b5e..42bbb4ae0cb 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -10,9 +10,6 @@ //! Syntax extensions in the Rust compiler. -#![crate_name = "syntax_ext"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -21,7 +18,6 @@ #![feature(proc_macro_internals)] extern crate fmt_macros; -extern crate log; #[macro_use] extern crate syntax; extern crate syntax_pos; diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index 700386f68fe..a8a54a97ac3 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -69,9 +69,9 @@ pub fn modify(sess: &ParseSess, attr_macros: Vec::new(), bang_macros: Vec::new(), in_root: true, - handler: handler, - is_proc_macro_crate: is_proc_macro_crate, - is_test_crate: is_test_crate, + handler, + is_proc_macro_crate, + is_test_crate, }; visit::walk_crate(&mut collect, &krate); (collect.derives, collect.attr_macros, collect.bang_macros) @@ -183,7 +183,7 @@ impl<'a> CollectProcMacros<'a> { if self.in_root && item.vis == ast::Visibility::Public { self.derives.push(ProcMacroDerive { span: item.span, - trait_name: trait_name, + trait_name, function_name: item.ident, attrs: proc_attrs, }); diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 514cc26666e..919804d7efd 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -161,7 +161,7 @@ impl SyntaxContext { syntax_contexts.push(SyntaxContextData { outer_mark: mark, prev_ctxt: self, - modern: modern, + modern, }); SyntaxContext(syntax_contexts.len() as u32 - 1) }) @@ -323,8 +323,8 @@ impl NameAndSpan { pub fn name(&self) -> Symbol { match self.format { ExpnFormat::MacroAttribute(s) | - ExpnFormat::MacroBang(s) | - ExpnFormat::CompilerDesugaring(s) => s, + ExpnFormat::MacroBang(s) => s, + ExpnFormat::CompilerDesugaring(ref kind) => kind.as_symbol(), } } } @@ -337,7 +337,27 @@ pub enum ExpnFormat { /// e.g. `format!()` MacroBang(Symbol), /// Desugaring done by the compiler during HIR lowering. - CompilerDesugaring(Symbol) + CompilerDesugaring(CompilerDesugaringKind) +} + +/// The kind of compiler desugaring. +#[derive(Clone, Hash, Debug, PartialEq, Eq)] +pub enum CompilerDesugaringKind { + BackArrow, + DotFill, + QuestionMark, +} + +impl CompilerDesugaringKind { + pub fn as_symbol(&self) -> Symbol { + use CompilerDesugaringKind::*; + let s = match *self { + BackArrow => "<-", + DotFill => "...", + QuestionMark => "?", + }; + Symbol::intern(s) + } } impl Encodable for SyntaxContext { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index e162bc26412..d34dcfa3ed3 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -14,9 +14,6 @@ //! //! This API is completely unstable and subject to change. -#![crate_name = "syntax_pos"] -#![crate_type = "dylib"] -#![crate_type = "rlib"] #![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/")] @@ -47,7 +44,7 @@ extern crate serialize; extern crate serialize as rustc_serialize; // used by deriving pub mod hygiene; -pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan}; +pub use hygiene::{SyntaxContext, ExpnInfo, ExpnFormat, NameAndSpan, CompilerDesugaringKind}; pub mod symbol; @@ -153,6 +150,17 @@ impl Span { } } + /// Check if this span arises from a compiler desugaring of kind `kind`. + pub fn is_compiler_desugaring(&self, kind: CompilerDesugaringKind) -> bool { + match self.ctxt.outer().expn_info() { + Some(info) => match info.callee.format { + ExpnFormat::CompilerDesugaring(k) => k == kind, + _ => false, + }, + None => false, + } + } + /// Check if a span is "internal" to a macro in which `unsafe` /// can be used without triggering the `unsafe_code` lint // (that is, a macro marked with `#[allow_internal_unsafe]`). @@ -184,8 +192,8 @@ impl Span { if !info.call_site.source_equal(&prev_span) { result.push(MacroBacktrace { call_site: info.call_site, - macro_decl_name: macro_decl_name, - def_site_span: def_site_span, + macro_decl_name, + def_site_span, }); } @@ -358,7 +366,7 @@ impl MultiSpan { for &(span, ref label) in &self.span_labels { span_labels.push(SpanLabel { - span: span, + span, is_primary: is_primary(span), label: Some(label.clone()) }); @@ -367,7 +375,7 @@ impl MultiSpan { for &span in &self.primary_spans { if !span_labels.iter().any(|sl| sl.span == span) { span_labels.push(SpanLabel { - span: span, + span, is_primary: true, label: None }); @@ -556,16 +564,16 @@ impl Decodable for FileMap { let multibyte_chars: Vec<MultiByteChar> = d.read_struct_field("multibyte_chars", 5, |d| Decodable::decode(d))?; Ok(FileMap { - name: name, - name_was_remapped: name_was_remapped, + name, + name_was_remapped, // `crate_of_origin` has to be set by the importer. // This value matches up with rustc::hir::def_id::INVALID_CRATE. // That constant is not available here unfortunately :( crate_of_origin: ::std::u32::MAX - 1, - start_pos: start_pos, - end_pos: end_pos, + start_pos, + end_pos, src: None, - src_hash: src_hash, + src_hash, external_src: RefCell::new(ExternalSource::AbsentOk), lines: RefCell::new(lines), multibyte_chars: RefCell::new(multibyte_chars) @@ -594,13 +602,13 @@ impl FileMap { let end_pos = start_pos.to_usize() + src.len(); FileMap { - name: name, - name_was_remapped: name_was_remapped, + name, + name_was_remapped, crate_of_origin: 0, src: Some(Rc::new(src)), - src_hash: src_hash, + src_hash, external_src: RefCell::new(ExternalSource::Unneeded), - start_pos: start_pos, + start_pos, end_pos: Pos::from_usize(end_pos), lines: RefCell::new(Vec::new()), multibyte_chars: RefCell::new(Vec::new()), @@ -687,8 +695,8 @@ impl FileMap { pub fn record_multibyte_char(&self, pos: BytePos, bytes: usize) { assert!(bytes >=2 && bytes <= 4); let mbc = MultiByteChar { - pos: pos, - bytes: bytes, + pos, + bytes, }; self.multibyte_chars.borrow_mut().push(mbc); } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 4864e4581fa..ad0e582b1c3 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -40,9 +40,6 @@ //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx //! [ti]: https://en.wikipedia.org/wiki/Terminfo -#![crate_name = "term"] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index 68cfc7033ef..c5e68eed407 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -231,7 +231,7 @@ impl<T: Write + Send> TerminfoTerminal<T> { }; TerminfoTerminal { - out: out, + out, ti: terminfo, num_colors: nc, } diff --git a/src/libterm/terminfo/parser/compiled.rs b/src/libterm/terminfo/parser/compiled.rs index 8d1ba378521..0cdea64db8b 100644 --- a/src/libterm/terminfo/parser/compiled.rs +++ b/src/libterm/terminfo/parser/compiled.rs @@ -337,8 +337,8 @@ pub fn msys_terminfo() -> TermInfo { TermInfo { names: vec!["cygwin".to_string()], // msys is a fork of an older cygwin version bools: HashMap::new(), - numbers: numbers, - strings: strings, + numbers, + strings, } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index bf71b11fc77..642eb285564 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -23,10 +23,11 @@ // running tests while providing a base that other test frameworks may // build off of. +// NB: this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to +// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by +// cargo) to detect this crate. #![crate_name = "test"] #![unstable(feature = "test", issue = "27812")] -#![crate_type = "rlib"] -#![crate_type = "dylib"] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/", @@ -34,12 +35,14 @@ #![deny(warnings)] #![feature(asm)] -#![feature(libc)] +#![cfg_attr(unix, feature(libc))] #![feature(set_stdio)] #![feature(panic_unwind)] +#![feature(staged_api)] extern crate getopts; extern crate term; +#[cfg(unix)] extern crate libc; extern crate panic_unwind; @@ -235,8 +238,8 @@ pub struct Metric { impl Metric { pub fn new(value: f64, noise: f64) -> Metric { Metric { - value: value, - noise: noise, + value, + noise, } } } @@ -492,17 +495,17 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> { }; let test_opts = TestOpts { - list: list, - filter: filter, + list, + filter, filter_exact: exact, - run_ignored: run_ignored, - run_tests: run_tests, - bench_benchmarks: bench_benchmarks, - logfile: logfile, - nocapture: nocapture, - color: color, - quiet: quiet, - test_threads: test_threads, + run_ignored, + run_tests, + bench_benchmarks, + logfile, + nocapture, + color, + quiet, + test_threads, skip: matches.opt_strs("skip"), options: Options::new(), }; @@ -565,8 +568,8 @@ impl<T: Write> ConsoleTestState<T> { }; Ok(ConsoleTestState { - out: out, - log_out: log_out, + out, + log_out, use_color: use_color(opts), quiet: opts.quiet, total: 0, @@ -1330,7 +1333,7 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA let TestDescAndFn {desc, testfn} = test; Some(TestDescAndFn { desc: TestDesc { ignore: false, ..desc }, - testfn: testfn, + testfn, }) } else { None @@ -1367,7 +1370,7 @@ pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAnd }; TestDescAndFn { desc: x.desc, - testfn: testfn, + testfn, } }).collect() } @@ -1527,8 +1530,8 @@ impl MetricMap { /// negative direction represents a regression. pub fn insert_metric(&mut self, name: &str, value: f64, noise: f64) { let m = Metric { - value: value, - noise: noise, + value, + noise, }; let MetricMap(ref mut map) = *self; map.insert(name.to_owned(), m); @@ -1689,7 +1692,7 @@ pub mod bench { let mb_s = bs.bytes * 1000 / ns_iter; BenchSamples { - ns_iter_summ: ns_iter_summ, + ns_iter_summ, mb_s: mb_s as usize, } } diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index be9aa6c5d40..dc1464b905b 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -16,7 +16,7 @@ fn main() { if target.contains("linux") { if target.contains("musl") && !target.contains("mips") { - println!("cargo:rustc-link-lib=static=unwind"); + // musl is handled in lib.rs } else if !target.contains("android") { println!("cargo:rustc-link-lib=gcc_s"); } @@ -41,5 +41,7 @@ fn main() { println!("cargo:rustc-link-lib=unwind"); } else if target.contains("haiku") { println!("cargo:rustc-link-lib=gcc_s"); + } else if target.contains("redox") { + println!("cargo:rustc-link-lib=gcc"); } } diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index d4d52322ada..461b49aa363 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -9,12 +9,11 @@ // except according to those terms. #![no_std] -#![crate_name = "unwind"] -#![crate_type = "rlib"] #![unstable(feature = "panic_unwind", issue = "32837")] #![deny(warnings)] #![feature(cfg_target_vendor)] +#![feature(link_cfg)] #![feature(staged_api)] #![feature(unwind_attributes)] #![feature(static_nobundle)] @@ -28,3 +27,8 @@ extern crate libc; mod libunwind; #[cfg(not(target_env = "msvc"))] pub use libunwind::*; + +#[cfg(all(target_env = "musl", not(target_arch = "mips")))] +#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))] +#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] +extern {} diff --git a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs index edbb77fe390..bb292e2e52a 100644 --- a/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs +++ b/src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs @@ -15,6 +15,7 @@ // libsyntax is not compiled for it. #![deny(plugin_as_library)] +#![allow(unused_extern_crates)] extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library diff --git a/src/test/compile-fail/E0254.rs b/src/test/compile-fail/E0254.rs index 89227f6b010..996a6b97cd9 100644 --- a/src/test/compile-fail/E0254.rs +++ b/src/test/compile-fail/E0254.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(alloc)] +#![allow(unused_extern_crates)] extern crate alloc; //~^ NOTE previous import of the extern crate `alloc` here diff --git a/src/test/compile-fail/E0259.rs b/src/test/compile-fail/E0259.rs index 60bcd2ae076..c285c4d9e00 100644 --- a/src/test/compile-fail/E0259.rs +++ b/src/test/compile-fail/E0259.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(alloc, libc)] +#![allow(unused_extern_crates)] extern crate alloc; //~^ NOTE previous import of the extern crate `alloc` here diff --git a/src/test/compile-fail/E0260.rs b/src/test/compile-fail/E0260.rs index 5e802bbbe3d..ad8888e58f7 100644 --- a/src/test/compile-fail/E0260.rs +++ b/src/test/compile-fail/E0260.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(alloc)] +#![allow(unused_extern_crates)] extern crate alloc; //~^ NOTE previous import of the extern crate `alloc` here diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index 1f9dfdb1847..847393ba2b8 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -22,5 +22,5 @@ impl Foo for isize { pub fn main() { let x: isize = Foo::<A=usize>::bar(); - //~^ ERROR unexpected binding of associated item in expression path + //~^ ERROR associated type bindings are not allowed here } diff --git a/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs b/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs new file mode 100644 index 00000000000..fc4bca865c9 --- /dev/null +++ b/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs @@ -0,0 +1,9 @@ +// 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. diff --git a/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs b/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs index fbb3824cd40..f7514df800d 100644 --- a/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs +++ b/src/test/compile-fail/borrowck/borrowck-borrow-from-temporary.rs @@ -11,10 +11,12 @@ // Test lifetimes are linked properly when we take reference // to interior. +fn id<T>(x: T) -> T { x } + struct Foo(isize); fn foo<'a>() -> &'a isize { - let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough + let &Foo(ref x) = &id(Foo(3)); //~ ERROR borrowed value does not live long enough x } diff --git a/src/test/compile-fail/enable-unstable-lib-feature.rs b/src/test/compile-fail/enable-unstable-lib-feature.rs index c65b2366bf1..bc9e2345f0e 100644 --- a/src/test/compile-fail/enable-unstable-lib-feature.rs +++ b/src/test/compile-fail/enable-unstable-lib-feature.rs @@ -16,6 +16,7 @@ #![deny(non_snake_case)] // To trigger a hard error // Shouldn't generate a warning about unstable features +#[allow(unused_extern_crates)] extern crate stability_cfg2; pub fn BOGUS() { } //~ ERROR diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/compile-fail/feature-gate-fn_must_use.rs new file mode 100644 index 00000000000..2dd6b904072 --- /dev/null +++ b/src/test/compile-fail/feature-gate-fn_must_use.rs @@ -0,0 +1,31 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(rustc_attrs)] + +struct MyStruct; + +impl MyStruct { + #[must_use] + fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental +} + +#[must_use] +fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental + + +// Feature gates are tidy-required to have a specially named (or +// comment-annotated) compile-fail test (which MUST fail), but for +// backwards-compatibility reasons, we want `#[must_use]` on functions to be +// compilable even if the `fn_must_use` feature is absent, thus necessitating +// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this +// dilemma until a superior solution can be devised. +#[rustc_error] +fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 29a2b0609fc..204190d64ac 100644 --- a/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -680,6 +680,7 @@ mod must_use { mod inner { #![must_use="1400"] } #[must_use = "1400"] fn f() { } + //~^ WARN `#[must_use]` on functions is experimental #[must_use = "1400"] struct S; diff --git a/src/test/compile-fail/foreign-fn-return-lifetime.rs b/src/test/compile-fail/foreign-fn-return-lifetime.rs new file mode 100644 index 00000000000..da77066150c --- /dev/null +++ b/src/test/compile-fail/foreign-fn-return-lifetime.rs @@ -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. + +extern "C" { + fn g(_: &u8) -> &u8; // OK + fn f() -> &u8; //~ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/src/test/compile-fail/issue-11493.rs b/src/test/compile-fail/issue-11493.rs index 333ff7118d4..3045c06ca4c 100644 --- a/src/test/compile-fail/issue-11493.rs +++ b/src/test/compile-fail/issue-11493.rs @@ -10,7 +10,9 @@ // This file must never have a trailing newline +fn id<T>(x: T) -> T { x } + fn main() { let x = Some(3); - let y = x.as_ref().unwrap_or(&5); //~ ERROR: borrowed value does not live long enough + let y = x.as_ref().unwrap_or(&id(5)); //~ ERROR: borrowed value does not live long enough } diff --git a/src/test/compile-fail/issue-12567.rs b/src/test/compile-fail/issue-12567.rs index 15d9a318d29..30cdd07b399 100644 --- a/src/test/compile-fail/issue-12567.rs +++ b/src/test/compile-fail/issue-12567.rs @@ -15,12 +15,12 @@ fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { (&[], &[]) => println!("both empty"), (&[], &[hd, ..]) | (&[hd, ..], &[]) => println!("one empty"), - //~^^ ERROR: cannot move out of type `[T]`, a non-copy array - //~^^^ ERROR: cannot move out of type `[T]`, a non-copy array + //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice + //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice (&[hd1, ..], &[hd2, ..]) => println!("both nonempty"), - //~^^ ERROR: cannot move out of type `[T]`, a non-copy array - //~^^^ ERROR: cannot move out of type `[T]`, a non-copy array + //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice + //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice } } diff --git a/src/test/compile-fail/issue-17545.rs b/src/test/compile-fail/issue-17545.rs index 45bc5ee07a5..9264305e6ea 100644 --- a/src/test/compile-fail/issue-17545.rs +++ b/src/test/compile-fail/issue-17545.rs @@ -10,9 +10,11 @@ #![feature(fn_traits)] +fn id<T>(x: T) -> T { x } + pub fn foo<'a, F: Fn(&'a ())>(bar: F) { bar.call(( - &(), //~ ERROR borrowed value does not live long enough + &id(()), //~ ERROR borrowed value does not live long enough )); } fn main() {} diff --git a/src/test/compile-fail/issue-17718-constants-not-static.rs b/src/test/compile-fail/issue-17718-constants-not-static.rs index db56d2c6cf3..9b7ed463499 100644 --- a/src/test/compile-fail/issue-17718-constants-not-static.rs +++ b/src/test/compile-fail/issue-17718-constants-not-static.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn id<T>(x: T) -> T { x } + const FOO: usize = 3; -fn foo() -> &'static usize { &FOO } +fn foo() -> &'static usize { &id(FOO) } //~^ ERROR: borrowed value does not live long enough fn main() { diff --git a/src/test/compile-fail/issue-27592.rs b/src/test/compile-fail/issue-27592.rs index ccf5eabc111..731d4fb2bf6 100644 --- a/src/test/compile-fail/issue-27592.rs +++ b/src/test/compile-fail/issue-27592.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Regression test for issue #27591. +// Regression test for issue #27592. fn write<'a, F: ::std::ops::FnOnce()->::std::fmt::Arguments<'a> + 'a>(fcn: F) { use std::fmt::Write; @@ -23,7 +23,7 @@ impl ::std::fmt::Write for Stream { } fn main() { - write(|| format_args!("{}", "Hello world")); + write(|| format_args!("{}", String::from("Hello world"))); //~^ ERROR borrowed value does not live long enough //~| ERROR borrowed value does not live long enough } diff --git a/src/test/compile-fail/issue-32995.rs b/src/test/compile-fail/issue-32995.rs index 4b7f82943ba..ffbd0c0c22a 100644 --- a/src/test/compile-fail/issue-32995.rs +++ b/src/test/compile-fail/issue-32995.rs @@ -19,15 +19,11 @@ fn main() { //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - macro_rules! pathexpr { - ($p:path) => { $p } - } - - let p = pathexpr!(::std::str()::from_utf8)(b"foo").unwrap(); + let p = ::std::str::()::from_utf8(b"foo").unwrap(); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted - let p = pathexpr!(::std::str::from_utf8())(b"foo").unwrap(); + let p = ::std::str::from_utf8::()(b"foo").unwrap(); //~^ ERROR parenthesized parameters may only be used with a trait //~| WARN previously accepted diff --git a/src/test/compile-fail/issue-36116.rs b/src/test/compile-fail/issue-36116.rs index 737955b2ff3..3afbfa61984 100644 --- a/src/test/compile-fail/issue-36116.rs +++ b/src/test/compile-fail/issue-36116.rs @@ -8,16 +8,30 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Unnecessary path disambiguator is ok + +#![feature(rustc_attrs)] +#![allow(unused)] + +macro_rules! m { + ($p: path) => { + let _ = $p(0); + let _: $p; + } +} + struct Foo<T> { _a: T, } -fn main() { - let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>); - //~^ ERROR unnecessary path disambiguator - //~| NOTE try removing `::` +struct S<T>(T); + +fn f() { + let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>); //~ WARN unnecessary path disambiguator + let g: Foo::<i32> = Foo { _a: 42 }; //~ WARN unnecessary path disambiguator - let g: Foo::<i32> = Foo { _a: 42 }; - //~^ ERROR unnecessary path disambiguator - //~| NOTE try removing `::` + m!(S::<u8>); // OK, no warning } + +#[rustc_error] +fn main() {} //~ ERROR compilation successful diff --git a/src/test/compile-fail/issue-36881.rs b/src/test/compile-fail/issue-36881.rs index e05dc066199..0f5aa24926b 100644 --- a/src/test/compile-fail/issue-36881.rs +++ b/src/test/compile-fail/issue-36881.rs @@ -11,6 +11,7 @@ // aux-build:issue-36881-aux.rs fn main() { + #[allow(unused_extern_crates)] extern crate issue_36881_aux; use issue_36881_aux::Foo; //~ ERROR unresolved import } diff --git a/src/test/compile-fail/issue-43424.rs b/src/test/compile-fail/issue-43424.rs new file mode 100644 index 00000000000..431fc8a5aa2 --- /dev/null +++ b/src/test/compile-fail/issue-43424.rs @@ -0,0 +1,22 @@ +// 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. + +#![allow(unused)] + +macro_rules! m { + ($attr_path: path) => { + #[$attr_path] + fn f() {} + } +} + +m!(inline<u8>); //~ ERROR: unexpected generic arguments in path + +fn main() {} diff --git a/src/test/compile-fail/issue-43431.rs b/src/test/compile-fail/issue-43431.rs new file mode 100644 index 00000000000..e9f62152888 --- /dev/null +++ b/src/test/compile-fail/issue-43431.rs @@ -0,0 +1,24 @@ +// 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(fn_traits)] + +trait CallSingle<A, B> { + fn call(&self, a: A) -> B where Self: Fn(A) -> B; +} + +impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F { + fn call(&self, a: A) -> B { + <Self as Fn(A) -> B>::call(self, (a,)) + //~^ ERROR associated type bindings are not allowed here + } +} + +fn main() {} diff --git a/src/test/compile-fail/issue-43784-associated-type.rs b/src/test/compile-fail/issue-43784-associated-type.rs new file mode 100644 index 00000000000..94b5c0034a7 --- /dev/null +++ b/src/test/compile-fail/issue-43784-associated-type.rs @@ -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. + +pub trait Partial<X: ?Sized>: Copy { +} + +pub trait Complete { + type Assoc: Partial<Self>; +} + +impl<T> Partial<T> for T::Assoc where + T: Complete +{ +} + +impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied + type Assoc = T; +} diff --git a/src/test/compile-fail/issue-43784-supertrait.rs b/src/test/compile-fail/issue-43784-supertrait.rs new file mode 100644 index 00000000000..e70df113da3 --- /dev/null +++ b/src/test/compile-fail/issue-43784-supertrait.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Partial: Copy { +} + +pub trait Complete: Partial { +} + +impl<T> Partial for T where T: Complete {} +impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied diff --git a/src/test/compile-fail/lint-stability-deprecated.rs b/src/test/compile-fail/lint-stability-deprecated.rs index 8443518b3f5..9bc2c021904 100644 --- a/src/test/compile-fail/lint-stability-deprecated.rs +++ b/src/test/compile-fail/lint-stability-deprecated.rs @@ -14,7 +14,7 @@ // aux-build:stability_cfg2.rs #![warn(deprecated)] -#![allow(dead_code)] +#![allow(dead_code, unused_extern_crates)] #![feature(staged_api, test_feature, rustc_attrs)] #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/compile-fail/lint-unused-extern-crate.rs b/src/test/compile-fail/lint-unused-extern-crate.rs index b12ef6277bb..a3cfa134983 100644 --- a/src/test/compile-fail/lint-unused-extern-crate.rs +++ b/src/test/compile-fail/lint-unused-extern-crate.rs @@ -12,12 +12,15 @@ // aux-build:lint_unused_extern_crate2.rs // aux-build:lint_unused_extern_crate3.rs // aux-build:lint_unused_extern_crate4.rs +// aux-build:lint_unused_extern_crate5.rs #![deny(unused_extern_crates)] #![allow(unused_variables)] #![allow(deprecated)] -extern crate lint_unused_extern_crate4; //~ ERROR: unused extern crate +extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate + +pub extern crate lint_unused_extern_crate4; // no error, it is reexported extern crate lint_unused_extern_crate3; // no error, it is used diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs index ea2dfca0714..a2778a83130 100644 --- a/src/test/compile-fail/macro-reexport-malformed-1.rs +++ b/src/test/compile-fail/macro-reexport-malformed-1.rs @@ -11,5 +11,6 @@ #![no_std] #![feature(macro_reexport)] +#[allow(unused_extern_crates)] #[macro_reexport] //~ ERROR bad macro reexport extern crate std; diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs index 844955fb7e6..c5af9e3799d 100644 --- a/src/test/compile-fail/macro-reexport-malformed-2.rs +++ b/src/test/compile-fail/macro-reexport-malformed-2.rs @@ -11,5 +11,6 @@ #![no_std] #![feature(macro_reexport)] +#[allow(unused_extern_crates)] #[macro_reexport="foo"] //~ ERROR bad macro reexport extern crate std; diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs index 381c22854e6..d72d1ee004e 100644 --- a/src/test/compile-fail/macro-reexport-malformed-3.rs +++ b/src/test/compile-fail/macro-reexport-malformed-3.rs @@ -11,5 +11,6 @@ #![no_std] #![feature(macro_reexport)] +#[allow(unused_extern_crates)] #[macro_reexport(foo="bar")] //~ ERROR bad macro reexport extern crate std; diff --git a/src/test/compile-fail/macro-use-bad-args-1.rs b/src/test/compile-fail/macro-use-bad-args-1.rs index 39c09c69779..a07cc834411 100644 --- a/src/test/compile-fail/macro-use-bad-args-1.rs +++ b/src/test/compile-fail/macro-use-bad-args-1.rs @@ -10,5 +10,6 @@ #![no_std] +#[allow(unused_extern_crates)] #[macro_use(foo(bar))] //~ ERROR bad macro import extern crate std; diff --git a/src/test/compile-fail/macro-use-bad-args-2.rs b/src/test/compile-fail/macro-use-bad-args-2.rs index 11a0108b99b..89004f16897 100644 --- a/src/test/compile-fail/macro-use-bad-args-2.rs +++ b/src/test/compile-fail/macro-use-bad-args-2.rs @@ -10,5 +10,6 @@ #![no_std] +#[allow(unused_extern_crates)] #[macro_use(foo="bar")] //~ ERROR bad macro import extern crate std; diff --git a/src/test/compile-fail/method-call-type-binding.rs b/src/test/compile-fail/method-call-type-binding.rs index 3ae878ed1cb..6c0793ee78f 100644 --- a/src/test/compile-fail/method-call-type-binding.rs +++ b/src/test/compile-fail/method-call-type-binding.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() { - 0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item + 0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here } diff --git a/src/test/compile-fail/move-out-of-array-1.rs b/src/test/compile-fail/move-out-of-array-1.rs index 148dec02823..796b13538b2 100644 --- a/src/test/compile-fail/move-out-of-array-1.rs +++ b/src/test/compile-fail/move-out-of-array-1.rs @@ -24,5 +24,5 @@ fn main() { } fn foo(a: [D; 4], i: usize) -> D { - a[i] //~ ERROR cannot move out of type `[D; 4]` + a[i] //~ ERROR cannot move out of type `[D; 4]`, a non-copy array } diff --git a/src/test/compile-fail/move-out-of-slice-1.rs b/src/test/compile-fail/move-out-of-slice-1.rs index f3efc68701e..9ca9e0984e4 100644 --- a/src/test/compile-fail/move-out-of-slice-1.rs +++ b/src/test/compile-fail/move-out-of-slice-1.rs @@ -15,7 +15,7 @@ struct A; fn main() { let a: Box<[A]> = Box::new([A]); match a { - box [a] => {}, //~ ERROR cannot move out of type `[A]` + box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice _ => {} } } diff --git a/src/test/compile-fail/no-std-inject.rs b/src/test/compile-fail/no-std-inject.rs index f384eafa34b..49064853d21 100644 --- a/src/test/compile-fail/no-std-inject.rs +++ b/src/test/compile-fail/no-std-inject.rs @@ -9,6 +9,7 @@ // except according to those terms. #![no_std] +#![allow(unused_extern_crates)] extern crate core; //~ ERROR: the name `core` is defined multiple times extern crate std; diff --git a/src/test/compile-fail/placement-expr-unstable.rs b/src/test/compile-fail/placement-expr-unstable.rs index cc73cbe15fe..35695efe1a9 100644 --- a/src/test/compile-fail/placement-expr-unstable.rs +++ b/src/test/compile-fail/placement-expr-unstable.rs @@ -12,8 +12,6 @@ #![feature(placement_in_syntax)] -extern crate core; - fn main() { use std::boxed::HEAP; //~ ERROR use of unstable library feature diff --git a/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs b/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs index 9c985839c4d..46c486c63a3 100644 --- a/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs +++ b/src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs @@ -12,6 +12,8 @@ // are treated as rvalues and their lifetime is not bounded to // the static scope. +fn id<T>(x: T) -> T { x } + struct Test; enum MyEnum { @@ -19,12 +21,14 @@ enum MyEnum { } fn structLifetime<'a>() -> &'a Test { - let testValue = &Test; //~ ERROR borrowed value does not live long enough + let testValue = &id(Test); + //~^ ERROR borrowed value does not live long enough testValue } fn variantLifetime<'a>() -> &'a MyEnum { - let testValue = &MyEnum::Variant1; //~ ERROR borrowed value does not live long enough + let testValue = &id(MyEnum::Variant1); + //~^ ERROR borrowed value does not live long enough testValue } diff --git a/src/test/compile-fail/regions-ret.rs b/src/test/compile-fail/regions-ret.rs index 61c98d69d80..c7cd3ced98d 100644 --- a/src/test/compile-fail/regions-ret.rs +++ b/src/test/compile-fail/regions-ret.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn id<T>(x: T) -> T { x } + fn f(_x: &isize) -> &isize { - return &3; //~ ERROR borrowed value does not live long enough + return &id(3); //~ ERROR borrowed value does not live long enough } fn main() { diff --git a/src/test/compile-fail/regions-var-type-out-of-scope.rs b/src/test/compile-fail/regions-var-type-out-of-scope.rs index 8955a26de0b..031091c4523 100644 --- a/src/test/compile-fail/regions-var-type-out-of-scope.rs +++ b/src/test/compile-fail/regions-var-type-out-of-scope.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn id<T>(x: T) -> T { x } + fn foo(cond: bool) { // Here we will infer a type that uses the // region of the if stmt then block: let mut x; if cond { - x = &3; //~ ERROR borrowed value does not live long enough + x = &id(3); //~ ERROR borrowed value does not live long enough assert_eq!(*x, 3); } } diff --git a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs index 87a17c0f19a..6a04a2c3704 100644 --- a/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs +++ b/src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[allow(unused_extern_crates)] extern crate std; //~^ ERROR the name `std` is defined multiple times diff --git a/src/test/compile-fail/resolve_self_super_hint.rs b/src/test/compile-fail/resolve_self_super_hint.rs index 09951348448..a89fd802baf 100644 --- a/src/test/compile-fail/resolve_self_super_hint.rs +++ b/src/test/compile-fail/resolve_self_super_hint.rs @@ -9,6 +9,7 @@ // except according to those terms. #![feature(alloc)] +#![allow(unused_extern_crates)] mod a { extern crate alloc; diff --git a/src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs b/src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs new file mode 100644 index 00000000000..512fb24a0c2 --- /dev/null +++ b/src/test/compile-fail/stability-attribute-non-staged-force-unstable.rs @@ -0,0 +1,16 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Zforce-unstable-if-unmarked + +#[unstable] //~ ERROR: stability attributes may not be used +#[stable] //~ ERROR: stability attributes may not be used +#[rustc_deprecated] //~ ERROR: stability attributes may not be used +fn main() { } diff --git a/src/test/compile-fail/static-reference-to-fn-2.rs b/src/test/compile-fail/static-reference-to-fn-2.rs index 460154f25d7..8d9f442b81d 100644 --- a/src/test/compile-fail/static-reference-to-fn-2.rs +++ b/src/test/compile-fail/static-reference-to-fn-2.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn id<T>(x: T) -> T { x } + struct StateMachineIter<'a> { statefn: &'a StateMachineFunc<'a> } @@ -23,19 +25,19 @@ impl<'a> Iterator for StateMachineIter<'a> { } fn state1(self_: &mut StateMachineIter) -> Option<&'static str> { - self_.statefn = &(state2 as StateMachineFunc); + self_.statefn = &id(state2 as StateMachineFunc); //~^ ERROR borrowed value does not live long enough return Some("state1"); } fn state2(self_: &mut StateMachineIter) -> Option<(&'static str)> { - self_.statefn = &(state3 as StateMachineFunc); + self_.statefn = &id(state3 as StateMachineFunc); //~^ ERROR borrowed value does not live long enough return Some("state2"); } fn state3(self_: &mut StateMachineIter) -> Option<(&'static str)> { - self_.statefn = &(finished as StateMachineFunc); + self_.statefn = &id(finished as StateMachineFunc); //~^ ERROR borrowed value does not live long enough return Some("state3"); } @@ -46,7 +48,8 @@ fn finished(_: &mut StateMachineIter) -> Option<(&'static str)> { fn state_iter() -> StateMachineIter<'static> { StateMachineIter { - statefn: &(state1 as StateMachineFunc) //~ ERROR borrowed value does not live long enough + statefn: &id(state1 as StateMachineFunc) + //~^ ERROR borrowed value does not live long enough } } diff --git a/src/test/compile-fail/static-region-bound.rs b/src/test/compile-fail/static-region-bound.rs index eca22bfdda0..90ed401659c 100644 --- a/src/test/compile-fail/static-region-bound.rs +++ b/src/test/compile-fail/static-region-bound.rs @@ -10,11 +10,13 @@ #![feature(box_syntax)] +fn id<T>(x: T) -> T { x } + fn f<T:'static>(_: T) {} fn main() { let x: Box<_> = box 3; f(x); - let x = &3; //~ ERROR borrowed value does not live long enough + let x = &id(3); //~ ERROR borrowed value does not live long enough f(x); } diff --git a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs index 548a5078a74..42fffe546c2 100644 --- a/src/test/parse-fail/unboxed-closure-sugar-used-on-struct-3.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct-3.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z parse-only - -// Test that parentheses form doesn't work in expression paths. +// Test that parentheses form parses in expression paths. struct Bar<A,R> { f: A, r: R @@ -21,10 +19,10 @@ impl<A,B> Bar<A,B> { } fn bar() { - let b = Box::Bar::<isize,usize>::new(); // OK + let b = Bar::<isize, usize>::new(); // OK - let b = Box::Bar::()::new(); - //~^ ERROR `::` is not supported before parenthesized generic arguments + let b = Bar::(isize, usize)::new(); // OK too (for the parser) + //~^ ERROR parenthesized parameters may only be used with a trait } -fn main() { } +fn main() {} diff --git a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs index fd6c8ad08d6..5fcde4facbe 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs @@ -16,6 +16,7 @@ struct Bar<A> { fn foo(b: Box<Bar()>) { //~^ ERROR parenthesized parameters may only be used with a trait + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn main() { } diff --git a/src/test/compile-fail/unused-attr.rs b/src/test/compile-fail/unused-attr.rs index 6416e1cacdc..e20d03478ec 100644 --- a/src/test/compile-fail/unused-attr.rs +++ b/src/test/compile-fail/unused-attr.rs @@ -9,7 +9,7 @@ // except according to those terms. #![deny(unused_attributes)] -#![allow(dead_code, unused_imports)] +#![allow(dead_code, unused_imports, unused_extern_crates)] #![feature(custom_attribute)] #![foo] //~ ERROR unused attribute diff --git a/src/test/mir-opt/issue-43457.rs b/src/test/mir-opt/issue-43457.rs new file mode 100644 index 00000000000..708784df317 --- /dev/null +++ b/src/test/mir-opt/issue-43457.rs @@ -0,0 +1,55 @@ +// 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. + +// compile-flags: -Z identify_regions -Z span_free_formats +// ignore-tidy-linelength + +// Regression test for #43457: an `EndRegion` was missing from output +// because compiler was using a faulty means for region map lookup. + +use std::cell::RefCell; + +fn rc_refcell_test(r: RefCell<i32>) { + r.borrow_mut(); +} + +fn main() { } + +// END RUST SOURCE +// START rustc.node5.SimplifyCfg-qualify-consts.after.mir +// +// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () { +// let mut _0: (); +// scope 1 { +// let _2: std::cell::RefCell<i32>; +// } +// let mut _3: std::cell::RefMut<'17dce, i32>; +// let mut _4: &'17dce std::cell::RefCell<i32>; +// +// bb0: { +// StorageLive(_2); +// _2 = _1; +// StorageLive(_4); +// _4 = &'17dce _2; +// _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1; +// } +// +// bb1: { +// drop(_3) -> bb2; +// } +// +// bb2: { +// StorageDead(_4); +// EndRegion('17dce); +// _0 = (); +// StorageDead(_2); +// return; +// } +// } diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs index 95c307c5670..cb018ff1bfa 100644 --- a/src/test/parse-fail/type-parameters-in-field-exprs.rs +++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs @@ -24,4 +24,6 @@ fn main() { //~^ ERROR field expressions may not have generic arguments f.x::<>; //~^ ERROR field expressions may not have generic arguments + f.x::(); + //~^ ERROR field expressions may not have generic arguments } diff --git a/src/test/run-make/alloc-extern-crates/Makefile b/src/test/run-make/alloc-extern-crates/Makefile index b8c52378554..7197f4e17e3 100644 --- a/src/test/run-make/alloc-extern-crates/Makefile +++ b/src/test/run-make/alloc-extern-crates/Makefile @@ -2,4 +2,4 @@ all: $(RUSTC) fakealloc.rs - $(RUSTC) ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs) + $(RUSTC) --crate-type=rlib ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs) diff --git a/src/test/run-pass-fulldeps/issue-13560.rs b/src/test/run-pass-fulldeps/issue-13560.rs index 88be7fe1212..0ceb5ed5e75 100644 --- a/src/test/run-pass-fulldeps/issue-13560.rs +++ b/src/test/run-pass-fulldeps/issue-13560.rs @@ -11,7 +11,6 @@ // aux-build:issue-13560-1.rs // aux-build:issue-13560-2.rs // aux-build:issue-13560-3.rs -// ignore-musl // Regression test for issue #13560, the test itself is all in the dependent // libraries. The fail which previously failed to compile is the one numbered 3. diff --git a/src/test/run-pass-fulldeps/linkage-visibility.rs b/src/test/run-pass-fulldeps/linkage-visibility.rs index f884bb2098e..9839a2c7041 100644 --- a/src/test/run-pass-fulldeps/linkage-visibility.rs +++ b/src/test/run-pass-fulldeps/linkage-visibility.rs @@ -11,7 +11,6 @@ // aux-build:linkage-visibility.rs // ignore-android: FIXME(#10356) // ignore-windows: std::dynamic_lib does not work on Windows well -// ignore-musl // ignore-emscripten no dynamic linking extern crate linkage_visibility as foo; diff --git a/src/test/run-pass/builtin-clone-unwind.rs b/src/test/run-pass/builtin-clone-unwind.rs new file mode 100644 index 00000000000..90a41135286 --- /dev/null +++ b/src/test/run-pass/builtin-clone-unwind.rs @@ -0,0 +1,65 @@ +// 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. + +// Test that builtin implementations of `Clone` cleanup everything +// in case of unwinding. + +use std::thread; +use std::rc::Rc; + +struct S(Rc<()>); + +impl Clone for S { + fn clone(&self) -> Self { + if Rc::strong_count(&self.0) == 7 { + panic!("oops"); + } + + S(self.0.clone()) + } +} + +fn main() { + let counter = Rc::new(()); + + // Unwinding with tuples... + let ccounter = counter.clone(); + let result = std::panic::catch_unwind(move || { + let _ = ( + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter) + ).clone(); + }); + + assert!(result.is_err()); + assert_eq!( + 1, + Rc::strong_count(&counter) + ); + + // ... and with arrays. + let ccounter = counter.clone(); + let child = std::panic::catch_unwind(move || { + let _ = [ + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter.clone()), + S(ccounter) + ].clone(); + }); + + assert!(result.is_err()); + assert_eq!( + 1, + Rc::strong_count(&counter) + ); +} diff --git a/src/test/run-pass/builtin-clone.rs b/src/test/run-pass/builtin-clone.rs new file mode 100644 index 00000000000..95903610931 --- /dev/null +++ b/src/test/run-pass/builtin-clone.rs @@ -0,0 +1,54 @@ +// 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. + +// Test that `Clone` is correctly implemented for builtin types. +// Also test that cloning an array or a tuple is done right, i.e. +// each component is cloned. + +fn test_clone<T: Clone>(arg: T) { + let _ = arg.clone(); +} + +fn foo() { } + +#[derive(Debug, PartialEq, Eq)] +struct S(i32); + +impl Clone for S { + fn clone(&self) -> Self { + S(self.0 + 1) + } +} + +fn main() { + test_clone(foo); + test_clone([1; 56]); + test_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); + + let a = [S(0), S(1), S(2)]; + let b = [S(1), S(2), S(3)]; + assert_eq!(b, a.clone()); + + let a = ( + (S(1), S(0)), + ( + (S(0), S(0), S(1)), + S(0) + ) + ); + let b = ( + (S(2), S(1)), + ( + (S(1), S(1), S(2)), + S(1) + ) + ); + assert_eq!(b, a.clone()); +} diff --git a/src/test/run-pass/deprecation-in-force-unstable.rs b/src/test/run-pass/deprecation-in-force-unstable.rs new file mode 100644 index 00000000000..542117eca12 --- /dev/null +++ b/src/test/run-pass/deprecation-in-force-unstable.rs @@ -0,0 +1,14 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:-Zforce-unstable-if-unmarked + +#[deprecated] // should work even with -Zforce-unstable-if-unmarked +fn main() { } diff --git a/src/test/run-pass/issue-37725.rs b/src/test/run-pass/issue-37725.rs index 5ed1295c85c..a8fb11f9c62 100644 --- a/src/test/run-pass/issue-37725.rs +++ b/src/test/run-pass/issue-37725.rs @@ -8,7 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { - s.clone(); +trait Foo { + fn foo(&self); +} + +fn foo<'a>(s: &'a mut ()) where &'a mut (): Foo { + s.foo(); } fn main() {} diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs b/src/test/run-pass/issue-43205.rs index fdb010a04f4..0e613ac0727 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs +++ b/src/test/run-pass/issue-43205.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - z.push((x,y)); +fn main() { + &&[()][0]; + println!("{:?}", &[(),()][1]); } diff --git a/src/test/compile-fail/feature-gate-rvalue_static_promotion.rs b/src/test/run-pass/issue-43910.rs index f33d0a71481..d61ce7f4689 100644 --- a/src/test/compile-fail/feature-gate-rvalue_static_promotion.rs +++ b/src/test/run-pass/issue-43910.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#[allow(unused_variables)] +#![deny(unused_variables)] + fn main() { - let x: &'static u32 = &42; //~ error: does not live long enough - let y: &'static Option<u32> = &None; //~ error: does not live long enough + #[allow(unused_variables)] + let x = 12; } diff --git a/src/test/run-pass/issue-43923.rs b/src/test/run-pass/issue-43923.rs new file mode 100644 index 00000000000..e1992e4fc50 --- /dev/null +++ b/src/test/run-pass/issue-43923.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct A<T: ?Sized> { ptr: T } + +fn foo<T>(x: &A<[T]>) {} + +fn main() { + let a = foo; + let b = A { ptr: [a, a, a] }; + a(&A { ptr: [()] }); +} diff --git a/src/test/run-pass/lint-unknown-lints-at-crate-level.rs b/src/test/run-pass/lint-unknown-lints-at-crate-level.rs new file mode 100644 index 00000000000..1e510c28e78 --- /dev/null +++ b/src/test/run-pass/lint-unknown-lints-at-crate-level.rs @@ -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. + +// compile-flags: -D warnings -D unknown-lints + +#![allow(unknown_lints)] +#![allow(random_lint_name)] + +fn main() {} diff --git a/src/test/run-pass/rvalue-static-promotion.rs b/src/test/run-pass/rvalue-static-promotion.rs index 30643cfc3eb..e57491930a4 100644 --- a/src/test/run-pass/rvalue-static-promotion.rs +++ b/src/test/run-pass/rvalue-static-promotion.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(rvalue_static_promotion)] - #[allow(unused_variables)] fn main() { let x: &'static u32 = &42; diff --git a/src/test/run-pass/union/union-basic.rs b/src/test/run-pass/union/union-basic.rs index de744520cc6..079f6a6b641 100644 --- a/src/test/run-pass/union/union-basic.rs +++ b/src/test/run-pass/union/union-basic.rs @@ -10,10 +10,6 @@ // aux-build:union.rs -// FIXME: This test case makes little-endian assumptions. -// ignore-s390x -// ignore-sparc - extern crate union; use std::mem::{size_of, align_of, zeroed}; @@ -39,7 +35,7 @@ fn local() { assert_eq!(w.b, 0); w.a = 1; assert_eq!(w.a, 1); - assert_eq!(w.b, 1); + assert_eq!(w.b.to_le(), 1); } } @@ -60,7 +56,7 @@ fn xcrate() { assert_eq!(w.b, 0); w.a = 1; assert_eq!(w.a, 1); - assert_eq!(w.b, 1); + assert_eq!(w.b.to_le(), 1); } } diff --git a/src/test/run-pass/wrong-hashset-issue-42918.rs b/src/test/run-pass/wrong-hashset-issue-42918.rs new file mode 100644 index 00000000000..5a23adeceb5 --- /dev/null +++ b/src/test/run-pass/wrong-hashset-issue-42918.rs @@ -0,0 +1,38 @@ +// 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. +// +// compile-flags: -O + +use std::collections::HashSet; + +#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)] +enum MyEnum { + E0, + + E1, + + E2, + E3, + E4, + + E5, + E6, + E7, +} + + +fn main() { + use MyEnum::*; + let s: HashSet<_> = [E4, E1].iter().cloned().collect(); + let mut v: Vec<_> = s.into_iter().collect(); + v.sort(); + + assert_eq!([E1, E4], &v[..]); +} diff --git a/src/test/rustdoc/issue-43869.rs b/src/test/rustdoc/issue-43869.rs new file mode 100644 index 00000000000..2d18e4be532 --- /dev/null +++ b/src/test/rustdoc/issue-43869.rs @@ -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(conservative_impl_trait)] + +pub fn g() -> impl Iterator<Item=u8> { + Some(1u8).into_iter() +} + +pub fn h() -> (impl Iterator<Item=u8>) { + Some(1u8).into_iter() +} + +pub fn i() -> impl Iterator<Item=u8> + 'static { + Some(1u8).into_iter() +} + +pub fn j() -> impl Iterator<Item=u8> + Clone { + Some(1u8).into_iter() +} + +// @has issue_43869/fn.g.html +// @has issue_43869/fn.h.html +// @has issue_43869/fn.i.html +// @has issue_43869/fn.j.html diff --git a/src/test/rustdoc/remove-duplicates.rs b/src/test/rustdoc/remove-duplicates.rs new file mode 100644 index 00000000000..6c4f6d0700a --- /dev/null +++ b/src/test/rustdoc/remove-duplicates.rs @@ -0,0 +1,24 @@ +// 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. + +#![crate_name = "foo"] + +mod foo { + pub use bar::*; + pub mod bar { + pub trait Foo { + fn foo(); + } + } +} + +// @count foo/index.html '//*[@class="trait"]' 1 +pub use foo::bar::*; +pub use foo::*; diff --git a/src/test/ui/issue-13483.rs b/src/test/ui/issue-13483.rs new file mode 100644 index 00000000000..86378043912 --- /dev/null +++ b/src/test/ui/issue-13483.rs @@ -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. + +fn main() { + if true { + } else if { + } else { + } +} + +fn foo() { + if true { + } else if { + } + bar(); +} + +fn bar() {} diff --git a/src/test/ui/issue-13483.stderr b/src/test/ui/issue-13483.stderr new file mode 100644 index 00000000000..3446969dfd2 --- /dev/null +++ b/src/test/ui/issue-13483.stderr @@ -0,0 +1,14 @@ +error: missing condition for `if` statemement + --> $DIR/issue-13483.rs:13:14 + | +13 | } else if { + | ^ expected if condition here + +error: missing condition for `if` statemement + --> $DIR/issue-13483.rs:20:14 + | +20 | } else if { + | ^ expected if condition here + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/issue-41652/issue_41652.stderr b/src/test/ui/issue-41652/issue_41652.stderr index 8a55c9989e1..5d143697908 100644 --- a/src/test/ui/issue-41652/issue_41652.stderr +++ b/src/test/ui/issue-41652/issue_41652.stderr @@ -5,6 +5,7 @@ error[E0599]: no method named `f` found for type `{integer}` in the current scop | ^ | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter + = help: try with `{integer}::f` note: candidate #1 is defined in the trait `issue_41652_b::Tr` --> $DIR/auxiliary/issue_41652_b.rs:14:5 | diff --git a/src/test/ui/issue-44023.rs b/src/test/ui/issue-44023.rs new file mode 100644 index 00000000000..295d4808289 --- /dev/null +++ b/src/test/ui/issue-44023.rs @@ -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. + +#![feature(non_ascii_idents)] + +pub fn main () {} + +fn საჭმელად_გემრიელი_სადილი ( ) -> isize { +} diff --git a/src/test/ui/issue-44023.stderr b/src/test/ui/issue-44023.stderr new file mode 100644 index 00000000000..a17512ba4ab --- /dev/null +++ b/src/test/ui/issue-44023.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/issue-44023.rs:15:42 + | +15 | fn საჭმელად_გემრიელი_სადილი ( ) -> isize { + | __________________________________________^ +16 | | } + | |_^ expected isize, found () + | + = note: expected type `isize` + found type `()` + +error: aborting due to previous error + diff --git a/src/test/ui/issue-44078.rs b/src/test/ui/issue-44078.rs new file mode 100644 index 00000000000..ef47214f2b3 --- /dev/null +++ b/src/test/ui/issue-44078.rs @@ -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() { + "😊""; +} diff --git a/src/test/ui/issue-44078.stderr b/src/test/ui/issue-44078.stderr new file mode 100644 index 00000000000..389f3b2479a --- /dev/null +++ b/src/test/ui/issue-44078.stderr @@ -0,0 +1,10 @@ +error: unterminated double quote string + --> $DIR/issue-44078.rs:12:8 + | +12 | "😊""; + | ________^ +13 | | } + | |__^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr index 6764c58f4bb..1ee00997997 100644 --- a/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -1,25 +1,10 @@ -error[E0308]: mismatched types +error[E0623]: lifetime mismatch --> $DIR/ex2b-push-no-existing-names.rs:16:12 | +15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) { + | -------- -------- these two types are declared with different lifetimes... 16 | x.push(y); - | ^ lifetime mismatch - | - = note: expected type `Ref<'_, _>` - found type `Ref<'_, _>` -note: the anonymous lifetime #3 defined on the function body at 15:1... - --> $DIR/ex2b-push-no-existing-names.rs:15:1 - | -15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) { -16 | | x.push(y); -17 | | } - | |_^ -note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1 - --> $DIR/ex2b-push-no-existing-names.rs:15:1 - | -15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) { -16 | | x.push(y); -17 | | } - | |_^ + | ^ ...but data from `y` flows into `x` here error: aborting due to previous error diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr index 4c878f3c0dc..74a40c87c2f 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch --> $DIR/ex3-both-anon-regions-2.rs:12:9 | 11 | fn foo((v, w): (&u8, &u8), x: &u8) { - | --- --- these references are not declared with the same lifetime... + | --- --- these two types are declared with different lifetimes... 12 | v = x; | ^ ...but data from `x` flows here diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs index 7bd5ebf805f..51271243bdf 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) { - v = x; +fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { + z.push((x,y)); } fn main() { } + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr index 08506b8befa..898866c75f2 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -1,10 +1,18 @@ error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-3.rs:12:9 + --> $DIR/ex3-both-anon-regions-3.rs:12:13 | -11 | fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) { - | --- --- these references are not declared with the same lifetime... -12 | v = x; - | ^ ...but data flows here +11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { + | --- --- these two types are declared with different lifetimes... +12 | z.push((x,y)); + | ^ ...but data flows into `z` here -error: aborting due to previous error +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-3.rs:12:15 + | +11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { + | --- --- these two types are declared with different lifetimes... +12 | z.push((x,y)); + | ^ ...but data flows into `z` here + +error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr deleted file mode 100644 index 9c2630fc811..00000000000 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0601]: main function not found - -error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-4.rs:12:13 - | -11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | --- --- these references are not declared with the same lifetime... -12 | z.push((x,y)); - | ^ ...but data flows into `z` here - -error[E0623]: lifetime mismatch - --> $DIR/ex3-both-anon-regions-4.rs:12:15 - | -11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { - | --- --- these references are not declared with the same lifetime... -12 | z.push((x,y)); - | ^ ...but data flows into `z` here - -error: aborting due to 3 previous errors - diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs new file mode 100644 index 00000000000..2fbf31aead5 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +struct Ref<'a, 'b> { + a: &'a u32, + b: &'b u32, +} + +fn foo(mut x: Ref, y: Ref) { + x.b = y.b; +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr new file mode 100644 index 00000000000..26f31defc9e --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr @@ -0,0 +1,10 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11 + | +15 | fn foo(mut x: Ref, y: Ref) { + | --- --- these two types are declared with different lifetimes... +16 | x.b = y.b; + | ^^^ ...but data from `y` flows into `x` here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs new file mode 100644 index 00000000000..120a7ca74ae --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +struct Ref<'a, 'b> { + a: &'a u32, + b: &'b u32, +} + +fn foo(mut x: Ref) { + x.a = x.b; +} + +fn main() {} \ No newline at end of file diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr new file mode 100644 index 00000000000..1b5ac7c7b57 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr @@ -0,0 +1,12 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11 + | +15 | fn foo(mut x: Ref) { + | --- + | | + | this type was declared with multiple lifetimes... +16 | x.a = x.b; + | ^^^ ...but data with one lifetime flows into the other here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs new file mode 100644 index 00000000000..67ba8ee532a --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +struct Ref<'a> { + x: &'a u32, +} + +fn foo(mut x: Vec<Ref>, y: Ref) { + x.push(y); +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr new file mode 100644 index 00000000000..6ad795400b3 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr @@ -0,0 +1,10 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12 + | +14 | fn foo(mut x: Vec<Ref>, y: Ref) { + | --- --- these two types are declared with different lifetimes... +15 | x.push(y); + | ^ ...but data from `y` flows into `x` here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs new file mode 100644 index 00000000000..a8b1f53fc98 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs @@ -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. + +struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 } + +fn foo(mut x: Ref, y: &u32) { + y = x.b; +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr new file mode 100644 index 00000000000..31c7ebf6504 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr @@ -0,0 +1,12 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9 + | +13 | fn foo(mut x: Ref, y: &u32) { + | --- ---- + | | + | these two types are declared with different lifetimes... +14 | y = x.b; + | ^^^ ...but data from `x` flows into `y` here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs new file mode 100644 index 00000000000..4933dbb7e7a --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs @@ -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. + +struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 } + +fn foo(mut y: Ref, x: &u32) { + y.b = x; +} + +fn main() { } diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr new file mode 100644 index 00000000000..d54b526aef9 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr @@ -0,0 +1,10 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11 + | +13 | fn foo(mut y: Ref, x: &u32) { + | --- ---- these two types are declared with different lifetimes... +14 | y.b = x; + | ^ ...but data from `x` flows into `y` here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs new file mode 100644 index 00000000000..e1594b1a277 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Ref<'a, 'b> { + a: &'a u32, + b: &'b u32, +} + +fn foo(mut x: Ref, y: &u32) { + x.b = y; +} + +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr new file mode 100644 index 00000000000..bb7b9ea6843 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr @@ -0,0 +1,10 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11 + | +16 | fn foo(mut x: Ref, y: &u32) { + | --- ---- these two types are declared with different lifetimes... +17 | x.b = y; + | ^ ...but data from `y` flows into `x` here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs new file mode 100644 index 00000000000..0dc257ac092 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + field: i32 +} + +impl Foo { + fn foo<'a>(&self, x: &i32) -> &i32 { + x + } +} + +fn main() { } + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr new file mode 100644 index 00000000000..890f9b311e7 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr @@ -0,0 +1,23 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5 + | +17 | x + | ^ + | +note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3... + --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3 + | +16 | / fn foo<'a>(&self, x: &i32) -> &i32 { +17 | | x +18 | | } + | |___^ +note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:3 + --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3 + | +16 | / fn foo<'a>(&self, x: &i32) -> &i32 { +17 | | x +18 | | } + | |___^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs new file mode 100644 index 00000000000..0940ce15d1e --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + field: i32, +} + +impl Foo { + fn foo<'a>(&self, x: &Foo) -> &Foo { + if true { x } else { self } + } +} + +fn main() {} + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr new file mode 100644 index 00000000000..43f00c32c62 --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr @@ -0,0 +1,23 @@ +error[E0312]: lifetime of reference outlives lifetime of borrowed content... + --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19 + | +17 | if true { x } else { self } + | ^ + | +note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:5... + --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5 + | +16 | / fn foo<'a>(&self, x: &Foo) -> &Foo { +17 | | if true { x } else { self } +18 | | } + | |_____^ +note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:5 + --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5 + | +16 | / fn foo<'a>(&self, x: &Foo) -> &Foo { +17 | | if true { x } else { self } +18 | | } + | |_____^ + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs new file mode 100644 index 00000000000..3a7ba415c0d --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs @@ -0,0 +1,18 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +trait Foo { + fn foo<'a>(x: &mut Vec<&u8>, y: &u8); +} +impl Foo for () { + fn foo(x: &mut Vec<&u8>, y: &u8) { + x.push(y); + } +} +fn main() {} diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr new file mode 100644 index 00000000000..9591df8e8aa --- /dev/null +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr @@ -0,0 +1,10 @@ +error[E0623]: lifetime mismatch + --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16 + | +14 | fn foo(x: &mut Vec<&u8>, y: &u8) { + | --- --- these two types are declared with different lifetimes... +15 | x.push(y); + | ^ ...but data from `y` flows into `x` here + +error: aborting due to previous error + diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs index 9ebff511876..be48d07b94e 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// 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. // diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr index a183d1fffc0..d3291063859 100644 --- a/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr +++ b/src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr @@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch --> $DIR/ex3-both-anon-regions.rs:12:12 | 11 | fn foo(x: &mut Vec<&u8>, y: &u8) { - | --- --- these references are not declared with the same lifetime... + | --- --- these two types are declared with different lifetimes... 12 | x.push(y); | ^ ...but data from `y` flows into `x` here diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.rs b/src/test/ui/lifetimes/borrowck-let-suggestion.rs index eeafaab44c6..1c904648f9e 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.rs +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.rs @@ -9,7 +9,7 @@ // except according to those terms. fn f() { - let x = [1].iter(); + let x = vec![1].iter(); } fn main() { diff --git a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr index d1ba9246588..6316c066660 100644 --- a/src/test/ui/lifetimes/borrowck-let-suggestion.stderr +++ b/src/test/ui/lifetimes/borrowck-let-suggestion.stderr @@ -1,14 +1,15 @@ error[E0597]: borrowed value does not live long enough - --> $DIR/borrowck-let-suggestion.rs:12:23 + --> $DIR/borrowck-let-suggestion.rs:12:27 | -12 | let x = [1].iter(); - | --- ^ temporary value dropped here while still borrowed +12 | let x = vec![1].iter(); + | ------- ^ temporary value dropped here while still borrowed | | | temporary value created here 13 | } | - temporary value needs to live until here | = note: consider using a `let` binding to increase its lifetime + = note: this error originates in a macro outside of the current crate error: aborting due to previous error diff --git a/src/test/ui/lint/fn_must_use.rs b/src/test/ui/lint/fn_must_use.rs index 5aea5f2ca06..c549ded4db2 100644 --- a/src/test/ui/lint/fn_must_use.rs +++ b/src/test/ui/lint/fn_must_use.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(fn_must_use)] #![warn(unused_must_use)] struct MyStruct { diff --git a/src/test/ui/lint/fn_must_use.stderr b/src/test/ui/lint/fn_must_use.stderr index 20eb7452aea..242837793a0 100644 --- a/src/test/ui/lint/fn_must_use.stderr +++ b/src/test/ui/lint/fn_must_use.stderr @@ -1,18 +1,18 @@ warning: unused return value of `need_to_use_this_value` which must be used: it's important - --> $DIR/fn_must_use.rs:30:5 + --> $DIR/fn_must_use.rs:31:5 | -30 | need_to_use_this_value(); +31 | need_to_use_this_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/fn_must_use.rs:11:9 + --> $DIR/fn_must_use.rs:12:9 | -11 | #![warn(unused_must_use)] +12 | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used - --> $DIR/fn_must_use.rs:33:5 + --> $DIR/fn_must_use.rs:34:5 | -33 | m.need_to_use_this_method_value(); +34 | m.need_to_use_this_method_value(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/resolve/enums-are-namespaced-xc.stderr b/src/test/ui/resolve/enums-are-namespaced-xc.stderr index 4b32ecff2fb..a401861274d 100644 --- a/src/test/ui/resolve/enums-are-namespaced-xc.stderr +++ b/src/test/ui/resolve/enums-are-namespaced-xc.stderr @@ -6,7 +6,7 @@ error[E0425]: cannot find value `A` in module `namespaced_enums` | help: possible candidate is found in another module, you can import it into scope | -12 | use namespaced_enums::Foo::A; +14 | use namespaced_enums::Foo::A; | error[E0425]: cannot find function `B` in module `namespaced_enums` @@ -17,7 +17,7 @@ error[E0425]: cannot find function `B` in module `namespaced_enums` | help: possible candidate is found in another module, you can import it into scope | -12 | use namespaced_enums::Foo::B; +14 | use namespaced_enums::Foo::B; | error[E0422]: cannot find struct, variant or union type `C` in module `namespaced_enums` @@ -28,7 +28,7 @@ error[E0422]: cannot find struct, variant or union type `C` in module `namespace | help: possible candidate is found in another module, you can import it into scope | -12 | use namespaced_enums::Foo::C; +14 | use namespaced_enums::Foo::C; | error: aborting due to 3 previous errors diff --git a/src/test/ui/resolve/issue-21221-3.stderr b/src/test/ui/resolve/issue-21221-3.stderr index f4d183192b6..da849ecc71a 100644 --- a/src/test/ui/resolve/issue-21221-3.stderr +++ b/src/test/ui/resolve/issue-21221-3.stderr @@ -6,7 +6,7 @@ error[E0405]: cannot find trait `OuterTrait` in this scope | help: possible candidate is found in another module, you can import it into scope | -16 | use issue_21221_3::outer::OuterTrait; +18 | use issue_21221_3::outer::OuterTrait; | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/issue-21221-4.stderr b/src/test/ui/resolve/issue-21221-4.stderr index eb71ee893ce..78059ed37be 100644 --- a/src/test/ui/resolve/issue-21221-4.stderr +++ b/src/test/ui/resolve/issue-21221-4.stderr @@ -6,7 +6,7 @@ error[E0405]: cannot find trait `T` in this scope | help: possible candidate is found in another module, you can import it into scope | -16 | use issue_21221_4::T; +18 | use issue_21221_4::T; | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/issue-3907.stderr b/src/test/ui/resolve/issue-3907.stderr index 70b4599dbf8..7a4d0ca698e 100644 --- a/src/test/ui/resolve/issue-3907.stderr +++ b/src/test/ui/resolve/issue-3907.stderr @@ -6,7 +6,7 @@ error[E0404]: expected trait, found type alias `Foo` | help: possible better candidate is found in another module, you can import it into scope | -12 | use issue_3907::Foo; +14 | use issue_3907::Foo; | error: cannot continue compilation due to previous error diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 47141eda33c..ee1481ec6f2 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -10,7 +10,7 @@ error[E0423]: expected value, found struct `Z` | help: possible better candidate is found in another module, you can import it into scope | -15 | use m::n::Z; +16 | use m::n::Z; | error[E0423]: expected value, found struct `S` @@ -24,7 +24,7 @@ error[E0423]: expected value, found struct `S` | help: possible better candidate is found in another module, you can import it into scope | -13 | use m::S; +15 | use m::S; | error[E0423]: expected value, found struct `xcrate::S` @@ -38,7 +38,7 @@ error[E0423]: expected value, found struct `xcrate::S` | help: possible better candidate is found in another module, you can import it into scope | -13 | use m::S; +15 | use m::S; | error[E0603]: tuple struct `Z` is private diff --git a/src/test/ui/resolve/use_suggestion_placement.rs b/src/test/ui/resolve/use_suggestion_placement.rs new file mode 100644 index 00000000000..e0027fed4d6 --- /dev/null +++ b/src/test/ui/resolve/use_suggestion_placement.rs @@ -0,0 +1,27 @@ +// 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. + +macro_rules! y { + () => {} +} + +mod m { + pub const A: i32 = 0; +} + +fn main() { + y!(); + let _ = A; + foo(); +} + +fn foo() { + type Dict<K, V> = HashMap<K, V>; +} diff --git a/src/test/ui/resolve/use_suggestion_placement.stderr b/src/test/ui/resolve/use_suggestion_placement.stderr new file mode 100644 index 00000000000..5c74d8bed66 --- /dev/null +++ b/src/test/ui/resolve/use_suggestion_placement.stderr @@ -0,0 +1,38 @@ +error[E0425]: cannot find value `A` in this scope + --> $DIR/use_suggestion_placement.rs:21:13 + | +21 | let _ = A; + | ^ not found in this scope + | +help: possible candidate is found in another module, you can import it into scope + | +11 | use m::A; + | + +error[E0412]: cannot find type `HashMap` in this scope + --> $DIR/use_suggestion_placement.rs:26:23 + | +26 | type Dict<K, V> = HashMap<K, V>; + | ^^^^^^^ not found in this scope + | +help: possible candidates are found in other modules, you can import them into scope + | +11 | use std::collections::HashMap; + | +11 | use std::collections::hash_map::HashMap; + | + +error[E0091]: type parameter `K` is unused + --> $DIR/use_suggestion_placement.rs:26:15 + | +26 | type Dict<K, V> = HashMap<K, V>; + | ^ unused type parameter + +error[E0091]: type parameter `V` is unused + --> $DIR/use_suggestion_placement.rs:26:18 + | +26 | type Dict<K, V> = HashMap<K, V>; + | ^ unused type parameter + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/span/E0536.stderr b/src/test/ui/span/E0536.stderr index b2da0c6a296..c33b89953e2 100644 --- a/src/test/ui/span/E0536.stderr +++ b/src/test/ui/span/E0536.stderr @@ -2,7 +2,7 @@ error[E0536]: expected 1 cfg-pattern --> $DIR/E0536.rs:11:7 | 11 | #[cfg(not())] //~ ERROR E0536 - | ^^^ + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/E0537.stderr b/src/test/ui/span/E0537.stderr index 29873943f44..9d66ddbaae3 100644 --- a/src/test/ui/span/E0537.stderr +++ b/src/test/ui/span/E0537.stderr @@ -2,7 +2,7 @@ error[E0537]: invalid predicate `unknown` --> $DIR/E0537.rs:11:7 | 11 | #[cfg(unknown())] //~ ERROR E0537 - | ^^^^^^^ + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs index 1206d716672..9e316b989a4 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.rs +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn id<T>(x: T) -> T { x } + fn f() { let old = ['o']; // statement 0 let mut v1 = Vec::new(); // statement 1 @@ -21,7 +23,7 @@ fn f() { let mut v3 = Vec::new(); // statement 5 - v3.push(&'x'); // statement 6 + v3.push(&id('x')); // statement 6 //~^ ERROR borrowed value does not live long enough //~| NOTE temporary value created here //~| NOTE temporary value only lives until here @@ -31,7 +33,7 @@ fn f() { let mut v4 = Vec::new(); // (sub) statement 0 - v4.push(&'y'); + v4.push(&id('y')); //~^ ERROR borrowed value does not live long enough //~| NOTE temporary value created here //~| NOTE temporary value only lives until here @@ -42,7 +44,7 @@ fn f() { let mut v5 = Vec::new(); // statement 8 - v5.push(&'z'); + v5.push(&id('z')); //~^ ERROR borrowed value does not live long enough //~| NOTE temporary value created here //~| NOTE temporary value only lives until here diff --git a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr index 6ed1b7c2622..86c6f28ef1c 100644 --- a/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr +++ b/src/test/ui/span/borrowck-let-suggestion-suffixes.stderr @@ -1,49 +1,49 @@ error[E0597]: `young[..]` does not live long enough - --> $DIR/borrowck-let-suggestion-suffixes.rs:52:1 + --> $DIR/borrowck-let-suggestion-suffixes.rs:54:1 | -19 | v2.push(&young[0]); // statement 4 +21 | v2.push(&young[0]); // statement 4 | -------- borrow occurs here ... -52 | } +54 | } | ^ `young[..]` dropped here while still borrowed | = note: values in a scope are dropped in the opposite order they are created error[E0597]: borrowed value does not live long enough - --> $DIR/borrowck-let-suggestion-suffixes.rs:24:18 + --> $DIR/borrowck-let-suggestion-suffixes.rs:26:22 | -24 | v3.push(&'x'); // statement 6 - | --- ^ temporary value dropped here while still borrowed +26 | v3.push(&id('x')); // statement 6 + | ------- ^ temporary value dropped here while still borrowed | | | temporary value created here ... -52 | } +54 | } | - temporary value needs to live until here | = note: consider using a `let` binding to increase its lifetime error[E0597]: borrowed value does not live long enough - --> $DIR/borrowck-let-suggestion-suffixes.rs:34:22 + --> $DIR/borrowck-let-suggestion-suffixes.rs:36:26 | -34 | v4.push(&'y'); - | --- ^ temporary value dropped here while still borrowed +36 | v4.push(&id('y')); + | ------- ^ temporary value dropped here while still borrowed | | | temporary value created here ... -40 | } // (statement 7) +42 | } // (statement 7) | - temporary value needs to live until here | = note: consider using a `let` binding to increase its lifetime error[E0597]: borrowed value does not live long enough - --> $DIR/borrowck-let-suggestion-suffixes.rs:45:18 + --> $DIR/borrowck-let-suggestion-suffixes.rs:47:22 | -45 | v5.push(&'z'); - | --- ^ temporary value dropped here while still borrowed +47 | v5.push(&id('z')); + | ------- ^ temporary value dropped here while still borrowed | | | temporary value created here ... -52 | } +54 | } | - temporary value needs to live until here | = note: consider using a `let` binding to increase its lifetime diff --git a/src/test/ui/span/import-ty-params.rs b/src/test/ui/span/import-ty-params.rs index d1e3d20f4ba..793ea68beba 100644 --- a/src/test/ui/span/import-ty-params.rs +++ b/src/test/ui/span/import-ty-params.rs @@ -21,10 +21,10 @@ macro_rules! import { } fn f1() { - import! { a::b::c::S<u8> } //~ ERROR generic arguments in import path + import! { a::b::c::S<u8> } //~ ERROR unexpected generic arguments in path } fn f2() { - import! { a::b::c::S<> } //~ ERROR generic arguments in import path + import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path } fn main() {} diff --git a/src/test/ui/span/import-ty-params.stderr b/src/test/ui/span/import-ty-params.stderr index de959a14cc5..e2c3e34c471 100644 --- a/src/test/ui/span/import-ty-params.stderr +++ b/src/test/ui/span/import-ty-params.stderr @@ -1,14 +1,14 @@ -error: generic arguments in import path - --> $DIR/import-ty-params.rs:24:25 +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:24:15 | -24 | import! { a::b::c::S<u8> } //~ ERROR generic arguments in import path - | ^^^^ +24 | import! { a::b::c::S<u8> } //~ ERROR unexpected generic arguments in path + | ^^^^^^^^^^^^^^ -error: generic arguments in import path - --> $DIR/import-ty-params.rs:27:25 +error: unexpected generic arguments in path + --> $DIR/import-ty-params.rs:27:15 | -27 | import! { a::b::c::S<> } //~ ERROR generic arguments in import path - | ^^ +27 | import! { a::b::c::S<> } //~ ERROR unexpected generic arguments in path + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-15480.rs b/src/test/ui/span/issue-15480.rs index ea5f4d3fe60..871e0af50bf 100644 --- a/src/test/ui/span/issue-15480.rs +++ b/src/test/ui/span/issue-15480.rs @@ -8,9 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +fn id<T>(x: T) -> T { x } + fn main() { let v = vec![ - &3 + &id(3) ]; for &&x in &v { diff --git a/src/test/ui/span/issue-15480.stderr b/src/test/ui/span/issue-15480.stderr index ce1c6e81b96..7f4ca19241c 100644 --- a/src/test/ui/span/issue-15480.stderr +++ b/src/test/ui/span/issue-15480.stderr @@ -1,12 +1,12 @@ error[E0597]: borrowed value does not live long enough - --> $DIR/issue-15480.rs:14:6 + --> $DIR/issue-15480.rs:16:6 | -13 | &3 - | - temporary value created here -14 | ]; +15 | &id(3) + | ----- temporary value created here +16 | ]; | ^ temporary value dropped here while still borrowed ... -19 | } +21 | } | - temporary value needs to live until here | = note: consider using a `let` binding to increase its lifetime diff --git a/src/test/ui/span/issue-24690.stderr b/src/test/ui/span/issue-24690.stderr index 4f1c870d874..d4c0eb21342 100644 --- a/src/test/ui/span/issue-24690.stderr +++ b/src/test/ui/span/issue-24690.stderr @@ -10,6 +10,7 @@ note: lint level defined here 18 | #![warn(unused)] | ^^^^^^ = note: #[warn(unused_variables)] implied by #[warn(unused)] + = note: to disable this warning, consider using `_theOtherTwo` instead warning: variable `theTwo` should have a snake case name such as `the_two` --> $DIR/issue-24690.rs:22:9 diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr index ff62adbfbd5..08ec2a87fcd 100644 --- a/src/test/ui/span/issue-7575.stderr +++ b/src/test/ui/span/issue-7575.stderr @@ -5,6 +5,7 @@ error[E0599]: no method named `f9` found for type `usize` in the current scope | ^^ | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter + = help: try with `usize::f9` note: candidate #1 is defined in the trait `CtxtFn` --> $DIR/issue-7575.rs:16:5 | @@ -36,6 +37,7 @@ error[E0599]: no method named `fff` found for type `Myisize` in the current scop | ^^^ | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter + = help: try with `Myisize::fff` note: candidate #1 is defined in an impl for the type `Myisize` --> $DIR/issue-7575.rs:51:5 | @@ -51,6 +53,7 @@ error[E0599]: no method named `is_str` found for type `T` in the current scope | ^^^^^^ | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter + = help: try with `T::is_str` note: candidate #1 is defined in the trait `ManyImplTrait` --> $DIR/issue-7575.rs:57:5 | diff --git a/src/test/ui/span/macro-ty-params.rs b/src/test/ui/span/macro-ty-params.rs index 08a7518dff9..c2443b024ce 100644 --- a/src/test/ui/span/macro-ty-params.rs +++ b/src/test/ui/span/macro-ty-params.rs @@ -16,16 +16,6 @@ macro_rules! m { fn main() { foo::<T>!(); - //~^ ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path foo::<>!(); - //~^ ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path m!(MyTrait<>); - //~^ ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path - //~| ERROR generic arguments in macro path } diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr index f7115a04826..1d2f7bb2f07 100644 --- a/src/test/ui/span/macro-ty-params.stderr +++ b/src/test/ui/span/macro-ty-params.stderr @@ -1,3 +1,15 @@ +error: unexpected generic arguments in path + --> $DIR/macro-ty-params.rs:20:8 + | +20 | m!(MyTrait<>); + | ^^^^^^^^^ + +error: unexpected generic arguments in path + --> $DIR/macro-ty-params.rs:20:8 + | +20 | m!(MyTrait<>); + | ^^^^^^^^^ + error: generic arguments in macro path --> $DIR/macro-ty-params.rs:18:8 | @@ -5,16 +17,16 @@ error: generic arguments in macro path | ^^^^^ error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:22:8 + --> $DIR/macro-ty-params.rs:19:8 | -22 | foo::<>!(); +19 | foo::<>!(); | ^^^^ error: generic arguments in macro path - --> $DIR/macro-ty-params.rs:26:15 + --> $DIR/macro-ty-params.rs:20:15 | -26 | m!(MyTrait<>); +20 | m!(MyTrait<>); | ^^ -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs index a524562f2d9..99b0d6ed296 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.rs @@ -10,6 +10,8 @@ #![feature(box_syntax)] +fn id<T>(x: T) -> T { x } + trait Foo { } impl<'a> Foo for &'a isize { } @@ -17,7 +19,7 @@ impl<'a> Foo for &'a isize { } fn main() { let blah; { - let ss: &isize = &1; + let ss: &isize = &id(1); blah = box ss as Box<Foo>; } } diff --git a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr index e671f1daf61..6a3625441b4 100644 --- a/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr +++ b/src/test/ui/span/regions-close-over-borrowed-ref-in-obj.stderr @@ -1,12 +1,12 @@ error[E0597]: borrowed value does not live long enough - --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:22:5 + --> $DIR/regions-close-over-borrowed-ref-in-obj.rs:24:5 | -20 | let ss: &isize = &1; - | - temporary value created here -21 | blah = box ss as Box<Foo>; -22 | } +22 | let ss: &isize = &id(1); + | ----- temporary value created here +23 | blah = box ss as Box<Foo>; +24 | } | ^ temporary value dropped here while still borrowed -23 | } +25 | } | - temporary value needs to live until here error: aborting due to previous error diff --git a/src/test/ui/span/slice-borrow.rs b/src/test/ui/span/slice-borrow.rs index 4ca0ccaa731..1b022f23246 100644 --- a/src/test/ui/span/slice-borrow.rs +++ b/src/test/ui/span/slice-borrow.rs @@ -13,7 +13,7 @@ fn main() { let y; { - let x: &[isize] = &[1, 2, 3, 4, 5]; + let x: &[isize] = &vec![1, 2, 3, 4, 5]; y = &x[1..]; } } diff --git a/src/test/ui/span/slice-borrow.stderr b/src/test/ui/span/slice-borrow.stderr index b60ccd0fbf3..5e8edf80df6 100644 --- a/src/test/ui/span/slice-borrow.stderr +++ b/src/test/ui/span/slice-borrow.stderr @@ -1,13 +1,15 @@ error[E0597]: borrowed value does not live long enough --> $DIR/slice-borrow.rs:18:5 | -16 | let x: &[isize] = &[1, 2, 3, 4, 5]; - | --------------- temporary value created here +16 | let x: &[isize] = &vec![1, 2, 3, 4, 5]; + | ------------------- temporary value created here 17 | y = &x[1..]; 18 | } | ^ temporary value dropped here while still borrowed 19 | } | - temporary 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/visibility-ty-params.rs b/src/test/ui/span/visibility-ty-params.rs index 8d4817e80b9..2a4a5edd04c 100644 --- a/src/test/ui/span/visibility-ty-params.rs +++ b/src/test/ui/span/visibility-ty-params.rs @@ -13,11 +13,11 @@ macro_rules! m { } struct S<T>(T); -m!{ S<u8> } //~ ERROR generic arguments in visibility path +m!{ S<u8> } //~ ERROR unexpected generic arguments in path //~^ ERROR expected module, found struct `S` mod m { - m!{ m<> } //~ ERROR generic arguments in visibility path + m!{ m<> } //~ ERROR unexpected generic arguments in path } fn main() {} diff --git a/src/test/ui/span/visibility-ty-params.stderr b/src/test/ui/span/visibility-ty-params.stderr index 0460b7ca025..673b9a38e03 100644 --- a/src/test/ui/span/visibility-ty-params.stderr +++ b/src/test/ui/span/visibility-ty-params.stderr @@ -1,22 +1,14 @@ -error[E0577]: expected module, found struct `S` +error: unexpected generic arguments in path --> $DIR/visibility-ty-params.rs:16:5 | -16 | m!{ S<u8> } //~ ERROR generic arguments in visibility path - | -^^^^ - | | - | did you mean `m`? +16 | m!{ S<u8> } //~ ERROR unexpected generic arguments in path + | ^^^^^ -error: generic arguments in visibility path - --> $DIR/visibility-ty-params.rs:16:6 +error: unexpected generic arguments in path + --> $DIR/visibility-ty-params.rs:20:9 | -16 | m!{ S<u8> } //~ ERROR generic arguments in visibility path - | ^^^^ +20 | m!{ m<> } //~ ERROR unexpected generic arguments in path + | ^^^ -error: generic arguments in visibility path - --> $DIR/visibility-ty-params.rs:20:10 - | -20 | m!{ m<> } //~ ERROR generic arguments in visibility path - | ^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/union-sized-field.rs b/src/test/ui/union-sized-field.rs new file mode 100644 index 00000000000..eeca5ab7404 --- /dev/null +++ b/src/test/ui/union-sized-field.rs @@ -0,0 +1,26 @@ +// 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(untagged_unions)] + +union Foo<T: ?Sized> { + value: T, +} + +struct Foo2<T: ?Sized> { + value: T, + t: u32, +} + +enum Foo3<T: ?Sized> { + Value(T), +} + +fn main() {} diff --git a/src/test/ui/union-sized-field.stderr b/src/test/ui/union-sized-field.stderr new file mode 100644 index 00000000000..ea90d97c4c3 --- /dev/null +++ b/src/test/ui/union-sized-field.stderr @@ -0,0 +1,32 @@ +error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied + --> $DIR/union-sized-field.rs:14:5 + | +14 | value: T, + | ^^^^^^^^ `T` does not have a constant size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `T` + = help: consider adding a `where T: std::marker::Sized` bound + = note: no field of a union may have a dynamically sized type + +error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied + --> $DIR/union-sized-field.rs:18:5 + | +18 | value: T, + | ^^^^^^^^ `T` does not have a constant size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `T` + = help: consider adding a `where T: std::marker::Sized` bound + = note: only the last field of a struct may have a dynamically sized type + +error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied + --> $DIR/union-sized-field.rs:23:11 + | +23 | Value(T), + | ^^ `T` does not have a constant size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `T` + = help: consider adding a `where T: std::marker::Sized` bound + = note: no field of an enum variant may have a dynamically sized type + +error: aborting due to 3 previous errors + diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index b8efb88acfb..7a09ae48b91 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -94,6 +94,7 @@ static TARGETS: &'static [&'static str] = &[ "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", "x86_64-unknown-netbsd", + "x86_64-unknown-redox", ]; static MINGW: &'static [&'static str] = &[ @@ -181,15 +182,15 @@ fn main() { t!(io::stdin().read_to_string(&mut passphrase)); Builder { - rust_release: rust_release, - cargo_release: cargo_release, - rls_release: rls_release, - input: input, - output: output, + rust_release, + cargo_release, + rls_release, + input, + output, gpg_passphrase: passphrase, digests: BTreeMap::new(), - s3_address: s3_address, - date: date, + s3_address, + date, rust_version: String::new(), cargo_version: String::new(), rls_version: String::new(), diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 7704f7b1fd52607104cc7fdc435d636c9de1fe9 +Subproject 3d3f2c05d742e5f907e951aa8849b03f0bc1a89 diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index 0b9b9599be6..b7fb3670165 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -175,8 +175,8 @@ fn parse_expected(last_nonfollow_error: Option<usize>, msg); Some((which, Error { - line_num: line_num, - kind: kind, - msg: msg, + line_num, + kind, + msg, })) } diff --git a/src/tools/compiletest/src/json.rs b/src/tools/compiletest/src/json.rs index 23782c3ccc9..77ee93c3007 100644 --- a/src/tools/compiletest/src/json.rs +++ b/src/tools/compiletest/src/json.rs @@ -148,8 +148,8 @@ fn push_expected_errors(expected_errors: &mut Vec<Error>, let kind = ErrorKind::from_str(&diagnostic.level).ok(); expected_errors.push(Error { line_num: span.line_start, - kind: kind, - msg: msg, + kind, + msg, }); } } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 6fa758aeabe..15216f52d91 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -14,6 +14,7 @@ #![deny(warnings)] +#[cfg(any(target_os = "macos", target_os = "ios"))] extern crate libc; extern crate test; extern crate getopts; @@ -39,7 +40,6 @@ use util::logv; use self::header::EarlyProps; -pub mod procsrv; pub mod util; mod json; pub mod header; @@ -176,9 +176,9 @@ pub fn parse_config(args: Vec<String> ) -> Config { target_rustcflags: matches.opt_str("target-rustcflags"), target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), - gdb: gdb, - gdb_version: gdb_version, - gdb_native_rust: gdb_native_rust, + gdb, + gdb_version, + gdb_native_rust, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), system_llvm: matches.opt_present("system-llvm"), @@ -192,7 +192,7 @@ pub fn parse_config(args: Vec<String> ) -> Config { lldb_python_dir: matches.opt_str("lldb-python-dir"), verbose: matches.opt_present("verbose"), quiet: matches.opt_present("quiet"), - color: color, + color, remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from), cc: matches.opt_str("cc").unwrap(), @@ -470,8 +470,8 @@ pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn test::TestDescAndFn { desc: test::TestDesc { name: make_test_name(config, testpaths), - ignore: ignore, - should_panic: should_panic, + ignore, + should_panic, allow_fail: false, }, testfn: make_test_closure(config, testpaths), diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs deleted file mode 100644 index b6d89c1f51a..00000000000 --- a/src/tools/compiletest/src/procsrv.rs +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::env; -use std::ffi::OsString; -use std::io::prelude::*; -use std::io; -use std::path::PathBuf; -use std::process::{Child, Command, ExitStatus, Output, Stdio}; - -/// Get the name of the environment variable that holds dynamic library -/// locations -pub fn dylib_env_var() -> &'static str { - if cfg!(windows) { - "PATH" - } else if cfg!(target_os = "macos") { - "DYLD_LIBRARY_PATH" - } else if cfg!(target_os = "haiku") { - "LIBRARY_PATH" - } else { - "LD_LIBRARY_PATH" - } -} - -/// Add `lib_path` and `aux_path` (if it is `Some`) to the dynamic library -/// env var -fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) { - // Need to be sure to put both the lib_path and the aux path in the dylib - // search path for the child. - let var = dylib_env_var(); - let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new())) - .collect::<Vec<_>>(); - if let Some(p) = aux_path { - path.insert(0, PathBuf::from(p)) - } - path.insert(0, PathBuf::from(lib_path)); - - // Add the new dylib search path var - let newpath = env::join_paths(&path).unwrap(); - cmd.env(var, newpath); -} - -/// Represents exit status, stdout and stderr of a completed process -pub struct Result { - pub status: ExitStatus, - pub out: String, - pub err: String, -} - -/// Runs a test program -/// -/// # Params -/// - `lib_path` Path to search for required library -/// - `prog` command to run -/// - `aux_path` Optional extra path to search for required -/// auxiliary libraries -/// - `args` List of arguments to pass to `prog` -/// - `env` List of environment variables to set, `.0` is variable name, -/// `.1` is value -/// - `input` String to be fed as stdin -/// - `current_dir` Optional working dir to run command in -/// -pub fn run(lib_path: &str, - prog: &str, - aux_path: Option<&str>, - args: &[String], - env: Vec<(String, String)>, - input: Option<String>, - current_dir: Option<String>) - -> io::Result<Result> { - - let mut cmd = Command::new(prog); - cmd.args(args) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .stdin(Stdio::piped()); - - add_target_env(&mut cmd, lib_path, aux_path); - for (key, val) in env { - cmd.env(&key, &val); - } - if let Some(cwd) = current_dir { - cmd.current_dir(cwd); - } - - let mut process = cmd.spawn()?; - if let Some(input) = input { - process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); - } - let Output { status, stdout, stderr } = process.wait_with_output().unwrap(); - - Ok(Result { - status: status, - out: String::from_utf8(stdout).unwrap(), - err: String::from_utf8(stderr).unwrap(), - }) -} - -/// Same as `run`, but return process rather than waiting on completion -pub fn run_background(lib_path: &str, - prog: &str, - aux_path: Option<&str>, - args: &[String], - env: Vec<(String, String)>, - input: Option<String>, - current_dir: Option<String>) - -> io::Result<Child> { - - let mut cmd = Command::new(prog); - cmd.args(args) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()); - add_target_env(&mut cmd, lib_path, aux_path); - for (key, val) in env { - cmd.env(&key, &val); - } - if let Some(cwd) = current_dir { - cmd.current_dir(cwd); - } - - let mut process = cmd.spawn()?; - if let Some(input) = input { - process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); - } - - Ok(process) -} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 769748c63c0..d2a0c776b33 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -17,22 +17,35 @@ use errors::{self, ErrorKind, Error}; use filetime::FileTime; use json; use header::TestProps; -use procsrv; use test::TestPaths; use util::logv; +use std::collections::HashMap; use std::collections::HashSet; use std::env; +use std::ffi::OsString; use std::fs::{self, File, create_dir_all}; use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::{Path, PathBuf}; -use std::process::{Command, Output, ExitStatus}; +use std::process::{Command, Output, ExitStatus, Stdio}; use std::str; -use std::collections::HashMap; use extract_gdb_version; +/// The name of the environment variable that holds dynamic library locations. +pub fn dylib_env_var() -> &'static str { + if cfg!(windows) { + "PATH" + } else if cfg!(target_os = "macos") { + "DYLD_LIBRARY_PATH" + } else if cfg!(target_os = "haiku") { + "LIBRARY_PATH" + } else { + "LD_LIBRARY_PATH" + } +} + pub fn run(config: Config, testpaths: &TestPaths) { match &*config.target { @@ -59,7 +72,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { let base_cx = TestCx { config: &config, props: &base_props, - testpaths: testpaths, + testpaths, revision: None }; base_cx.init_all(); @@ -72,7 +85,7 @@ pub fn run(config: Config, testpaths: &TestPaths) { let rev_cx = TestCx { config: &config, props: &revision_props, - testpaths: testpaths, + testpaths, revision: Some(revision) }; rev_cx.run_revision(); @@ -325,37 +338,23 @@ impl<'test> TestCx<'test> { } } - fn print_source(&self, - src: String, - pretty_type: &str) - -> ProcRes { + fn print_source(&self, src: String, pretty_type: &str) -> ProcRes { let aux_dir = self.aux_output_dir_name(); - self.compose_and_run(self.make_pp_args(pretty_type.to_owned()), - self.props.exec_env.clone(), + + let mut rustc = Command::new(&self.config.rustc_path); + rustc.arg("-") + .arg("-Zunstable-options") + .args(&["--unpretty", &pretty_type]) + .args(&["--target", &self.config.target]) + .arg("-L").arg(&aux_dir) + .args(self.split_maybe_args(&self.config.target_rustcflags)) + .args(&self.props.compile_flags) + .envs(self.props.exec_env.clone()); + + self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - Some(src), - None) - } - - fn make_pp_args(&self, - pretty_type: String) - -> ProcArgs { - let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec!["-".to_owned(), - "-Zunstable-options".to_owned(), - "--unpretty".to_owned(), - pretty_type, - format!("--target={}", self.config.target), - "-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; - args.extend(self.split_maybe_args(&self.config.target_rustcflags)); - args.extend(self.props.compile_flags.iter().cloned()); - ProcArgs { - prog: self.config.rustc_path.to_str().unwrap().to_owned(), - args: args, - } + Some(src)) } fn compare_source(&self, @@ -379,45 +378,35 @@ actual:\n\ } fn typecheck_source(&self, src: String) -> ProcRes { - let args = self.make_typecheck_args(); - self.compose_and_run_compiler(args, Some(src)) - } + let mut rustc = Command::new(&self.config.rustc_path); + + let out_dir = self.output_base_name().with_extension("pretty-out"); + let _ = fs::remove_dir_all(&out_dir); + create_dir_all(&out_dir).unwrap(); - fn make_typecheck_args(&self) -> ProcArgs { - let aux_dir = self.aux_output_dir_name(); let target = if self.props.force_host { &*self.config.host } else { &*self.config.target }; - let out_dir = self.output_base_name().with_extension("pretty-out"); - let _ = fs::remove_dir_all(&out_dir); - create_dir_all(&out_dir).unwrap(); + let aux_dir = self.aux_output_dir_name(); + + rustc.arg("-") + .arg("-Zno-trans") + .arg("--out-dir").arg(&out_dir) + .arg(&format!("--target={}", target)) + .arg("-L").arg(&self.config.build_base) + .arg("-L").arg(aux_dir); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec!["-".to_owned(), - "-Zno-trans".to_owned(), - "--out-dir".to_owned(), - out_dir.to_str().unwrap().to_owned(), - format!("--target={}", target), - "-L".to_owned(), - self.config.build_base.to_str().unwrap().to_owned(), - "-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; if let Some(revision) = self.revision { - args.extend(vec![ - "--cfg".to_string(), - revision.to_string(), - ]); - } - args.extend(self.split_maybe_args(&self.config.target_rustcflags)); - args.extend(self.props.compile_flags.iter().cloned()); - // FIXME (#9639): This needs to handle non-utf8 paths - ProcArgs { - prog: self.config.rustc_path.to_str().unwrap().to_owned(), - args: args, + rustc.args(&["--cfg", revision]); } + + rustc.args(self.split_maybe_args(&self.config.target_rustcflags)); + rustc.args(&self.props.compile_flags); + + self.compose_and_run_compiler(rustc, Some(src)) } fn run_debuginfo_gdb_test(&self) { @@ -500,32 +489,19 @@ actual:\n\ debug!("script_str = {}", script_str); self.dump_output_file(&script_str, "debugger.script"); + let adb_path = &self.config.adb_path; - procsrv::run("", - &self.config.adb_path, - None, - &[ - "push".to_owned(), - exe_file.to_str().unwrap().to_owned(), - self.config.adb_test_dir.clone() - ], - Vec::new(), - None, - None) - .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); - - procsrv::run("", - &self.config.adb_path, - None, - &[ - "forward".to_owned(), - "tcp:5039".to_owned(), - "tcp:5039".to_owned() - ], - Vec::new(), - None, - None) - .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); + Command::new(adb_path) + .arg("push") + .arg(&exe_file) + .arg(&self.config.adb_test_dir) + .status() + .expect(&format!("failed to exec `{:?}`", adb_path)); + + Command::new(adb_path) + .args(&["forward", "tcp:5039", "tcp:5039"]) + .status() + .expect(&format!("failed to exec `{:?}`", adb_path)); let adb_arg = format!("export LD_LIBRARY_PATH={}; \ gdbserver{} :5039 {}/{}", @@ -537,23 +513,17 @@ actual:\n\ .unwrap()); debug!("adb arg: {}", adb_arg); - let mut process = procsrv::run_background("", - &self.config.adb_path - , - None, - &[ - "shell".to_owned(), - adb_arg.clone() - ], - Vec::new(), - None, - None) - .expect(&format!("failed to exec `{:?}`", self.config.adb_path)); + let mut adb = Command::new(adb_path) + .args(&["shell", &adb_arg]) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .expect(&format!("failed to exec `{:?}`", adb_path)); // Wait for the gdbserver to print out "Listening on port ..." // at which point we know that it's started and then we can // execute the debugger below. - let mut stdout = BufReader::new(process.stdout.take().unwrap()); + let mut stdout = BufReader::new(adb.stdout.take().unwrap()); let mut line = String::new(); loop { line.truncate(0); @@ -574,33 +544,29 @@ actual:\n\ let mut gdb_path = tool_path; gdb_path.push_str("/bin/gdb"); - let procsrv::Result { - out, - err, - status - } = procsrv::run("", - &gdb_path, - None, - &debugger_opts, - Vec::new(), - None, - None) + let Output { + status, + stdout, + stderr + } = Command::new(&gdb_path) + .args(&debugger_opts) + .output() .expect(&format!("failed to exec `{:?}`", gdb_path)); let cmdline = { - let cmdline = self.make_cmdline("", - &format!("{}-gdb", self.config.target), - &debugger_opts); + let mut gdb = Command::new(&format!("{}-gdb", self.config.target)); + gdb.args(&debugger_opts); + let cmdline = self.make_cmdline(&gdb, ""); logv(self.config, format!("executing {}", cmdline)); cmdline }; debugger_run_result = ProcRes { - status: status, - stdout: out, - stderr: err, - cmdline: cmdline + status, + stdout: String::from_utf8(stdout).unwrap(), + stderr: String::from_utf8(stderr).unwrap(), + cmdline, }; - if process.kill().is_err() { + if adb.kill().is_err() { println!("Adb process is already finished."); } } @@ -679,19 +645,14 @@ actual:\n\ "-nx".to_owned(), format!("-command={}", debugger_script.to_str().unwrap())]; - let proc_args = ProcArgs { - prog: self.config.gdb.as_ref().unwrap().to_owned(), - args: debugger_opts, - }; - - let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)]; + let mut gdb = Command::new(self.config.gdb.as_ref().unwrap()); + gdb.args(&debugger_opts) + .env("PYTHONPATH", rust_pp_module_abs_path); debugger_run_result = - self.compose_and_run(proc_args, - environment, + self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, - None, None); } } @@ -852,7 +813,7 @@ actual:\n\ self.dump_output(&out, &err); ProcRes { - status: status, + status, stdout: out, stderr: err, cmdline: format!("{:?}", cmd) @@ -899,9 +860,9 @@ actual:\n\ } DebuggerCommands { - commands: commands, - check_lines: check_lines, - breakpoint_lines: breakpoint_lines, + commands, + check_lines, + breakpoint_lines, } } @@ -1154,10 +1115,11 @@ actual:\n\ } fn compile_test(&self) -> ProcRes { - let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut extra_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; + let mut rustc = self.make_compile_args( + &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name())); + + rustc.arg("-L").arg(&self.aux_output_dir_name()); + match self.config.mode { CompileFail | Ui => { // compile-fail and ui tests tend to have tons of unused code as @@ -1165,15 +1127,12 @@ actual:\n\ // want to actually assert warnings about all this code. Instead // let's just ignore unused code warnings by defaults and tests // can turn it back on if needed. - extra_args.push("-A".to_owned()); - extra_args.push("unused".to_owned()); + rustc.args(&["-A", "unused"]); } _ => {} } - let args = self.make_compile_args(extra_args, - &self.testpaths.file, - TargetLocation::ThisFile(self.make_exe_name())); - self.compose_and_run_compiler(args, None) + + self.compose_and_run_compiler(rustc, None) } fn document(&self, out_dir: &Path) -> ProcRes { @@ -1197,22 +1156,20 @@ actual:\n\ } let aux_dir = self.aux_output_dir_name(); - let mut args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned(), - "-o".to_owned(), - out_dir.to_str().unwrap().to_owned(), - self.testpaths.file.to_str().unwrap().to_owned()]; - args.extend(self.props.compile_flags.iter().cloned()); - let args = ProcArgs { - prog: self.config.rustdoc_path - .as_ref().expect("--rustdoc-path passed").to_str().unwrap().to_owned(), - args: args, - }; - self.compose_and_run_compiler(args, None) + + let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed"); + let mut rustdoc = Command::new(rustdoc_path); + + rustdoc.arg("-L").arg(aux_dir) + .arg("-o").arg(out_dir) + .arg(&self.testpaths.file) + .args(&self.props.compile_flags); + + self.compose_and_run_compiler(rustdoc, None) } fn exec_compiled_test(&self) -> ProcRes { - let env = self.props.exec_env.clone(); + let env = &self.props.exec_env; match &*self.config.target { // This is pretty similar to below, we're transforming: @@ -1230,41 +1187,39 @@ actual:\n\ // the process) and then report back the same result. _ if self.config.remote_test_client.is_some() => { let aux_dir = self.aux_output_dir_name(); - let mut args = self.make_run_args(); - let mut program = args.prog.clone(); + let ProcArgs { mut prog, args } = self.make_run_args(); if let Ok(entries) = aux_dir.read_dir() { for entry in entries { let entry = entry.unwrap(); if !entry.path().is_file() { continue } - program.push_str(":"); - program.push_str(entry.path().to_str().unwrap()); + prog.push_str(":"); + prog.push_str(entry.path().to_str().unwrap()); } } - args.args.insert(0, program); - args.args.insert(0, "run".to_string()); - args.prog = self.config.remote_test_client.clone().unwrap() - .into_os_string().into_string().unwrap(); - self.compose_and_run(args, - env, + let mut test_client = Command::new( + self.config.remote_test_client.as_ref().unwrap()); + test_client + .args(&["run", &prog]) + .args(args) + .envs(env.clone()); + self.compose_and_run(test_client, self.config.run_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - None, None) } _ => { let aux_dir = self.aux_output_dir_name(); - let working_dir = - Some(self.output_base_name() - .parent().unwrap() - .to_str().unwrap().to_owned()); - self.compose_and_run(self.make_run_args(), - env, + let ProcArgs { prog, args } = self.make_run_args(); + let mut program = Command::new(&prog); + program.args(args) + .current_dir(&self.output_base_name().parent().unwrap()) + .envs(env.clone()); + self.compose_and_run(program, self.config.run_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - None, - working_dir) + None) } } } @@ -1293,23 +1248,33 @@ actual:\n\ } } - fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> ProcRes { + fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes { if !self.props.aux_builds.is_empty() { create_dir_all(&self.aux_output_dir_name()).unwrap(); } let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let extra_link_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; for rel_ab in &self.props.aux_builds { let aux_testpaths = self.compute_aux_test_paths(rel_ab); let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); - let mut crate_type = if aux_props.no_prefer_dynamic { - Vec::new() + let aux_output = { + let f = self.make_lib_name(&self.testpaths.file); + let parent = f.parent().unwrap(); + TargetLocation::ThisDirectory(parent.to_path_buf()) + }; + let aux_cx = TestCx { + config: self.config, + props: &aux_props, + testpaths: &aux_testpaths, + revision: self.revision + }; + let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output); + + let crate_type = if aux_props.no_prefer_dynamic { + None } else if (self.config.target.contains("musl") && !aux_props.force_host) || self.config.target.contains("emscripten") { // We primarily compile all auxiliary libraries as dynamic libraries @@ -1321,28 +1286,20 @@ actual:\n\ // dynamic libraries so we just go back to building a normal library. Note, // however, that for MUSL if the library is built with `force_host` then // it's ok to be a dylib as the host should always support dylibs. - vec!["--crate-type=lib".to_owned()] + Some("lib") } else { - vec!["--crate-type=dylib".to_owned()] - }; - crate_type.extend(extra_link_args.clone()); - let aux_output = { - let f = self.make_lib_name(&self.testpaths.file); - let parent = f.parent().unwrap(); - TargetLocation::ThisDirectory(parent.to_path_buf()) - }; - let aux_cx = TestCx { - config: self.config, - props: &aux_props, - testpaths: &aux_testpaths, - revision: self.revision + Some("dylib") }; - let aux_args = aux_cx.make_compile_args(crate_type, &aux_testpaths.file, aux_output); - let auxres = aux_cx.compose_and_run(aux_args, - Vec::new(), + + if let Some(crate_type) = crate_type { + aux_rustc.args(&["--crate-type", crate_type]); + } + + aux_rustc.arg("-L").arg(&aux_dir); + + let auxres = aux_cx.compose_and_run(aux_rustc, aux_cx.config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - None, None); if !auxres.status.success() { self.fatal_proc_rec( @@ -1352,40 +1309,65 @@ actual:\n\ } } - self.compose_and_run(args, - self.props.rustc_env.clone(), + rustc.envs(self.props.rustc_env.clone()); + self.compose_and_run(rustc, self.config.compile_lib_path.to_str().unwrap(), Some(aux_dir.to_str().unwrap()), - input, - None) + input) } fn compose_and_run(&self, - ProcArgs{ args, prog }: ProcArgs, - procenv: Vec<(String, String)> , + mut command: Command, lib_path: &str, aux_path: Option<&str>, - input: Option<String>, - working_dir: Option<String>) -> ProcRes { - self.program_output(lib_path, prog, aux_path, args, procenv, input, working_dir) - } + input: Option<String>) -> ProcRes { + let cmdline = + { + let cmdline = self.make_cmdline(&command, lib_path); + logv(self.config, format!("executing {}", cmdline)); + cmdline + }; - fn make_compile_args(&self, - extras: Vec<String> , - input_file: &Path, - output_file: TargetLocation) - -> ProcArgs - { - let target = if self.props.force_host { - &*self.config.host - } else { - &*self.config.target + command + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .stdin(Stdio::piped()); + + // Need to be sure to put both the lib_path and the aux path in the dylib + // search path for the child. + let mut path = env::split_paths(&env::var_os(dylib_env_var()).unwrap_or(OsString::new())) + .collect::<Vec<_>>(); + if let Some(p) = aux_path { + path.insert(0, PathBuf::from(p)) + } + path.insert(0, PathBuf::from(lib_path)); + + // Add the new dylib search path var + let newpath = env::join_paths(&path).unwrap(); + command.env(dylib_env_var(), newpath); + + let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command)); + if let Some(input) = input { + child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap(); + } + let Output { status, stdout, stderr } = child.wait_with_output().unwrap(); + + let result = ProcRes { + status, + stdout: String::from_utf8(stdout).unwrap(), + stderr: String::from_utf8(stderr).unwrap(), + cmdline, }; - // FIXME (#9639): This needs to handle non-utf8 paths - let mut args = vec![input_file.to_str().unwrap().to_owned(), - "-L".to_owned(), - self.config.build_base.to_str().unwrap().to_owned()]; + self.dump_output(&result.stdout, &result.stderr); + + result + } + + fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command { + let mut rustc = Command::new(&self.config.rustc_path); + rustc.arg(input_file) + .arg("-L").arg(&self.config.build_base); // Optionally prevent default --target if specified in test compile-flags. let custom_target = self.props.compile_flags @@ -1393,26 +1375,23 @@ actual:\n\ .fold(false, |acc, x| acc || x.starts_with("--target")); if !custom_target { - args.extend(vec![ - format!("--target={}", target), - ]); + let target = if self.props.force_host { + &*self.config.host + } else { + &*self.config.target + }; + + rustc.arg(&format!("--target={}", target)); } if let Some(revision) = self.revision { - args.extend(vec![ - "--cfg".to_string(), - revision.to_string(), - ]); + rustc.args(&["--cfg", revision]); } if let Some(ref incremental_dir) = self.props.incremental_dir { - args.extend(vec![ - "-Z".to_string(), - format!("incremental={}", incremental_dir.display()), - ]); + rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]); } - match self.config.mode { CompileFail | ParseFail | @@ -1421,19 +1400,14 @@ actual:\n\ // fashion, then you want JSON mode. Old-skool error // patterns still match the raw compiler output. if self.props.error_patterns.is_empty() { - args.extend(["--error-format", - "json"] - .iter() - .map(|s| s.to_string())); + rustc.args(&["--error-format", "json"]); } } MirOpt => { - args.extend(["-Zdump-mir=all", - "-Zmir-opt-level=3", - "-Zdump-mir-exclude-pass-number"] - .iter() - .map(|s| s.to_string())); - + rustc.args(&[ + "-Zdump-mir=all", + "-Zmir-opt-level=3", + "-Zdump-mir-exclude-pass-number"]); let mir_dump_dir = self.get_mir_dump_dir(); create_dir_all(mir_dump_dir.as_path()).unwrap(); @@ -1441,7 +1415,7 @@ actual:\n\ dir_opt.push_str(mir_dump_dir.to_str().unwrap()); debug!("dir_opt: {:?}", dir_opt); - args.push(dir_opt); + rustc.arg(dir_opt); } RunPass | RunFail | @@ -1458,32 +1432,28 @@ actual:\n\ } } - args.extend_from_slice(&extras); if !self.props.no_prefer_dynamic { - args.push("-C".to_owned()); - args.push("prefer-dynamic".to_owned()); + rustc.args(&["-C", "prefer-dynamic"]); } - let path = match output_file { + + match output_file { TargetLocation::ThisFile(path) => { - args.push("-o".to_owned()); - path + rustc.arg("-o").arg(path); } TargetLocation::ThisDirectory(path) => { - args.push("--out-dir".to_owned()); - path + rustc.arg("--out-dir").arg(path); } - }; - args.push(path.to_str().unwrap().to_owned()); + } + if self.props.force_host { - args.extend(self.split_maybe_args(&self.config.host_rustcflags)); + rustc.args(self.split_maybe_args(&self.config.host_rustcflags)); } else { - args.extend(self.split_maybe_args(&self.config.target_rustcflags)); - } - args.extend(self.props.compile_flags.iter().cloned()); - ProcArgs { - prog: self.config.rustc_path.to_str().unwrap().to_owned(), - args: args, + rustc.args(self.split_maybe_args(&self.config.target_rustcflags)); } + + rustc.args(&self.props.compile_flags); + + rustc } fn make_lib_name(&self, auxfile: &Path) -> PathBuf { @@ -1532,8 +1502,8 @@ actual:\n\ let prog = args.remove(0); ProcArgs { - prog: prog, - args: args, + prog, + args, } } @@ -1554,50 +1524,12 @@ actual:\n\ } } - fn program_output(&self, - lib_path: &str, - prog: String, - aux_path: Option<&str>, - args: Vec<String>, - env: Vec<(String, String)>, - input: Option<String>, - working_dir: Option<String>) - -> ProcRes { - let cmdline = - { - let cmdline = self.make_cmdline(lib_path, - &prog, - &args); - logv(self.config, format!("executing {}", cmdline)); - cmdline - }; - - let procsrv::Result { - out, - err, - status - } = procsrv::run(lib_path, - &prog, - aux_path, - &args, - env, - input, - working_dir).expect(&format!("failed to exec `{}`", prog)); - self.dump_output(&out, &err); - ProcRes { - status: status, - stdout: out, - stderr: err, - cmdline: cmdline, - } - } - - fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String { + fn make_cmdline(&self, command: &Command, libpath: &str) -> String { use util; // Linux and mac don't require adjusting the library search path if cfg!(unix) { - format!("{} {}", prog, args.join(" ")) + format!("{:?}", command) } else { // Build the LD_LIBRARY_PATH variable as it would be seen on the command line // for diagnostic purposes @@ -1605,7 +1537,7 @@ actual:\n\ format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path)) } - format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" ")) + format!("{} {:?}", lib_path_cmd_prefix(libpath), command) } } @@ -1723,30 +1655,22 @@ actual:\n\ fn compile_test_and_save_ir(&self) -> ProcRes { let aux_dir = self.aux_output_dir_name(); - // FIXME (#9639): This needs to handle non-utf8 paths - let mut link_args = vec!["-L".to_owned(), - aux_dir.to_str().unwrap().to_owned()]; - let llvm_args = vec!["--emit=llvm-ir".to_owned(),]; - link_args.extend(llvm_args); - let args = self.make_compile_args(link_args, - &self.testpaths.file, - TargetLocation::ThisDirectory( - self.output_base_name().parent() - .unwrap() - .to_path_buf())); - self.compose_and_run_compiler(args, None) + + let output_file = TargetLocation::ThisDirectory( + self.output_base_name().parent().unwrap().to_path_buf()); + let mut rustc = self.make_compile_args(&self.testpaths.file, output_file); + rustc.arg("-L").arg(aux_dir) + .arg("--emit=llvm-ir"); + + self.compose_and_run_compiler(rustc, None) } fn check_ir_with_filecheck(&self) -> ProcRes { let irfile = self.output_base_name().with_extension("ll"); - let prog = self.config.llvm_filecheck.as_ref().unwrap(); - let proc_args = ProcArgs { - // FIXME (#9639): This needs to handle non-utf8 paths - prog: prog.to_str().unwrap().to_owned(), - args: vec![format!("-input-file={}", irfile.to_str().unwrap()), - self.testpaths.file.to_str().unwrap().to_owned()] - }; - self.compose_and_run(proc_args, Vec::new(), "", None, None, None) + let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap()); + filecheck.arg("--input-file").arg(irfile) + .arg(&self.testpaths.file); + self.compose_and_run(filecheck, "", None, None) } fn run_codegen_test(&self) { @@ -2179,7 +2103,7 @@ actual:\n\ .env("RUSTDOC", cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed"))) .env("TMPDIR", &tmpdir) - .env("LD_LIB_PATH_ENVVAR", procsrv::dylib_env_var()) + .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path)) .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path)) .env("LLVM_COMPONENTS", &self.config.llvm_components) diff --git a/src/tools/rls b/src/tools/rls -Subproject 5d4bbd9052fe2af849a7d017b85df98ad002c20 +Subproject 25ffb3a3d7809b4fa112f3e04e926eb539dd5e9 |
