diff options
Diffstat (limited to 'src')
500 files changed, 5238 insertions, 3251 deletions
diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 6bbf0928783..546e73e33d7 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -2,11 +2,24 @@ FROM ubuntu:16.04 RUN apt-get update && apt-get install -y --no-install-recommends \ g++ \ + automake \ + bison \ + bzip2 \ + flex \ + help2man \ + libtool-bin \ + texinfo \ + unzip \ + wget \ + xz-utils \ + libncurses-dev \ + gawk \ make \ file \ curl \ ca-certificates \ python2.7 \ + python3 \ git \ cmake \ sudo \ @@ -35,6 +48,18 @@ RUN add-apt-repository ppa:team-gcc-arm-embedded/ppa && \ apt-get update && \ apt-get install -y --no-install-recommends gcc-arm-embedded +COPY scripts/rustbuild-setup.sh dist-various-1/build-riscv-toolchain.sh dist-various-1/riscv64-unknown-linux-gnu.config dist-various-1/crosstool-ng.sh /build/ +RUN ./crosstool-ng.sh + +# Crosstool-ng will refuse to build as root +RUN sh ./rustbuild-setup.sh +USER rustbuild + +RUN ./build-riscv-toolchain.sh + +USER root +ENV PATH=/x-tools/riscv64-unknown-linux-gnu/bin:$PATH + COPY dist-various-1/build-rumprun.sh /build RUN ./build-rumprun.sh @@ -129,6 +154,7 @@ ENV TARGETS=$TARGETS,riscv32imc-unknown-none-elf ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf ENV TARGETS=$TARGETS,riscv64gc-unknown-none-elf +ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-gnu ENV TARGETS=$TARGETS,armebv7r-none-eabi ENV TARGETS=$TARGETS,armebv7r-none-eabihf ENV TARGETS=$TARGETS,armv7r-none-eabi @@ -147,6 +173,9 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-gcc \ AR_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-ar \ CXX_thumbv7neon_unknown_linux_gnueabihf=arm-linux-gnueabihf-g++ \ + CC_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-gcc \ + AR_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-ar \ + CXX_riscv64gc_unknown_linux_gnu=riscv64-unknown-linux-gnu-g++ \ CC_riscv32i_unknown_none_elf=false \ CC_riscv32imc_unknown_none_elf=false \ CC_riscv32imac_unknown_none_elf=false \ diff --git a/src/ci/docker/dist-various-1/build-riscv-toolchain.sh b/src/ci/docker/dist-various-1/build-riscv-toolchain.sh new file mode 100755 index 00000000000..9cb5700b3b6 --- /dev/null +++ b/src/ci/docker/dist-various-1/build-riscv-toolchain.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + rm /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + set -x +} + +mkdir -p /tmp/build-riscv +cp riscv64-unknown-linux-gnu.config /tmp/build-riscv/.config +cd /tmp/build-riscv +hide_output ct-ng build +cd .. +rm -rf build-riscv diff --git a/src/ci/docker/dist-various-1/crosstool-ng.sh b/src/ci/docker/dist-various-1/crosstool-ng.sh new file mode 100755 index 00000000000..b01fdd0bf65 --- /dev/null +++ b/src/ci/docker/dist-various-1/crosstool-ng.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -ex + +# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz +url="https://ci-mirrors.rust-lang.org/rustc/crosstool-ng-1.24.0.tar.gz" +curl -Lf $url | tar xzf - +cd crosstool-ng-crosstool-ng-1.24.0 +./bootstrap +./configure --prefix=/usr/local +make -j$(nproc) +make install +cd .. +rm -rf crosstool-ng-crosstool-ng-1.24.0 diff --git a/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config b/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config new file mode 100644 index 00000000000..dd06065b197 --- /dev/null +++ b/src/ci/docker/dist-various-1/riscv64-unknown-linux-gnu.config @@ -0,0 +1,908 @@ +# +# Automatically generated file; DO NOT EDIT. +# crosstool-NG Configuration +# +CT_CONFIGURE_has_static_link=y +CT_CONFIGURE_has_cxx11=y +CT_CONFIGURE_has_wget=y +CT_CONFIGURE_has_curl=y +CT_CONFIGURE_has_make_3_81_or_newer=y +CT_CONFIGURE_has_make_4_0_or_newer=y +CT_CONFIGURE_has_libtool_2_4_or_newer=y +CT_CONFIGURE_has_libtoolize_2_4_or_newer=y +CT_CONFIGURE_has_autoconf_2_65_or_newer=y +CT_CONFIGURE_has_autoreconf_2_65_or_newer=y +CT_CONFIGURE_has_automake_1_15_or_newer=y +CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y +CT_CONFIGURE_has_python_3_4_or_newer=y +CT_CONFIGURE_has_bison_2_7_or_newer=y +CT_CONFIGURE_has_python=y +CT_CONFIGURE_has_dtc=y +CT_CONFIGURE_has_svn=y +CT_CONFIGURE_has_git=y +CT_CONFIGURE_has_md5sum=y +CT_CONFIGURE_has_sha1sum=y +CT_CONFIGURE_has_sha256sum=y +CT_CONFIGURE_has_sha512sum=y +CT_CONFIGURE_has_install_with_strip_program=y +CT_CONFIG_VERSION_CURRENT="3" +CT_CONFIG_VERSION="3" +CT_MODULES=y + +# +# Paths and misc options +# + +# +# crosstool-NG behavior +# +# CT_OBSOLETE is not set +CT_EXPERIMENTAL=y +# CT_ALLOW_BUILD_AS_ROOT is not set +# CT_DEBUG_CT is not set + +# +# Paths +# +CT_LOCAL_TARBALLS_DIR="${HOME}/src" +CT_SAVE_TARBALLS=y +# CT_TARBALLS_BUILDROOT_LAYOUT is not set +CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}" +CT_PREFIX_DIR="/x-tools/${CT_TARGET}" +CT_RM_RF_PREFIX_DIR=y +CT_REMOVE_DOCS=y +CT_INSTALL_LICENSES=y +CT_PREFIX_DIR_RO=y +CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y +# CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set + +# +# Downloading +# +CT_DOWNLOAD_AGENT_WGET=y +# CT_DOWNLOAD_AGENT_CURL is not set +# CT_DOWNLOAD_AGENT_NONE is not set +# CT_FORBID_DOWNLOAD is not set +# CT_FORCE_DOWNLOAD is not set +CT_CONNECT_TIMEOUT=10 +CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary" +# CT_ONLY_DOWNLOAD is not set +# CT_USE_MIRROR is not set +CT_VERIFY_DOWNLOAD_DIGEST=y +CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y +# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set +# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set +# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set +CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512" +# CT_VERIFY_DOWNLOAD_SIGNATURE is not set + +# +# Extracting +# +# CT_FORCE_EXTRACT is not set +CT_OVERRIDE_CONFIG_GUESS_SUB=y +# CT_ONLY_EXTRACT is not set +CT_PATCH_BUNDLED=y +# CT_PATCH_LOCAL is not set +# CT_PATCH_BUNDLED_LOCAL is not set +# CT_PATCH_LOCAL_BUNDLED is not set +# CT_PATCH_NONE is not set +CT_PATCH_ORDER="bundled" + +# +# Build behavior +# +CT_PARALLEL_JOBS=0 +CT_LOAD="" +CT_USE_PIPES=y +CT_EXTRA_CFLAGS_FOR_BUILD="" +CT_EXTRA_LDFLAGS_FOR_BUILD="" +CT_EXTRA_CFLAGS_FOR_HOST="" +CT_EXTRA_LDFLAGS_FOR_HOST="" +# CT_CONFIG_SHELL_SH is not set +# CT_CONFIG_SHELL_ASH is not set +CT_CONFIG_SHELL_BASH=y +# CT_CONFIG_SHELL_CUSTOM is not set +CT_CONFIG_SHELL="${bash}" + +# +# Logging +# +# CT_LOG_ERROR is not set +# CT_LOG_WARN is not set +# CT_LOG_INFO is not set +# CT_LOG_EXTRA is not set +CT_LOG_ALL=y +# CT_LOG_DEBUG is not set +CT_LOG_LEVEL_MAX="ALL" +# CT_LOG_SEE_TOOLS_WARN is not set +CT_LOG_TO_FILE=y +CT_LOG_FILE_COMPRESS=y + +# +# Target options +# +# CT_ARCH_ALPHA is not set +# CT_ARCH_ARC is not set +# CT_ARCH_ARM is not set +# CT_ARCH_AVR is not set +# CT_ARCH_M68K is not set +# CT_ARCH_MICROBLAZE is not set +# CT_ARCH_MIPS is not set +# CT_ARCH_MOXIE is not set +# CT_ARCH_MSP430 is not set +# CT_ARCH_NIOS2 is not set +# CT_ARCH_POWERPC is not set +CT_ARCH_RISCV=y +# CT_ARCH_S390 is not set +# CT_ARCH_SH is not set +# CT_ARCH_SPARC is not set +# CT_ARCH_X86 is not set +# CT_ARCH_XTENSA is not set +CT_ARCH="riscv" +CT_ARCH_CHOICE_KSYM="RISCV" +CT_ARCH_TUNE="" +CT_ARCH_RISCV_SHOW=y + +# +# Options for riscv +# +CT_ARCH_RISCV_PKG_KSYM="" +CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA" +CT_ARCH_SUFFIX="" +# CT_OMIT_TARGET_VENDOR is not set + +# +# Generic target options +# +# CT_MULTILIB is not set +# CT_DEMULTILIB is not set +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_USE_MMU=y +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_BITNESS=64 +# CT_ARCH_32 is not set +CT_ARCH_64=y + +# +# Target optimisations +# +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_ABI=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_ARCH="rv64gc" +CT_ARCH_ABI="" +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" + +# +# Toolchain options +# + +# +# General toolchain options +# +CT_FORCE_SYSROOT=y +CT_USE_SYSROOT=y +CT_SYSROOT_NAME="sysroot" +CT_SYSROOT_DIR_PREFIX="" +CT_WANTS_STATIC_LINK=y +CT_WANTS_STATIC_LINK_CXX=y +# CT_STATIC_TOOLCHAIN is not set +CT_SHOW_CT_VERSION=y +CT_TOOLCHAIN_PKGVERSION="" +CT_TOOLCHAIN_BUGURL="" + +# +# Tuple completion and aliasing +# +CT_TARGET_VENDOR="unknown" +CT_TARGET_ALIAS_SED_EXPR="" +CT_TARGET_ALIAS="" + +# +# Toolchain type +# +# CT_NATIVE is not set +CT_CROSS=y +# CT_CROSS_NATIVE is not set +# CT_CANADIAN is not set +CT_TOOLCHAIN_TYPE="cross" + +# +# Build system +# +CT_BUILD="" +CT_BUILD_PREFIX="" +CT_BUILD_SUFFIX="" + +# +# Misc options +# +# CT_TOOLCHAIN_ENABLE_NLS is not set + +# +# Operating System +# +CT_KERNEL_SUPPORTS_SHARED_LIBS=y +# CT_KERNEL_BARE_METAL is not set +CT_KERNEL_LINUX=y +CT_KERNEL="linux" +CT_KERNEL_CHOICE_KSYM="LINUX" +CT_KERNEL_LINUX_SHOW=y + +# +# Options for linux +# +CT_KERNEL_LINUX_PKG_KSYM="LINUX" +CT_LINUX_DIR_NAME="linux" +CT_LINUX_PKG_NAME="linux" +CT_LINUX_SRC_RELEASE=y +# CT_LINUX_SRC_DEVEL is not set +# CT_LINUX_SRC_CUSTOM is not set +CT_LINUX_PATCH_GLOBAL=y +# CT_LINUX_PATCH_BUNDLED is not set +# CT_LINUX_PATCH_LOCAL is not set +# CT_LINUX_PATCH_BUNDLED_LOCAL is not set +# CT_LINUX_PATCH_LOCAL_BUNDLED is not set +# CT_LINUX_PATCH_NONE is not set +CT_LINUX_PATCH_ORDER="global" +CT_LINUX_V_4_20=y +# CT_LINUX_V_4_19 is not set +# CT_LINUX_V_4_18 is not set +# CT_LINUX_V_4_17 is not set +# CT_LINUX_V_4_16 is not set +# CT_LINUX_V_4_15 is not set +# CT_LINUX_V_4_14 is not set +# CT_LINUX_V_4_13 is not set +# CT_LINUX_V_4_12 is not set +# CT_LINUX_V_4_11 is not set +# CT_LINUX_V_4_10 is not set +# CT_LINUX_V_4_9 is not set +# CT_LINUX_V_4_4 is not set +# CT_LINUX_V_4_1 is not set +# CT_LINUX_V_3_16 is not set +# CT_LINUX_V_3_13 is not set +# CT_LINUX_V_3_12 is not set +# CT_LINUX_V_3_10 is not set +# CT_LINUX_V_3_4 is not set +# CT_LINUX_V_3_2 is not set +# CT_LINUX_NO_VERSIONS is not set +CT_LINUX_VERSION="4.20.8" +CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})" +CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign" +CT_LINUX_later_than_4_8=y +CT_LINUX_4_8_or_later=y +CT_LINUX_later_than_3_7=y +CT_LINUX_3_7_or_later=y +CT_LINUX_later_than_3_2=y +CT_LINUX_3_2_or_later=y +CT_LINUX_REQUIRE_3_2_or_later=y +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y +CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS" + +# +# Common kernel options +# +CT_SHARED_LIBS=y + +# +# Binary utilities +# +CT_ARCH_BINFMT_ELF=y +CT_BINUTILS_BINUTILS=y +CT_BINUTILS="binutils" +CT_BINUTILS_CHOICE_KSYM="BINUTILS" +CT_BINUTILS_BINUTILS_SHOW=y + +# +# Options for binutils +# +CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS" +CT_BINUTILS_DIR_NAME="binutils" +CT_BINUTILS_USE_GNU=y +CT_BINUTILS_USE="BINUTILS" +CT_BINUTILS_PKG_NAME="binutils" +CT_BINUTILS_SRC_RELEASE=y +# CT_BINUTILS_SRC_DEVEL is not set +# CT_BINUTILS_SRC_CUSTOM is not set +CT_BINUTILS_PATCH_GLOBAL=y +# CT_BINUTILS_PATCH_BUNDLED is not set +# CT_BINUTILS_PATCH_LOCAL is not set +# CT_BINUTILS_PATCH_BUNDLED_LOCAL is not set +# CT_BINUTILS_PATCH_LOCAL_BUNDLED is not set +# CT_BINUTILS_PATCH_NONE is not set +CT_BINUTILS_PATCH_ORDER="global" +CT_BINUTILS_V_2_32=y +# CT_BINUTILS_V_2_31 is not set +# CT_BINUTILS_V_2_30 is not set +# CT_BINUTILS_V_2_29 is not set +# CT_BINUTILS_V_2_28 is not set +# CT_BINUTILS_V_2_27 is not set +# CT_BINUTILS_V_2_26 is not set +# CT_BINUTILS_NO_VERSIONS is not set +CT_BINUTILS_VERSION="2.32" +CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)" +CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig" +CT_BINUTILS_later_than_2_30=y +CT_BINUTILS_2_30_or_later=y +CT_BINUTILS_later_than_2_27=y +CT_BINUTILS_2_27_or_later=y +CT_BINUTILS_later_than_2_25=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_REQUIRE_2_25_or_later=y +CT_BINUTILS_later_than_2_23=y +CT_BINUTILS_2_23_or_later=y + +# +# GNU binutils +# +CT_BINUTILS_HAS_HASH_STYLE=y +CT_BINUTILS_HAS_GOLD=y +CT_BINUTILS_HAS_PLUGINS=y +CT_BINUTILS_HAS_PKGVERSION_BUGURL=y +CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y +CT_BINUTILS_LINKER_LD=y +CT_BINUTILS_LINKERS_LIST="ld" +CT_BINUTILS_LINKER_DEFAULT="bfd" +# CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_RELRO=m +CT_BINUTILS_EXTRA_CONFIG_ARRAY="" +# CT_BINUTILS_FOR_TARGET is not set +CT_ALL_BINUTILS_CHOICES="BINUTILS" + +# +# C-library +# +CT_LIBC_GLIBC=y +# CT_LIBC_MUSL is not set +# CT_LIBC_UCLIBC is not set +CT_LIBC="glibc" +CT_LIBC_CHOICE_KSYM="GLIBC" +CT_THREADS="nptl" +CT_LIBC_GLIBC_SHOW=y + +# +# Options for glibc +# +CT_LIBC_GLIBC_PKG_KSYM="GLIBC" +CT_GLIBC_DIR_NAME="glibc" +CT_GLIBC_USE_GNU=y +CT_GLIBC_USE="GLIBC" +CT_GLIBC_PKG_NAME="glibc" +CT_GLIBC_SRC_RELEASE=y +# CT_GLIBC_SRC_DEVEL is not set +# CT_GLIBC_SRC_CUSTOM is not set +CT_GLIBC_PATCH_GLOBAL=y +# CT_GLIBC_PATCH_BUNDLED is not set +# CT_GLIBC_PATCH_LOCAL is not set +# CT_GLIBC_PATCH_BUNDLED_LOCAL is not set +# CT_GLIBC_PATCH_LOCAL_BUNDLED is not set +# CT_GLIBC_PATCH_NONE is not set +CT_GLIBC_PATCH_ORDER="global" +CT_GLIBC_V_2_29=y +# CT_GLIBC_NO_VERSIONS is not set +CT_GLIBC_VERSION="2.29" +CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)" +CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_GLIBC_SIGNATURE_FORMAT="packed/.sig" +CT_GLIBC_2_29_or_later=y +CT_GLIBC_2_29_or_older=y +CT_GLIBC_REQUIRE_2_29_or_later=y +CT_GLIBC_later_than_2_27=y +CT_GLIBC_2_27_or_later=y +CT_GLIBC_later_than_2_26=y +CT_GLIBC_2_26_or_later=y +CT_GLIBC_later_than_2_25=y +CT_GLIBC_2_25_or_later=y +CT_GLIBC_later_than_2_24=y +CT_GLIBC_2_24_or_later=y +CT_GLIBC_later_than_2_23=y +CT_GLIBC_2_23_or_later=y +CT_GLIBC_later_than_2_20=y +CT_GLIBC_2_20_or_later=y +CT_GLIBC_later_than_2_17=y +CT_GLIBC_2_17_or_later=y +CT_GLIBC_later_than_2_14=y +CT_GLIBC_2_14_or_later=y +CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y +CT_GLIBC_DEP_BINUTILS=y +CT_GLIBC_DEP_GCC=y +CT_GLIBC_DEP_PYTHON=y +CT_GLIBC_BUILD_SSP=y +CT_GLIBC_HAS_LIBIDN_ADDON=y +# CT_GLIBC_USE_LIBIDN_ADDON is not set +CT_GLIBC_NO_SPARC_V8=y +CT_GLIBC_HAS_OBSOLETE_RPC=y +CT_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_GLIBC_CONFIGPARMS="" +CT_GLIBC_EXTRA_CFLAGS="" +CT_GLIBC_ENABLE_OBSOLETE_RPC=y +# CT_GLIBC_ENABLE_FORTIFIED_BUILD is not set +# CT_GLIBC_DISABLE_VERSIONING is not set +CT_GLIBC_OLDEST_ABI="" +CT_GLIBC_FORCE_UNWIND=y +# CT_GLIBC_LOCALES is not set +CT_GLIBC_KERNEL_VERSION_NONE=y +# CT_GLIBC_KERNEL_VERSION_AS_HEADERS is not set +# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_GLIBC_MIN_KERNEL="" +CT_GLIBC_SSP_DEFAULT=y +# CT_GLIBC_SSP_NO is not set +# CT_GLIBC_SSP_YES is not set +# CT_GLIBC_SSP_ALL is not set +# CT_GLIBC_SSP_STRONG is not set +# CT_GLIBC_ENABLE_WERROR is not set +CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC" +CT_LIBC_SUPPORT_THREADS_ANY=y +CT_LIBC_SUPPORT_THREADS_NATIVE=y + +# +# Common C library options +# +CT_THREADS_NATIVE=y +# CT_CREATE_LDSO_CONF is not set +CT_LIBC_XLDD=y + +# +# C compiler +# +CT_CC_CORE_PASSES_NEEDED=y +CT_CC_CORE_PASS_1_NEEDED=y +CT_CC_CORE_PASS_2_NEEDED=y +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y +CT_CC_GCC=y +CT_CC="gcc" +CT_CC_CHOICE_KSYM="GCC" +CT_CC_GCC_SHOW=y + +# +# Options for gcc +# +CT_CC_GCC_PKG_KSYM="GCC" +CT_GCC_DIR_NAME="gcc" +CT_GCC_USE_GNU=y +# CT_GCC_USE_LINARO is not set +CT_GCC_USE="GCC" +CT_GCC_PKG_NAME="gcc" +CT_GCC_SRC_RELEASE=y +# CT_GCC_SRC_DEVEL is not set +# CT_GCC_SRC_CUSTOM is not set +CT_GCC_PATCH_GLOBAL=y +# CT_GCC_PATCH_BUNDLED is not set +# CT_GCC_PATCH_LOCAL is not set +# CT_GCC_PATCH_BUNDLED_LOCAL is not set +# CT_GCC_PATCH_LOCAL_BUNDLED is not set +# CT_GCC_PATCH_NONE is not set +CT_GCC_PATCH_ORDER="global" +CT_GCC_V_8=y +# CT_GCC_V_7 is not set +# CT_GCC_NO_VERSIONS is not set +CT_GCC_VERSION="8.3.0" +CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})" +CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_GCC_SIGNATURE_FORMAT="" +CT_GCC_later_than_7=y +CT_GCC_7_or_later=y +CT_GCC_REQUIRE_7_or_later=y +CT_GCC_later_than_6=y +CT_GCC_6_or_later=y +CT_GCC_later_than_5=y +CT_GCC_5_or_later=y +CT_GCC_REQUIRE_5_or_later=y +CT_GCC_later_than_4_9=y +CT_GCC_4_9_or_later=y +CT_GCC_REQUIRE_4_9_or_later=y +CT_GCC_later_than_4_8=y +CT_GCC_4_8_or_later=y +CT_CC_GCC_HAS_LIBMPX=y +CT_CC_GCC_ENABLE_CXX_FLAGS="" +CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_EXTRA_CONFIG_ARRAY="" +CT_CC_GCC_STATIC_LIBSTDCXX=y +# CT_CC_GCC_SYSTEM_ZLIB is not set +CT_CC_GCC_CONFIG_TLS=m + +# +# Optimisation features +# +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_USE_LTO=y + +# +# Settings for libraries running on target +# +CT_CC_GCC_ENABLE_TARGET_OPTSPACE=y +# CT_CC_GCC_LIBMUDFLAP is not set +# CT_CC_GCC_LIBGOMP is not set +# CT_CC_GCC_LIBSSP is not set +# CT_CC_GCC_LIBQUADMATH is not set +# CT_CC_GCC_LIBSANITIZER is not set + +# +# Misc. obscure options. +# +CT_CC_CXA_ATEXIT=y +# CT_CC_GCC_DISABLE_PCH is not set +CT_CC_GCC_SJLJ_EXCEPTIONS=m +CT_CC_GCC_LDBL_128=m +# CT_CC_GCC_BUILD_ID is not set +CT_CC_GCC_LNK_HASH_STYLE_DEFAULT=y +# CT_CC_GCC_LNK_HASH_STYLE_SYSV is not set +# CT_CC_GCC_LNK_HASH_STYLE_GNU is not set +# CT_CC_GCC_LNK_HASH_STYLE_BOTH is not set +CT_CC_GCC_LNK_HASH_STYLE="" +CT_CC_GCC_DEC_FLOAT_AUTO=y +# CT_CC_GCC_DEC_FLOAT_BID is not set +# CT_CC_GCC_DEC_FLOAT_DPD is not set +# CT_CC_GCC_DEC_FLOATS_NO is not set +CT_ALL_CC_CHOICES="GCC" + +# +# Additional supported languages: +# +CT_CC_LANG_CXX=y +# CT_CC_LANG_FORTRAN is not set +# CT_CC_LANG_ADA is not set +# CT_CC_LANG_OBJC is not set +# CT_CC_LANG_OBJCXX is not set +# CT_CC_LANG_GOLANG is not set +CT_CC_LANG_OTHERS="" + +# +# Debug facilities +# +# CT_DEBUG_DUMA is not set +CT_DEBUG_GDB=y +CT_DEBUG_GDB_PKG_KSYM="GDB" +CT_GDB_DIR_NAME="gdb" +CT_GDB_USE_GNU=y +CT_GDB_USE="GDB" +CT_GDB_PKG_NAME="gdb" +CT_GDB_SRC_RELEASE=y +# CT_GDB_SRC_DEVEL is not set +# CT_GDB_SRC_CUSTOM is not set +CT_GDB_PATCH_GLOBAL=y +# CT_GDB_PATCH_BUNDLED is not set +# CT_GDB_PATCH_LOCAL is not set +# CT_GDB_PATCH_BUNDLED_LOCAL is not set +# CT_GDB_PATCH_LOCAL_BUNDLED is not set +# CT_GDB_PATCH_NONE is not set +CT_GDB_PATCH_ORDER="global" +CT_GDB_V_8_2=y +# CT_GDB_V_8_1 is not set +# CT_GDB_V_8_0 is not set +# CT_GDB_NO_VERSIONS is not set +CT_GDB_VERSION="8.2.1" +CT_GDB_MIRRORS="$(CT_Mirrors GNU gdb) $(CT_Mirrors sourceware gdb/releases)" +CT_GDB_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GDB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GDB_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_GDB_SIGNATURE_FORMAT="" +CT_GDB_later_than_8_0=y +CT_GDB_8_0_or_later=y +CT_GDB_REQUIRE_8_0_or_later=y +CT_GDB_later_than_7_12=y +CT_GDB_7_12_or_later=y +CT_GDB_later_than_7_2=y +CT_GDB_7_2_or_later=y +CT_GDB_later_than_7_0=y +CT_GDB_7_0_or_later=y +CT_GDB_CROSS=y +# CT_GDB_CROSS_STATIC is not set +# CT_GDB_CROSS_SIM is not set +# CT_GDB_CROSS_PYTHON is not set +CT_GDB_CROSS_EXTRA_CONFIG_ARRAY="" +# CT_GDB_NATIVE is not set +# CT_GDB_GDBSERVER is not set +CT_GDB_HAS_PKGVERSION_BUGURL=y +CT_GDB_HAS_PYTHON=y +CT_GDB_INSTALL_GDBINIT=y +CT_GDB_HAS_IPA_LIB=y +# CT_DEBUG_LTRACE is not set +# CT_DEBUG_STRACE is not set +CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE" + +# +# Companion libraries +# +# CT_COMPLIBS_CHECK is not set +# CT_COMP_LIBS_CLOOG is not set +CT_COMP_LIBS_EXPAT=y +CT_COMP_LIBS_EXPAT_PKG_KSYM="EXPAT" +CT_EXPAT_DIR_NAME="expat" +CT_EXPAT_PKG_NAME="expat" +CT_EXPAT_SRC_RELEASE=y +# CT_EXPAT_SRC_DEVEL is not set +# CT_EXPAT_SRC_CUSTOM is not set +CT_EXPAT_PATCH_GLOBAL=y +# CT_EXPAT_PATCH_BUNDLED is not set +# CT_EXPAT_PATCH_LOCAL is not set +# CT_EXPAT_PATCH_BUNDLED_LOCAL is not set +# CT_EXPAT_PATCH_LOCAL_BUNDLED is not set +# CT_EXPAT_PATCH_NONE is not set +CT_EXPAT_PATCH_ORDER="global" +CT_EXPAT_V_2_2=y +# CT_EXPAT_NO_VERSIONS is not set +CT_EXPAT_VERSION="2.2.6" +CT_EXPAT_MIRRORS="http://downloads.sourceforge.net/project/expat/expat/${CT_EXPAT_VERSION}" +CT_EXPAT_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_EXPAT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_EXPAT_ARCHIVE_FORMATS=".tar.bz2" +CT_EXPAT_SIGNATURE_FORMAT="" +CT_COMP_LIBS_GETTEXT=y +CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT" +CT_GETTEXT_DIR_NAME="gettext" +CT_GETTEXT_PKG_NAME="gettext" +CT_GETTEXT_SRC_RELEASE=y +# CT_GETTEXT_SRC_DEVEL is not set +# CT_GETTEXT_SRC_CUSTOM is not set +CT_GETTEXT_PATCH_GLOBAL=y +# CT_GETTEXT_PATCH_BUNDLED is not set +# CT_GETTEXT_PATCH_LOCAL is not set +# CT_GETTEXT_PATCH_BUNDLED_LOCAL is not set +# CT_GETTEXT_PATCH_LOCAL_BUNDLED is not set +# CT_GETTEXT_PATCH_NONE is not set +CT_GETTEXT_PATCH_ORDER="global" +CT_GETTEXT_V_0_19_8_1=y +# CT_GETTEXT_NO_VERSIONS is not set +CT_GETTEXT_VERSION="0.19.8.1" +CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)" +CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz" +CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig" +CT_COMP_LIBS_GMP=y +CT_COMP_LIBS_GMP_PKG_KSYM="GMP" +CT_GMP_DIR_NAME="gmp" +CT_GMP_PKG_NAME="gmp" +CT_GMP_SRC_RELEASE=y +# CT_GMP_SRC_DEVEL is not set +# CT_GMP_SRC_CUSTOM is not set +CT_GMP_PATCH_GLOBAL=y +# CT_GMP_PATCH_BUNDLED is not set +# CT_GMP_PATCH_LOCAL is not set +# CT_GMP_PATCH_BUNDLED_LOCAL is not set +# CT_GMP_PATCH_LOCAL_BUNDLED is not set +# CT_GMP_PATCH_NONE is not set +CT_GMP_PATCH_ORDER="global" +CT_GMP_V_6_1=y +# CT_GMP_NO_VERSIONS is not set +CT_GMP_VERSION="6.1.2" +CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)" +CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2" +CT_GMP_SIGNATURE_FORMAT="packed/.sig" +CT_GMP_later_than_5_1_0=y +CT_GMP_5_1_0_or_later=y +CT_GMP_later_than_5_0_0=y +CT_GMP_5_0_0_or_later=y +CT_GMP_REQUIRE_5_0_0_or_later=y +CT_COMP_LIBS_ISL=y +CT_COMP_LIBS_ISL_PKG_KSYM="ISL" +CT_ISL_DIR_NAME="isl" +CT_ISL_PKG_NAME="isl" +CT_ISL_SRC_RELEASE=y +# CT_ISL_SRC_DEVEL is not set +# CT_ISL_SRC_CUSTOM is not set +CT_ISL_PATCH_GLOBAL=y +# CT_ISL_PATCH_BUNDLED is not set +# CT_ISL_PATCH_LOCAL is not set +# CT_ISL_PATCH_BUNDLED_LOCAL is not set +# CT_ISL_PATCH_LOCAL_BUNDLED is not set +# CT_ISL_PATCH_NONE is not set +CT_ISL_PATCH_ORDER="global" +CT_ISL_V_0_20=y +# CT_ISL_V_0_19 is not set +# CT_ISL_V_0_18 is not set +# CT_ISL_V_0_17 is not set +# CT_ISL_V_0_16 is not set +# CT_ISL_V_0_15 is not set +# CT_ISL_NO_VERSIONS is not set +CT_ISL_VERSION="0.20" +CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_ISL_SIGNATURE_FORMAT="" +CT_ISL_later_than_0_18=y +CT_ISL_0_18_or_later=y +CT_ISL_later_than_0_15=y +CT_ISL_0_15_or_later=y +CT_ISL_REQUIRE_0_15_or_later=y +CT_ISL_later_than_0_14=y +CT_ISL_0_14_or_later=y +CT_ISL_REQUIRE_0_14_or_later=y +CT_ISL_later_than_0_13=y +CT_ISL_0_13_or_later=y +CT_ISL_later_than_0_12=y +CT_ISL_0_12_or_later=y +CT_ISL_REQUIRE_0_12_or_later=y +# CT_COMP_LIBS_LIBELF is not set +CT_COMP_LIBS_LIBICONV=y +CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV" +CT_LIBICONV_DIR_NAME="libiconv" +CT_LIBICONV_PKG_NAME="libiconv" +CT_LIBICONV_SRC_RELEASE=y +# CT_LIBICONV_SRC_DEVEL is not set +# CT_LIBICONV_SRC_CUSTOM is not set +CT_LIBICONV_PATCH_GLOBAL=y +# CT_LIBICONV_PATCH_BUNDLED is not set +# CT_LIBICONV_PATCH_LOCAL is not set +# CT_LIBICONV_PATCH_BUNDLED_LOCAL is not set +# CT_LIBICONV_PATCH_LOCAL_BUNDLED is not set +# CT_LIBICONV_PATCH_NONE is not set +CT_LIBICONV_PATCH_ORDER="global" +CT_LIBICONV_V_1_15=y +# CT_LIBICONV_NO_VERSIONS is not set +CT_LIBICONV_VERSION="1.15" +CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)" +CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz" +CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig" +CT_COMP_LIBS_MPC=y +CT_COMP_LIBS_MPC_PKG_KSYM="MPC" +CT_MPC_DIR_NAME="mpc" +CT_MPC_PKG_NAME="mpc" +CT_MPC_SRC_RELEASE=y +# CT_MPC_SRC_DEVEL is not set +# CT_MPC_SRC_CUSTOM is not set +CT_MPC_PATCH_GLOBAL=y +# CT_MPC_PATCH_BUNDLED is not set +# CT_MPC_PATCH_LOCAL is not set +# CT_MPC_PATCH_BUNDLED_LOCAL is not set +# CT_MPC_PATCH_LOCAL_BUNDLED is not set +# CT_MPC_PATCH_NONE is not set +CT_MPC_PATCH_ORDER="global" +CT_MPC_V_1_1=y +# CT_MPC_V_1_0 is not set +# CT_MPC_NO_VERSIONS is not set +CT_MPC_VERSION="1.1.0" +CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)" +CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_MPC_ARCHIVE_FORMATS=".tar.gz" +CT_MPC_SIGNATURE_FORMAT="packed/.sig" +CT_MPC_1_1_0_or_later=y +CT_MPC_1_1_0_or_older=y +CT_COMP_LIBS_MPFR=y +CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR" +CT_MPFR_DIR_NAME="mpfr" +CT_MPFR_PKG_NAME="mpfr" +CT_MPFR_SRC_RELEASE=y +# CT_MPFR_SRC_DEVEL is not set +# CT_MPFR_SRC_CUSTOM is not set +CT_MPFR_PATCH_GLOBAL=y +# CT_MPFR_PATCH_BUNDLED is not set +# CT_MPFR_PATCH_LOCAL is not set +# CT_MPFR_PATCH_BUNDLED_LOCAL is not set +# CT_MPFR_PATCH_LOCAL_BUNDLED is not set +# CT_MPFR_PATCH_NONE is not set +CT_MPFR_PATCH_ORDER="global" +CT_MPFR_V_4_0=y +# CT_MPFR_V_3_1 is not set +# CT_MPFR_NO_VERSIONS is not set +CT_MPFR_VERSION="4.0.2" +CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)" +CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip" +CT_MPFR_SIGNATURE_FORMAT="packed/.asc" +CT_MPFR_later_than_4_0_0=y +CT_MPFR_4_0_0_or_later=y +CT_MPFR_later_than_3_0_0=y +CT_MPFR_3_0_0_or_later=y +CT_MPFR_REQUIRE_3_0_0_or_later=y +CT_COMP_LIBS_NCURSES=y +CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES" +CT_NCURSES_DIR_NAME="ncurses" +CT_NCURSES_PKG_NAME="ncurses" +CT_NCURSES_SRC_RELEASE=y +# CT_NCURSES_SRC_DEVEL is not set +# CT_NCURSES_SRC_CUSTOM is not set +CT_NCURSES_PATCH_GLOBAL=y +# CT_NCURSES_PATCH_BUNDLED is not set +# CT_NCURSES_PATCH_LOCAL is not set +# CT_NCURSES_PATCH_BUNDLED_LOCAL is not set +# CT_NCURSES_PATCH_LOCAL_BUNDLED is not set +# CT_NCURSES_PATCH_NONE is not set +CT_NCURSES_PATCH_ORDER="global" +CT_NCURSES_V_6_1=y +# CT_NCURSES_V_6_0 is not set +# CT_NCURSES_NO_VERSIONS is not set +CT_NCURSES_VERSION="6.1" +CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)" +CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_NCURSES_ARCHIVE_FORMATS=".tar.gz" +CT_NCURSES_SIGNATURE_FORMAT="packed/.sig" +# CT_NCURSES_NEW_ABI is not set +CT_NCURSES_HOST_CONFIG_ARGS="" +CT_NCURSES_HOST_DISABLE_DB=y +CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100" +CT_NCURSES_TARGET_CONFIG_ARGS="" +# CT_NCURSES_TARGET_DISABLE_DB is not set +CT_NCURSES_TARGET_FALLBACKS="" +CT_COMP_LIBS_ZLIB=y +CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB" +CT_ZLIB_DIR_NAME="zlib" +CT_ZLIB_PKG_NAME="zlib" +CT_ZLIB_SRC_RELEASE=y +# CT_ZLIB_SRC_DEVEL is not set +# CT_ZLIB_SRC_CUSTOM is not set +CT_ZLIB_PATCH_GLOBAL=y +# CT_ZLIB_PATCH_BUNDLED is not set +# CT_ZLIB_PATCH_LOCAL is not set +# CT_ZLIB_PATCH_BUNDLED_LOCAL is not set +# CT_ZLIB_PATCH_LOCAL_BUNDLED is not set +# CT_ZLIB_PATCH_NONE is not set +CT_ZLIB_PATCH_ORDER="global" +CT_ZLIB_V_1_2_11=y +# CT_ZLIB_NO_VERSIONS is not set +CT_ZLIB_VERSION="1.2.11" +CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}" +CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_ZLIB_SIGNATURE_FORMAT="packed/.asc" +CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB" +CT_LIBICONV_NEEDED=y +CT_GETTEXT_NEEDED=y +CT_GMP_NEEDED=y +CT_MPFR_NEEDED=y +CT_ISL_NEEDED=y +CT_MPC_NEEDED=y +CT_EXPAT_NEEDED=y +CT_NCURSES_NEEDED=y +CT_ZLIB_NEEDED=y +CT_LIBICONV=y +CT_GETTEXT=y +CT_GMP=y +CT_MPFR=y +CT_ISL=y +CT_MPC=y +CT_EXPAT=y +CT_NCURSES=y +CT_ZLIB=y + +# +# Companion tools +# +# CT_COMP_TOOLS_FOR_HOST is not set +# CT_COMP_TOOLS_AUTOCONF is not set +# CT_COMP_TOOLS_AUTOMAKE is not set +# CT_COMP_TOOLS_BISON is not set +# CT_COMP_TOOLS_DTC is not set +# CT_COMP_TOOLS_LIBTOOL is not set +# CT_COMP_TOOLS_M4 is not set +# CT_COMP_TOOLS_MAKE is not set +CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE" + +# +# Test suite +# +# CT_TEST_SUITE_GCC is not set diff --git a/src/doc/rustc-guide b/src/doc/rustc-guide -Subproject b5c6babcdd4ce1fa90458b7827a5fde082e79e8 +Subproject 92baf7293dd2d418d2ac4b141b0faa822075d9f diff --git a/src/doc/unstable-book/src/language-features/slice-patterns.md b/src/doc/unstable-book/src/language-features/slice-patterns.md deleted file mode 100644 index cdb74495884..00000000000 --- a/src/doc/unstable-book/src/language-features/slice-patterns.md +++ /dev/null @@ -1,32 +0,0 @@ -# `slice_patterns` - -The tracking issue for this feature is: [#62254] - -[#62254]: https://github.com/rust-lang/rust/issues/62254 - ------------------------- - -The `slice_patterns` feature gate lets you use `..` to indicate any number of -elements inside a pattern matching a slice. This wildcard can only be used once -for a given array. If there's an pattern before the `..`, the subslice will be -matched against that pattern. For example: - -```rust -#![feature(slice_patterns)] - -fn is_symmetric(list: &[u32]) -> bool { - match list { - &[] | &[_] => true, - &[x, ref inside @ .., y] if x == y => is_symmetric(inside), - &[..] => false, - } -} - -fn main() { - let sym = &[0, 1, 4, 2, 4, 1, 0]; - assert!(is_symmetric(sym)); - - let not_sym = &[0, 1, 7, 2, 4, 1, 0]; - assert!(!is_symmetric(not_sym)); -} -``` diff --git a/src/liballoc/benches/btree/map.rs b/src/liballoc/benches/btree/map.rs index eb5f51d9adc..ea69769279f 100644 --- a/src/liballoc/benches/btree/map.rs +++ b/src/liballoc/benches/btree/map.rs @@ -146,6 +146,36 @@ pub fn iter_100000(b: &mut Bencher) { bench_iter(b, 100000); } +fn bench_iter_mut(b: &mut Bencher, size: i32) { + let mut map = BTreeMap::<i32, i32>::new(); + let mut rng = thread_rng(); + + for _ in 0..size { + map.insert(rng.gen(), rng.gen()); + } + + b.iter(|| { + for kv in map.iter_mut() { + black_box(kv); + } + }); +} + +#[bench] +pub fn iter_mut_20(b: &mut Bencher) { + bench_iter_mut(b, 20); +} + +#[bench] +pub fn iter_mut_1000(b: &mut Bencher) { + bench_iter_mut(b, 1000); +} + +#[bench] +pub fn iter_mut_100000(b: &mut Bencher) { + bench_iter_mut(b, 100000); +} + fn bench_first_and_last(b: &mut Bencher, size: i32) { let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); b.iter(|| { diff --git a/src/liballoc/benches/btree/set.rs b/src/liballoc/benches/btree/set.rs index 18502ded308..d7c1d95a452 100644 --- a/src/liballoc/benches/btree/set.rs +++ b/src/liballoc/benches/btree/set.rs @@ -14,19 +14,13 @@ fn random(n: usize) -> BTreeSet<usize> { } fn neg(n: usize) -> BTreeSet<i32> { - let mut set = BTreeSet::new(); - for i in -(n as i32)..=-1 { - set.insert(i); - } + let set: BTreeSet<i32> = (-(n as i32)..=-1).collect(); assert_eq!(set.len(), n); set } fn pos(n: usize) -> BTreeSet<i32> { - let mut set = BTreeSet::new(); - for i in 1..=(n as i32) { - set.insert(i); - } + let set: BTreeSet<i32> = (1..=(n as i32)).collect(); assert_eq!(set.len(), n); set } @@ -56,6 +50,43 @@ macro_rules! set_bench { }; } +const BUILD_SET_SIZE: usize = 100; + +#[bench] +pub fn build_and_clear(b: &mut Bencher) { + b.iter(|| pos(BUILD_SET_SIZE).clear()) +} + +#[bench] +pub fn build_and_drop(b: &mut Bencher) { + b.iter(|| pos(BUILD_SET_SIZE)) +} + +#[bench] +pub fn build_and_into_iter(b: &mut Bencher) { + b.iter(|| pos(BUILD_SET_SIZE).into_iter().count()) +} + +#[bench] +pub fn build_and_pop_all(b: &mut Bencher) { + b.iter(|| { + let mut s = pos(BUILD_SET_SIZE); + while s.pop_first().is_some() {} + s + }); +} + +#[bench] +pub fn build_and_remove_all(b: &mut Bencher) { + b.iter(|| { + let mut s = pos(BUILD_SET_SIZE); + while let Some(elt) = s.iter().copied().next() { + s.remove(&elt); + } + s + }); +} + set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]} set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]} set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]} diff --git a/src/liballoc/benches/string.rs b/src/liballoc/benches/string.rs index 599c8b16828..5c95160ba2d 100644 --- a/src/liballoc/benches/string.rs +++ b/src/liballoc/benches/string.rs @@ -1,5 +1,5 @@ use std::iter::repeat; -use test::Bencher; +use test::{black_box, Bencher}; #[bench] fn bench_with_capacity(b: &mut Bencher) { diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 302c2bcd5e4..e70f881bc3d 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1968,7 +1968,7 @@ where (i, false) => i, }, (_, Unbounded) => 0, - (true, Included(_)) => min_node.keys().len(), + (true, Included(_)) => min_node.len(), (true, Excluded(_)) => 0, }; @@ -1987,9 +1987,9 @@ where } (i, false) => i, }, - (_, Unbounded) => max_node.keys().len(), + (_, Unbounded) => max_node.len(), (true, Included(_)) => 0, - (true, Excluded(_)) => max_node.keys().len(), + (true, Excluded(_)) => max_node.len(), }; if !diverged { diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index f40e0b0c304..d9cdebb4f73 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -54,10 +54,8 @@ pub const CAPACITY: usize = 2 * B - 1; /// `NodeHeader` because we do not want unnecessary padding between `len` and the keys. /// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited /// by `as_header`.) -/// See `into_key_slice` for an explanation of K2. K2 cannot be safely transmuted around -/// because the size of `NodeHeader` depends on its alignment! #[repr(C)] -struct NodeHeader<K, V, K2 = ()> { +struct NodeHeader<K, V> { /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. /// This either points to an actual node or is null. parent: *const InternalNode<K, V>, @@ -72,9 +70,6 @@ struct NodeHeader<K, V, K2 = ()> { /// This next to `parent_idx` to encourage the compiler to join `len` and /// `parent_idx` into the same 32-bit word, reducing space overhead. len: u16, - - /// See `into_key_slice`. - keys_start: [K2; 0], } #[repr(C)] struct LeafNode<K, V> { @@ -128,7 +123,7 @@ unsafe impl Sync for NodeHeader<(), ()> {} // We use just a header in order to save space, since no operation on an empty tree will // ever take a pointer past the first key. static EMPTY_ROOT_NODE: NodeHeader<(), ()> = - NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0, keys_start: [] }; + NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 }; /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden /// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an @@ -390,14 +385,13 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> { } /// Borrows a view into the keys stored in the node. - /// Works on all possible nodes, including the shared root. - pub fn keys(&self) -> &[K] { + /// The caller must ensure that the node is not the shared root. + pub unsafe fn keys(&self) -> &[K] { self.reborrow().into_key_slice() } /// Borrows a view into the values stored in the node. /// The caller must ensure that the node is not the shared root. - /// This function is not public, so doesn't have to support shared roots like `keys` does. fn vals(&self) -> &[V] { self.reborrow().into_val_slice() } @@ -515,7 +509,6 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> { } /// The caller must ensure that the node is not the shared root. - /// This function is not public, so doesn't have to support shared roots like `keys` does. fn keys_mut(&mut self) -> &mut [K] { unsafe { self.reborrow_mut().into_key_slice_mut() } } @@ -527,48 +520,11 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> { } impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> { - fn into_key_slice(self) -> &'a [K] { - // We have to be careful here because we might be pointing to the shared root. - // In that case, we must not create an `&LeafNode`. We could just return - // an empty slice whenever the length is 0 (this includes the shared root), - // but we want to avoid that run-time check. - // Instead, we create a slice pointing into the node whenever possible. - // We can sometimes do this even for the shared root, as the slice will be - // empty and `NodeHeader` contains an empty `keys_start` array. - // We cannot *always* do this because: - // - `keys_start` is not correctly typed because we want `NodeHeader`'s size to - // not depend on the alignment of `K` (needed because `as_header` should be safe). - // For this reason, `NodeHeader` has this `K2` parameter (that's usually `()` - // and hence just adds a size-0-align-1 field, not affecting layout). - // If the correctly typed header is more highly aligned than the allocated header, - // we cannot transmute safely. - // - Even if we can transmute, the offset of a correctly typed `keys_start` might - // be different and outside the bounds of the allocated header! - // So we do an alignment check and a size check first, that will be evaluated - // at compile-time, and only do any run-time check in the rare case that - // the compile-time checks signal danger. - if (mem::align_of::<NodeHeader<K, V, K>>() > mem::align_of::<NodeHeader<K, V>>() - || mem::size_of::<NodeHeader<K, V, K>>() != mem::size_of::<NodeHeader<K, V>>()) - && self.is_shared_root() - { - &[] - } else { - // If we are a `LeafNode<K, V>`, we can always transmute to - // `NodeHeader<K, V, K>` and `keys_start` always has the same offset - // as the actual `keys`. - // Thanks to the checks above, we know that we can transmute to - // `NodeHeader<K, V, K>` and that `keys_start` will be - // in-bounds of some allocation even if this is the shared root! - // (We might be one-past-the-end, but that is allowed by LLVM.) - // Thus we can use `NodeHeader<K, V, K>` - // to compute the pointer where the keys start. - // This entire hack will become unnecessary once - // <https://github.com/rust-lang/rfcs/pull/2582> lands, then we can just take a raw - // pointer to the `keys` field of `*const InternalNode<K, V>`. - let header = self.as_header() as *const _ as *const NodeHeader<K, V, K>; - let keys = unsafe { &(*header).keys_start as *const _ as *const K }; - unsafe { slice::from_raw_parts(keys, self.len()) } - } + /// The caller must ensure that the node is not the shared root. + unsafe fn into_key_slice(self) -> &'a [K] { + debug_assert!(!self.is_shared_root()); + // We cannot be the shared root, so `as_leaf` is okay. + slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) } /// The caller must ensure that the node is not the shared root. @@ -578,9 +534,10 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> { unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) } } + /// The caller must ensure that the node is not the shared root. fn into_slices(self) -> (&'a [K], &'a [V]) { let k = unsafe { ptr::read(&self) }; - (k.into_key_slice(), self.into_val_slice()) + (unsafe { k.into_key_slice() }, self.into_val_slice()) } } diff --git a/src/liballoc/collections/btree/search.rs b/src/liballoc/collections/btree/search.rs index 48cbf67eea2..579624cdd2b 100644 --- a/src/liballoc/collections/btree/search.rs +++ b/src/liballoc/collections/btree/search.rs @@ -61,16 +61,18 @@ where { // This function is defined over all borrow types (immutable, mutable, owned), // and may be called on the shared root in each case. - // Crucially, we use `keys()` here, i.e., we work with immutable data. - // `keys_mut()` does not support the shared root, so we cannot use it. // Using `keys()` is fine here even if BorrowType is mutable, as all we return // is an index -- not a reference. - for (i, k) in node.keys().iter().enumerate() { - match key.cmp(k.borrow()) { - Ordering::Greater => {} - Ordering::Equal => return (i, true), - Ordering::Less => return (i, false), + let len = node.len(); + if len > 0 { + let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root + for (i, k) in keys.iter().enumerate() { + match key.cmp(k.borrow()) { + Ordering::Greater => {} + Ordering::Equal => return (i, true), + Ordering::Less => return (i, false), + } } } - (node.keys().len(), false) + (len, false) } diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 35ce1354f52..f5be72c39b2 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -4,6 +4,7 @@ use std::convert::TryFrom; use std::fmt::Debug; use std::iter::FromIterator; use std::ops::Bound::{self, Excluded, Included, Unbounded}; +use std::ops::RangeBounds; use std::rc::Rc; use super::DeterministicRng; @@ -68,6 +69,11 @@ fn test_basic_small() { assert_eq!(map.last_key_value(), None); assert_eq!(map.keys().count(), 0); assert_eq!(map.values().count(), 0); + assert_eq!(map.range(..).next(), None); + assert_eq!(map.range(..1).next(), None); + assert_eq!(map.range(1..).next(), None); + assert_eq!(map.range(1..=1).next(), None); + assert_eq!(map.range(1..2).next(), None); assert_eq!(map.insert(1, 1), None); // 1 key-value pair: @@ -118,6 +124,11 @@ fn test_basic_small() { assert_eq!(map.last_key_value(), None); assert_eq!(map.keys().count(), 0); assert_eq!(map.values().count(), 0); + assert_eq!(map.range(..).next(), None); + assert_eq!(map.range(..1).next(), None); + assert_eq!(map.range(1..).next(), None); + assert_eq!(map.range(1..=1).next(), None); + assert_eq!(map.range(1..2).next(), None); assert_eq!(map.remove(&1), None); } @@ -128,7 +139,6 @@ fn test_iter() { #[cfg(miri)] let size = 200; - // Forwards let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test<T>(size: usize, mut iter: T) @@ -154,7 +164,6 @@ fn test_iter_rev() { #[cfg(miri)] let size = 200; - // Forwards let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test<T>(size: usize, mut iter: T) @@ -275,7 +284,6 @@ fn test_iter_mixed() { #[cfg(miri)] let size = 200; - // Forwards let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test<T>(size: usize, mut iter: T) @@ -299,27 +307,147 @@ fn test_iter_mixed() { test(size, map.into_iter()); } -#[test] -fn test_range_small() { - let size = 5; - - // Forwards - let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - - let mut j = 0; - for ((&k, &v), i) in map.range(2..).zip(2..size) { - assert_eq!(k, i); - assert_eq!(v, i); - j += 1; - } - assert_eq!(j, size - 2); +fn range_keys(map: &BTreeMap<i32, i32>, range: impl RangeBounds<i32>) -> Vec<i32> { + map.range(range) + .map(|(&k, &v)| { + assert_eq!(k, v); + k + }) + .collect() } #[test] -fn test_range_inclusive() { - let size = 500; +fn test_range_small() { + let size = 4; + + let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect(); + let all: Vec<_> = (1..=size).collect(); + let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); + assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size))), all); + assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size))), all); + assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); + assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); + assert_eq!(range_keys(&map, ..), all); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(1), Included(1))), first); + assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); + assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); + assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); + assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size))), last); + assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); + assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); + + assert_eq!(range_keys(&map, ..3), vec![1, 2]); + assert_eq!(range_keys(&map, 3..), vec![3, 4]); + assert_eq!(range_keys(&map, 2..=3), vec![2, 3]); +} + +#[test] +fn test_range_depth_2() { + // Assuming that node.CAPACITY is 11, having 12 pairs implies a depth 2 tree + // with 2 leaves. Depending on details we don't want or need to rely upon, + // the single key at the root will be 6 or 7. + + let map: BTreeMap<_, _> = (1..=12).map(|i| (i, i)).collect(); + for &root in &[6, 7] { + assert_eq!(range_keys(&map, (Excluded(root), Excluded(root + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(root), Included(root + 1))), vec![root + 1]); + assert_eq!(range_keys(&map, (Included(root), Excluded(root + 1))), vec![root]); + assert_eq!(range_keys(&map, (Included(root), Included(root + 1))), vec![root, root + 1]); + + assert_eq!(range_keys(&map, (Excluded(root - 1), Excluded(root))), vec![]); + assert_eq!(range_keys(&map, (Included(root - 1), Excluded(root))), vec![root - 1]); + assert_eq!(range_keys(&map, (Excluded(root - 1), Included(root))), vec![root]); + assert_eq!(range_keys(&map, (Included(root - 1), Included(root))), vec![root - 1, root]); + } +} + +#[test] +fn test_range_large() { + let size = 200; - let map: BTreeMap<_, _> = (0..=size).map(|i| (i, i)).collect(); + let map: BTreeMap<_, _> = (1..=size).map(|i| (i, i)).collect(); + let all: Vec<_> = (1..=size).collect(); + let (first, last) = (vec![all[0]], vec![all[size as usize - 1]]); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Excluded(0), Included(size))), all); + assert_eq!(range_keys(&map, (Excluded(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(0), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(0), Included(size))), all); + assert_eq!(range_keys(&map, (Included(0), Unbounded)), all); + assert_eq!(range_keys(&map, (Included(1), Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size + 1))), all); + assert_eq!(range_keys(&map, (Included(1), Included(size))), all); + assert_eq!(range_keys(&map, (Included(1), Unbounded)), all); + assert_eq!(range_keys(&map, (Unbounded, Excluded(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size + 1))), all); + assert_eq!(range_keys(&map, (Unbounded, Included(size))), all); + assert_eq!(range_keys(&map, ..), all); + + assert_eq!(range_keys(&map, (Excluded(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Included(0))), vec![]); + assert_eq!(range_keys(&map, (Included(0), Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Excluded(1))), vec![]); + assert_eq!(range_keys(&map, (Unbounded, Included(0))), vec![]); + assert_eq!(range_keys(&map, (Excluded(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Excluded(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(0), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(0), Included(1))), first); + assert_eq!(range_keys(&map, (Included(1), Excluded(2))), first); + assert_eq!(range_keys(&map, (Included(1), Included(1))), first); + assert_eq!(range_keys(&map, (Unbounded, Excluded(2))), first); + assert_eq!(range_keys(&map, (Unbounded, Included(1))), first); + assert_eq!(range_keys(&map, (Excluded(size - 1), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Included(size))), last); + assert_eq!(range_keys(&map, (Excluded(size - 1), Unbounded)), last); + assert_eq!(range_keys(&map, (Included(size), Excluded(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size + 1))), last); + assert_eq!(range_keys(&map, (Included(size), Included(size))), last); + assert_eq!(range_keys(&map, (Included(size), Unbounded)), last); + assert_eq!(range_keys(&map, (Excluded(size), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Included(size))), vec![]); + assert_eq!(range_keys(&map, (Excluded(size), Unbounded)), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Excluded(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Included(size + 1))), vec![]); + assert_eq!(range_keys(&map, (Included(size + 1), Unbounded)), vec![]); fn check<'a, L, R>(lhs: L, rhs: R) where @@ -331,18 +459,9 @@ fn test_range_inclusive() { assert_eq!(lhs, rhs); } - check(map.range(size + 1..=size + 1), vec![]); - check(map.range(size..=size), vec![(&size, &size)]); - check(map.range(size..=size + 1), vec![(&size, &size)]); - check(map.range(0..=0), vec![(&0, &0)]); - check(map.range(0..=size - 1), map.range(..size)); - check(map.range(-1..=-1), vec![]); - check(map.range(-1..=size), map.range(..)); - check(map.range(..=size), map.range(..)); - check(map.range(..=200), map.range(..201)); + check(map.range(..=100), map.range(..101)); check(map.range(5..=8), vec![(&5, &5), (&6, &6), (&7, &7), (&8, &8)]); - check(map.range(-1..=0), vec![(&0, &0)]); - check(map.range(-1..=2), vec![(&0, &0), (&1, &1), (&2, &2)]); + check(map.range(-1..=2), vec![(&1, &1), (&2, &2)]); } #[test] diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index beb0bac17d2..2a3d92edc49 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -21,7 +21,6 @@ extern crate alloc; use rustc_data_structures::cold_path; -use rustc_data_structures::sync::MTLock; use smallvec::SmallVec; use std::cell::{Cell, RefCell}; @@ -116,11 +115,6 @@ impl<T> Default for TypedArena<T> { } impl<T> TypedArena<T> { - pub fn in_arena(&self, ptr: *const T) -> bool { - let ptr = ptr as *const T as *mut T; - - self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end()) - } /// Allocates an object in the `TypedArena`, returning a reference to it. #[inline] pub fn alloc(&self, object: T) -> &mut T { @@ -334,12 +328,6 @@ impl Default for DroplessArena { } impl DroplessArena { - pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool { - let ptr = ptr as *const u8 as *mut u8; - - self.chunks.borrow().iter().any(|chunk| chunk.start() <= ptr && ptr < chunk.end()) - } - #[inline] fn align(&self, align: usize) { let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1); @@ -500,66 +488,5 @@ impl DroplessArena { } } -#[derive(Default)] -// FIXME(@Zoxc): this type is entirely unused in rustc -pub struct SyncTypedArena<T> { - lock: MTLock<TypedArena<T>>, -} - -impl<T> SyncTypedArena<T> { - #[inline(always)] - pub fn alloc(&self, object: T) -> &mut T { - // Extend the lifetime of the result since it's limited to the lock guard - unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) } - } - - #[inline(always)] - pub fn alloc_slice(&self, slice: &[T]) -> &mut [T] - where - T: Copy, - { - // Extend the lifetime of the result since it's limited to the lock guard - unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) } - } - - #[inline(always)] - pub fn clear(&mut self) { - self.lock.get_mut().clear(); - } -} - -#[derive(Default)] -pub struct SyncDroplessArena { - lock: MTLock<DroplessArena>, -} - -impl SyncDroplessArena { - #[inline(always)] - pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool { - self.lock.lock().in_arena(ptr) - } - - #[inline(always)] - pub fn alloc_raw(&self, bytes: usize, align: usize) -> &mut [u8] { - // Extend the lifetime of the result since it's limited to the lock guard - unsafe { &mut *(self.lock.lock().alloc_raw(bytes, align) as *mut [u8]) } - } - - #[inline(always)] - pub fn alloc<T>(&self, object: T) -> &mut T { - // Extend the lifetime of the result since it's limited to the lock guard - unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) } - } - - #[inline(always)] - pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T] - where - T: Copy, - { - // Extend the lifetime of the result since it's limited to the lock guard - unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) } - } -} - #[cfg(test)] mod tests; diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 4354e1c7b5f..09f743fb81e 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -525,7 +525,8 @@ pub unsafe trait GlobalAlloc { /// The memory may or may not have been deallocated, /// and should be considered unusable (unless of course it was /// transferred back to the caller again via the return value of - /// this method). + /// this method). The new memory block is allocated with `layout`, but + /// with the `size` updated to `new_size`. /// /// If this method returns null, then ownership of the memory /// block has not been transferred to this allocator, and the diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 4afea12a362..af02e84d3fa 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -476,11 +476,15 @@ pub const fn type_name<T: ?Sized>() -> &'static str { /// /// This is intended for diagnostic use. The exact contents and format of the /// string are not specified, other than being a best-effort description of the -/// type. For example, `type_name_of::<Option<String>>(None)` could return +/// type. For example, `type_name_of_val::<Option<String>>(None)` could return /// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not /// `"foobar"`. In addition, the output may change between versions of the /// compiler. /// +/// This function does not resolve trait objects, +/// meaning that `type_name_of_val(&7u32 as &dyn Debug)` +/// may return `"dyn Debug"`, but not `"u32"`. +/// /// The type name should not be considered a unique identifier of a type; /// multiple types may share the same type name. /// diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 4fcd0d9737d..e7eecf7540a 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -187,8 +187,6 @@ //! ``` //! -// ignore-tidy-undocumented-unsafe - #![stable(feature = "rust1", since = "1.0.0")] use crate::cmp::Ordering; @@ -368,6 +366,10 @@ impl<T> Cell<T> { if ptr::eq(self, other) { return; } + // SAFETY: This can be risky if called from separate threads, but `Cell` + // is `!Sync` so this won't happen. This also won't invalidate any + // pointers since `Cell` makes sure nothing else will be pointing into + // either of these `Cell`s. unsafe { ptr::swap(self.value.get(), other.value.get()); } @@ -387,6 +389,8 @@ impl<T> Cell<T> { /// ``` #[stable(feature = "move_cell", since = "1.17.0")] pub fn replace(&self, val: T) -> T { + // SAFETY: This can cause data races if called from a separate thread, + // but `Cell` is `!Sync` so this won't happen. mem::replace(unsafe { &mut *self.value.get() }, val) } @@ -423,6 +427,8 @@ impl<T: Copy> Cell<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self) -> T { + // SAFETY: This can cause data races if called from a separate thread, + // but `Cell` is `!Sync` so this won't happen. unsafe { *self.value.get() } } @@ -491,6 +497,9 @@ impl<T: ?Sized> Cell<T> { #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] pub fn get_mut(&mut self) -> &mut T { + // SAFETY: This can cause data races if called from a separate thread, + // but `Cell` is `!Sync` so this won't happen, and `&mut` guarantees + // unique access. unsafe { &mut *self.value.get() } } @@ -510,6 +519,7 @@ impl<T: ?Sized> Cell<T> { #[inline] #[stable(feature = "as_cell", since = "1.37.0")] pub fn from_mut(t: &mut T) -> &Cell<T> { + // SAFETY: `&mut` ensures unique access. unsafe { &*(t as *mut T as *const Cell<T>) } } } @@ -553,6 +563,7 @@ impl<T> Cell<[T]> { /// ``` #[stable(feature = "as_cell", since = "1.37.0")] pub fn as_slice_of_cells(&self) -> &[Cell<T>] { + // SAFETY: `Cell<T>` has the same memory layout as `T`. unsafe { &*(self as *const Cell<[T]> as *const [Cell<T>]) } } } @@ -816,6 +827,8 @@ impl<T: ?Sized> RefCell<T> { #[inline] pub fn try_borrow(&self) -> Result<Ref<'_, T>, BorrowError> { match BorrowRef::new(&self.borrow) { + // SAFETY: `BorrowRef` ensures that there is only immutable access + // to the value while borrowed. Some(b) => Ok(Ref { value: unsafe { &*self.value.get() }, borrow: b }), None => Err(BorrowError { _private: () }), } @@ -891,6 +904,7 @@ impl<T: ?Sized> RefCell<T> { #[inline] pub fn try_borrow_mut(&self) -> Result<RefMut<'_, T>, BorrowMutError> { match BorrowRefMut::new(&self.borrow) { + // SAFETY: `BorrowRef` guarantees unique access. Some(b) => Ok(RefMut { value: unsafe { &mut *self.value.get() }, borrow: b }), None => Err(BorrowMutError { _private: () }), } @@ -940,6 +954,7 @@ impl<T: ?Sized> RefCell<T> { #[inline] #[stable(feature = "cell_get_mut", since = "1.11.0")] pub fn get_mut(&mut self) -> &mut T { + // SAFETY: `&mut` guarantees unique access. unsafe { &mut *self.value.get() } } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index e68f3c58a3e..900ef63f1df 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -10,7 +10,6 @@ use crate::mem; use crate::num::flt2dec; use crate::ops::Deref; use crate::result; -use crate::slice; use crate::str; mod builders; @@ -234,8 +233,6 @@ pub struct Formatter<'a> { precision: Option<usize>, buf: &'a mut (dyn Write + 'a), - curarg: slice::Iter<'a, ArgumentV1<'a>>, - args: &'a [ArgumentV1<'a>], } // NB. Argument is essentially an optimized partially applied formatting function, @@ -1043,8 +1040,6 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { buf: output, align: rt::v1::Alignment::Unknown, fill: ' ', - args: args.args, - curarg: args.args.iter(), }; let mut idx = 0; @@ -1063,7 +1058,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { // a string piece. for (arg, piece) in fmt.iter().zip(args.pieces.iter()) { formatter.buf.write_str(*piece)?; - formatter.run(arg)?; + run(&mut formatter, arg, &args.args)?; idx += 1; } } @@ -1077,6 +1072,39 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { Ok(()) } +fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result { + fmt.fill = arg.format.fill; + fmt.align = arg.format.align; + fmt.flags = arg.format.flags; + fmt.width = getcount(args, &arg.format.width); + fmt.precision = getcount(args, &arg.format.precision); + + // Extract the correct argument + let value = { + #[cfg(bootstrap)] + { + match arg.position { + rt::v1::Position::At(i) => args[i], + } + } + #[cfg(not(bootstrap))] + { + args[arg.position] + } + }; + + // Then actually do some printing + (value.formatter)(value.value, fmt) +} + +fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> { + match *cnt { + rt::v1::Count::Is(n) => Some(n), + rt::v1::Count::Implied => None, + rt::v1::Count::Param(i) => args[i].as_usize(), + } +} + /// Padding after the end of something. Returned by `Formatter::padding`. #[must_use = "don't forget to write the post padding"] struct PostPadding { @@ -1114,41 +1142,6 @@ impl<'a> Formatter<'a> { align: self.align, width: self.width, precision: self.precision, - - // These only exist in the struct for the `run` method, - // which won’t be used together with this method. - curarg: self.curarg.clone(), - args: self.args, - } - } - - // First up is the collection of functions used to execute a format string - // at runtime. This consumes all of the compile-time statics generated by - // the format! syntax extension. - fn run(&mut self, arg: &rt::v1::Argument) -> Result { - // Fill in the format parameters into the formatter - self.fill = arg.format.fill; - self.align = arg.format.align; - self.flags = arg.format.flags; - self.width = self.getcount(&arg.format.width); - self.precision = self.getcount(&arg.format.precision); - - // Extract the correct argument - let value = match arg.position { - rt::v1::Position::Next => *self.curarg.next().unwrap(), - rt::v1::Position::At(i) => self.args[i], - }; - - // Then actually do some printing - (value.formatter)(value.value, self) - } - - fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> { - match *cnt { - rt::v1::Count::Is(n) => Some(n), - rt::v1::Count::Implied => None, - rt::v1::Count::Param(i) => self.args[i].as_usize(), - rt::v1::Count::NextParam => self.curarg.next()?.as_usize(), } } diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 826ae36d2d1..fd81f93242b 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -7,7 +7,10 @@ #[derive(Copy, Clone)] pub struct Argument { + #[cfg(bootstrap)] pub position: Position, + #[cfg(not(bootstrap))] + pub position: usize, pub format: FormatSpec, } @@ -37,12 +40,11 @@ pub enum Alignment { pub enum Count { Is(usize), Param(usize), - NextParam, Implied, } +#[cfg(bootstrap)] #[derive(Copy, Clone)] pub enum Position { - Next, At(usize), } diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index a65d47cc2c1..25dfc573e41 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -208,6 +208,11 @@ pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> { #[stable(feature = "iter_empty", since = "1.2.0")] pub struct Empty<T>(marker::PhantomData<T>); +#[stable(feature = "iter_empty_send_sync", since = "1.42.0")] +unsafe impl<T> Send for Empty<T> {} +#[stable(feature = "iter_empty_send_sync", since = "1.42.0")] +unsafe impl<T> Sync for Empty<T> {} + #[stable(feature = "core_impl_debug", since = "1.9.0")] impl<T> fmt::Debug for Empty<T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 15720ddcfc6..f77b4d7461e 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -133,7 +133,7 @@ #![feature(associated_type_bounds)] #![feature(const_type_id)] #![feature(const_caller_location)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #[prelude_import] #[allow(unused)] diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 36064488eb2..4c3b81ea5ec 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -87,27 +87,28 @@ impl<T> ManuallyDrop<T> { slot.value } - /// Takes the contained value out. + /// Takes the value from the `ManuallyDrop<T>` container out. /// /// This method is primarily intended for moving out values in drop. /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, /// you can use this method to take the value and use it however desired. - /// `Drop` will be invoked on the returned value following normal end-of-scope rules. /// - /// If you have ownership of the container, you can use [`ManuallyDrop::into_inner`] instead. + /// Whenever possible, it is preferrable to use [`into_inner`][`ManuallyDrop::into_inner`] + /// instead, which prevents duplicating the content of the `ManuallyDrop<T>`. /// /// # Safety /// - /// This function semantically moves out the contained value without preventing further usage. - /// It is up to the user of this method to ensure that this container is not used again. + /// This function semantically moves out the contained value without preventing further usage, + /// leaving the state of this container unchanged. + /// It is your responsibility to ensure that this `ManuallyDrop` is not used again. /// /// [`ManuallyDrop::drop`]: #method.drop /// [`ManuallyDrop::into_inner`]: #method.into_inner #[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"] - #[unstable(feature = "manually_drop_take", issue = "55422")] + #[stable(feature = "manually_drop_take", since = "1.42.0")] #[inline] pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T { - ManuallyDrop::into_inner(ptr::read(slot)) + ptr::read(&slot.value) } } diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index d7b351f1345..c1976868bf7 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -169,22 +169,12 @@ mod mut_ptr; /// i.e., you do not usually have to worry about such issues unless you call `drop_in_place` /// manually. #[stable(feature = "drop_in_place", since = "1.8.0")] -#[inline(always)] -pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { - real_drop_in_place(&mut *to_drop) -} - -// The real `drop_in_place` -- the one that gets called implicitly when variables go -// out of scope -- should have a safe reference and not a raw pointer as argument -// type. When we drop a local variable, we access it with a pointer that behaves -// like a safe reference; transmuting that to a raw pointer does not mean we can -// actually access it with raw pointers. #[lang = "drop_in_place"] #[allow(unconditional_recursion)] -unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) { +pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { // Code here does not matter - this is replaced by the // real drop glue by the compiler. - real_drop_in_place(to_drop) + drop_in_place(to_drop) } /// Creates a null raw pointer. diff --git a/src/libcore/str/lossy.rs b/src/libcore/str/lossy.rs index 8a1fb9de546..88b2bc551b7 100644 --- a/src/libcore/str/lossy.rs +++ b/src/libcore/str/lossy.rs @@ -3,8 +3,6 @@ use crate::fmt::{self, Write}; use crate::mem; use crate::str as core_str; -// ignore-tidy-undocumented-unsafe - /// Lossy UTF-8 string. #[unstable(feature = "str_internals", issue = "none")] pub struct Utf8Lossy { @@ -17,6 +15,7 @@ impl Utf8Lossy { } pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy { + // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required. unsafe { mem::transmute(bytes) } } @@ -60,6 +59,8 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { while i < self.source.len() { let i_ = i; + // SAFETY: `i` starts at `0`, is less than `self.source.len()`, and + // only increases, so `0 <= i < self.source.len()`. let byte = unsafe { *self.source.get_unchecked(i) }; i += 1; @@ -69,6 +70,7 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { macro_rules! error { () => {{ + // SAFETY: We have checked up to `i` that source is valid UTF-8. unsafe { let r = Utf8LossyChunk { valid: core_str::from_utf8_unchecked(&self.source[0..i_]), @@ -130,6 +132,7 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> { } let r = Utf8LossyChunk { + // SAFETY: We have checked that the entire source is valid UTF-8. valid: unsafe { core_str::from_utf8_unchecked(self.source) }, broken: &[], }; diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index ab771b1164b..5a7cddd4041 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1,5 +1,4 @@ // ignore-tidy-filelength -// ignore-tidy-undocumented-unsafe //! String manipulation. //! @@ -341,6 +340,7 @@ impl Utf8Error { #[stable(feature = "rust1", since = "1.0.0")] pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { run_utf8_validation(v)?; + // SAFETY: Just ran validation. Ok(unsafe { from_utf8_unchecked(v) }) } @@ -379,6 +379,7 @@ pub fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { #[stable(feature = "str_mut_extras", since = "1.20.0")] pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { run_utf8_validation(v)?; + // SAFETY: Just ran validation. Ok(unsafe { from_utf8_unchecked_mut(v) }) } @@ -581,7 +582,7 @@ impl<'a> Iterator for Chars<'a> { #[inline] fn next(&mut self) -> Option<char> { next_code_point(&mut self.iter).map(|ch| { - // str invariant says `ch` is a valid Unicode Scalar Value + // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value. unsafe { char::from_u32_unchecked(ch) } }) } @@ -628,7 +629,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> { #[inline] fn next_back(&mut self) -> Option<char> { next_code_point_reverse(&mut self.iter).map(|ch| { - // str invariant says `ch` is a valid Unicode Scalar Value + // SAFETY: `str` invariant says `ch` is a valid Unicode Scalar Value. unsafe { char::from_u32_unchecked(ch) } }) } @@ -658,6 +659,7 @@ impl<'a> Chars<'a> { #[stable(feature = "iter_to_slice", since = "1.4.0")] #[inline] pub fn as_str(&self) -> &'a str { + // SAFETY: `Chars` is only made from a str, which guarantees the iter is valid UTF-8. unsafe { from_utf8_unchecked(self.iter.as_slice()) } } } @@ -1102,6 +1104,7 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { fn get_end(&mut self) -> Option<&'a str> { if !self.finished && (self.allow_trailing_empty || self.end - self.start > 0) { self.finished = true; + // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. unsafe { let string = self.matcher.haystack().get_unchecked(self.start..self.end); Some(string) @@ -1119,6 +1122,7 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { let haystack = self.matcher.haystack(); match self.matcher.next_match() { + // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries. Some((a, b)) => unsafe { let elt = haystack.get_unchecked(self.start..a); self.start = b; @@ -1151,11 +1155,13 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { let haystack = self.matcher.haystack(); match self.matcher.next_match_back() { + // SAFETY: `Searcher` guarantees that `a` and `b` lie on unicode boundaries. Some((a, b)) => unsafe { let elt = haystack.get_unchecked(b..self.end); self.end = a; Some(elt) }, + // SAFETY: `self.start` and `self.end` always lie on unicode boundaries. None => unsafe { self.finished = true; Some(haystack.get_unchecked(self.start..self.end)) @@ -1297,6 +1303,7 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { fn next(&mut self) -> Option<(usize, &'a str)> { self.0 .next_match() + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) }) } @@ -1307,6 +1314,7 @@ impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { { self.0 .next_match_back() + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. .map(|(start, end)| unsafe { (start, self.0.haystack().get_unchecked(start..end)) }) } } @@ -1348,6 +1356,7 @@ where impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> { #[inline] fn next(&mut self) -> Option<&'a str> { + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. self.0.next_match().map(|(a, b)| unsafe { // Indices are known to be on utf8 boundaries self.0.haystack().get_unchecked(a..b) @@ -1359,6 +1368,7 @@ impl<'a, P: Pattern<'a>> MatchesInternal<'a, P> { where P::Searcher: ReverseSearcher<'a>, { + // SAFETY: `Searcher` guarantees that `start` and `end` lie on unicode boundaries. self.0.next_match_back().map(|(a, b)| unsafe { // Indices are known to be on utf8 boundaries self.0.haystack().get_unchecked(a..b) @@ -1579,6 +1589,10 @@ fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { if align != usize::max_value() && align.wrapping_sub(index) % usize_bytes == 0 { let ptr = v.as_ptr(); while index < blocks_end { + // SAFETY: since `align - index` and `ascii_block_size` are + // multiples of `usize_bytes`, `block = ptr.add(index)` is + // always aligned with a `usize` so it's safe to dereference + // both `block` and `block.offset(1)`. unsafe { let block = ptr.add(index) as *const usize; // break if there is a nonascii byte @@ -1804,6 +1818,7 @@ mod traits { && slice.is_char_boundary(self.start) && slice.is_char_boundary(self.end) { + // SAFETY: just checked that `start` and `end` are on a char boundary. Some(unsafe { self.get_unchecked(slice) }) } else { None @@ -1815,6 +1830,7 @@ mod traits { && slice.is_char_boundary(self.start) && slice.is_char_boundary(self.end) { + // SAFETY: just checked that `start` and `end` are on a char boundary. Some(unsafe { self.get_unchecked_mut(slice) }) } else { None @@ -1845,6 +1861,7 @@ mod traits { && slice.is_char_boundary(self.start) && slice.is_char_boundary(self.end) { + // SAFETY: just checked that `start` and `end` are on a char boundary. unsafe { self.get_unchecked_mut(slice) } } else { super::slice_error_fail(slice, self.start, self.end) @@ -1873,6 +1890,7 @@ mod traits { #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { if slice.is_char_boundary(self.end) { + // SAFETY: just checked that `end` is on a char boundary. Some(unsafe { self.get_unchecked(slice) }) } else { None @@ -1881,6 +1899,7 @@ mod traits { #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { if slice.is_char_boundary(self.end) { + // SAFETY: just checked that `end` is on a char boundary. Some(unsafe { self.get_unchecked_mut(slice) }) } else { None @@ -1903,8 +1922,8 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.end) { + // SAFETY: just checked that `end` is on a char boundary. unsafe { self.get_unchecked_mut(slice) } } else { super::slice_error_fail(slice, 0, self.end) @@ -1934,6 +1953,7 @@ mod traits { #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary. Some(unsafe { self.get_unchecked(slice) }) } else { None @@ -1942,6 +1962,7 @@ mod traits { #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary. Some(unsafe { self.get_unchecked_mut(slice) }) } else { None @@ -1966,8 +1987,8 @@ mod traits { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - // is_char_boundary checks that the index is in [0, .len()] if slice.is_char_boundary(self.start) { + // SAFETY: just checked that `start` is on a char boundary. unsafe { self.get_unchecked_mut(slice) } } else { super::slice_error_fail(slice, self.start, slice.len()) @@ -2238,7 +2259,6 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")] #[inline(always)] - // SAFETY: const sound because we transmute two types with the same layout #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn as_bytes(&self) -> &[u8] { @@ -2247,6 +2267,7 @@ impl str { str: &'a str, slice: &'a [u8], } + // SAFETY: const sound because we transmute two types with the same layout unsafe { Slices { str: self }.slice } } @@ -2573,6 +2594,7 @@ impl str { pub fn split_at(&self, mid: usize) -> (&str, &str) { // is_char_boundary checks that the index is in [0, .len()] if self.is_char_boundary(mid) { + // SAFETY: just checked that `mid` is on a char boundary. unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) } } else { slice_error_fail(self, 0, mid) @@ -2617,6 +2639,7 @@ impl str { if self.is_char_boundary(mid) { let len = self.len(); let ptr = self.as_mut_ptr(); + // SAFETY: just checked that `mid` is on a char boundary. unsafe { ( from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)), @@ -3805,10 +3828,8 @@ impl str { if let Some((_, b)) = matcher.next_reject_back() { j = b; } - unsafe { - // Searcher is known to return valid indices - self.get_unchecked(i..j) - } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { self.get_unchecked(i..j) } } /// Returns a string slice with all prefixes that match a pattern @@ -3844,10 +3865,8 @@ impl str { if let Some((a, _)) = matcher.next_reject() { i = a; } - unsafe { - // Searcher is known to return valid indices - self.get_unchecked(i..self.len()) - } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { self.get_unchecked(i..self.len()) } } /// Returns a string slice with the prefix removed. @@ -3878,10 +3897,8 @@ impl str { "The first search step from Searcher \ must include the first character" ); - unsafe { - // Searcher is known to return valid indices. - Some(self.get_unchecked(len..)) - } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some(self.get_unchecked(len..)) } } else { None } @@ -3919,10 +3936,8 @@ impl str { "The first search step from ReverseSearcher \ must include the last character" ); - unsafe { - // Searcher is known to return valid indices. - Some(self.get_unchecked(..start)) - } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { Some(self.get_unchecked(..start)) } } else { None } @@ -3970,10 +3985,8 @@ impl str { if let Some((_, b)) = matcher.next_reject_back() { j = b; } - unsafe { - // Searcher is known to return valid indices - self.get_unchecked(0..j) - } + // SAFETY: `Searcher` is known to return valid indices. + unsafe { self.get_unchecked(0..j) } } /// Returns a string slice with all prefixes that match a pattern @@ -4166,6 +4179,7 @@ impl str { /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] pub fn make_ascii_uppercase(&mut self) { + // SAFETY: safe because we transmute two types with the same layout. let me = unsafe { self.as_bytes_mut() }; me.make_ascii_uppercase() } @@ -4191,6 +4205,7 @@ impl str { /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] pub fn make_ascii_lowercase(&mut self) { + // SAFETY: safe because we transmute two types with the same layout. let me = unsafe { self.as_bytes_mut() }; me.make_ascii_lowercase() } @@ -4357,6 +4372,7 @@ impl Default for &str { impl Default for &mut str { /// Creates an empty mutable str fn default() -> Self { + // SAFETY: The empty string is valid UTF-8. unsafe { from_utf8_unchecked_mut(&mut []) } } } @@ -4412,6 +4428,7 @@ impl_fn_for_zst! { #[derive(Clone)] struct UnsafeBytesToStr impl<'a> Fn = |bytes: &'a [u8]| -> &'a str { + // SAFETY: not safe unsafe { from_utf8_unchecked(bytes) } }; } diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 46d9499394a..ef64d8b0fdf 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -3,8 +3,6 @@ //! For more details, see the traits [`Pattern`], [`Searcher`], //! [`ReverseSearcher`], and [`DoubleEndedSearcher`]. -// ignore-tidy-undocumented-unsafe - #![unstable( feature = "pattern", reason = "API not fully fleshed out and ready to be stabilized", @@ -271,6 +269,14 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { #[inline] fn next(&mut self) -> SearchStep { let old_finger = self.finger; + // SAFETY: 1-4 guarantee safety of `get_unchecked` + // 1. `self.finger` and `self.finger_back` are kept on unicode boundaries + // (this is invariant) + // 2. `self.finger >= 0` since it starts at 0 and only increases + // 3. `self.finger < self.finger_back` because otherwise the char `iter` + // would return `SearchStep::Done` + // 4. `self.finger` comes before the end of the haystack because `self.finger_back` + // starts at the end and only decreases let slice = unsafe { self.haystack.get_unchecked(old_finger..self.finger_back) }; let mut iter = slice.chars(); let old_len = iter.iter.len(); @@ -293,6 +299,7 @@ unsafe impl<'a> Searcher<'a> for CharSearcher<'a> { // get the haystack after the last character found let bytes = self.haystack.as_bytes().get(self.finger..self.finger_back)?; // the last byte of the utf8 encoded needle + // SAFETY: we have an invariant that `utf8_size < 5` let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) }; if let Some(index) = memchr::memchr(last_byte, bytes) { // The new finger is the index of the byte we found, @@ -336,6 +343,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { #[inline] fn next_back(&mut self) -> SearchStep { let old_finger = self.finger_back; + // SAFETY: see the comment for next() above let slice = unsafe { self.haystack.get_unchecked(self.finger..old_finger) }; let mut iter = slice.chars(); let old_len = iter.iter.len(); @@ -363,6 +371,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { return None; }; // the last byte of the utf8 encoded needle + // SAFETY: we have an invariant that `utf8_size < 5` let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) }; if let Some(index) = memchr::memrchr(last_byte, bytes) { // we searched a slice that was offset by self.finger, diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index fae95ca5cdb..9d449bb9915 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -112,8 +112,6 @@ //! println!("live threads: {}", old_thread_count + 1); //! ``` -// ignore-tidy-undocumented-unsafe - #![stable(feature = "rust1", since = "1.0.0")] #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))] #![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))] @@ -350,6 +348,7 @@ impl AtomicBool { #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] pub fn get_mut(&mut self) -> &mut bool { + // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *(self.v.get() as *mut bool) } } @@ -400,6 +399,8 @@ impl AtomicBool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> bool { + // SAFETY: any data races are prevented by atomic intrinsics and the raw + // pointer passed in is valid because we got it from a reference. unsafe { atomic_load(self.v.get(), order) != 0 } } @@ -432,6 +433,8 @@ impl AtomicBool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, val: bool, order: Ordering) { + // SAFETY: any data races are prevented by atomic intrinsics and the raw + // pointer passed in is valid because we got it from a reference. unsafe { atomic_store(self.v.get(), val as u8, order); } @@ -463,6 +466,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] pub fn swap(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } @@ -558,6 +562,7 @@ impl AtomicBool { success: Ordering, failure: Ordering, ) -> Result<bool, bool> { + // SAFETY: data races are prevented by atomic intrinsics. match unsafe { atomic_compare_exchange(self.v.get(), current as u8, new as u8, success, failure) } { @@ -615,6 +620,7 @@ impl AtomicBool { success: Ordering, failure: Ordering, ) -> Result<bool, bool> { + // SAFETY: data races are prevented by atomic intrinsics. match unsafe { atomic_compare_exchange_weak(self.v.get(), current as u8, new as u8, success, failure) } { @@ -661,6 +667,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } } @@ -756,6 +763,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } } @@ -797,6 +805,7 @@ impl AtomicBool { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "8")] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } @@ -872,6 +881,7 @@ impl<T> AtomicPtr<T> { #[inline] #[stable(feature = "atomic_access", since = "1.15.0")] pub fn get_mut(&mut self) -> &mut *mut T { + // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *self.p.get() } } @@ -923,6 +933,7 @@ impl<T> AtomicPtr<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn load(&self, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_load(self.p.get() as *mut usize, order) as *mut T } } @@ -957,6 +968,7 @@ impl<T> AtomicPtr<T> { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn store(&self, ptr: *mut T, order: Ordering) { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.p.get() as *mut usize, ptr as usize, order); } @@ -990,6 +1002,7 @@ impl<T> AtomicPtr<T> { #[stable(feature = "rust1", since = "1.0.0")] #[cfg(target_has_atomic = "ptr")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T } } @@ -1074,6 +1087,7 @@ impl<T> AtomicPtr<T> { success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { let res = atomic_compare_exchange( self.p.get() as *mut usize, @@ -1137,6 +1151,7 @@ impl<T> AtomicPtr<T> { success: Ordering, failure: Ordering, ) -> Result<*mut T, *mut T> { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { let res = atomic_compare_exchange_weak( self.p.get() as *mut usize, @@ -1290,6 +1305,7 @@ assert_eq!(some_var.load(Ordering::SeqCst), 5); #[inline] #[$stable_access] pub fn get_mut(&mut self) -> &mut $int_type { + // SAFETY: the mutable reference guarantees unique ownership. unsafe { &mut *self.v.get() } } } @@ -1344,6 +1360,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 5); #[inline] #[$stable] pub fn load(&self, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_load(self.v.get(), order) } } } @@ -1378,6 +1395,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); #[inline] #[$stable] pub fn store(&self, val: $int_type, order: Ordering) { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_store(self.v.get(), val, order); } } } @@ -1408,6 +1426,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); #[$stable] #[$cfg_cas] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_swap(self.v.get(), val, order) } } } @@ -1510,6 +1529,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); new: $int_type, success: Ordering, failure: Ordering) -> Result<$int_type, $int_type> { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_compare_exchange(self.v.get(), current, new, success, failure) } } } @@ -1562,6 +1582,7 @@ loop { new: $int_type, success: Ordering, failure: Ordering) -> Result<$int_type, $int_type> { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_compare_exchange_weak(self.v.get(), current, new, success, failure) } @@ -1596,6 +1617,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); #[$stable] #[$cfg_cas] pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_add(self.v.get(), val, order) } } } @@ -1628,6 +1650,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); #[$stable] #[$cfg_cas] pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_sub(self.v.get(), val, order) } } } @@ -1663,6 +1686,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b100001); #[$stable] #[$cfg_cas] pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_and(self.v.get(), val, order) } } } @@ -1699,6 +1723,7 @@ assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); #[$stable_nand] #[$cfg_cas] pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_nand(self.v.get(), val, order) } } } @@ -1734,6 +1759,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b111111); #[$stable] #[$cfg_cas] pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_or(self.v.get(), val, order) } } } @@ -1769,6 +1795,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110); #[$stable] #[$cfg_cas] pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { atomic_xor(self.v.get(), val, order) } } } @@ -1880,6 +1907,7 @@ assert!(max_foo == 42); issue = "48655")] #[$cfg_cas] pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { $max_fn(self.v.get(), val, order) } } } @@ -1932,6 +1960,7 @@ assert_eq!(min_foo, 12); issue = "48655")] #[$cfg_cas] pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { + // SAFETY: data races are prevented by atomic intrinsics. unsafe { $min_fn(self.v.get(), val, order) } } } @@ -1960,7 +1989,9 @@ extern { } let mut atomic = ", stringify!($atomic_type), "::new(1); -unsafe { +", +// SAFETY: Safe as long as `my_atomic_op` is atomic. +"unsafe { my_atomic_op(atomic.as_mut_ptr()); } # } @@ -2526,6 +2557,7 @@ pub fn fence(order: Ordering) { // https://github.com/WebAssembly/tool-conventions/issues/59. We should // follow that discussion and implement a solution when one comes about! #[cfg(not(target_arch = "wasm32"))] + // SAFETY: using an atomic fence is safe. unsafe { match order { Acquire => intrinsics::atomic_fence_acq(), @@ -2613,6 +2645,7 @@ pub fn fence(order: Ordering) { #[inline] #[stable(feature = "compiler_fences", since = "1.21.0")] pub fn compiler_fence(order: Ordering) { + // SAFETY: using an atomic fence is safe. unsafe { match order { Acquire => intrinsics::atomic_singlethreadfence_acq(), diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 8c034938c2b..f0420247acf 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -19,7 +19,7 @@ #![feature(range_is_empty)] #![feature(raw)] #![feature(saturating_neg)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(sort_internals)] #![feature(slice_partition_at_index)] #![feature(specialization)] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 323ce3b6cbb..b65635be54a 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -37,5 +37,4 @@ byteorder = { version = "1.3" } chalk-engine = { version = "0.9.0", default-features=false } smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" -rustc_error_codes = { path = "../librustc_error_codes" } rustc_session = { path = "../librustc_session" } diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index cb3fdff53a3..15e92d8d842 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -123,6 +123,9 @@ macro_rules! arena_types { [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>, [] upvars: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, + // Interned types + [] tys: rustc::ty::TyS<$tcx>, + // HIR types [few] hir_forest: rustc::hir::map::Forest<$tcx>, [] arm: rustc_hir::Arm<$tcx>, @@ -176,7 +179,7 @@ macro_rules! declare_arena { ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => { #[derive(Default)] pub struct Arena<$tcx> { - dropless: DroplessArena, + pub dropless: DroplessArena, drop: DropArena, $($name: arena_for_type!($a[$ty]),)* } diff --git a/src/librustc/benches/lib.rs b/src/librustc/benches/lib.rs index ffb12f11c51..de82b262e49 100644 --- a/src/librustc/benches/lib.rs +++ b/src/librustc/benches/lib.rs @@ -1,4 +1,4 @@ -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(test)] extern crate test; diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 5a99e796553..86eab3d92d3 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -8,7 +8,6 @@ use crate::hir::map::Map; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -112,7 +111,7 @@ impl Target { ItemKind::Union(..) => Target::Union, ItemKind::Trait(..) => Target::Trait, ItemKind::TraitAlias(..) => Target::TraitAlias, - ItemKind::Impl(..) => Target::Impl, + ItemKind::Impl { .. } => Target::Impl, } } @@ -144,7 +143,7 @@ impl Target { let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id); let containing_item = tcx.hir().expect_item(parent_hir_id); let containing_impl_is_for_trait = match &containing_item.kind { - hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(), + hir::ItemKind::Impl { ref of_trait, .. } => of_trait.is_some(), _ => bug!("parent of an ImplItem must be an Impl"), }; if containing_impl_is_for_trait { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 46c5ee272d2..6d7f53133a6 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -341,7 +341,7 @@ impl<'hir> Map<'hir> { | ItemKind::Use(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) - | ItemKind::Impl(..) => return None, + | ItemKind::Impl { .. } => return None, }, Node::ForeignItem(item) => match item.kind { ForeignItemKind::Fn(..) => DefKind::Fn, @@ -604,7 +604,7 @@ impl<'hir> Map<'hir> { | ItemKind::Union(_, ref generics) | ItemKind::Trait(_, _, ref generics, ..) | ItemKind::TraitAlias(ref generics, _) - | ItemKind::Impl(_, _, _, ref generics, ..) => Some(generics), + | ItemKind::Impl { ref generics, .. } => Some(generics), _ => None, }, _ => None, @@ -821,7 +821,7 @@ impl<'hir> Map<'hir> { | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::Trait(..) - | ItemKind::Impl(..) => true, + | ItemKind::Impl { .. } => true, _ => false, }, Node::ForeignItem(fi) => match fi.kind { @@ -1332,7 +1332,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Impl(..) => "impl", + ItemKind::Impl { .. } => "impl", }; format!("{} {}{}", item_str, path_str(), id_str) } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index febf4f21a67..77182b97fd4 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -65,7 +65,6 @@ use crate::ty::{ Region, Ty, TyCtxt, TypeFoldable, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_error_codes::*; use rustc_errors::{pluralize, struct_span_err}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; use rustc_hir as hir; @@ -254,7 +253,7 @@ fn emit_msg_span( fn item_scope_tag(item: &hir::Item<'_>) -> &'static str { match item.kind { - hir::ItemKind::Impl(..) => "impl", + hir::ItemKind::Impl { .. } => "impl", hir::ItemKind::Struct(..) => "struct", hir::ItemKind::Union(..) => "union", hir::ItemKind::Enum(..) => "enum", diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 70f7987faf4..9947dea2340 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -13,8 +13,6 @@ use rustc_span::symbol::kw; use rustc_span::Span; use std::borrow::Cow; -use rustc_error_codes::*; - struct FindLocalByTypeVisitor<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs index d6e50209f72..8f4c6439920 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -5,7 +5,6 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::util::common::ErrorReported; -use rustc_error_codes::*; use rustc_errors::struct_span_err; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 2344d408a43..df37f53606b 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -5,8 +5,6 @@ use crate::ty; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir::{FunctionRetTy, TyKind}; -use rustc_error_codes::*; - impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// When given a `ConcreteFailure` for a function with parameters containing a named region and /// an anonymous region, emit an descriptive diagnostic error. diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 6303104e39d..11dda71b8cb 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -5,8 +5,6 @@ use crate::ty::error::TypeError; use crate::ty::{self, Region}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; -use rustc_error_codes::*; - impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub(super) fn note_region_origin( &self, diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 0bc49a29015..18c25ef0dd9 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -19,7 +19,6 @@ use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; use rustc_hir::def_id::DefId; -use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::Span; use std::fmt; @@ -295,62 +294,59 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { - let mut process_constraint = |constraint: &Constraint<'tcx>| { - let (a_region, b_vid, b_data, retain) = match *constraint { + let mut constraints = IndexVec::from_elem_n(Vec::new(), var_values.values.len()); + let mut changes = Vec::new(); + for constraint in self.data.constraints.keys() { + let (a_vid, a_region, b_vid, b_data) = match *constraint { Constraint::RegSubVar(a_region, b_vid) => { let b_data = var_values.value_mut(b_vid); - (a_region, b_vid, b_data, false) + (None, a_region, b_vid, b_data) } Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) { - VarValue::ErrorValue => return (false, false), + VarValue::ErrorValue => continue, VarValue::Value(a_region) => { let b_data = var_values.value_mut(b_vid); - let retain = match *b_data { - VarValue::Value(ReStatic) | VarValue::ErrorValue => false, - _ => true, - }; - (a_region, b_vid, b_data, retain) + (Some(a_vid), a_region, b_vid, b_data) } }, Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => { // These constraints are checked after expansion // is done, in `collect_errors`. - return (false, false); + continue; } }; - - let changed = self.expand_node(a_region, b_vid, b_data); - (changed, retain) - }; - - // Using bitsets to track the remaining elements is faster than using a - // `Vec` by itself (which requires removing elements, which requires - // element shuffling, which is slow). - let constraints: Vec<_> = self.data.constraints.keys().collect(); - let mut live_indices: BitSet<usize> = BitSet::new_filled(constraints.len()); - let mut killed_indices: BitSet<usize> = BitSet::new_empty(constraints.len()); - let mut changed = true; - while changed { - changed = false; - for index in live_indices.iter() { - let constraint = constraints[index]; - let (edge_changed, retain) = process_constraint(constraint); - changed |= edge_changed; - if !retain { - let changed = killed_indices.insert(index); - debug_assert!(changed); + if self.expand_node(a_region, b_vid, b_data) { + changes.push(b_vid); + } + if let Some(a_vid) = a_vid { + match *b_data { + VarValue::Value(ReStatic) | VarValue::ErrorValue => (), + _ => { + constraints[a_vid].push((a_vid, b_vid)); + constraints[b_vid].push((a_vid, b_vid)); + } } } - live_indices.subtract(&killed_indices); + } - // We could clear `killed_indices` here, but we don't need to and - // it's cheaper not to. + while let Some(vid) = changes.pop() { + constraints[vid].retain(|&(a_vid, b_vid)| { + let a_region = match *var_values.value(a_vid) { + VarValue::ErrorValue => return false, + VarValue::Value(a_region) => a_region, + }; + let b_data = var_values.value_mut(b_vid); + if self.expand_node(a_region, b_vid, b_data) { + changes.push(b_vid); + } + match *b_data { + VarValue::Value(ReStatic) | VarValue::ErrorValue => false, + _ => true, + } + }); } } - // This function is very hot in some workloads. There's a single callsite - // so always inlining is ok even though it's large. - #[inline(always)] fn expand_node( &self, a_region: Region<'tcx>, @@ -790,8 +786,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { self.var_infos[node_idx].origin.span(), &format!( "collect_error_for_expanding_node() could not find \ - error for var {:?} in universe {:?}, lower_bounds={:#?}, \ - upper_bounds={:#?}", + error for var {:?} in universe {:?}, lower_bounds={:#?}, \ + upper_bounds={:#?}", node_idx, node_universe, lower_bounds, upper_bounds ), ); diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index ee214bea7b8..fe3a5d149f6 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -15,8 +15,6 @@ use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_hir::Node; use rustc_span::Span; -use rustc_error_codes::*; - pub type OpaqueTypeMap<'tcx> = DefIdMap<OpaqueTypeDecl<'tcx>>; /// Information about the opaque types whose values we diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b894aabd901..69ca4063694 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -42,7 +42,7 @@ #![feature(optin_builtin_traits)] #![feature(option_expect_none)] #![feature(range_is_empty)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(specialization)] #![feature(unboxed_closures)] #![feature(thread_local)] diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index e4af54f7771..a349b34eb1a 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -32,7 +32,9 @@ pub enum ExportedSymbol<'tcx> { } impl<'tcx> ExportedSymbol<'tcx> { - pub fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName { + /// This is the symbol name of an instance if it is instantiated in the + /// local crate. + pub fn symbol_name_for_local_instance(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName { match *self { ExportedSymbol::NonGeneric(def_id) => tcx.symbol_name(ty::Instance::mono(tcx, def_id)), ExportedSymbol::Generic(def_id, substs) => { @@ -50,9 +52,22 @@ impl<'tcx> ExportedSymbol<'tcx> { } ExportedSymbol::Generic(..) | ExportedSymbol::NoDefId(_) => cmp::Ordering::Less, }, - ExportedSymbol::Generic(..) => match *other { + ExportedSymbol::Generic(self_def_id, self_substs) => match *other { ExportedSymbol::NonGeneric(_) => cmp::Ordering::Greater, - ExportedSymbol::Generic(..) => self.symbol_name(tcx).cmp(&other.symbol_name(tcx)), + ExportedSymbol::Generic(other_def_id, other_substs) => { + // We compare the symbol names because they are cached as query + // results which makes them relatively cheap to access repeatedly. + // + // It might be even faster to build a local cache of stable IDs + // for sorting. Exported symbols are really only sorted once + // in order to make the `exported_symbols` query result stable. + let self_symbol_name = + tcx.symbol_name(ty::Instance::new(self_def_id, self_substs)); + let other_symbol_name = + tcx.symbol_name(ty::Instance::new(other_def_id, other_substs)); + + self_symbol_name.cmp(&other_symbol_name) + } ExportedSymbol::NoDefId(_) => cmp::Ordering::Less, }, ExportedSymbol::NoDefId(self_symbol_name) => match *other { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 643359f098b..27b769742a9 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -24,8 +24,6 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use syntax::ast; -use rustc_error_codes::*; - // The actual lang items defined come at the end of this file in one handy table. // So you probably just want to nip down to the end. macro_rules! language_item_table { diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index fdffd1251ce..5571f8f2313 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -15,8 +15,6 @@ use rustc_span::Span; use rustc_target::spec::PanicStrategy; use syntax::ast; -use rustc_error_codes::*; - macro_rules! weak_lang_items { ($($name:ident, $item:ident, $sym:ident;)*) => ( diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 42d896af801..349dbd74ad1 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -16,8 +16,6 @@ use rustc_span::{Pos, Span}; use rustc_target::spec::abi::Abi; use std::{any::Any, env, fmt}; -use rustc_error_codes::*; - #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)] pub enum ErrorHandled { /// Already reported a lint or an error for this evaluation. diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index e7a4c5b5921..51ce575e51f 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,7 +1,6 @@ use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId}; use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; use crate::session::config::OptLevel; -use crate::traits::TraitQueryMode; use crate::ty::print::obsolete::DefPathBasedNames; use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_data_structures::base_n; @@ -168,9 +167,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(..) => return true, }; - // We shouldn't encounter any overflow here, so we use TraitQueryMode::Standard\ - // to report an error if overflow somehow occurs. - tcx.substitute_normalize_and_test_predicates((def_id, &substs, TraitQueryMode::Standard)) + tcx.substitute_normalize_and_test_predicates((def_id, &substs)) } pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index a20e011b91a..deb2d6ac630 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -557,6 +557,9 @@ rustc_queries! { desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } } + /// The `symbol_name` query provides the symbol name for calling a + /// given instance from the local crate. In particular, it will also + /// look up the correct symbol name of instances from upstream crates. query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName { no_force desc { "computing the symbol for `{}`", key } @@ -971,6 +974,11 @@ rustc_queries! { } Linking { + /// The list of symbols exported from the given crate. + /// + /// - All names contained in `exported_symbols(cnum)` are guaranteed to + /// correspond to a publicly visible symbol in `cnum` machine code. + /// - The `exported_symbols` sets of different crates do not intersect. query exported_symbols(_: CrateNum) -> Arc<Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)>> { desc { "exported_symbols" } @@ -1148,11 +1156,11 @@ rustc_queries! { desc { "normalizing `{:?}`", goal } } - query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>, traits::TraitQueryMode)) -> bool { + query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { no_force desc { |tcx| - "testing substituted normalized predicates in mode {:?}:`{}`", - key.2, tcx.def_path_str(key.0) + "testing substituted normalized predicates:`{}`", + tcx.def_path_str(key.0) } } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 89b28aeda1c..c97c5c2077f 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -337,7 +337,10 @@ impl AutoTraitFinder<'tcx> { &Err(SelectionError::Unimplemented) => { if self.is_param_no_infer(pred.skip_binder().trait_ref.substs) { already_visited.remove(&pred); - self.add_user_pred(&mut user_computed_preds, ty::Predicate::Trait(pred)); + self.add_user_pred( + &mut user_computed_preds, + ty::Predicate::Trait(pred, ast::Constness::NotConst), + ); predicates.push_back(pred); } else { debug!( @@ -405,7 +408,7 @@ impl AutoTraitFinder<'tcx> { let mut should_add_new = true; user_computed_preds.retain(|&old_pred| { match (&new_pred, old_pred) { - (&ty::Predicate::Trait(new_trait), ty::Predicate::Trait(old_trait)) => { + (&ty::Predicate::Trait(new_trait, _), ty::Predicate::Trait(old_trait, _)) => { if new_trait.def_id() == old_trait.def_id() { let new_substs = new_trait.skip_binder().trait_ref.substs; let old_substs = old_trait.skip_binder().trait_ref.substs; @@ -627,7 +630,7 @@ impl AutoTraitFinder<'tcx> { // We check this by calling is_of_param on the relevant types // from the various possible predicates match &predicate { - &ty::Predicate::Trait(p) => { + &ty::Predicate::Trait(p, _) => { if self.is_param_no_infer(p.skip_binder().trait_ref.substs) && !only_projections && is_new_pred diff --git a/src/librustc/traits/engine.rs b/src/librustc/traits/engine.rs index 5b804480119..84bfc86e6a9 100644 --- a/src/librustc/traits/engine.rs +++ b/src/librustc/traits/engine.rs @@ -1,6 +1,6 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; -use crate::ty::{self, ToPredicate, Ty, TyCtxt}; +use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_hir::def_id::DefId; use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError}; @@ -33,7 +33,7 @@ pub trait TraitEngine<'tcx>: 'tcx { cause, recursion_depth: 0, param_env, - predicate: trait_ref.to_predicate(), + predicate: trait_ref.without_const().to_predicate(), }, ); } diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc/traits/error_reporting/mod.rs index db3173989ac..d1c369d0abb 100644 --- a/src/librustc/traits/error_reporting/mod.rs +++ b/src/librustc/traits/error_reporting/mod.rs @@ -19,7 +19,9 @@ use crate::ty::error::ExpectedFound; use crate::ty::fast_reject; use crate::ty::fold::TypeFolder; use crate::ty::SubtypePredicate; -use crate::ty::{self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{ + self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, +}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; @@ -30,8 +32,6 @@ use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; use syntax::ast; -use rustc_error_codes::*; - impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_fulfillment_errors( &self, @@ -130,7 +130,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let (cond, error) = match (cond, error) { - (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) => (cond, error), + (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error), _ => { // FIXME: make this work in other cases too. return false; @@ -138,7 +138,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) { - if let ty::Predicate::Trait(implication) = implication { + if let ty::Predicate::Trait(implication, _) = implication { let error = error.to_poly_trait_ref(); let implication = implication.to_poly_trait_ref(); // FIXME: I'm just not taking associated types at all here. @@ -530,7 +530,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return; } match obligation.predicate { - ty::Predicate::Trait(ref trait_predicate) => { + ty::Predicate::Trait(ref trait_predicate, _) => { let trait_predicate = self.resolve_vars_if_possible(trait_predicate); if self.tcx.sess.has_errors() && trait_predicate.references_error() { @@ -583,7 +583,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "{}", message.unwrap_or_else(|| format!( "the trait bound `{}` is not satisfied{}", - trait_ref.to_predicate(), + trait_ref.without_const().to_predicate(), post_message, )) ); @@ -695,7 +695,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_pred }); let unit_obligation = Obligation { - predicate: ty::Predicate::Trait(predicate), + predicate: ty::Predicate::Trait( + predicate, + ast::Constness::NotConst, + ), ..obligation.clone() }; if self.predicate_may_hold(&unit_obligation) { @@ -988,7 +991,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> PredicateObligation<'tcx> { let new_trait_ref = ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) }; - Obligation::new(cause, param_env, new_trait_ref.to_predicate()) + Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate()) } } @@ -1076,7 +1079,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let mut err = match predicate { - ty::Predicate::Trait(ref data) => { + ty::Predicate::Trait(ref data, _) => { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref); @@ -1269,8 +1272,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) .value; - let obligation = - Obligation::new(ObligationCause::dummy(), param_env, cleaned_pred.to_predicate()); + let obligation = Obligation::new( + ObligationCause::dummy(), + param_env, + cleaned_pred.without_const().to_predicate(), + ); self.predicate_may_hold(&obligation) }) diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc/traits/error_reporting/suggestions.rs index bf6891214ac..4559007ea42 100644 --- a/src/librustc/traits/error_reporting/suggestions.rs +++ b/src/librustc/traits/error_reporting/suggestions.rs @@ -6,7 +6,7 @@ use super::{ use crate::infer::InferCtxt; use crate::traits::object_safety::object_safety_violations; use crate::ty::TypeckTables; -use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, @@ -20,8 +20,6 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; -use rustc_error_codes::*; - impl<'a, 'tcx> InferCtxt<'a, 'tcx> { crate fn suggest_restricting_param_bound( &self, @@ -50,7 +48,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } else { " where" }, - trait_ref.to_predicate(), + trait_ref.without_const().to_predicate(), ), Applicability::MachineApplicable, ); @@ -88,8 +86,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .. }) | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(_, _, _, generics, ..), - .. + kind: hir::ItemKind::Impl { generics, .. }, .. }) if projection.is_some() => { // Missing associated type bound. suggest_restriction(&generics, "the associated type", err); @@ -115,7 +112,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .. }) | hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(_, _, _, generics, ..), + kind: hir::ItemKind::Impl { generics, .. }, span, .. }) @@ -341,8 +338,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty); let substs = self.tcx.mk_substs_trait(new_self_ty, &[]); let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs); - let new_obligation = - Obligation::new(ObligationCause::dummy(), param_env, new_trait_ref.to_predicate()); + let new_obligation = Obligation::new( + ObligationCause::dummy(), + param_env, + new_trait_ref.without_const().to_predicate(), + ); if self.predicate_must_hold_modulo_regions(&new_obligation) { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { // We have a very specific type of error, where just borrowing this argument @@ -1123,7 +1123,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // the type. The last generator has information about where the bound was introduced. At // least one generator should be present for this diagnostic to be modified. let (mut trait_ref, mut target_ty) = match obligation.predicate { - ty::Predicate::Trait(p) => { + ty::Predicate::Trait(p, _) => { (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty())) } _ => (None, None), @@ -1546,7 +1546,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.note(&format!("required because it appears within the type `{}`", ty)); obligated_types.push(ty); - let parent_predicate = parent_trait_ref.to_predicate(); + let parent_predicate = parent_trait_ref.without_const().to_predicate(); if !self.is_recursive_obligation(obligated_types, &data.parent_code) { self.note_obligation_cause_code( err, @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { parent_trait_ref.print_only_trait_path(), parent_trait_ref.skip_binder().self_ty() )); - let parent_predicate = parent_trait_ref.to_predicate(); + let parent_predicate = parent_trait_ref.without_const().to_predicate(); self.note_obligation_cause_code( err, &parent_predicate, diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 9e5abc80822..0aac6fb81e4 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -16,7 +16,6 @@ use super::CodeSelectionError; use super::{ConstEvalFailure, Unimplemented}; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; -use crate::traits::TraitQueryMode; impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { type Predicate = ty::Predicate<'tcx>; @@ -63,9 +62,6 @@ pub struct FulfillmentContext<'tcx> { // a snapshot (they don't *straddle* a snapshot, so there // is no trouble there). usable_in_snapshot: bool, - - // The `TraitQueryMode` used when constructing a `SelectionContext` - query_mode: TraitQueryMode, } #[derive(Clone, Debug)] @@ -79,26 +75,12 @@ pub struct PendingPredicateObligation<'tcx> { static_assert_size!(PendingPredicateObligation<'_>, 136); impl<'a, 'tcx> FulfillmentContext<'tcx> { - /// Creates a new fulfillment context with `TraitQueryMode::Standard` - /// You almost always want to use this instead of `with_query_mode` + /// Creates a new fulfillment context. pub fn new() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), register_region_obligations: true, usable_in_snapshot: false, - query_mode: TraitQueryMode::Standard, - } - } - - /// Creates a new fulfillment context with the specified query mode. - /// This should only be used when you want to ignore overflow, - /// rather than reporting it as an error. - pub fn with_query_mode(query_mode: TraitQueryMode) -> FulfillmentContext<'tcx> { - FulfillmentContext { - predicates: ObligationForest::new(), - register_region_obligations: true, - usable_in_snapshot: false, - query_mode, } } @@ -107,7 +89,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { predicates: ObligationForest::new(), register_region_obligations: true, usable_in_snapshot: true, - query_mode: TraitQueryMode::Standard, } } @@ -116,7 +97,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { predicates: ObligationForest::new(), register_region_obligations: false, usable_in_snapshot: false, - query_mode: TraitQueryMode::Standard, } } @@ -237,7 +217,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { &mut self, infcx: &InferCtxt<'_, 'tcx>, ) -> Result<(), Vec<FulfillmentError<'tcx>>> { - let mut selcx = SelectionContext::with_query_mode(infcx, self.query_mode); + let mut selcx = SelectionContext::new(infcx); self.select(&mut selcx) } @@ -331,7 +311,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } match obligation.predicate { - ty::Predicate::Trait(ref data) => { + ty::Predicate::Trait(ref data, _) => { let trait_obligation = obligation.with(data.clone()); if data.is_global() { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 2e5da2b0382..daaba95cf6b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -29,7 +29,7 @@ use crate::mir::interpret::ErrorHandled; use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::subst::{InternalSubsts, SubstsRef}; -use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt}; +use crate::ty::{self, AdtKind, GenericParamDefKind, List, ToPredicate, Ty, TyCtxt, WithConstness}; use crate::util::common::ErrorReported; use chalk_engine; use rustc_hir as hir; @@ -95,7 +95,7 @@ pub enum IntercrateMode { } /// The mode that trait queries run in. -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TraitQueryMode { // Standard/un-canonicalized queries get accurate // spans etc. passed in and hence can do reasonable @@ -732,7 +732,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( param_env, cause: ObligationCause::misc(span, hir::DUMMY_HIR_ID), recursion_depth: 0, - predicate: trait_ref.to_predicate(), + predicate: trait_ref.without_const().to_predicate(), }; let result = infcx.predicate_must_hold_modulo_regions(&obligation); @@ -1014,17 +1014,16 @@ where /// environment. If this returns false, then either normalize /// encountered an error or one of the predicates did not hold. Used /// when creating vtables to check for unsatisfiable methods. -fn normalize_and_test_predicates<'tcx>( +pub fn normalize_and_test_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: Vec<ty::Predicate<'tcx>>, - mode: TraitQueryMode, ) -> bool { - debug!("normalize_and_test_predicates(predicates={:?}, mode={:?})", predicates, mode); + debug!("normalize_and_test_predicates(predicates={:?})", predicates); let result = tcx.infer_ctxt().enter(|infcx| { let param_env = ty::ParamEnv::reveal_all(); - let mut selcx = SelectionContext::with_query_mode(&infcx, mode); - let mut fulfill_cx = FulfillmentContext::with_query_mode(mode); + let mut selcx = SelectionContext::new(&infcx); + let mut fulfill_cx = FulfillmentContext::new(); let cause = ObligationCause::dummy(); let Normalized { value: predicates, obligations } = normalize(&mut selcx, param_env, cause.clone(), &predicates); @@ -1044,12 +1043,12 @@ fn normalize_and_test_predicates<'tcx>( fn substitute_normalize_and_test_predicates<'tcx>( tcx: TyCtxt<'tcx>, - key: (DefId, SubstsRef<'tcx>, TraitQueryMode), + key: (DefId, SubstsRef<'tcx>), ) -> bool { debug!("substitute_normalize_and_test_predicates(key={:?})", key); let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates; - let result = normalize_and_test_predicates(tcx, predicates, key.2); + let result = normalize_and_test_predicates(tcx, predicates); debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result); result @@ -1102,10 +1101,7 @@ fn vtable_methods<'tcx>( // Note that this method could then never be called, so we // do not want to try and codegen it, in that case (see #23435). let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); - // We don't expect overflow here, so report an error if it somehow ends - // up happening. - if !normalize_and_test_predicates(tcx, predicates.predicates, TraitQueryMode::Standard) - { + if !normalize_and_test_predicates(tcx, predicates.predicates) { debug!("vtable_methods: predicates do not hold"); return None; } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index ce57fb81104..15f81bb3f47 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -12,7 +12,7 @@ use super::elaborate_predicates; use crate::traits::{self, Obligation, ObligationCause}; use crate::ty::subst::{InternalSubsts, Subst}; -use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; @@ -234,7 +234,7 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o .map(|(predicate, _)| predicate.subst_supertrait(tcx, &trait_ref)) .any(|predicate| { match predicate { - ty::Predicate::Trait(ref data) => { + ty::Predicate::Trait(ref data, _) => { // In the case of a trait predicate, we can skip the "self" type. data.skip_binder().input_types().skip(1).any(has_self_ty) } @@ -285,7 +285,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { let predicates = tcx.predicates_of(def_id); let predicates = predicates.instantiate_identity(tcx).predicates; elaborate_predicates(tcx, predicates).any(|predicate| match predicate { - ty::Predicate::Trait(ref trait_pred) => { + ty::Predicate::Trait(ref trait_pred, _) => { trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0) } ty::Predicate::Projection(..) @@ -585,6 +585,7 @@ fn receiver_is_dispatchable<'tcx>( def_id: unsize_did, substs: tcx.mk_substs_trait(tcx.types.self_param, &[unsized_self_ty.into()]), } + .without_const() .to_predicate(); // U: Trait<Arg1, ..., ArgN> @@ -598,7 +599,7 @@ fn receiver_is_dispatchable<'tcx>( } }); - ty::TraitRef { def_id: unsize_did, substs }.to_predicate() + ty::TraitRef { def_id: unsize_did, substs }.without_const().to_predicate() }; let caller_bounds: Vec<Predicate<'tcx>> = param_env @@ -620,6 +621,7 @@ fn receiver_is_dispatchable<'tcx>( def_id: dispatch_from_dyn_did, substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]), } + .without_const() .to_predicate(); Obligation::new(ObligationCause::dummy(), param_env, predicate) diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 1afe153bb13..669ec5ccc9b 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -11,8 +11,6 @@ use rustc_span::Span; use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; -use rustc_error_codes::*; - #[derive(Clone, Debug)] pub struct OnUnimplementedFormatString(Symbol); diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 5bc211ade40..62672a78104 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -16,7 +16,7 @@ use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; use crate::ty::fold::{TypeFoldable, TypeFolder}; use crate::ty::subst::{InternalSubsts, Subst}; -use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt}; +use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; @@ -738,7 +738,12 @@ fn get_paranoid_cache_value_obligation<'a, 'tcx>( depth: usize, ) -> PredicateObligation<'tcx> { let trait_ref = projection_ty.trait_ref(infcx.tcx).to_poly_trait_ref(); - Obligation { cause, recursion_depth: depth, param_env, predicate: trait_ref.to_predicate() } + Obligation { + cause, + recursion_depth: depth, + param_env, + predicate: trait_ref.without_const().to_predicate(), + } } /// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not @@ -772,7 +777,7 @@ fn normalize_to_error<'a, 'tcx>( cause, recursion_depth: depth, param_env, - predicate: trait_ref.to_predicate(), + predicate: trait_ref.without_const().to_predicate(), }; let tcx = selcx.infcx().tcx; let def_id = projection_ty.item_def_id; diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 34866b684de..2e5ef5adcd3 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -6,8 +6,6 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_span::source_map::Span; use std::iter::FromIterator; -use rustc_error_codes::*; - impl<'cx, 'tcx> At<'cx, 'tcx> { /// Given a type `ty` of some value being dropped, computes a set /// of "kinds" (types, regions) that must be outlive the execution diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc/traits/query/type_op/prove_predicate.rs index c0a0cbe9a38..15870ec95d8 100644 --- a/src/librustc/traits/query/type_op/prove_predicate.rs +++ b/src/librustc/traits/query/type_op/prove_predicate.rs @@ -24,7 +24,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> { // `&T`, accounts for about 60% percentage of the predicates // we have to prove. No need to canonicalize and all that for // such cases. - if let Predicate::Trait(trait_ref) = key.value.predicate { + if let Predicate::Trait(trait_ref, _) = key.value.predicate { if let Some(sized_def_id) = tcx.lang_items().sized_trait() { if trait_ref.def_id() == sized_def_id { if trait_ref.skip_binder().self_ty().is_trivially_sized(tcx) { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index fb1c46834d3..ac1ca4db9d6 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -37,7 +37,7 @@ use crate::middle::lang_items; use crate::ty::fast_reject; use crate::ty::relate::TypeRelation; use crate::ty::subst::{Subst, SubstsRef}; -use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_hir::def_id::DefId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -51,7 +51,7 @@ use std::cmp; use std::fmt::{self, Display}; use std::iter; use std::rc::Rc; -use syntax::attr; +use syntax::{ast, attr}; pub struct SelectionContext<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, @@ -718,7 +718,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match obligation.predicate { - ty::Predicate::Trait(ref t) => { + ty::Predicate::Trait(ref t, _) => { debug_assert!(!t.has_escaping_bound_vars()); let obligation = obligation.with(t.clone()); self.evaluate_trait_predicate_recursively(previous_stack, obligation) @@ -945,7 +945,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // trait refs. This is important because it's only a cycle // if the regions match exactly. let cycle = stack.iter().skip(1).take_while(|s| s.depth >= cycle_depth); - let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate)); + let cycle = cycle.map(|stack| { + ty::Predicate::Trait(stack.obligation.predicate, ast::Constness::NotConst) + }); if self.coinductive_match(cycle) { debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref); Some(EvaluatedToOk) @@ -1060,7 +1062,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool { let result = match predicate { - ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()), + ty::Predicate::Trait(ref data, _) => self.tcx().trait_is_auto(data.def_id()), _ => false, }; debug!("coinductive_predicate({:?}) = {:?}", predicate, result); @@ -1417,6 +1419,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("winnowed to {} candidates for {:?}: {:?}", candidates.len(), stack, candidates); + let needs_infer = stack.obligation.predicate.needs_infer(); + // If there are STILL multiple candidates, we can further // reduce the list by dropping duplicates -- including // resolving specializations. @@ -1424,7 +1428,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut i = 0; while i < candidates.len() { let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| { - self.candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j]) + self.candidate_should_be_dropped_in_favor_of( + &candidates[i], + &candidates[j], + needs_infer, + ) }); if is_dup { debug!("Dropping candidate #{}/{}: {:?}", i, candidates.len(), candidates[i]); @@ -2258,6 +2266,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, victim: &EvaluatedCandidate<'tcx>, other: &EvaluatedCandidate<'tcx>, + needs_infer: bool, ) -> bool { if victim.candidate == other.candidate { return true; @@ -2339,10 +2348,55 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match victim.candidate { ImplCandidate(victim_def) => { let tcx = self.tcx(); - return tcx.specializes((other_def, victim_def)) - || tcx - .impls_are_allowed_to_overlap(other_def, victim_def) - .is_some(); + if tcx.specializes((other_def, victim_def)) { + return true; + } + return match tcx.impls_are_allowed_to_overlap(other_def, victim_def) { + Some(ty::ImplOverlapKind::Permitted { marker: true }) => { + // Subtle: If the predicate we are evaluating has inference + // variables, do *not* allow discarding candidates due to + // marker trait impls. + // + // Without this restriction, we could end up accidentally + // constrainting inference variables based on an arbitrarily + // chosen trait impl. + // + // Imagine we have the following code: + // + // ```rust + // #[marker] trait MyTrait {} + // impl MyTrait for u8 {} + // impl MyTrait for bool {} + // ``` + // + // And we are evaluating the predicate `<_#0t as MyTrait>`. + // + // During selection, we will end up with one candidate for each + // impl of `MyTrait`. If we were to discard one impl in favor + // of the other, we would be left with one candidate, causing + // us to "successfully" select the predicate, unifying + // _#0t with (for example) `u8`. + // + // However, we have no reason to believe that this unification + // is correct - we've essentially just picked an arbitrary + // *possibility* for _#0t, and required that this be the *only* + // possibility. + // + // Eventually, we will either: + // 1) Unify all inference variables in the predicate through + // some other means (e.g. type-checking of a function). We will + // then be in a position to drop marker trait candidates + // without constraining inference variables (since there are + // none left to constrin) + // 2) Be left with some unconstrained inference variables. We + // will then correctly report an inference error, since the + // existence of multiple marker trait impls tells us nothing + // about which one should actually apply. + !needs_infer + } + Some(_) => true, + None => false, + }; } ParamCandidate(ref cand) => { // Prefer the impl to a global where clause candidate. @@ -3314,7 +3368,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx.require_lang_item(lang_items::SizedTraitLangItem, None), tcx.mk_substs_trait(source, &[]), ); - nested.push(predicate_to_obligation(tr.to_predicate())); + nested.push(predicate_to_obligation(tr.without_const().to_predicate())); // If the type is `Foo + 'a`, ensure that the type // being cast to `Foo + 'a` outlives `'a`: diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f5199dbdabb..e559ea391cd 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -25,8 +25,6 @@ use rustc_span::DUMMY_SP; use super::util::impl_trait_ref_and_oblig; use super::{FulfillmentContext, SelectionContext}; -use rustc_error_codes::*; - /// Information pertinent to an overlapping impl error. #[derive(Debug)] pub struct OverlapError { diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index c176f139bf8..9509b6220eb 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -163,7 +163,7 @@ impl<'tcx> Children { tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) { match overlap_kind { - ty::ImplOverlapKind::Permitted => {} + ty::ImplOverlapKind::Permitted { marker: _ } => {} ty::ImplOverlapKind::Issue33140 => { last_lint = Some(FutureCompatOverlapError { error: overlap_error(overlap), diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 65fd809657b..f3bd98b8551 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -4,7 +4,7 @@ use smallvec::SmallVec; use crate::ty::outlives::Component; use crate::ty::subst::{GenericArg, Subst, SubstsRef}; -use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt}; +use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -13,8 +13,8 @@ use super::{Normalized, Obligation, ObligationCause, PredicateObligation, Select fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { match *pred { - ty::Predicate::Trait(ref data) => { - ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data)) + ty::Predicate::Trait(ref data, constness) => { + ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness) } ty::Predicate::RegionOutlives(ref data) => { @@ -99,14 +99,14 @@ pub fn elaborate_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> Elaborator<'tcx> { - elaborate_predicates(tcx, vec![trait_ref.to_predicate()]) + elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()]) } pub fn elaborate_trait_refs<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>, ) -> Elaborator<'tcx> { - let predicates = trait_refs.map(|trait_ref| trait_ref.to_predicate()).collect(); + let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect(); elaborate_predicates(tcx, predicates) } @@ -127,7 +127,7 @@ impl Elaborator<'tcx> { fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) { let tcx = self.visited.tcx; match *predicate { - ty::Predicate::Trait(ref data) => { + ty::Predicate::Trait(ref data, _) => { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); @@ -358,7 +358,7 @@ impl<'tcx> TraitAliasExpander<'tcx> { fn expand(&mut self, item: &TraitAliasExpansionInfo<'tcx>) -> bool { let tcx = self.tcx; let trait_ref = item.trait_ref(); - let pred = trait_ref.to_predicate(); + let pred = trait_ref.without_const().to_predicate(); debug!("expand_trait_aliases: trait_ref={:?}", trait_ref); @@ -370,13 +370,9 @@ impl<'tcx> TraitAliasExpander<'tcx> { // Don't recurse if this trait alias is already on the stack for the DFS search. let anon_pred = anonymize_predicate(tcx, &pred); - if item - .path - .iter() - .rev() - .skip(1) - .any(|(tr, _)| anonymize_predicate(tcx, &tr.to_predicate()) == anon_pred) - { + if item.path.iter().rev().skip(1).any(|(tr, _)| { + anonymize_predicate(tcx, &tr.without_const().to_predicate()) == anon_pred + }) { return false; } @@ -471,7 +467,7 @@ impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits< fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> { while let Some(pred) = self.base_iterator.next() { - if let ty::Predicate::Trait(data) = pred { + if let ty::Predicate::Trait(data, _) = pred { return Some(data.to_poly_trait_ref()); } } @@ -545,7 +541,12 @@ pub fn predicate_for_trait_ref<'tcx>( trait_ref: ty::TraitRef<'tcx>, recursion_depth: usize, ) -> PredicateObligation<'tcx> { - Obligation { cause, param_env, recursion_depth, predicate: trait_ref.to_predicate() } + Obligation { + cause, + param_env, + recursion_depth, + predicate: trait_ref.without_const().to_predicate(), + } } pub fn predicate_for_trait_def( @@ -651,7 +652,7 @@ pub fn impl_is_default(tcx: TyCtxt<'_>, node_item_def_id: DefId) -> bool { match tcx.hir().as_local_hir_id(node_item_def_id) { Some(hir_id) => { let item = tcx.hir().expect_item(hir_id); - if let hir::ItemKind::Impl(_, _, defaultness, ..) = item.kind { + if let hir::ItemKind::Impl { defaultness, .. } = item.kind { defaultness.is_default() } else { false diff --git a/src/librustc/traits/wf.rs b/src/librustc/traits/wf.rs index 2301395f557..a0cb8446c92 100644 --- a/src/librustc/traits/wf.rs +++ b/src/librustc/traits/wf.rs @@ -3,7 +3,7 @@ use crate::infer::InferCtxt; use crate::middle::lang_items; use crate::traits::{self, AssocTypeBoundData}; use crate::ty::subst::SubstsRef; -use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Ident}; @@ -62,7 +62,7 @@ pub fn predicate_obligations<'a, 'tcx>( // (*) ok to skip binders, because wf code is prepared for it match *predicate { - ty::Predicate::Trait(ref t) => { + ty::Predicate::Trait(ref t, _) => { wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*) } ty::Predicate::RegionOutlives(..) => {} @@ -229,9 +229,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // | // = note: expected type `u32` // found type `()` - if let Some(hir::ItemKind::Impl(.., impl_items)) = item.map(|i| &i.kind) { + if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) { let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); - if let Some(impl_item) = impl_items + if let Some(impl_item) = items .iter() .filter(|item| item.ident == trait_assoc_item.ident) .next() @@ -245,7 +245,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { } } } - ty::Predicate::Trait(proj) => { + ty::Predicate::Trait(proj, _) => { // An associated item obligation born out of the `trait` failed to be met. // Point at the `impl` that failed the obligation, the associated item that // needed to meet the obligation, and the definition of that associated item, @@ -279,14 +279,14 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool` if let ( ty::Projection(ty::ProjectionTy { item_def_id, .. }), - Some(hir::ItemKind::Impl(.., impl_items)), + Some(hir::ItemKind::Impl { items, .. }), ) = (&proj.skip_binder().self_ty().kind, item.map(|i| &i.kind)) { if let Some((impl_item, trait_assoc_item)) = trait_assoc_items .filter(|i| i.def_id == *item_def_id) .next() .and_then(|trait_assoc_item| { - impl_items + items .iter() .filter(|i| i.ident == trait_assoc_item.ident) .next() @@ -350,7 +350,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.compute_trait_ref(&trait_ref, Elaborate::None); if !data.has_escaping_bound_vars() { - let predicate = trait_ref.to_predicate(); + let predicate = trait_ref.without_const().to_predicate(); let cause = self.cause(traits::ProjectionWf(data)); self.out.push(traits::Obligation::new(cause, self.param_env, predicate)); } @@ -378,7 +378,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem, None), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; - self.out.push(traits::Obligation::new(cause, self.param_env, trait_ref.to_predicate())); + self.out.push(traits::Obligation::new( + cause, + self.param_env, + trait_ref.without_const().to_predicate(), + )); } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ef776c88a8f..a51f0f7f24c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -51,10 +51,9 @@ use rustc_session::config::CrateType; use rustc_session::config::{BorrowckMode, OutputFilenames}; use rustc_session::Session; -use arena::SyncDroplessArena; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_data_structures::sharded::ShardedHashMap; +use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{ hash_stable_hashmap, HashStable, StableHasher, StableVec, }; @@ -83,21 +82,11 @@ use syntax::ast; use syntax::attr; use syntax::expand::allocator::AllocatorKind; -pub struct AllArenas { - pub interner: SyncDroplessArena, -} - -impl AllArenas { - pub fn new() -> Self { - AllArenas { interner: SyncDroplessArena::default() } - } -} - type InternedSet<'tcx, T> = ShardedHashMap<Interned<'tcx, T>, ()>; pub struct CtxtInterners<'tcx> { /// The arena that types, regions, etc. are allocated from. - arena: &'tcx SyncDroplessArena, + arena: &'tcx WorkerLocal<Arena<'tcx>>, /// Specifically use a speedy hash algorithm for these hash sets, since /// they're accessed quite often. @@ -117,7 +106,7 @@ pub struct CtxtInterners<'tcx> { } impl<'tcx> CtxtInterners<'tcx> { - fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> { + fn new(arena: &'tcx WorkerLocal<Arena<'tcx>>) -> CtxtInterners<'tcx> { CtxtInterners { arena, type_: Default::default(), @@ -1125,7 +1114,6 @@ impl<'tcx> TyCtxt<'tcx> { lint_store: Lrc<dyn Any + sync::Send + sync::Sync>, local_providers: ty::query::Providers<'tcx>, extern_providers: ty::query::Providers<'tcx>, - arenas: &'tcx AllArenas, arena: &'tcx WorkerLocal<Arena<'tcx>>, resolutions: ty::ResolverOutputs, hir: hir_map::Map<'tcx>, @@ -1136,7 +1124,7 @@ impl<'tcx> TyCtxt<'tcx> { let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| { s.fatal(&err); }); - let interners = CtxtInterners::new(&arenas.interner); + let interners = CtxtInterners::new(arena); let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -1567,11 +1555,11 @@ pub trait Lift<'tcx>: fmt::Debug { } macro_rules! nop_lift { - ($ty:ty => $lifted:ty) => { + ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for $ty { type Lifted = $lifted; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { - if tcx.interners.arena.in_arena(*self as *const _) { + if tcx.interners.$set.contains_pointer_to(&Interned(*self)) { Some(unsafe { mem::transmute(*self) }) } else { None @@ -1582,14 +1570,14 @@ macro_rules! nop_lift { } macro_rules! nop_list_lift { - ($ty:ty => $lifted:ty) => { + ($set:ident; $ty:ty => $lifted:ty) => { impl<'a, 'tcx> Lift<'tcx> for &'a List<$ty> { type Lifted = &'tcx List<$lifted>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { if self.is_empty() { return Some(List::empty()); } - if tcx.interners.arena.in_arena(*self as *const _) { + if tcx.interners.$set.contains_pointer_to(&Interned(*self)) { Some(unsafe { mem::transmute(*self) }) } else { None @@ -1599,21 +1587,21 @@ macro_rules! nop_list_lift { }; } -nop_lift! {Ty<'a> => Ty<'tcx>} -nop_lift! {Region<'a> => Region<'tcx>} -nop_lift! {Goal<'a> => Goal<'tcx>} -nop_lift! {&'a Const<'a> => &'tcx Const<'tcx>} +nop_lift! {type_; Ty<'a> => Ty<'tcx>} +nop_lift! {region; Region<'a> => Region<'tcx>} +nop_lift! {goal; Goal<'a> => Goal<'tcx>} +nop_lift! {const_; &'a Const<'a> => &'tcx Const<'tcx>} -nop_list_lift! {Goal<'a> => Goal<'tcx>} -nop_list_lift! {Clause<'a> => Clause<'tcx>} -nop_list_lift! {Ty<'a> => Ty<'tcx>} -nop_list_lift! {ExistentialPredicate<'a> => ExistentialPredicate<'tcx>} -nop_list_lift! {Predicate<'a> => Predicate<'tcx>} -nop_list_lift! {CanonicalVarInfo => CanonicalVarInfo} -nop_list_lift! {ProjectionKind => ProjectionKind} +nop_list_lift! {goal_list; Goal<'a> => Goal<'tcx>} +nop_list_lift! {clauses; Clause<'a> => Clause<'tcx>} +nop_list_lift! {type_list; Ty<'a> => Ty<'tcx>} +nop_list_lift! {existential_predicates; ExistentialPredicate<'a> => ExistentialPredicate<'tcx>} +nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} +nop_list_lift! {canonical_var_infos; CanonicalVarInfo => CanonicalVarInfo} +nop_list_lift! {projs; ProjectionKind => ProjectionKind} // This is the impl for `&'a InternalSubsts<'a>`. -nop_list_lift! {GenericArg<'a> => GenericArg<'tcx>} +nop_list_lift! {substs; GenericArg<'a> => GenericArg<'tcx>} pub mod tls { use super::{ptr_eq, GlobalCtxt, TyCtxt}; @@ -1937,6 +1925,11 @@ impl<'tcx, T: 'tcx + ?Sized> Clone for Interned<'tcx, T> { } impl<'tcx, T: 'tcx + ?Sized> Copy for Interned<'tcx, T> {} +impl<'tcx, T: 'tcx + ?Sized> IntoPointer for Interned<'tcx, T> { + fn into_pointer(&self) -> *const () { + self.0 as *const _ as *const () + } +} // N.B., an `Interned<Ty>` compares and hashes as a `TyKind`. impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { @@ -2089,7 +2082,7 @@ macro_rules! slice_interners { $(impl<'tcx> TyCtxt<'tcx> { pub fn $method(self, v: &[$ty]) -> &'tcx List<$ty> { self.interners.$field.intern_ref(v, || { - Interned(List::from_arena(&self.interners.arena, v)) + Interned(List::from_arena(&*self.arena, v)) }).0 } })+ diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index b16db6ae5b1..0dddca98c62 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -150,6 +150,15 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { } } +impl TypeFoldable<'tcx> for syntax::ast::Constness { + fn super_fold_with<F: TypeFolder<'tcx>>(&self, _: &mut F) -> Self { + *self + } + fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> bool { + false + } +} + /// The `TypeFolder` trait defines the actual *folding*. There is a /// method defined for every foldable type. Each of these has a /// default implementation that does an "identity" fold. Within each diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 9be50d19a50..1ea695e40b2 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -141,7 +141,12 @@ impl<'tcx> InstanceDef<'tcx> { } pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool { - tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + match *self { + InstanceDef::Item(def_id) => { + tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) + } + _ => false, + } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index e6acb6b74dc..0470ab20dc4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -6,6 +6,7 @@ pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::Variance::*; +use crate::arena::Arena; use crate::hir::exports::ExportMap; use crate::hir::map as hir_map; @@ -25,7 +26,6 @@ use crate::ty::layout::VariantIdx; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef}; use crate::ty::util::{Discr, IntTypeExt}; use crate::ty::walk::TypeWalker; -use arena::SyncDroplessArena; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; @@ -52,7 +52,7 @@ use std::ops::Deref; use std::ops::Range; use std::slice; use std::{mem, ptr}; -use syntax::ast::{self, Ident, Name, NodeId}; +use syntax::ast::{self, Constness, Ident, Name, NodeId}; use syntax::attr; pub use self::sty::BoundRegion::*; @@ -74,7 +74,7 @@ pub use crate::ty::diagnostics::*; pub use self::binding::BindingMode; pub use self::binding::BindingMode::*; -pub use self::context::{keep_local, tls, AllArenas, FreeRegionInfo, TyCtxt}; +pub use self::context::{keep_local, tls, FreeRegionInfo, TyCtxt}; pub use self::context::{ CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, ResolvedOpaqueTy, UserType, UserTypeAnnotationIndex, @@ -604,7 +604,7 @@ unsafe impl<T: Sync> Sync for List<T> {} impl<T: Copy> List<T> { #[inline] - fn from_arena<'tcx>(arena: &'tcx SyncDroplessArena, slice: &[T]) -> &'tcx List<T> { + fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List<T> { assert!(!mem::needs_drop::<T>()); assert!(mem::size_of::<T>() != 0); assert!(slice.len() != 0); @@ -617,7 +617,9 @@ impl<T: Copy> List<T> { let size = offset + slice.len() * mem::size_of::<T>(); - let mem = arena.alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>())); + let mem = arena + .dropless + .alloc_raw(size, cmp::max(mem::align_of::<T>(), mem::align_of::<usize>())); unsafe { let result = &mut *(mem.as_mut_ptr() as *mut List<T>); // Write the length @@ -1066,7 +1068,11 @@ pub enum Predicate<'tcx> { /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be /// the `Self` type of the trait reference and `A`, `B`, and `C` /// would be the type parameters. - Trait(PolyTraitPredicate<'tcx>), + /// + /// A trait predicate will have `Constness::Const` if it originates + /// from a bound on a `const fn` without the `?const` opt-out (e.g., + /// `const fn foobar<Foo: Bar>() {}`). + Trait(PolyTraitPredicate<'tcx>, Constness), /// `where 'a: 'b` RegionOutlives(PolyRegionOutlivesPredicate<'tcx>), @@ -1189,8 +1195,8 @@ impl<'tcx> Predicate<'tcx> { let substs = &trait_ref.skip_binder().substs; match *self { - Predicate::Trait(ref binder) => { - Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs))) + Predicate::Trait(ref binder, constness) => { + Predicate::Trait(binder.map_bound(|data| data.subst(tcx, substs)), constness) } Predicate::Subtype(ref binder) => { Predicate::Subtype(binder.map_bound(|data| data.subst(tcx, substs))) @@ -1334,15 +1340,33 @@ pub trait ToPredicate<'tcx> { fn to_predicate(&self) -> Predicate<'tcx>; } -impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { +impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<TraitRef<'tcx>> { + fn to_predicate(&self) -> Predicate<'tcx> { + ty::Predicate::Trait( + ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }), + self.constness, + ) + } +} + +impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&TraitRef<'tcx>> { + fn to_predicate(&self) -> Predicate<'tcx> { + ty::Predicate::Trait( + ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.value.clone() }), + self.constness, + ) + } +} + +impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<PolyTraitRef<'tcx>> { fn to_predicate(&self) -> Predicate<'tcx> { - ty::Predicate::Trait(ty::Binder::dummy(ty::TraitPredicate { trait_ref: self.clone() })) + ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness) } } -impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> { +impl<'tcx> ToPredicate<'tcx> for ConstnessAnd<&PolyTraitRef<'tcx>> { fn to_predicate(&self) -> Predicate<'tcx> { - ty::Predicate::Trait(self.to_poly_trait_predicate()) + ty::Predicate::Trait(self.value.to_poly_trait_predicate(), self.constness) } } @@ -1411,7 +1435,7 @@ impl<'tcx> Predicate<'tcx> { /// with depth 0 are bound by the predicate. pub fn walk_tys(&'a self) -> impl Iterator<Item = Ty<'tcx>> + 'a { match *self { - ty::Predicate::Trait(ref data) => { + ty::Predicate::Trait(ref data, _) => { WalkTysIter::InputTypes(data.skip_binder().input_types()) } ty::Predicate::Subtype(binder) => { @@ -1437,7 +1461,7 @@ impl<'tcx> Predicate<'tcx> { pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> { match *self { - Predicate::Trait(ref t) => Some(t.to_poly_trait_ref()), + Predicate::Trait(ref t, _) => Some(t.to_poly_trait_ref()), Predicate::Projection(..) | Predicate::Subtype(..) | Predicate::RegionOutlives(..) @@ -1698,6 +1722,33 @@ impl<'tcx> ParamEnv<'tcx> { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct ConstnessAnd<T> { + pub constness: Constness, + pub value: T, +} + +// FIXME(ecstaticmorse): Audit all occurrences of `without_const().to_predicate()` to ensure that +// the constness of trait bounds is being propagated correctly. +pub trait WithConstness: Sized { + #[inline] + fn with_constness(self, constness: Constness) -> ConstnessAnd<Self> { + ConstnessAnd { constness, value: self } + } + + #[inline] + fn with_const(self) -> ConstnessAnd<Self> { + self.with_constness(Constness::Const) + } + + #[inline] + fn without_const(self) -> ConstnessAnd<Self> { + self.with_constness(Constness::NotConst) + } +} + +impl<T> WithConstness for T {} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable)] pub struct ParamEnvAnd<'tcx, T> { pub param_env: ParamEnv<'tcx>, @@ -2589,7 +2640,12 @@ impl<'tcx> ::std::ops::Deref for Attributes<'tcx> { #[derive(Debug, PartialEq, Eq)] pub enum ImplOverlapKind { /// These impls are always allowed to overlap. - Permitted, + Permitted { + /// Whether or not the impl is permitted due to the trait being + /// a marker trait (a trait with #[marker], or a trait with + /// no associated items and #![feature(overlapping_marker_traits)] enabled) + marker: bool, + }, /// These impls are allowed to overlap, but that raises /// an issue #33140 future-compatibility warning. /// @@ -2709,7 +2765,7 @@ impl<'tcx> TyCtxt<'tcx> { if self.impl_trait_ref(def_id1).map_or(false, |tr| tr.references_error()) || self.impl_trait_ref(def_id2).map_or(false, |tr| tr.references_error()) { - return Some(ImplOverlapKind::Permitted); + return Some(ImplOverlapKind::Permitted { marker: false }); } match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) { @@ -2719,7 +2775,7 @@ impl<'tcx> TyCtxt<'tcx> { "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)", def_id1, def_id2 ); - return Some(ImplOverlapKind::Permitted); + return Some(ImplOverlapKind::Permitted { marker: false }); } (ImplPolarity::Positive, ImplPolarity::Negative) | (ImplPolarity::Negative, ImplPolarity::Positive) => { @@ -2755,7 +2811,7 @@ impl<'tcx> TyCtxt<'tcx> { "impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)", def_id1, def_id2 ); - Some(ImplOverlapKind::Permitted) + Some(ImplOverlapKind::Permitted { marker: true }) } else { if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { if let Some(self_ty2) = self.issue33140_self_ty(def_id2) { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 8b1b2bb5865..9091de55b7d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1791,7 +1791,12 @@ define_print_and_forward_display! { ty::Predicate<'tcx> { match *self { - ty::Predicate::Trait(ref data) => p!(print(data)), + ty::Predicate::Trait(ref data, constness) => { + if let ast::Constness::Const = constness { + p!(write("const ")); + } + p!(print(data)) + } ty::Predicate::Subtype(ref predicate) => p!(print(predicate)), ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)), ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)), diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 3fb3720a563..cbf335ad607 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -125,15 +125,6 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { } } -impl<'tcx> Key for (DefId, SubstsRef<'tcx>, traits::TraitQueryMode) { - fn query_crate(&self) -> CrateNum { - self.0.krate - } - fn default_span(&self, tcx: TyCtxt<'_>) -> Span { - self.0.default_span(tcx) - } -} - impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { fn query_crate(&self) -> CrateNum { self.1.def_id().krate diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 84efbe21f10..117a38c655e 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -25,8 +25,6 @@ use std::hash::{Hash, Hasher}; use std::mem; use std::ptr; -use rustc_error_codes::*; - pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> { pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>, pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 62e895af7f3..25f9dc5b0c7 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -15,6 +15,7 @@ use smallvec::SmallVec; use std::fmt; use std::rc::Rc; use std::sync::Arc; +use syntax::ast; impl fmt::Debug for ty::GenericParamDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -234,7 +235,12 @@ impl fmt::Debug for ty::ProjectionPredicate<'tcx> { impl fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { - ty::Predicate::Trait(ref a) => a.fmt(f), + ty::Predicate::Trait(ref a, constness) => { + if let ast::Constness::Const = constness { + write!(f, "const ")?; + } + a.fmt(f) + } ty::Predicate::Subtype(ref pair) => pair.fmt(f), ty::Predicate::RegionOutlives(ref pair) => pair.fmt(f), ty::Predicate::TypeOutlives(ref pair) => pair.fmt(f), @@ -474,7 +480,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::Predicate<'a> { type Lifted = ty::Predicate<'tcx>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { match *self { - ty::Predicate::Trait(ref binder) => tcx.lift(binder).map(ty::Predicate::Trait), + ty::Predicate::Trait(ref binder, constness) => { + tcx.lift(binder).map(|binder| ty::Predicate::Trait(binder, constness)) + } ty::Predicate::Subtype(ref binder) => tcx.lift(binder).map(ty::Predicate::Subtype), ty::Predicate::RegionOutlives(ref binder) => { tcx.lift(binder).map(ty::Predicate::RegionOutlives) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 84236128482..13f623aadb1 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -12,7 +12,9 @@ use crate::mir::interpret::Scalar; use crate::mir::Promoted; use crate::ty::layout::VariantIdx; use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef}; -use crate::ty::{self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable}; +use crate::ty::{ + self, AdtDef, DefIdTree, Discr, Ty, TyCtxt, TypeFlags, TypeFoldable, WithConstness, +}; use crate::ty::{List, ParamEnv, ParamEnvAnd, TyS}; use polonius_engine::Atom; use rustc_data_structures::captures::Captures; @@ -665,14 +667,16 @@ impl<'tcx> Binder<ExistentialPredicate<'tcx>> { pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Predicate<'tcx> { use crate::ty::ToPredicate; match *self.skip_binder() { - ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(), + ExistentialPredicate::Trait(tr) => { + Binder(tr).with_self_ty(tcx, self_ty).without_const().to_predicate() + } ExistentialPredicate::Projection(p) => { ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))) } ExistentialPredicate::AutoTrait(did) => { let trait_ref = Binder(ty::TraitRef { def_id: did, substs: tcx.mk_substs_trait(self_ty, &[]) }); - trait_ref.to_predicate() + trait_ref.without_const().to_predicate() } } } diff --git a/src/librustc_ast_lowering/Cargo.toml b/src/librustc_ast_lowering/Cargo.toml index 408e9a75d93..4b786d6245f 100644 --- a/src/librustc_ast_lowering/Cargo.toml +++ b/src/librustc_ast_lowering/Cargo.toml @@ -17,7 +17,6 @@ rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_index = { path = "../librustc_index" } rustc_span = { path = "../librustc_span" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_errors = { path = "../librustc_errors" } rustc_session = { path = "../librustc_session" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index 2866a1624de..a24bb52150a 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -2,7 +2,6 @@ use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericAr use rustc::bug; use rustc_data_structures::thin_vec::ThinVec; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::Res; diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index beb53a19ac4..2025d0c1c8e 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -3,7 +3,6 @@ use super::{ImplTraitContext, ImplTraitPosition, ImplTraitTypeIdVisitor}; use rustc::arena::Arena; use rustc::bug; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -67,14 +66,14 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { if let Some(hir_id) = item_hir_id { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl(.., ref opt_trait_ref, _, _) = item.kind { - if opt_trait_ref.as_ref().map(|tr| tr.constness.is_some()).unwrap_or(false) { + if let ItemKind::Impl { constness, ref of_trait, .. } = item.kind { + if constness == Constness::Const { this.lctx .diagnostic() .span_err(item.span, "const trait impls are not yet implemented"); } - this.with_trait_impl_ref(opt_trait_ref, |this| visit::walk_item(this, item)); + this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); } else { visit::walk_item(this, item); } @@ -118,7 +117,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let old_len = self.in_scope_lifetimes.len(); let parent_generics = match self.items.get(&parent_hir_id).unwrap().kind { - hir::ItemKind::Impl(_, _, _, ref generics, ..) + hir::ItemKind::Impl { ref generics, .. } | hir::ItemKind::Trait(_, _, ref generics, ..) => &generics.params[..], _ => &[], }; @@ -173,7 +172,7 @@ impl<'hir> LoweringContext<'_, 'hir> { vec } ItemKind::MacroDef(..) => SmallVec::new(), - ItemKind::Fn(..) | ItemKind::Impl(.., None, _, _) => smallvec![i.id], + ItemKind::Fn(..) | ItemKind::Impl { of_trait: None, .. } => smallvec![i.id], ItemKind::Static(ref ty, ..) => { let mut ids = smallvec![i.id]; if self.sess.features_untracked().impl_trait_in_bindings { @@ -361,15 +360,16 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_generics(generics, ImplTraitContext::disallowed()), ) } - ItemKind::Impl( + ItemKind::Impl { unsafety, polarity, defaultness, - ref ast_generics, - ref trait_ref, - ref ty, - ref impl_items, - ) => { + constness, + generics: ref ast_generics, + of_trait: ref trait_ref, + self_ty: ref ty, + items: ref impl_items, + } => { let def_id = self.resolver.definitions().local_def_id(id); // Lower the "impl header" first. This ordering is important @@ -417,15 +417,16 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }); - hir::ItemKind::Impl( + hir::ItemKind::Impl { unsafety, polarity, - self.lower_defaultness(defaultness, true /* [1] */), + defaultness: self.lower_defaultness(defaultness, true /* [1] */), + constness, generics, - trait_ref, - lowered_ty, - new_impl_items, - ) + of_trait: trait_ref, + self_ty: lowered_ty, + items: new_impl_items, + } } ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref items) => { let bounds = self.lower_param_bounds(bounds, ImplTraitContext::disallowed()); diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 76a0889c376..284ede3b4fa 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -41,7 +41,6 @@ use rustc::{bug, span_bug}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; @@ -1250,10 +1249,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let bounds = this.arena.alloc_from_iter(bounds.iter().filter_map( |bound| match *bound { - GenericBound::Trait(ref ty, TraitBoundModifier::None) => { + GenericBound::Trait(ref ty, TraitBoundModifier::None) + | GenericBound::Trait(ref ty, TraitBoundModifier::MaybeConst) => { Some(this.lower_poly_trait_ref(ty, itctx.reborrow())) } - GenericBound::Trait(_, TraitBoundModifier::Maybe) => None, + // `?const ?Bound` will cause an error during AST validation + // anyways, so treat it like `?Bound` as compilation proceeds. + GenericBound::Trait(_, TraitBoundModifier::Maybe) + | GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => { + None + } GenericBound::Outlives(ref lifetime) => { if lifetime_bound.is_none() { lifetime_bound = Some(this.lower_lifetime(lifetime)); @@ -2158,10 +2163,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &PolyTraitRef, mut itctx: ImplTraitContext<'_, 'hir>, ) -> hir::PolyTraitRef<'hir> { - if p.trait_ref.constness.is_some() { - self.diagnostic().span_err(p.span, "`?const` on trait bounds is not yet implemented"); - } - let bound_generic_params = self.lower_generic_params( &p.bound_generic_params, &NodeMap::default(), @@ -2300,7 +2301,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lower_trait_bound_modifier(&mut self, f: TraitBoundModifier) -> hir::TraitBoundModifier { match f { TraitBoundModifier::None => hir::TraitBoundModifier::None, - TraitBoundModifier::Maybe => hir::TraitBoundModifier::Maybe, + TraitBoundModifier::MaybeConst => hir::TraitBoundModifier::MaybeConst, + + // `MaybeConstMaybe` will cause an error during AST validation, but we need to pick a + // placeholder for compilation to proceed. + TraitBoundModifier::MaybeConstMaybe | TraitBoundModifier::Maybe => { + hir::TraitBoundModifier::Maybe + } } } diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index 65347d379bd..e5f7df6dbf9 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -3,7 +3,6 @@ use super::{GenericArgsCtor, ParenthesizedGenericArgs}; use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; use rustc::span_bug; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; diff --git a/src/librustc_ast_passes/Cargo.toml b/src/librustc_ast_passes/Cargo.toml index 2d45e280444..25b1acebd2a 100644 --- a/src/librustc_ast_passes/Cargo.toml +++ b/src/librustc_ast_passes/Cargo.toml @@ -12,7 +12,6 @@ path = "lib.rs" log = "0.4" rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_feature = { path = "../librustc_feature" } rustc_parse = { path = "../librustc_parse" } rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index c915b7ba216..152086bfce0 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -23,8 +23,6 @@ use syntax::print::pprust; use syntax::visit::{self, Visitor}; use syntax::walk_list; -use rustc_error_codes::*; - /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`). #[derive(Clone, Copy)] enum BoundContext { @@ -612,9 +610,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } match item.kind { - ItemKind::Impl(unsafety, polarity, _, _, Some(..), ref ty, ref impl_items) => { + ItemKind::Impl { + unsafety, + polarity, + defaultness: _, + constness: _, + generics: _, + of_trait: Some(_), + ref self_ty, + ref items, + } => { self.invalid_visibility(&item.vis, None); - if let TyKind::Err = ty.kind { + if let TyKind::Err = self_ty.kind { self.err_handler() .struct_span_err(item.span, "`impl Trait for .. {}` is an obsolete syntax") .help("use `auto trait Trait {}` instead") @@ -629,7 +636,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ) .emit(); } - for impl_item in impl_items { + for impl_item in items { self.invalid_visibility(&impl_item.vis, None); if let AssocItemKind::Fn(ref sig, _) = impl_item.kind { self.check_trait_fn_not_const(sig.header.constness); @@ -637,7 +644,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - ItemKind::Impl(unsafety, polarity, defaultness, _, None, _, _) => { + ItemKind::Impl { + unsafety, + polarity, + defaultness, + constness, + generics: _, + of_trait: None, + self_ty: _, + items: _, + } => { self.invalid_visibility( &item.vis, Some("place qualifiers on individual impl items instead"), @@ -660,6 +676,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .note("only trait implementations may be annotated with default") .emit(); } + if constness == Constness::Const { + self.err_handler() + .struct_span_err(item.span, "inherent impls cannot be `const`") + .note("only trait implementations may be annotated with `const`") + .emit(); + } } ItemKind::Fn(ref sig, ref generics, _) => { self.visit_fn_header(&sig.header); @@ -893,23 +915,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_param_bound(&mut self, bound: &'a GenericBound) { - if let GenericBound::Trait(poly, maybe_bound) = bound { - match poly.trait_ref.constness { - Some(Constness::NotConst) => { - if *maybe_bound == TraitBoundModifier::Maybe { - self.err_handler() - .span_err(bound.span(), "`?const` and `?` are mutually exclusive"); - } - - if let Some(ctx) = self.bound_context { - let msg = format!("`?const` is not permitted in {}", ctx.description()); - self.err_handler().span_err(bound.span(), &msg); - } + match bound { + GenericBound::Trait(_, TraitBoundModifier::MaybeConst) => { + if let Some(ctx) = self.bound_context { + let msg = format!("`?const` is not permitted in {}", ctx.description()); + self.err_handler().span_err(bound.span(), &msg); } + } - Some(Constness::Const) => panic!("Parser should reject bare `const` on bounds"), - None => {} + GenericBound::Trait(_, TraitBoundModifier::MaybeConstMaybe) => { + self.err_handler() + .span_err(bound.span(), "`?const` and `?` are mutually exclusive"); } + + _ => {} } visit::walk_param_bound(self, bound) diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 1e4b1ae0777..953127429d5 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -1,4 +1,3 @@ -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Handler}; use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP}; use rustc_feature::{Features, GateIssue, UnstableFeatures}; @@ -339,7 +338,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Impl(_, polarity, defaultness, ..) => { + ast::ItemKind::Impl { polarity, defaultness, .. } => { if polarity == ast::ImplPolarity::Negative { gate_feature_post!( &self, @@ -470,29 +469,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_expr(self, e) } - fn visit_arm(&mut self, arm: &'a ast::Arm) { - visit::walk_arm(self, arm) - } - fn visit_pat(&mut self, pattern: &'a ast::Pat) { match &pattern.kind { - PatKind::Slice(pats) => { - for pat in &*pats { - let span = pat.span; - let inner_pat = match &pat.kind { - PatKind::Ident(.., Some(pat)) => pat, - _ => pat, - }; - if inner_pat.is_rest() { - gate_feature_post!( - &self, - slice_patterns, - span, - "subslice patterns are unstable" - ); - } - } - } PatKind::Box(..) => { gate_feature_post!( &self, diff --git a/src/librustc_ast_passes/lib.rs b/src/librustc_ast_passes/lib.rs index eadbc485296..5de45f4e1f3 100644 --- a/src/librustc_ast_passes/lib.rs +++ b/src/librustc_ast_passes/lib.rs @@ -2,7 +2,7 @@ //! parsed by `rustc_parse` and then lowered, after the passes in this crate, //! by `rustc_ast_lowering`. -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] pub mod ast_validation; pub mod feature_gate; diff --git a/src/librustc_builtin_macros/Cargo.toml b/src/librustc_builtin_macros/Cargo.toml index f291eaf9358..3ce7f5d770e 100644 --- a/src/librustc_builtin_macros/Cargo.toml +++ b/src/librustc_builtin_macros/Cargo.toml @@ -22,4 +22,3 @@ smallvec = { version = "1.0", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } rustc_expand = { path = "../librustc_expand" } rustc_span = { path = "../librustc_span" } -rustc_error_codes = { path = "../librustc_error_codes" } diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs index a6b45e0567c..4723544316f 100644 --- a/src/librustc_builtin_macros/asm.rs +++ b/src/librustc_builtin_macros/asm.rs @@ -12,8 +12,6 @@ use syntax::ptr::P; use syntax::token::{self, Token}; use syntax::tokenstream::{self, TokenStream}; -use rustc_error_codes::*; - enum State { Asm, Outputs, diff --git a/src/librustc_builtin_macros/deriving/default.rs b/src/librustc_builtin_macros/deriving/default.rs index 72c41ad9745..b4f059e94c1 100644 --- a/src/librustc_builtin_macros/deriving/default.rs +++ b/src/librustc_builtin_macros/deriving/default.rs @@ -9,8 +9,6 @@ use rustc_span::Span; use syntax::ast::{Expr, MetaItem}; use syntax::ptr::P; -use rustc_error_codes::*; - pub fn expand_deriving_default( cx: &mut ExtCtxt<'_>, span: Span, diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 9226f458165..f8918016c1b 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -705,15 +705,16 @@ impl<'a> TraitDef<'a> { self.span, Ident::invalid(), a, - ast::ItemKind::Impl( + ast::ItemKind::Impl { unsafety, - ast::ImplPolarity::Positive, - ast::Defaultness::Final, - trait_generics, - opt_trait_ref, - self_type, - methods.into_iter().chain(associated_types).collect(), - ), + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Final, + constness: ast::Constness::NotConst, + generics: trait_generics, + of_trait: opt_trait_ref, + self_ty: self_type, + items: methods.into_iter().chain(associated_types).collect(), + }, ) } diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs index 4d83a6635ab..914dcdf1969 100644 --- a/src/librustc_builtin_macros/deriving/mod.rs +++ b/src/librustc_builtin_macros/deriving/mod.rs @@ -156,15 +156,16 @@ fn inject_impl_of_structural_trait( span, ast::Ident::invalid(), attrs, - ItemKind::Impl( - ast::Unsafety::Normal, - ast::ImplPolarity::Positive, - ast::Defaultness::Final, + ItemKind::Impl { + unsafety: ast::Unsafety::Normal, + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Final, + constness: ast::Constness::NotConst, generics, - Some(trait_ref), - self_type, - Vec::new(), - ), + of_trait: Some(trait_ref), + self_ty: self_type, + items: Vec::new(), + }, ); push(Annotatable::Item(newitem)); diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 6fca74e2239..3f4e24ca993 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -590,17 +590,6 @@ impl<'a, 'b> Context<'a, 'b> { parse::NextArgument(ref arg) => { // Build the position let pos = { - let pos = |c, arg| { - let mut path = Context::rtpath(self.ecx, "Position"); - path.push(self.ecx.ident_of(c, sp)); - match arg { - Some(i) => { - let arg = self.ecx.expr_usize(sp, i); - self.ecx.expr_call_global(sp, path, vec![arg]) - } - None => self.ecx.expr_path(self.ecx.path_global(sp, path)), - } - }; match arg.position { parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => { // Map to index in final generated argument array @@ -615,7 +604,7 @@ impl<'a, 'b> Context<'a, 'b> { arg_idx } }; - pos("At", Some(arg_idx)) + self.ecx.expr_usize(sp, arg_idx) } // should never be the case, because names are already diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index eb192b27405..9f8b4e72a9c 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -32,5 +32,4 @@ rustc_hir = { path = "../librustc_hir" } rustc_incremental = { path = "../librustc_incremental" } rustc_index = { path = "../librustc_index" } rustc_target = { path = "../librustc_target" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 11f5d3007e6..4679f650133 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -1103,7 +1103,11 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> { let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { if level.is_below_threshold(export_threshold) { - symbols.push(symbol.symbol_name(tcx).to_string()); + symbols.push(symbol_export::symbol_name_for_instance_in_crate( + tcx, + symbol, + LOCAL_CRATE, + )); } } @@ -1124,12 +1128,7 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> { continue; } - // FIXME rust-lang/rust#64319, rust-lang/rust#64872: - // We want to block export of generics from dylibs, - // but we must fix rust-lang/rust#65890 before we can - // do that robustly. - - symbols.push(symbol.symbol_name(tcx).to_string()); + symbols.push(symbol_export::symbol_name_for_instance_in_crate(tcx, symbol, cnum)); } } } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index a406b5f103b..bd44b4a38fd 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -8,6 +8,7 @@ use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::ty::Instance; use rustc::ty::{SymbolName, TyCtxt}; +use rustc_codegen_utils::symbol_names; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; @@ -358,3 +359,32 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel SymbolExportLevel::Rust } } + +/// This is the symbol name of the given instance instantiated in a specific crate. +pub fn symbol_name_for_instance_in_crate<'tcx>( + tcx: TyCtxt<'tcx>, + symbol: ExportedSymbol<'tcx>, + instantiating_crate: CrateNum, +) -> String { + // If this is something instantiated in the local crate then we might + // already have cached the name as a query result. + if instantiating_crate == LOCAL_CRATE { + return symbol.symbol_name_for_local_instance(tcx).to_string(); + } + + // This is something instantiated in an upstream crate, so we have to use + // the slower (because uncached) version of computing the symbol name. + match symbol { + ExportedSymbol::NonGeneric(def_id) => symbol_names::symbol_name_for_instance_in_crate( + tcx, + Instance::mono(tcx, def_id), + instantiating_crate, + ), + ExportedSymbol::Generic(def_id, substs) => symbol_names::symbol_name_for_instance_in_crate( + tcx, + Instance::new(def_id, substs), + instantiating_crate, + ), + ExportedSymbol::NoDefId(symbol_name) => symbol_name.to_string(), + } +} diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 801bfdea70d..049faff7c49 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -2,7 +2,7 @@ use super::command::Command; use super::link::{self, get_linker, remove}; use super::linker::LinkerInfo; use super::lto::{self, SerializedModule}; -use super::symbol_export::ExportedSymbols; +use super::symbol_export::{symbol_name_for_instance_in_crate, ExportedSymbols}; use crate::{ CachedModuleCodegen, CodegenResults, CompiledModule, CrateInfo, ModuleCodegen, ModuleKind, RLIB_BYTECODE_EXTENSION, @@ -956,7 +956,7 @@ fn start_executing_work<B: ExtraBackendMethods>( let symbols = tcx .exported_symbols(cnum) .iter() - .map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl)) + .map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl)) .collect(); Arc::new(symbols) }; diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index e4531a77656..28b61e0b36d 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -13,8 +13,6 @@ use rustc_hir::def_id::DefId; use crate::traits::BuilderMethods; use rustc_hir as hir; -use rustc_error_codes::*; - pub enum IntPredicate { IntEQ, IntNE, diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index ee527ecb509..aba77231268 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -4,7 +4,7 @@ #![feature(box_syntax)] #![feature(core_intrinsics)] #![feature(libc)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(stmt_expr_attributes)] #![feature(try_blocks)] #![feature(in_band_lifetimes)] diff --git a/src/librustc_codegen_ssa/mir/statement.rs b/src/librustc_codegen_ssa/mir/statement.rs index 574c06d9ceb..8422c625d63 100644 --- a/src/librustc_codegen_ssa/mir/statement.rs +++ b/src/librustc_codegen_ssa/mir/statement.rs @@ -7,8 +7,6 @@ use super::OperandValue; use crate::traits::BuilderMethods; use crate::traits::*; -use rustc_error_codes::*; - impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_statement(&mut self, mut bx: Bx, statement: &mir::Statement<'tcx>) -> Bx { debug!("codegen_statement(statement={:?})", statement); diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 450dcd3b604..96a74f96fcf 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -91,8 +91,9 @@ use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::mir::mono::{InstantiationMode, MonoItem}; use rustc::session::config::SymbolManglingVersion; use rustc::ty::query::Providers; +use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Instance, TyCtxt}; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::Node; use rustc_span::symbol::Symbol; @@ -102,15 +103,70 @@ use log::debug; mod legacy; mod v0; +/// This function computes the symbol name for the given `instance` and the +/// given instantiating crate. That is, if you know that instance X is +/// instantiated in crate Y, this is the symbol name this instance would have. +pub fn symbol_name_for_instance_in_crate( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + instantiating_crate: CrateNum, +) -> String { + compute_symbol_name(tcx, instance, || instantiating_crate) +} + pub fn provide(providers: &mut Providers<'_>) { - *providers = Providers { - symbol_name: |tcx, instance| ty::SymbolName { name: symbol_name(tcx, instance) }, + *providers = Providers { symbol_name: symbol_name_provider, ..*providers }; +} - ..*providers - }; +// The `symbol_name` query provides the symbol name for calling a given +// instance from the local crate. In particular, it will also look up the +// correct symbol name of instances from upstream crates. +fn symbol_name_provider(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { + let symbol_name = compute_symbol_name(tcx, instance, || { + // This closure determines the instantiating crate for instances that + // need an instantiating-crate-suffix for their symbol name, in order + // to differentiate between local copies. + // + // For generics we might find re-usable upstream instances. For anything + // else we rely on their being a local copy available. + + if is_generic(instance.substs) { + let def_id = instance.def_id(); + + if !def_id.is_local() && tcx.sess.opts.share_generics() { + // If we are re-using a monomorphization from another crate, + // we have to compute the symbol hash accordingly. + let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id); + + upstream_monomorphizations + .and_then(|monos| monos.get(&instance.substs).cloned()) + // If there is no instance available upstream, there'll be + // one in the current crate. + .unwrap_or(LOCAL_CRATE) + } else { + // For generic functions defined in the current crate, there + // can be no upstream instances. Also, if we don't share + // generics, we'll instantiate a local copy too. + LOCAL_CRATE + } + } else { + // For non-generic things that need to avoid naming conflicts, we + // always instantiate a copy in the local crate. + LOCAL_CRATE + } + }); + + ty::SymbolName { name: Symbol::intern(&symbol_name) } } -fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { +/// Computes the symbol name for the given instance. This function will call +/// `compute_instantiating_crate` if it needs to factor the instantiating crate +/// into the symbol name. +fn compute_symbol_name( + tcx: TyCtxt<'tcx>, + instance: Instance<'tcx>, + compute_instantiating_crate: impl FnOnce() -> CrateNum, +) -> String { let def_id = instance.def_id(); let substs = instance.substs; @@ -121,11 +177,11 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { if def_id.is_local() { if tcx.plugin_registrar_fn(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return Symbol::intern(&tcx.sess.generate_plugin_registrar_symbol(disambiguator)); + return tcx.sess.generate_plugin_registrar_symbol(disambiguator); } if tcx.proc_macro_decls_static(LOCAL_CRATE) == Some(def_id) { let disambiguator = tcx.sess.local_crate_disambiguator(); - return Symbol::intern(&tcx.sess.generate_proc_macro_decls_symbol(disambiguator)); + return tcx.sess.generate_proc_macro_decls_symbol(disambiguator); } } @@ -162,29 +218,28 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { || !tcx.wasm_import_module_map(def_id.krate).contains_key(&def_id) { if let Some(name) = attrs.link_name { - return name; + return name.to_string(); } - return tcx.item_name(def_id); + return tcx.item_name(def_id).to_string(); } } if let Some(name) = attrs.export_name { // Use provided name - return name; + return name.to_string(); } if attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE) { // Don't mangle - return tcx.item_name(def_id); + return tcx.item_name(def_id).to_string(); } - let is_generic = substs.non_erasable_generics().next().is_some(); let avoid_cross_crate_conflicts = // If this is an instance of a generic function, we also hash in // the ID of the instantiating crate. This avoids symbol conflicts // in case the same instances is emitted in two crates of the same // project. - is_generic || + is_generic(substs) || // If we're dealing with an instance of a function that's inlined from // another crate but we're marking it as globally shared to our @@ -197,25 +252,8 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { _ => false, }; - let instantiating_crate = if avoid_cross_crate_conflicts { - Some(if is_generic { - if !def_id.is_local() && tcx.sess.opts.share_generics() { - // If we are re-using a monomorphization from another crate, - // we have to compute the symbol hash accordingly. - let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id); - - upstream_monomorphizations - .and_then(|monos| monos.get(&substs).cloned()) - .unwrap_or(LOCAL_CRATE) - } else { - LOCAL_CRATE - } - } else { - LOCAL_CRATE - }) - } else { - None - }; + let instantiating_crate = + if avoid_cross_crate_conflicts { Some(compute_instantiating_crate()) } else { None }; // Pick the crate responsible for the symbol mangling version, which has to: // 1. be stable for each instance, whether it's being defined or imported @@ -232,10 +270,12 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol { tcx.symbol_mangling_version(mangling_version_crate) }; - let mangled = match mangling_version { + match mangling_version { SymbolManglingVersion::Legacy => legacy::mangle(tcx, instance, instantiating_crate), SymbolManglingVersion::V0 => v0::mangle(tcx, instance, instantiating_crate), - }; + } +} - Symbol::intern(&mangled) +fn is_generic(substs: SubstsRef<'_>) -> bool { + substs.non_erasable_generics().next().is_some() } diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index 004db0a79a8..44cef727f03 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -136,9 +136,11 @@ bitflags::bitflags! { } } +// keep this in sync with the `-Z self-profile-events` help message in librustc_session/options.rs const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("none", EventFilter::NONE), ("all", EventFilter::ALL), + ("default", EventFilter::DEFAULT), ("generic-activity", EventFilter::GENERIC_ACTIVITIES), ("query-provider", EventFilter::QUERY_PROVIDERS), ("query-cache-hit", EventFilter::QUERY_CACHE_HITS), diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index 8b85d97a1d4..ee3f88ff167 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -137,6 +137,20 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> { } } +pub trait IntoPointer { + /// Returns a pointer which outlives `self`. + fn into_pointer(&self) -> *const (); +} + +impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> { + pub fn contains_pointer_to<T: Hash + IntoPointer>(&self, value: &T) -> bool { + let hash = make_hash(&value); + let shard = self.get_shard_by_hash(hash).lock(); + let value = value.into_pointer(); + shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some() + } +} + #[inline] fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 { let mut state = FxHasher::default(); diff --git a/src/librustc_error_codes/error_codes/E0195.md b/src/librustc_error_codes/error_codes/E0195.md index 3606521020a..b8c313d412e 100644 --- a/src/librustc_error_codes/error_codes/E0195.md +++ b/src/librustc_error_codes/error_codes/E0195.md @@ -1,4 +1,5 @@ -Your method's lifetime parameters do not match the trait declaration. +The lifetime parameters of the method do not match the trait declaration. + Erroneous code example: ```compile_fail,E0195 @@ -16,7 +17,7 @@ impl Trait for Foo { } ``` -The lifetime constraint `'b` for bar() implementation does not match the +The lifetime constraint `'b` for `bar()` implementation does not match the trait declaration. Ensure lifetime declarations match exactly in both trait declaration and implementation. Example: diff --git a/src/librustc_error_codes/error_codes/E0197.md b/src/librustc_error_codes/error_codes/E0197.md index 0d91157e572..c142b8f3664 100644 --- a/src/librustc_error_codes/error_codes/E0197.md +++ b/src/librustc_error_codes/error_codes/E0197.md @@ -1,13 +1,20 @@ +An inherent implementation was marked unsafe. + +Erroneous code example: + +```compile_fail,E0197 +struct Foo; + +unsafe impl Foo { } // error! +``` + Inherent implementations (one that do not implement a trait but provide methods associated with a type) are always safe because they are not implementing an unsafe trait. Removing the `unsafe` keyword from the inherent implementation will resolve this error. -```compile_fail,E0197 +``` struct Foo; -// this will cause this error -unsafe impl Foo { } -// converting it to this will fix it -impl Foo { } +impl Foo { } // ok! ``` diff --git a/src/librustc_error_codes/error_codes/E0198.md b/src/librustc_error_codes/error_codes/E0198.md index 6504d60dbd1..687214a2050 100644 --- a/src/librustc_error_codes/error_codes/E0198.md +++ b/src/librustc_error_codes/error_codes/E0198.md @@ -1,17 +1,18 @@ -A negative implementation is one that excludes a type from implementing a -particular trait. Not being able to use a trait is always a safe operation, -so negative implementations are always safe and never need to be marked as -unsafe. +A negative implementation was marked as unsafe. -```compile_fail -#![feature(optin_builtin_traits)] +Erroneous code example: +```compile_fail struct Foo; -// unsafe is unnecessary -unsafe impl !Clone for Foo { } +unsafe impl !Clone for Foo { } // error! ``` +A negative implementation is one that excludes a type from implementing a +particular trait. Not being able to use a trait is always a safe operation, +so negative implementations are always safe and never need to be marked as +unsafe. + This will compile: ```ignore (ignore auto_trait future compatibility warning) diff --git a/src/librustc_error_codes/error_codes/E0199.md b/src/librustc_error_codes/error_codes/E0199.md index d0c12dc6f17..88130e8e5e5 100644 --- a/src/librustc_error_codes/error_codes/E0199.md +++ b/src/librustc_error_codes/error_codes/E0199.md @@ -1,14 +1,23 @@ +A trait implementation was marked as unsafe while the trait is safe. + +Erroneous code example: + +```compile_fail,E0199 +struct Foo; + +trait Bar { } + +unsafe impl Bar for Foo { } // error! +``` + Safe traits should not have unsafe implementations, therefore marking an implementation for a safe trait unsafe will cause a compiler error. Removing -the unsafe marker on the trait noted in the error will resolve this problem. +the unsafe marker on the trait noted in the error will resolve this problem: -```compile_fail,E0199 +``` struct Foo; trait Bar { } -// this won't compile because Bar is safe -unsafe impl Bar for Foo { } -// this will compile -impl Bar for Foo { } +impl Bar for Foo { } // ok! ``` diff --git a/src/librustc_error_codes/error_codes/E0200.md b/src/librustc_error_codes/error_codes/E0200.md index 865e91430ac..7245bb59ce5 100644 --- a/src/librustc_error_codes/error_codes/E0200.md +++ b/src/librustc_error_codes/error_codes/E0200.md @@ -1,14 +1,23 @@ +An unsafe trait was implemented without an unsafe implementation. + +Erroneous code example: + +```compile_fail,E0200 +struct Foo; + +unsafe trait Bar { } + +impl Bar for Foo { } // error! +``` + Unsafe traits must have unsafe implementations. This error occurs when an implementation for an unsafe trait isn't marked as unsafe. This may be resolved by marking the unsafe implementation as unsafe. -```compile_fail,E0200 +``` struct Foo; unsafe trait Bar { } -// this won't compile because Bar is unsafe and impl isn't unsafe -impl Bar for Foo { } -// this will compile -unsafe impl Bar for Foo { } +unsafe impl Bar for Foo { } // ok! ``` diff --git a/src/librustc_error_codes/error_codes/E0201.md b/src/librustc_error_codes/error_codes/E0201.md index bdbf02f0033..0e1a7b7b7de 100644 --- a/src/librustc_error_codes/error_codes/E0201.md +++ b/src/librustc_error_codes/error_codes/E0201.md @@ -1,7 +1,7 @@ -It is an error to define two associated items (like methods, associated types, -associated functions, etc.) with the same identifier. +Two associated items (like methods, associated types, associated functions, +etc.) were defined with the same identifier. -For example: +Erroneous code example: ```compile_fail,E0201 struct Foo(u8); diff --git a/src/librustc_error_codes/error_codes/E0204.md b/src/librustc_error_codes/error_codes/E0204.md index 31569011135..96e44758be4 100644 --- a/src/librustc_error_codes/error_codes/E0204.md +++ b/src/librustc_error_codes/error_codes/E0204.md @@ -1,21 +1,24 @@ -An attempt to implement the `Copy` trait for a struct failed because one of the -fields does not implement `Copy`. To fix this, you must implement `Copy` for the -mentioned field. Note that this may not be possible, as in the example of +The `Copy` trait was implemented on a type which contains a field that doesn't +implement the `Copy` trait. + +Erroneous code example: ```compile_fail,E0204 struct Foo { - foo : Vec<u32>, + foo: Vec<u32>, } -impl Copy for Foo { } +impl Copy for Foo { } // error! ``` -This fails because `Vec<T>` does not implement `Copy` for any `T`. +The `Copy` trait is implemented by default only on primitive types. If your +type only contains primitive types, you'll be able to implement `Copy` on it. +Otherwise, it won't be possible. Here's another example that will fail: ```compile_fail,E0204 -#[derive(Copy)] +#[derive(Copy)] // error! struct Foo<'a> { ty: &'a mut bool, } diff --git a/src/librustc_error_codes/error_codes/E0527.md b/src/librustc_error_codes/error_codes/E0527.md index 4bff39dc770..97ea3126938 100644 --- a/src/librustc_error_codes/error_codes/E0527.md +++ b/src/librustc_error_codes/error_codes/E0527.md @@ -17,8 +17,6 @@ Ensure that the pattern is consistent with the size of the matched array. Additional elements can be matched with `..`: ``` -#![feature(slice_patterns)] - let r = &[1, 2, 3, 4]; match r { &[a, b, ..] => { // ok! diff --git a/src/librustc_error_codes/error_codes/E0528.md b/src/librustc_error_codes/error_codes/E0528.md index 4b6ea246991..54c2c4d4e9d 100644 --- a/src/librustc_error_codes/error_codes/E0528.md +++ b/src/librustc_error_codes/error_codes/E0528.md @@ -4,8 +4,6 @@ matched array. Example of erroneous code: ```compile_fail,E0528 -#![feature(slice_patterns)] - let r = &[1, 2]; match r { &[a, b, c, rest @ ..] => { // error: pattern requires at least 3 @@ -19,8 +17,6 @@ Ensure that the matched array has at least as many elements as the pattern requires. You can match an arbitrary number of remaining elements with `..`: ``` -#![feature(slice_patterns)] - let r = &[1, 2, 3, 4, 5]; match r { &[a, b, c, rest @ ..] => { // ok! diff --git a/src/librustc_error_codes/error_codes/E0730.md b/src/librustc_error_codes/error_codes/E0730.md index 803a2514865..bf1f72be325 100644 --- a/src/librustc_error_codes/error_codes/E0730.md +++ b/src/librustc_error_codes/error_codes/E0730.md @@ -18,8 +18,6 @@ Ensure that the pattern is consistent with the size of the matched array. Additional elements can be matched with `..`: ``` -#![feature(slice_patterns)] - let r = &[1, 2, 3, 4]; match r { &[a, b, ..] => { // ok! diff --git a/src/librustc_error_codes/lib.rs b/src/librustc_error_codes/lib.rs index 14210fd69ad..f051fdd11b8 100644 --- a/src/librustc_error_codes/lib.rs +++ b/src/librustc_error_codes/lib.rs @@ -6,16 +6,8 @@ macro_rules! register_diagnostics { pub static DIAGNOSTICS: &[(&str, &str)] = &[ $( (stringify!($ecode), $message), )* ]; - - $( - pub const $ecode: () = (); - )* - $( - pub const $code: () = (); - )* ) } mod error_codes; - -pub use error_codes::*; +pub use error_codes::DIAGNOSTICS; diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 73f66d55037..3c217c1d643 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -399,8 +399,5 @@ macro_rules! struct_span_err { #[macro_export] macro_rules! error_code { - ($code:ident) => {{ - let _ = $code; - $crate::DiagnosticId::Error(stringify!($code).to_owned()) - }}; + ($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }}; } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 526b4e2971b..b0e0cb611af 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1476,6 +1476,15 @@ impl EmitterWriter { None => return Ok(()), }; + // Render the replacements for each suggestion + let suggestions = suggestion.splice_lines(&**sm); + + if suggestions.is_empty() { + // Suggestions coming from macros can have malformed spans. This is a heavy handed + // approach to avoid ICEs by ignoring the suggestion outright. + return Ok(()); + } + let mut buffer = StyledBuffer::new(); // Render the suggestion message @@ -1492,9 +1501,6 @@ impl EmitterWriter { Some(Style::HeaderMsg), ); - // Render the replacements for each suggestion - let suggestions = suggestion.splice_lines(&**sm); - let mut row_num = 2; let mut notice_capitalization = false; for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) { @@ -1505,7 +1511,9 @@ impl EmitterWriter { let show_underline = !(parts.len() == 1 && parts[0].snippet.trim() == complete.trim()) && complete.lines().count() == 1; - let lines = sm.span_to_lines(parts[0].span).unwrap(); + let lines = sm + .span_to_lines(parts[0].span) + .expect("span_to_lines failed when emitting suggestion"); assert!(!lines.lines.is_empty()); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index e24e8719133..827e9b831f3 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -10,6 +10,7 @@ pub use emitter::ColorConfig; +use log::debug; use Level::*; use emitter::{is_case_difference, Emitter, EmitterWriter}; @@ -174,6 +175,15 @@ impl CodeSuggestion { self.substitutions .iter() + .filter(|subst| { + // Suggestions coming from macros can have malformed spans. This is a heavy + // handed approach to avoid ICEs by ignoring the suggestion outright. + let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err()); + if invalid { + debug!("splice_lines: suggestion contains an invalid span: {:?}", subst); + } + !invalid + }) .cloned() .map(|mut substitution| { // Assumption: all spans are in the same file, and all spans diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index bd3d6b589d0..11f94ab2e62 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -110,7 +110,7 @@ impl<'a> ExtCtxt<'a> { } pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef { - ast::TraitRef { path, constness: None, ref_id: ast::DUMMY_NODE_ID } + ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID } } pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { diff --git a/src/librustc_feature/accepted.rs b/src/librustc_feature/accepted.rs index d880fc84b38..007cee4c764 100644 --- a/src/librustc_feature/accepted.rs +++ b/src/librustc_feature/accepted.rs @@ -257,6 +257,8 @@ declare_features! ( /// Allows relaxing the coherence rules such that /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted. (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None), + /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`. + (accepted, slice_patterns, "1.42.0", Some(62254), None), // ------------------------------------------------------------------------- // feature-group-end: accepted features diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 4c8c47a5671..6af9b6c0872 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -262,9 +262,6 @@ declare_features! ( /// Allows using non lexical lifetimes (RFC 2094). (active, nll, "1.0.0", Some(43234), None), - /// Allows using slice patterns. - (active, slice_patterns, "1.0.0", Some(62254), None), - /// Allows the definition of `const` functions with some advanced features. (active, const_fn, "1.2.0", Some(57563), None), diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 5c1d600c837..b62a7e413e3 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -364,6 +364,7 @@ impl GenericArgs<'_> { pub enum TraitBoundModifier { None, Maybe, + MaybeConst, } /// The AST represents all type param bounds as types. @@ -2436,15 +2437,19 @@ pub enum ItemKind<'hir> { TraitAlias(Generics<'hir>, GenericBounds<'hir>), /// An implementation, e.g., `impl<A> Trait for Foo { .. }`. - Impl( - Unsafety, - ImplPolarity, - Defaultness, - Generics<'hir>, - Option<TraitRef<'hir>>, // (optional) trait this impl implements - &'hir Ty<'hir>, // self - &'hir [ImplItemRef<'hir>], - ), + Impl { + unsafety: Unsafety, + polarity: ImplPolarity, + defaultness: Defaultness, + constness: Constness, + generics: Generics<'hir>, + + /// The trait being implemented, if any. + of_trait: Option<TraitRef<'hir>>, + + self_ty: &'hir Ty<'hir>, + items: &'hir [ImplItemRef<'hir>], + }, } impl ItemKind<'_> { @@ -2465,7 +2470,7 @@ impl ItemKind<'_> { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Impl(..) => "impl", + ItemKind::Impl { .. } => "impl", } } @@ -2478,7 +2483,7 @@ impl ItemKind<'_> { | ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) | ItemKind::Trait(_, _, ref generics, _, _) - | ItemKind::Impl(_, _, _, ref generics, _, _, _) => generics, + | ItemKind::Impl { ref generics, .. } => generics, _ => return None, }) } diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 3dbc5253a9a..539a0eee0e3 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -566,12 +566,21 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) { // `visit_enum_def()` takes care of visiting the `Item`'s `HirId`. visitor.visit_enum_def(enum_definition, generics, item.hir_id, item.span) } - ItemKind::Impl(.., ref generics, ref opt_trait_reference, ref typ, impl_item_refs) => { + ItemKind::Impl { + unsafety: _, + defaultness: _, + polarity: _, + constness: _, + ref generics, + ref of_trait, + ref self_ty, + items, + } => { visitor.visit_id(item.hir_id); visitor.visit_generics(generics); - walk_list!(visitor, visit_trait_ref, opt_trait_reference); - visitor.visit_ty(typ); - walk_list!(visitor, visit_impl_item_ref, impl_item_refs); + walk_list!(visitor, visit_trait_ref, of_trait); + visitor.visit_ty(self_ty); + walk_list!(visitor, visit_impl_item_ref, items); } ItemKind::Struct(ref struct_definition, ref generics) | ItemKind::Union(ref struct_definition, ref generics) => { diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 759f423070a..b9598c93761 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -627,15 +627,16 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "union")); self.print_struct(struct_def, generics, item.ident.name, item.span, true); } - hir::ItemKind::Impl( + hir::ItemKind::Impl { unsafety, polarity, defaultness, + constness, ref generics, - ref opt_trait, - ref ty, - impl_items, - ) => { + ref of_trait, + ref self_ty, + items, + } => { self.head(""); self.print_visibility(&item.vis); self.print_defaultness(defaultness); @@ -647,23 +648,27 @@ impl<'a> State<'a> { self.s.space(); } + if constness == ast::Constness::Const { + self.word_nbsp("const"); + } + if let hir::ImplPolarity::Negative = polarity { self.s.word("!"); } - if let Some(ref t) = opt_trait { + if let Some(ref t) = of_trait { self.print_trait_ref(t); self.s.space(); self.word_space("for"); } - self.print_type(&ty); + self.print_type(&self_ty); self.print_where_clause(&generics.where_clause); self.s.space(); self.bopen(); self.print_inner_attributes(&item.attrs); - for impl_item in impl_items { + for impl_item in items { self.ann.nested(self, Nested::ImplItem(impl_item.id)); } self.bclose(item.span); diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index ddfed53fa33..c5e74868bda 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -315,7 +315,7 @@ impl DirtyCleanVisitor<'tcx> { //HirItem::Trait(..) => ("ItemTrait", LABELS_TRAIT), // An implementation, eg `impl<A> Trait for Foo { .. }` - HirItem::Impl(..) => ("ItemKind::Impl", LABELS_IMPL), + HirItem::Impl { .. } => ("ItemKind::Impl", LABELS_IMPL), _ => self.tcx.sess.span_fatal( attr.span, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c4444fbaa2f..d62c7539d5f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -15,7 +15,7 @@ use rustc::session::search_paths::PathKind; use rustc::session::Session; use rustc::traits; use rustc::ty::steal::Steal; -use rustc::ty::{self, AllArenas, GlobalCtxt, ResolverOutputs, TyCtxt}; +use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_builtin_macros; use rustc_codegen_ssa::back::link::emit_metadata; @@ -715,7 +715,6 @@ pub fn create_global_ctxt<'tcx>( outputs: OutputFilenames, crate_name: &str, global_ctxt: &'tcx Once<GlobalCtxt<'tcx>>, - all_arenas: &'tcx AllArenas, arena: &'tcx WorkerLocal<Arena<'tcx>>, ) -> QueryContext<'tcx> { let sess = &compiler.session(); @@ -746,7 +745,6 @@ pub fn create_global_ctxt<'tcx>( lint_store, local_providers, extern_providers, - &all_arenas, arena, resolver_outputs, hir_map, diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index bd9717d3f3d..0af9b17a299 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -7,7 +7,7 @@ use rustc::hir::map; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::session::Session; use rustc::ty::steal::Steal; -use rustc::ty::{AllArenas, GlobalCtxt, ResolverOutputs}; +use rustc::ty::{GlobalCtxt, ResolverOutputs}; use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::sync::{Lrc, Once, WorkerLocal}; @@ -66,7 +66,6 @@ pub struct Queries<'tcx> { compiler: &'tcx Compiler, gcx: Once<GlobalCtxt<'tcx>>, - all_arenas: AllArenas, arena: WorkerLocal<Arena<'tcx>>, dep_graph_future: Query<Option<DepGraphFuture>>, @@ -86,7 +85,6 @@ impl<'tcx> Queries<'tcx> { Queries { compiler, gcx: Once::new(), - all_arenas: AllArenas::new(), arena: WorkerLocal::new(|_| Arena::default()), dep_graph_future: Default::default(), parse: Default::default(), @@ -265,7 +263,6 @@ impl<'tcx> Queries<'tcx> { outputs, &crate_name, &self.gcx, - &self.all_arenas, &self.arena, )) }) diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index abf9f96e647..7e23e705779 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -13,7 +13,6 @@ log = "0.4" unicode-security = "0.0.2" rustc = { path = "../librustc" } rustc_errors = { path = "../librustc_errors" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 6314c2b9953..c8d3d5f9c83 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -251,7 +251,7 @@ impl EarlyLintPass for UnsafeCode { self.report_unsafe(cx, it.span, "declaration of an `unsafe` trait") } - ast::ItemKind::Impl(ast::Unsafety::Unsafe, ..) => { + ast::ItemKind::Impl { unsafety: ast::Unsafety::Unsafe, .. } => { self.report_unsafe(cx, it.span, "implementation of an `unsafe` trait") } @@ -431,7 +431,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { "a trait" } hir::ItemKind::TyAlias(..) => "a type alias", - hir::ItemKind::Impl(.., Some(ref trait_ref), _, impl_item_refs) => { + hir::ItemKind::Impl { of_trait: Some(ref trait_ref), items, .. } => { // If the trait is private, add the impl items to `private_traits` so they don't get // reported for missing docs. let real_trait = trait_ref.path.res.def_id(); @@ -439,7 +439,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { match cx.tcx.hir().find(hir_id) { Some(Node::Item(item)) => { if let hir::VisibilityKind::Inherited = item.vis.node { - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { self.private_traits.insert(impl_item_ref.id.hir_id); } } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 42ec8787cb2..3b8cce5635d 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -26,7 +26,6 @@ use rustc::ty::layout::{LayoutError, LayoutOf, TyLayout}; use rustc::ty::{self, print::Printer, subst::GenericArg, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId}; diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index 5a5aedc2e97..91aeccbb5e3 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -221,7 +221,7 @@ declare_lint_pass!(LintPassImpl => [LINT_PASS_IMPL_WITHOUT_MACRO]); impl EarlyLintPass for LintPassImpl { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - if let ItemKind::Impl(_, _, _, _, Some(lint_pass), _, _) = &item.kind { + if let ItemKind::Impl { of_trait: Some(lint_pass), .. } = &item.kind { if let Some(last) = lint_pass.path.segments.last() { if last.ident.name == sym::LintPass { let expn_data = lint_pass.path.span.ctxt().outer_expn_data(); diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index bbc3e57f5dd..d5bbdc53160 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -6,7 +6,6 @@ use rustc::lint::{LintLevelMap, LintLevelSets, LintSet, LintSource}; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index a2b7884241f..394da4a5bb0 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -350,7 +350,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_pat(&mut self, cx: &LateContext<'_, '_>, p: &hir::Pat<'_>) { - if let &PatKind::Binding(_, _, ident, _) = &p.kind { + if let &PatKind::Binding(_, hid, ident, _) = &p.kind { + if let hir::Node::Pat(parent_pat) = cx.tcx.hir().get(cx.tcx.hir().get_parent_node(hid)) + { + if let PatKind::Struct(_, field_pats, _) = &parent_pat.kind { + for field in field_pats.iter() { + if field.ident != ident { + // Only check if a new name has been introduced, to avoid warning + // on both the struct definition and this pattern. + self.check_snake_case(cx, "variable", &ident); + } + } + return; + } + } self.check_snake_case(cx, "variable", &ident); } } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 26cbda3d978..15158c09af0 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { ty::Opaque(def, _) => { let mut has_emitted = false; for (predicate, _) in cx.tcx.predicates_of(def).predicates { - if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate { + if let ty::Predicate::Trait(ref poly_trait_predicate, _) = predicate { let trait_ref = poly_trait_predicate.skip_binder().trait_ref; let def_id = trait_ref.def_id; let descr_pre = diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 0a0bcb190be..6da584733ae 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -26,7 +26,6 @@ syntax = { path = "../libsyntax" } rustc_expand = { path = "../librustc_expand" } rustc_parse = { path = "../librustc_parse" } rustc_span = { path = "../librustc_span" } -rustc_error_codes = { path = "../librustc_error_codes" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 181f872154c..351e72d4678 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -12,7 +12,6 @@ use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::TyCtxt; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 0fec4bff163..cf925ab9187 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -10,7 +10,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] #![feature(rustc_private)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(specialization)] #![feature(stmt_expr_attributes)] #![recursion_limit = "256"] diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 4745ad02a3a..578216454f9 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -241,8 +241,6 @@ use rustc_data_structures::owning_ref::OwningRef; use log::{debug, info, warn}; -use rustc_error_codes::*; - #[derive(Clone)] struct CrateMismatch { path: PathBuf, diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 9426d5e26f5..bbf6973be51 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -3,7 +3,6 @@ use rustc::session::parse::feature_err; use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 8ad92ce75a8..9d2bea28c8c 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1073,7 +1073,7 @@ impl EncodeContext<'tcx> { ctor: None, }), adt_def.repr) } - hir::ItemKind::Impl(_, _, defaultness, ..) => { + hir::ItemKind::Impl { defaultness, .. } => { let trait_ref = self.tcx.impl_trait_ref(def_id); let polarity = self.tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { @@ -1149,7 +1149,7 @@ impl EncodeContext<'tcx> { }) ) } - hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => { + hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => { let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); record!(self.per_def.children[def_id] <- associated_item_def_ids.iter().map(|&def_id| { @@ -1172,13 +1172,13 @@ impl EncodeContext<'tcx> { | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) - | hir::ItemKind::Impl(..) => self.encode_item_type(def_id), + | hir::ItemKind::Impl { .. } => self.encode_item_type(def_id), _ => {} } if let hir::ItemKind::Fn(..) = item.kind { record!(self.per_def.fn_sig[def_id] <- tcx.fn_sig(def_id)); } - if let hir::ItemKind::Impl(..) = item.kind { + if let hir::ItemKind::Impl { .. } = item.kind { if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { record!(self.per_def.impl_trait_ref[def_id] <- trait_ref); } @@ -1199,7 +1199,7 @@ impl EncodeContext<'tcx> { | hir::ItemKind::Enum(..) | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) - | hir::ItemKind::Impl(..) + | hir::ItemKind::Impl { .. } | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => { @@ -1645,7 +1645,7 @@ impl EncodeContext<'tcx> { hir::ItemKind::Union(..) => { self.encode_fields(def_id); } - hir::ItemKind::Impl(..) => { + hir::ItemKind::Impl { .. } => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.encode_info_for_impl_item(trait_item_def_id); } @@ -1666,7 +1666,7 @@ struct ImplVisitor<'tcx> { impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { - if let hir::ItemKind::Impl(..) = item.kind { + if let hir::ItemKind::Impl { .. } = item.kind { let impl_id = self.tcx.hir().local_def_id(item.hir_id); if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_id) { self.impls.entry(trait_ref.def_id).or_default().push(impl_id.index); diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index f9b61b9e2c9..00881e3ea6f 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -29,4 +29,3 @@ syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } rustc_apfloat = { path = "../librustc_apfloat" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } -rustc_error_codes = { path = "../librustc_error_codes" } diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs index 9a0c99b07e6..01b7c5645fe 100644 --- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs +++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs @@ -2,12 +2,13 @@ use std::collections::VecDeque; +use rustc::infer::NLLRegionVariableOrigin; use rustc::mir::{ Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc::ty::adjustment::PointerCast; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_index::vec::IndexVec; @@ -254,6 +255,23 @@ impl BorrowExplanation { } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { + fn free_region_constraint_info( + &self, + borrow_region: RegionVid, + outlived_region: RegionVid, + ) -> (ConstraintCategory, bool, Span, Option<RegionName>) { + let (category, from_closure, span) = self.regioncx.best_blame_constraint( + &self.body, + borrow_region, + NLLRegionVariableOrigin::FreeRegion, + |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region), + ); + + let outlived_fr_name = self.give_region_a_name(outlived_region); + + (category, from_closure, span, outlived_fr_name) + } + /// Returns structured explanation for *why* the borrow contains the /// point from `location`. This is key for the "3-point errors" /// [described in the NLL RFC][d]. @@ -278,14 +296,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location, borrow, kind_place ); - let regioncx = &self.nonlexical_regioncx; + let regioncx = &self.regioncx; let body: &Body<'_> = &self.body; let tcx = self.infcx.tcx; let borrow_region_vid = borrow.region; debug!("explain_why_borrow_contains_point: borrow_region_vid={:?}", borrow_region_vid); - let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, location); + let region_sub = self.regioncx.find_sub_region_live_at(borrow_region_vid, location); debug!("explain_why_borrow_contains_point: region_sub={:?}", region_sub); match find_use::find(body, regioncx, tcx, region_sub, location) { @@ -329,10 +347,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } None => { - if let Some(region) = regioncx.to_error_region_vid(borrow_region_vid) { - let (category, from_closure, span, region_name) = self - .nonlexical_regioncx - .free_region_constraint_info(self, borrow_region_vid, region); + if let Some(region) = self.to_error_region_vid(borrow_region_vid) { + let (category, from_closure, span, region_name) = + self.free_region_constraint_info(borrow_region_vid, region); if let Some(region_name) = region_name { let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref()); BorrowExplanation::MustBeValidFor { @@ -345,14 +362,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { debug!( "explain_why_borrow_contains_point: \ - Could not generate a region name" + Could not generate a region name" ); BorrowExplanation::Unexplained } } else { debug!( "explain_why_borrow_contains_point: \ - Could not generate an error region vid" + Could not generate an error region vid" ); BorrowExplanation::Unexplained } diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 3f3bdb9d36c..0fc73d33f90 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -32,7 +32,7 @@ mod region_errors; crate use mutability_errors::AccessKind; crate use outlives_suggestion::OutlivesSuggestionBuilder; crate use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionErrors}; -crate use region_name::{RegionErrorNamingCtx, RegionName, RegionNameSource}; +crate use region_name::{RegionName, RegionNameSource}; pub(super) struct IncludingDowncast(pub(super) bool); diff --git a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs index 1425c22e461..ee9489078bd 100644 --- a/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs +++ b/src/librustc_mir/borrow_check/diagnostics/outlives_suggestion.rs @@ -12,7 +12,7 @@ use smallvec::SmallVec; use crate::borrow_check::MirBorrowckCtxt; -use super::{ErrorConstraintInfo, RegionErrorNamingCtx, RegionName, RegionNameSource}; +use super::{ErrorConstraintInfo, RegionName, RegionNameSource}; /// The different things we could suggest. enum SuggestedConstraint { @@ -77,19 +77,15 @@ impl OutlivesSuggestionBuilder { fn region_vid_to_name( &self, mbcx: &MirBorrowckCtxt<'_, '_>, - renctx: &mut RegionErrorNamingCtx, region: RegionVid, ) -> Option<RegionName> { - mbcx.nonlexical_regioncx - .give_region_a_name(mbcx, renctx, region) - .filter(Self::region_name_is_suggestable) + mbcx.give_region_a_name(region).filter(Self::region_name_is_suggestable) } /// Compiles a list of all suggestions to be printed in the final big suggestion. fn compile_all_suggestions( &self, mbcx: &MirBorrowckCtxt<'_, '_>, - renctx: &mut RegionErrorNamingCtx, ) -> SmallVec<[SuggestedConstraint; 2]> { let mut suggested = SmallVec::new(); @@ -98,7 +94,7 @@ impl OutlivesSuggestionBuilder { let mut unified_already = FxHashSet::default(); for (fr, outlived) in &self.constraints_to_add { - let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, renctx, *fr) { + let fr_name = if let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) { fr_name } else { continue; @@ -107,9 +103,7 @@ impl OutlivesSuggestionBuilder { let outlived = outlived .iter() // if there is a `None`, we will just omit that constraint - .filter_map(|fr| { - self.region_vid_to_name(mbcx, renctx, *fr).map(|rname| (fr, rname)) - }) + .filter_map(|fr| self.region_vid_to_name(mbcx, *fr).map(|rname| (fr, rname))) .collect::<Vec<_>>(); // No suggestable outlived lifetimes. @@ -173,12 +167,11 @@ impl OutlivesSuggestionBuilder { &mut self, mbcx: &MirBorrowckCtxt<'_, '_>, errci: &ErrorConstraintInfo, - renctx: &mut RegionErrorNamingCtx, diag: &mut DiagnosticBuilder<'_>, ) { // Emit an intermediate note. - let fr_name = self.region_vid_to_name(mbcx, renctx, errci.fr); - let outlived_fr_name = self.region_vid_to_name(mbcx, renctx, errci.outlived_fr); + let fr_name = self.region_vid_to_name(mbcx, errci.fr); + let outlived_fr_name = self.region_vid_to_name(mbcx, errci.outlived_fr); if let (Some(fr_name), Some(outlived_fr_name)) = (fr_name, outlived_fr_name) { if let RegionNameSource::Static = outlived_fr_name.source { @@ -194,11 +187,7 @@ impl OutlivesSuggestionBuilder { /// If there is a suggestion to emit, add a diagnostic to the buffer. This is the final /// suggestion including all collected constraints. - crate fn add_suggestion( - &self, - mbcx: &mut MirBorrowckCtxt<'_, '_>, - renctx: &mut RegionErrorNamingCtx, - ) { + crate fn add_suggestion(&self, mbcx: &mut MirBorrowckCtxt<'_, '_>) { // No constraints to add? Done. if self.constraints_to_add.is_empty() { debug!("No constraints to suggest."); @@ -215,7 +204,7 @@ impl OutlivesSuggestionBuilder { } // Get all suggestable constraints. - let suggested = self.compile_all_suggestions(mbcx, renctx); + let suggested = self.compile_all_suggestions(mbcx); // If there are no suggestable constraints... if suggested.is_empty() { diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index dc63fa80275..b999dfa3031 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -1,27 +1,25 @@ //! Error reporting machinery for lifetime errors. use rustc::infer::{ - error_reporting::nice_region_error::NiceRegionError, region_constraints::GenericKind, - InferCtxt, NLLRegionVariableOrigin, + error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin, }; -use rustc::mir::{Body, ConstraintCategory, Location}; +use rustc::mir::ConstraintCategory; use rustc::ty::{self, RegionVid, Ty}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::def_id::DefId; -use rustc_index::vec::IndexVec; use rustc_span::symbol::kw; use rustc_span::Span; -use std::collections::VecDeque; use crate::util::borrowck_errors; use crate::borrow_check::{ - constraints::OutlivesConstraint, nll::ConstraintDescription, - region_infer::RegionInferenceContext, type_check::Locations, universal_regions::DefiningTy, + nll::ConstraintDescription, + region_infer::{values::RegionElement, TypeTest}, + universal_regions::DefiningTy, MirBorrowckCtxt, }; -use super::{OutlivesSuggestionBuilder, RegionErrorNamingCtx, RegionName, RegionNameSource}; +use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; impl ConstraintDescription for ConstraintCategory { fn description(&self) -> &'static str { @@ -46,13 +44,6 @@ impl ConstraintDescription for ConstraintCategory { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -enum Trace { - StartRegion, - FromOutlivesConstraint(OutlivesConstraint), - NotVisited, -} - /// A collection of errors encountered during region inference. This is needed to efficiently /// report errors after borrow checking. /// @@ -62,23 +53,8 @@ crate type RegionErrors<'tcx> = Vec<RegionErrorKind<'tcx>>; #[derive(Clone, Debug)] crate enum RegionErrorKind<'tcx> { - /// An error for a type test: `T: 'a` does not live long enough. - TypeTestDoesNotLiveLongEnough { - /// The span of the type test. - span: Span, - /// The generic type of the type test. - generic: GenericKind<'tcx>, - }, - - /// A generic bound failure for a type test. - TypeTestGenericBoundError { - /// The span of the type test. - span: Span, - /// The generic type of the type test. - generic: GenericKind<'tcx>, - /// The lower bound region. - lower_bound_region: ty::Region<'tcx>, - }, + /// A generic bound failure for a type test (`T: 'a`). + TypeTestError { type_test: TypeTest<'tcx> }, /// An unexpected hidden region for an opaque type. UnexpectedHiddenRegion { @@ -94,8 +70,8 @@ crate enum RegionErrorKind<'tcx> { BoundUniversalRegionError { /// The placeholder free region. longer_fr: RegionVid, - /// The region that erroneously must be outlived by `longer_fr`. - error_region: RegionVid, + /// The region element that erroneously must be outlived by `longer_fr`. + error_element: RegionElement, /// The origin of the placeholder region. fr_origin: NLLRegionVariableOrigin, }, @@ -128,26 +104,26 @@ pub struct ErrorConstraintInfo { pub(super) span: Span, } -impl<'tcx> RegionInferenceContext<'tcx> { +impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { /// Converts a region inference variable into a `ty::Region` that /// we can use for error reporting. If `r` is universally bound, /// then we use the name that we have on record for it. If `r` is /// existentially bound, then we check its inferred value and try /// to find a good name from that. Returns `None` if we can't find /// one (e.g., this is just some random part of the CFG). - pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> { - self.to_error_region_vid(r).and_then(|r| self.definitions[r].external_name) + pub(super) fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> { + self.to_error_region_vid(r).and_then(|r| self.regioncx.region_definition(r).external_name) } - /// Returns the [RegionVid] corresponding to the region returned by + /// Returns the `RegionVid` corresponding to the region returned by /// `to_error_region`. - pub fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> { - if self.universal_regions.is_universal_region(r) { + pub(super) fn to_error_region_vid(&self, r: RegionVid) -> Option<RegionVid> { + if self.regioncx.universal_regions().is_universal_region(r) { Some(r) } else { - let r_scc = self.constraint_sccs.scc(r); - let upper_bound = self.universal_upper_bound(r); - if self.scc_values.contains(r_scc, upper_bound) { + let upper_bound = self.regioncx.universal_upper_bound(r); + + if self.regioncx.upper_bound_in_region_scc(r, upper_bound) { self.to_error_region_vid(upper_bound) } else { None @@ -155,270 +131,134 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - /// Tries to find the best constraint to blame for the fact that - /// `R: from_region`, where `R` is some region that meets - /// `target_test`. This works by following the constraint graph, - /// creating a constraint path that forces `R` to outlive - /// `from_region`, and then finding the best choices within that - /// path to blame. - fn best_blame_constraint( - &self, - body: &Body<'tcx>, - from_region: RegionVid, - from_region_origin: NLLRegionVariableOrigin, - target_test: impl Fn(RegionVid) -> bool, - ) -> (ConstraintCategory, bool, Span) { - debug!( - "best_blame_constraint(from_region={:?}, from_region_origin={:?})", - from_region, from_region_origin - ); - - // Find all paths - let (path, target_region) = - self.find_constraint_paths_between_regions(from_region, target_test).unwrap(); - debug!( - "best_blame_constraint: path={:#?}", - path.iter() - .map(|&c| format!( - "{:?} ({:?}: {:?})", - c, - self.constraint_sccs.scc(c.sup), - self.constraint_sccs.scc(c.sub), - )) - .collect::<Vec<_>>() - ); - - // Classify each of the constraints along the path. - let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path - .iter() - .map(|constraint| { - if constraint.category == ConstraintCategory::ClosureBounds { - self.retrieve_closure_constraint_info(body, &constraint) - } else { - (constraint.category, false, constraint.locations.span(body)) - } - }) - .collect(); - debug!("best_blame_constraint: categorized_path={:#?}", categorized_path); - - // To find the best span to cite, we first try to look for the - // final constraint that is interesting and where the `sup` is - // not unified with the ultimate target region. The reason - // for this is that we have a chain of constraints that lead - // from the source to the target region, something like: - // - // '0: '1 ('0 is the source) - // '1: '2 - // '2: '3 - // '3: '4 - // '4: '5 - // '5: '6 ('6 is the target) - // - // Some of those regions are unified with `'6` (in the same - // SCC). We want to screen those out. After that point, the - // "closest" constraint we have to the end is going to be the - // most likely to be the point where the value escapes -- but - // we still want to screen for an "interesting" point to - // highlight (e.g., a call site or something). - let target_scc = self.constraint_sccs.scc(target_region); - let mut range = 0..path.len(); - - // As noted above, when reporting an error, there is typically a chain of constraints - // leading from some "source" region which must outlive some "target" region. - // In most cases, we prefer to "blame" the constraints closer to the target -- - // but there is one exception. When constraints arise from higher-ranked subtyping, - // we generally prefer to blame the source value, - // as the "target" in this case tends to be some type annotation that the user gave. - // Therefore, if we find that the region origin is some instantiation - // of a higher-ranked region, we start our search from the "source" point - // rather than the "target", and we also tweak a few other things. - // - // An example might be this bit of Rust code: - // - // ```rust - // let x: fn(&'static ()) = |_| {}; - // let y: for<'a> fn(&'a ()) = x; - // ``` - // - // In MIR, this will be converted into a combination of assignments and type ascriptions. - // In particular, the 'static is imposed through a type ascription: - // - // ```rust - // x = ...; - // AscribeUserType(x, fn(&'static ()) - // y = x; - // ``` - // - // We wind up ultimately with constraints like - // - // ```rust - // !a: 'temp1 // from the `y = x` statement - // 'temp1: 'temp2 - // 'temp2: 'static // from the AscribeUserType - // ``` - // - // and here we prefer to blame the source (the y = x statement). - let blame_source = match from_region_origin { - NLLRegionVariableOrigin::FreeRegion - | NLLRegionVariableOrigin::Existential { from_forall: false } => true, - NLLRegionVariableOrigin::Placeholder(_) - | NLLRegionVariableOrigin::Existential { from_forall: true } => false, - }; - - let find_region = |i: &usize| { - let constraint = path[*i]; - - let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); - - if blame_source { - match categorized_path[*i].0 { - ConstraintCategory::OpaqueType - | ConstraintCategory::Boring - | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, - ConstraintCategory::TypeAnnotation - | ConstraintCategory::Return - | ConstraintCategory::Yield => true, - _ => constraint_sup_scc != target_scc, - } - } else { - match categorized_path[*i].0 { - ConstraintCategory::OpaqueType - | ConstraintCategory::Boring - | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal => false, - _ => true, - } - } - }; - - let best_choice = - if blame_source { range.rev().find(find_region) } else { range.find(find_region) }; - - debug!( - "best_blame_constraint: best_choice={:?} blame_source={}", - best_choice, blame_source - ); - - if let Some(i) = best_choice { - if let Some(next) = categorized_path.get(i + 1) { - if categorized_path[i].0 == ConstraintCategory::Return - && next.0 == ConstraintCategory::OpaqueType + /// Returns `true` if a closure is inferred to be an `FnMut` closure. + fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { + if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) { + if let ty::BoundRegion::BrEnv = free_region.bound_region { + if let DefiningTy::Closure(def_id, substs) = + self.regioncx.universal_regions().defining_ty { - // The return expression is being influenced by the return type being - // impl Trait, point at the return type and not the return expr. - return *next; + return substs.as_closure().kind(def_id, self.infcx.tcx) + == ty::ClosureKind::FnMut; } } - return categorized_path[i]; } - // If that search fails, that is.. unusual. Maybe everything - // is in the same SCC or something. In that case, find what - // appears to be the most interesting point to report to the - // user via an even more ad-hoc guess. - categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0)); - debug!("`: sorted_path={:#?}", categorized_path); - - *categorized_path.first().unwrap() + false } - /// Walks the graph of constraints (where `'a: 'b` is considered - /// an edge `'a -> 'b`) to find all paths from `from_region` to - /// `to_region`. The paths are accumulated into the vector - /// `results`. The paths are stored as a series of - /// `ConstraintIndex` values -- in other words, a list of *edges*. - /// - /// Returns: a series of constraints as well as the region `R` - /// that passed the target test. - fn find_constraint_paths_between_regions( - &self, - from_region: RegionVid, - target_test: impl Fn(RegionVid) -> bool, - ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> { - let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); - context[from_region] = Trace::StartRegion; - - // Use a deque so that we do a breadth-first search. We will - // stop at the first match, which ought to be the shortest - // path (fewest constraints). - let mut deque = VecDeque::new(); - deque.push_back(from_region); - - while let Some(r) = deque.pop_front() { - debug!( - "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}", - from_region, - r, - self.region_value_str(r), - ); - - // Check if we reached the region we were looking for. If so, - // we can reconstruct the path that led to it and return it. - if target_test(r) { - let mut result = vec![]; - let mut p = r; - loop { - match context[p] { - Trace::NotVisited => { - bug!("found unvisited region {:?} on path to {:?}", p, r) - } - - Trace::FromOutlivesConstraint(c) => { - result.push(c); - p = c.sup; - } - - Trace::StartRegion => { - result.reverse(); - return Some((result, r)); - } + /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`. + pub(in crate::borrow_check) fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { + // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are + // buffered in the `MirBorrowckCtxt`. + + let mut outlives_suggestion = OutlivesSuggestionBuilder::default(); + + for nll_error in nll_errors.into_iter() { + match nll_error { + RegionErrorKind::TypeTestError { type_test } => { + // Try to convert the lower-bound region into something named we can print for the user. + let lower_bound_region = self.to_error_region(type_test.lower_bound); + + let type_test_span = type_test.locations.span(&self.body); + + if let Some(lower_bound_region) = lower_bound_region { + let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); + self.infcx + .construct_generic_bound_failure( + region_scope_tree, + type_test_span, + None, + type_test.generic_kind, + lower_bound_region, + ) + .buffer(&mut self.errors_buffer); + } else { + // FIXME. We should handle this case better. It + // indicates that we have e.g., some region variable + // whose value is like `'a+'b` where `'a` and `'b` are + // distinct unrelated univesal regions that are not + // known to outlive one another. It'd be nice to have + // some examples where this arises to decide how best + // to report it; we could probably handle it by + // iterating over the universal regions and reporting + // an error that multiple bounds are required. + self.infcx + .tcx + .sess + .struct_span_err( + type_test_span, + &format!("`{}` does not live long enough", type_test.generic_kind), + ) + .buffer(&mut self.errors_buffer); } } - } - // Otherwise, walk over the outgoing constraints and - // enqueue any regions we find, keeping track of how we - // reached them. - - // A constraint like `'r: 'x` can come from our constraint - // graph. - let fr_static = self.universal_regions.fr_static; - let outgoing_edges_from_graph = - self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static); - - // Always inline this closure because it can be hot. - let mut handle_constraint = #[inline(always)] - |constraint: OutlivesConstraint| { - debug_assert_eq!(constraint.sup, r); - let sub_region = constraint.sub; - if let Trace::NotVisited = context[sub_region] { - context[sub_region] = Trace::FromOutlivesConstraint(constraint); - deque.push_back(sub_region); + RegionErrorKind::UnexpectedHiddenRegion { + opaque_type_def_id, + hidden_ty, + member_region, + } => { + let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); + opaque_types::unexpected_hidden_region_diagnostic( + self.infcx.tcx, + Some(region_scope_tree), + opaque_type_def_id, + hidden_ty, + member_region, + ) + .buffer(&mut self.errors_buffer); } - }; - // This loop can be hot. - for constraint in outgoing_edges_from_graph { - handle_constraint(constraint); - } + RegionErrorKind::BoundUniversalRegionError { + longer_fr, + fr_origin, + error_element, + } => { + let error_region = self.regioncx.region_from_element(longer_fr, error_element); + + // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. + let (_, span) = self.regioncx.find_outlives_blame_span( + &self.body, + longer_fr, + fr_origin, + error_region, + ); + + // FIXME: improve this error message + self.infcx + .tcx + .sess + .struct_span_err(span, "higher-ranked subtype error") + .buffer(&mut self.errors_buffer); + } - // Member constraints can also give rise to `'r: 'x` edges that - // were not part of the graph initially, so watch out for those. - // (But they are extremely rare; this loop is very cold.) - for constraint in self.applied_member_constraints(r) { - let p_c = &self.member_constraints[constraint.member_constraint_index]; - let constraint = OutlivesConstraint { - sup: r, - sub: constraint.min_choice, - locations: Locations::All(p_c.definition_span), - category: ConstraintCategory::OpaqueType, - }; - handle_constraint(constraint); + RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { + if is_reported { + self.report_region_error( + longer_fr, + fr_origin, + shorter_fr, + &mut outlives_suggestion, + ); + } else { + // We only report the first error, so as not to overwhelm the user. See + // `RegRegionErrorKind` docs. + // + // FIXME: currently we do nothing with these, but perhaps we can do better? + // FIXME: try collecting these constraints on the outlives suggestion + // builder. Does it make the suggestions any better? + debug!( + "Unreported region error: can't prove that {:?}: {:?}", + longer_fr, shorter_fr + ); + } + } } } - None + // Emit one outlives suggestions for each MIR def we borrowck + outlives_suggestion.add_suggestion(self); } /// Report an error because the universal region `fr` was required to outlive @@ -429,38 +269,38 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` /// /// Here we would be invoked with `fr = 'a` and `outlived_fr = `'b`. - pub(in crate::borrow_check) fn report_error<'a>( - &'a self, - mbcx: &MirBorrowckCtxt<'a, 'tcx>, + pub(in crate::borrow_check) fn report_region_error( + &mut self, fr: RegionVid, fr_origin: NLLRegionVariableOrigin, outlived_fr: RegionVid, outlives_suggestion: &mut OutlivesSuggestionBuilder, - renctx: &mut RegionErrorNamingCtx, - ) -> DiagnosticBuilder<'a> { - debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); + ) { + debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let (category, _, span) = self.best_blame_constraint(&mbcx.body, fr, fr_origin, |r| { - self.provides_universal_region(r, fr, outlived_fr) - }); + let (category, _, span) = + self.regioncx.best_blame_constraint(&self.body, fr, fr_origin, |r| { + self.regioncx.provides_universal_region(r, fr, outlived_fr) + }); - debug!("report_error: category={:?} {:?}", category, span); + debug!("report_region_error: category={:?} {:?}", category, span); // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - let tables = mbcx.infcx.tcx.typeck_tables_of(mbcx.mir_def_id); - let nice = NiceRegionError::new_from_span(mbcx.infcx, span, o, f, Some(tables)); + let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id); + let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables)); if let Some(diag) = nice.try_report_from_nll() { - return diag; + diag.buffer(&mut self.errors_buffer); + return; } } let (fr_is_local, outlived_fr_is_local): (bool, bool) = ( - self.universal_regions.is_local_free_region(fr), - self.universal_regions.is_local_free_region(outlived_fr), + self.regioncx.universal_regions().is_local_free_region(fr), + self.regioncx.universal_regions().is_local_free_region(outlived_fr), ); debug!( - "report_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}", + "report_region_error: fr_is_local={:?} outlived_fr_is_local={:?} category={:?}", fr_is_local, outlived_fr_is_local, category ); @@ -473,52 +313,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { span, }; - match (category, fr_is_local, outlived_fr_is_local) { - (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(mbcx.infcx, fr) => { - self.report_fnmut_error(mbcx, &errci, renctx) + let diag = match (category, fr_is_local, outlived_fr_is_local) { + (ConstraintCategory::Return, true, false) if self.is_closure_fn_mut(fr) => { + self.report_fnmut_error(&errci) } (ConstraintCategory::Assignment, true, false) | (ConstraintCategory::CallArgument, true, false) => { - let mut db = self.report_escaping_data_error(mbcx, &errci, renctx); + let mut db = self.report_escaping_data_error(&errci); - outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db); + outlives_suggestion.intermediate_suggestion(self, &errci, &mut db); outlives_suggestion.collect_constraint(fr, outlived_fr); db } _ => { - let mut db = self.report_general_error(mbcx, &errci, renctx); + let mut db = self.report_general_error(&errci); - outlives_suggestion.intermediate_suggestion(mbcx, &errci, renctx, &mut db); + outlives_suggestion.intermediate_suggestion(self, &errci, &mut db); outlives_suggestion.collect_constraint(fr, outlived_fr); db } - } - } - - /// We have a constraint `fr1: fr2` that is not satisfied, where - /// `fr2` represents some universal region. Here, `r` is some - /// region where we know that `fr1: r` and this function has the - /// job of determining whether `r` is "to blame" for the fact that - /// `fr1: fr2` is required. - /// - /// This is true under two conditions: - /// - /// - `r == fr2` - /// - `fr2` is `'static` and `r` is some placeholder in a universe - /// that cannot be named by `fr1`; in that case, we will require - /// that `fr1: 'static` because it is the only way to `fr1: r` to - /// be satisfied. (See `add_incompatible_universe`.) - fn provides_universal_region(&self, r: RegionVid, fr1: RegionVid, fr2: RegionVid) -> bool { - debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2); - let result = { - r == fr2 || { - fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r) - } }; - debug!("provides_universal_region: result = {:?}", result); - result + + diag.buffer(&mut self.errors_buffer); } /// Report a specialized error when `FnMut` closures return a reference to a captured variable. @@ -537,15 +355,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// executing... /// = note: ...therefore, returned references to captured variables will escape the closure /// ``` - fn report_fnmut_error( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - errci: &ErrorConstraintInfo, - renctx: &mut RegionErrorNamingCtx, - ) -> DiagnosticBuilder<'_> { + fn report_fnmut_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; - let mut diag = mbcx + let mut diag = self .infcx .tcx .sess @@ -553,7 +366,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { // We should check if the return type of this closure is in fact a closure - in that // case, we can special case the error further. - let return_type_is_closure = self.universal_regions.unnormalized_output_ty.is_closure(); + let return_type_is_closure = + self.regioncx.universal_regions().unnormalized_output_ty.is_closure(); let message = if return_type_is_closure { "returns a closure that contains a reference to a captured variable, which then \ escapes the closure body" @@ -563,7 +377,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag.span_label(*span, message); - match self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap().source { + match self.give_region_a_name(*outlived_fr).unwrap().source { RegionNameSource::NamedEarlyBoundRegion(fr_span) | RegionNameSource::NamedFreeRegion(fr_span) | RegionNameSource::SynthesizedFreeEnvRegion(fr_span, _) @@ -598,30 +412,25 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// LL | ref_obj(x) /// | ^^^^^^^^^^ `x` escapes the function body here /// ``` - fn report_escaping_data_error( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - errci: &ErrorConstraintInfo, - renctx: &mut RegionErrorNamingCtx, - ) -> DiagnosticBuilder<'_> { + fn report_escaping_data_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { span, category, .. } = errci; - let fr_name_and_span = self.get_var_name_and_span_for_region( - mbcx.infcx.tcx, - &mbcx.body, - &mbcx.local_names, - &mbcx.upvars, + let fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( + self.infcx.tcx, + &self.body, + &self.local_names, + &self.upvars, errci.fr, ); - let outlived_fr_name_and_span = self.get_var_name_and_span_for_region( - mbcx.infcx.tcx, - &mbcx.body, - &mbcx.local_names, - &mbcx.upvars, + let outlived_fr_name_and_span = self.regioncx.get_var_name_and_span_for_region( + self.infcx.tcx, + &self.body, + &self.local_names, + &self.upvars, errci.outlived_fr, ); - let escapes_from = match self.universal_regions.defining_ty { + let escapes_from = match self.regioncx.universal_regions().defining_ty { DefiningTy::Closure(..) => "closure", DefiningTy::Generator(..) => "generator", DefiningTy::FnDef(..) => "function", @@ -634,15 +443,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { || (*category == ConstraintCategory::Assignment && escapes_from == "function") || escapes_from == "const" { - return self.report_general_error( - mbcx, - &ErrorConstraintInfo { fr_is_local: true, outlived_fr_is_local: false, ..*errci }, - renctx, - ); + return self.report_general_error(&ErrorConstraintInfo { + fr_is_local: true, + outlived_fr_is_local: false, + ..*errci + }); } let mut diag = - borrowck_errors::borrowed_data_escapes_closure(mbcx.infcx.tcx, *span, escapes_from); + borrowck_errors::borrowed_data_escapes_closure(self.infcx.tcx, *span, escapes_from); if let Some((Some(outlived_fr_name), outlived_fr_span)) = outlived_fr_name_and_span { diag.span_label( @@ -684,12 +493,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// | ^^^^^^^^^^^^^^ function was supposed to return data with lifetime `'a` but it /// | is returning data with lifetime `'b` /// ``` - fn report_general_error( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - errci: &ErrorConstraintInfo, - renctx: &mut RegionErrorNamingCtx, - ) -> DiagnosticBuilder<'_> { + fn report_general_error(&self, errci: &ErrorConstraintInfo) -> DiagnosticBuilder<'tcx> { let ErrorConstraintInfo { fr, fr_is_local, @@ -701,14 +505,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { } = errci; let mut diag = - mbcx.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough"); + self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough"); let mir_def_name = - if mbcx.infcx.tcx.is_closure(mbcx.mir_def_id) { "closure" } else { "function" }; + if self.infcx.tcx.is_closure(self.mir_def_id) { "closure" } else { "function" }; - let fr_name = self.give_region_a_name(mbcx, renctx, *fr).unwrap(); + let fr_name = self.give_region_a_name(*fr).unwrap(); fr_name.highlight_region_name(&mut diag); - let outlived_fr_name = self.give_region_a_name(mbcx, renctx, *outlived_fr).unwrap(); + let outlived_fr_name = self.give_region_a_name(*outlived_fr).unwrap(); outlived_fr_name.highlight_region_name(&mut diag); match (category, outlived_fr_is_local, fr_is_local) { @@ -735,7 +539,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - self.add_static_impl_trait_suggestion(mbcx.infcx, &mut diag, *fr, fr_name, *outlived_fr); + self.add_static_impl_trait_suggestion(&mut diag, *fr, fr_name, *outlived_fr); diag } @@ -751,8 +555,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn add_static_impl_trait_suggestion( &self, - infcx: &InferCtxt<'_, 'tcx>, - diag: &mut DiagnosticBuilder<'_>, + diag: &mut DiagnosticBuilder<'tcx>, fr: RegionVid, // We need to pass `fr_name` - computing it again will label it twice. fr_name: RegionName, @@ -761,11 +564,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let (Some(f), Some(ty::RegionKind::ReStatic)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. }, _)) = infcx + if let Some((ty::TyS { kind: ty::Opaque(did, substs), .. }, _)) = self + .infcx .tcx .is_suitable_region(f) .map(|r| r.def_id) - .map(|id| infcx.tcx.return_type_impl_trait(id)) + .map(|id| self.infcx.tcx.return_type_impl_trait(id)) .unwrap_or(None) { // Check whether or not the impl trait return type is intended to capture @@ -773,8 +577,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { // // eg. check for `impl Trait + 'static` instead of `impl Trait`. let has_static_predicate = { - let predicates_of = infcx.tcx.predicates_of(*did); - let bounds = predicates_of.instantiate(infcx.tcx, substs); + let predicates_of = self.infcx.tcx.predicates_of(*did); + let bounds = predicates_of.instantiate(self.infcx.tcx, substs); let mut found = false; for predicate in bounds.predicates { @@ -802,8 +606,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { diag.help(&format!("consider replacing `{}` with `{}`", fr_name, static_str)); } else { // Otherwise, we should suggest adding a constraint on the return type. - let span = infcx.tcx.def_span(*did); - if let Ok(snippet) = infcx.tcx.sess.source_map().span_to_snippet(span) { + let span = self.infcx.tcx.def_span(*did); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { let suggestable_fr_name = if fr_name.was_named() { fr_name.to_string() } else { @@ -830,130 +634,4 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } } - - crate fn free_region_constraint_info( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - borrow_region: RegionVid, - outlived_region: RegionVid, - ) -> (ConstraintCategory, bool, Span, Option<RegionName>) { - let (category, from_closure, span) = self.best_blame_constraint( - &mbcx.body, - borrow_region, - NLLRegionVariableOrigin::FreeRegion, - |r| self.provides_universal_region(r, borrow_region, outlived_region), - ); - - let mut renctx = RegionErrorNamingCtx::new(); - let outlived_fr_name = self.give_region_a_name(mbcx, &mut renctx, outlived_region); - - (category, from_closure, span, outlived_fr_name) - } - - // Finds some region R such that `fr1: R` and `R` is live at - // `elem`. - crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { - debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem); - self.find_constraint_paths_between_regions(fr1, |r| { - // First look for some `r` such that `fr1: r` and `r` is live at `elem` - debug!( - "find_sub_region_live_at: liveness_constraints for {:?} are {:?}", - r, - self.liveness_constraints.region_value_str(r), - ); - self.liveness_constraints.contains(r, elem) - }) - .or_else(|| { - // If we fail to find that, we may find some `r` such that - // `fr1: r` and `r` is a placeholder from some universe - // `fr1` cannot name. This would force `fr1` to be - // `'static`. - self.find_constraint_paths_between_regions(fr1, |r| { - self.cannot_name_placeholder(fr1, r) - }) - }) - .or_else(|| { - // If we fail to find THAT, it may be that `fr1` is a - // placeholder that cannot "fit" into its SCC. In that - // case, there should be some `r` where `fr1: r`, both - // `fr1` and `r` are in the same SCC, and `fr1` is a - // placeholder that `r` cannot name. We can blame that - // edge. - self.find_constraint_paths_between_regions(fr1, |r| { - self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r) - && self.cannot_name_placeholder(r, fr1) - }) - }) - .map(|(_path, r)| r) - .unwrap() - } - - // Finds a good span to blame for the fact that `fr1` outlives `fr2`. - crate fn find_outlives_blame_span( - &self, - body: &Body<'tcx>, - fr1: RegionVid, - fr1_origin: NLLRegionVariableOrigin, - fr2: RegionVid, - ) -> (ConstraintCategory, Span) { - let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| { - self.provides_universal_region(r, fr1, fr2) - }); - (category, span) - } - - fn retrieve_closure_constraint_info( - &self, - body: &Body<'tcx>, - constraint: &OutlivesConstraint, - ) -> (ConstraintCategory, bool, Span) { - let loc = match constraint.locations { - Locations::All(span) => return (constraint.category, false, span), - Locations::Single(loc) => loc, - }; - - let opt_span_category = - self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)); - opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or(( - constraint.category, - false, - body.source_info(loc).span, - )) - } - - /// Returns `true` if a closure is inferred to be an `FnMut` closure. - crate fn is_closure_fn_mut(&self, infcx: &InferCtxt<'_, 'tcx>, fr: RegionVid) -> bool { - if let Some(ty::ReFree(free_region)) = self.to_error_region(fr) { - if let ty::BoundRegion::BrEnv = free_region.bound_region { - if let DefiningTy::Closure(def_id, substs) = self.universal_regions.defining_ty { - let closure_kind_ty = substs.as_closure().kind_ty(def_id, infcx.tcx); - return Some(ty::ClosureKind::FnMut) == closure_kind_ty.to_opt_closure_kind(); - } - } - } - - false - } - - /// If `r2` represents a placeholder region, then this returns - /// `true` if `r1` cannot name that placeholder in its - /// value; otherwise, returns `false`. - fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool { - debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2); - - match self.definitions[r2].origin { - NLLRegionVariableOrigin::Placeholder(placeholder) => { - let universe1 = self.definitions[r1].universe; - debug!( - "cannot_name_value_of: universe1={:?} placeholder={:?}", - universe1, placeholder - ); - universe1.cannot_name(placeholder.universe) - } - - NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => { - false - } - } - } } diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 734e3861c62..47eb2d8940a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -2,18 +2,14 @@ use std::fmt::{self, Display}; use rustc::ty::print::RegionHighlightMode; use rustc::ty::subst::{GenericArgKind, SubstsRef}; -use rustc::ty::{self, RegionVid, Ty, TyCtxt}; -use rustc_data_structures::fx::FxHashMap; +use rustc::ty::{self, RegionVid, Ty}; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_span::symbol::kw; use rustc_span::{symbol::Symbol, Span, DUMMY_SP}; -use crate::borrow_check::{ - nll::ToRegionVid, region_infer::RegionInferenceContext, universal_regions::DefiningTy, - MirBorrowckCtxt, -}; +use crate::borrow_check::{nll::ToRegionVid, universal_regions::DefiningTy, MirBorrowckCtxt}; /// A name for a particular region used in emitting diagnostics. This name could be a generated /// name like `'1`, a name used by the user like `'a`, or a name like `'static`. @@ -55,46 +51,6 @@ crate enum RegionNameSource { AnonRegionFromAsyncFn(Span), } -/// Records region names that have been assigned before so that we can use the same ones in later -/// diagnostics. -#[derive(Debug, Clone)] -crate struct RegionErrorNamingCtx { - /// Record the region names generated for each region in the given - /// MIR def so that we can reuse them later in help/error messages. - renctx: FxHashMap<RegionVid, RegionName>, - - /// The counter for generating new region names. - counter: usize, -} - -impl RegionErrorNamingCtx { - crate fn new() -> Self { - Self { counter: 1, renctx: FxHashMap::default() } - } - - /// Get the name of `region` if it has previously been named. - crate fn get(&self, region: &RegionVid) -> Option<&RegionName> { - self.renctx.get(region) - } - - /// Give `region` the name `name`. - crate fn insert(&mut self, region: RegionVid, name: RegionName) { - self.renctx.insert(region, name); - } - - /// Creates a synthetic region named `'N`, where `N` is the next value of the counter. Then, - /// increment the counter. - /// - /// The name is not memoized. A separate call to `insert` should be made later. (Currently, - /// this happens at the end of `give_region_a_name`). - crate fn synthesize_region_name(&mut self) -> Symbol { - let c = self.counter; - self.counter += 1; - - Symbol::intern(&format!("'{:?}", c)) - } -} - impl RegionName { crate fn was_named(&self) -> bool { match self.source { @@ -161,7 +117,16 @@ impl Display for RegionName { } } -impl<'tcx> RegionInferenceContext<'tcx> { +impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { + /// Generate a synthetic region named `'N`, where `N` is the next value of the counter. Then, + /// increment the counter. + /// + /// This is _not_ idempotent. Call `give_region_a_name` when possible. + fn synthesize_region_name(&self) -> Symbol { + let c = self.next_region_name.replace_with(|counter| *counter + 1); + Symbol::intern(&format!("'{:?}", c)) + } + /// Maps from an internal MIR region vid to something that we can /// report to the user. In some cases, the region vids will map /// directly to lifetimes that the user has a name for (e.g., @@ -170,6 +135,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// that end, this function takes a "diagnostic" so that it can /// create auxiliary notes as needed. /// + /// The names are memoized, so this is both cheap to recompute and idempotent. + /// /// Example (function arguments): /// /// Suppose we are trying to give a name to the lifetime of the @@ -187,29 +154,28 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` /// /// and then return the name `'1` for us to use. - crate fn give_region_a_name( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - renctx: &mut RegionErrorNamingCtx, - fr: RegionVid, - ) -> Option<RegionName> { - debug!("give_region_a_name(fr={:?}, counter={:?})", fr, renctx.counter); + crate fn give_region_a_name(&self, fr: RegionVid) -> Option<RegionName> { + debug!( + "give_region_a_name(fr={:?}, counter={:?})", + fr, + self.next_region_name.try_borrow().unwrap() + ); - assert!(self.universal_regions.is_universal_region(fr)); + assert!(self.regioncx.universal_regions().is_universal_region(fr)); - if let Some(value) = renctx.get(&fr) { + if let Some(value) = self.region_names.try_borrow_mut().unwrap().get(&fr) { return Some(value.clone()); } let value = self - .give_name_from_error_region(mbcx, fr, renctx) - .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(mbcx, fr, renctx)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(mbcx, fr, renctx)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_output(mbcx, fr, renctx)) - .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(mbcx, fr, renctx)); + .give_name_from_error_region(fr) + .or_else(|| self.give_name_if_anonymous_region_appears_in_arguments(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_upvars(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_output(fr)) + .or_else(|| self.give_name_if_anonymous_region_appears_in_yield_ty(fr)); if let Some(ref value) = value { - renctx.insert(fr, value.clone()); + self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); } debug!("give_region_a_name: gave name {:?}", value); @@ -220,15 +186,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// *user* has a name for. In that case, we'll be able to map /// `fr` to a `Region<'tcx>`, and that region will be one of /// named variants. - fn give_name_from_error_region( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, - ) -> Option<RegionName> { + fn give_name_from_error_region(&self, fr: RegionVid) -> Option<RegionName> { let error_region = self.to_error_region(fr)?; - let tcx = mbcx.infcx.tcx; + let tcx = self.infcx.tcx; debug!("give_region_a_name: error_region = {:?}", error_region); match error_region { @@ -267,7 +228,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // happen if we have an elided name in an async fn for example: the // compiler will generate a region named `'_`, but reporting such a name is // not actually useful, so we synthesize a name for it instead. - let name = renctx.synthesize_region_name(); + let name = self.synthesize_region_name(); Some(RegionName { name, source: RegionNameSource::AnonRegionFromAsyncFn(span), @@ -276,13 +237,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { } ty::BoundRegion::BrEnv => { - let mir_hir_id = mbcx + let mir_hir_id = self .infcx .tcx .hir() - .as_local_hir_id(mbcx.mir_def_id) + .as_local_hir_id(self.mir_def_id) .expect("non-local mir"); - let def_ty = self.universal_regions.defining_ty; + let def_ty = self.regioncx.universal_regions().defining_ty; if let DefiningTy::Closure(def_id, substs) = def_ty { let args_span = if let hir::ExprKind::Closure(_, _, _, span, _) = @@ -292,7 +253,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } else { bug!("Closure is not defined by a closure expr"); }; - let region_name = renctx.synthesize_region_name(); + let region_name = self.synthesize_region_name(); let closure_kind_ty = substs.as_closure().kind_ty(def_id, tcx); let note = match closure_kind_ty.to_opt_closure_kind() { @@ -346,38 +307,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn give_name_if_anonymous_region_appears_in_arguments( &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, ) -> Option<RegionName> { - let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); - let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, fr)?; - - let arg_ty = - self.universal_regions.unnormalized_input_tys[implicit_inputs + argument_index]; - if let Some(region_name) = self.give_name_if_we_can_match_hir_ty_from_argument( - mbcx, - fr, - arg_ty, - argument_index, - renctx, - ) { + let implicit_inputs = self.regioncx.universal_regions().defining_ty.implicit_inputs(); + let argument_index = self.regioncx.get_argument_index_for_region(self.infcx.tcx, fr)?; + + let arg_ty = self.regioncx.universal_regions().unnormalized_input_tys + [implicit_inputs + argument_index]; + if let Some(region_name) = + self.give_name_if_we_can_match_hir_ty_from_argument(fr, arg_ty, argument_index) + { return Some(region_name); } - self.give_name_if_we_cannot_match_hir_ty(mbcx, fr, arg_ty, renctx) + self.give_name_if_we_cannot_match_hir_ty(fr, arg_ty) } fn give_name_if_we_can_match_hir_ty_from_argument( &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, needle_fr: RegionVid, argument_ty: Ty<'tcx>, argument_index: usize, - renctx: &mut RegionErrorNamingCtx, ) -> Option<RegionName> { - let mir_hir_id = mbcx.infcx.tcx.hir().as_local_hir_id(mbcx.mir_def_id)?; - let fn_decl = mbcx.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?; + let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id)?; + let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?; let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?; match argument_hir_ty.kind { // This indicates a variable with no type annotation, like @@ -387,13 +340,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // (`give_name_if_anonymous_region_appears_in_arguments`). hir::TyKind::Infer => None, - _ => self.give_name_if_we_can_match_hir_ty( - mbcx.infcx.tcx, - needle_fr, - argument_ty, - argument_hir_ty, - renctx, - ), + _ => self.give_name_if_we_can_match_hir_ty(needle_fr, argument_ty, argument_hir_ty), } } @@ -410,15 +357,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// ``` fn give_name_if_we_cannot_match_hir_ty( &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, needle_fr: RegionVid, argument_ty: Ty<'tcx>, - renctx: &mut RegionErrorNamingCtx, ) -> Option<RegionName> { - let counter = renctx.counter; + let counter = *self.next_region_name.try_borrow().unwrap(); let mut highlight = RegionHighlightMode::default(); highlight.highlighting_region_vid(needle_fr, counter); - let type_name = mbcx.infcx.extract_type_name(&argument_ty, Some(highlight)).0; + let type_name = self.infcx.extract_type_name(&argument_ty, Some(highlight)).0; debug!( "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -426,10 +371,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); let assigned_region_name = if type_name.find(&format!("'{}", counter)).is_some() { // Only add a label if we can confirm that a region was labelled. - let argument_index = self.get_argument_index_for_region(mbcx.infcx.tcx, needle_fr)?; - let (_, span) = self.get_argument_name_and_span_for_region( - &mbcx.body, - &mbcx.local_names, + let argument_index = + self.regioncx.get_argument_index_for_region(self.infcx.tcx, needle_fr)?; + let (_, span) = self.regioncx.get_argument_name_and_span_for_region( + &self.body, + &self.local_names, argument_index, ); @@ -437,7 +383,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // This counter value will already have been used, so this function will increment // it so the next value will be used next and return the region name that would // have been used. - name: renctx.synthesize_region_name(), + name: self.synthesize_region_name(), source: RegionNameSource::CannotMatchHirTy(span, type_name), }) } else { @@ -470,11 +416,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// to highlighting that closest type instead. fn give_name_if_we_can_match_hir_ty( &self, - tcx: TyCtxt<'tcx>, needle_fr: RegionVid, argument_ty: Ty<'tcx>, argument_hir_ty: &hir::Ty<'_>, - renctx: &mut RegionErrorNamingCtx, ) -> Option<RegionName> { let search_stack: &mut Vec<(Ty<'tcx>, &hir::Ty<'_>)> = &mut vec![(argument_ty, argument_hir_ty)]; @@ -492,10 +436,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { hir::TyKind::Rptr(_lifetime, referent_hir_ty), ) => { if region.to_region_vid() == needle_fr { - let region_name = renctx.synthesize_region_name(); + let region_name = self.synthesize_region_name(); // Just grab the first character, the `&`. - let source_map = tcx.sess.source_map(); + let source_map = self.infcx.tcx.sess.source_map(); let ampersand_span = source_map.start_point(hir_ty.span); return Some(RegionName { @@ -525,7 +469,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { substs, needle_fr, last_segment, - renctx, search_stack, ) { return Some(name); @@ -570,7 +513,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { substs: SubstsRef<'tcx>, needle_fr: RegionVid, last_segment: &'hir hir::PathSegment<'hir>, - renctx: &mut RegionErrorNamingCtx, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, ) -> Option<RegionName> { // Did the user give explicit arguments? (e.g., `Foo<..>`) @@ -582,7 +524,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { | hir::LifetimeName::Error | hir::LifetimeName::Static | hir::LifetimeName::Underscore => { - let region_name = renctx.synthesize_region_name(); + let region_name = self.synthesize_region_name(); let ampersand_span = lifetime.span; Some(RegionName { name: region_name, @@ -663,16 +605,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// | let x = Some(&22); /// - fully elaborated type of `x` is `Option<&'1 u32>` /// ``` - fn give_name_if_anonymous_region_appears_in_upvars( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, - ) -> Option<RegionName> { - let upvar_index = self.get_upvar_index_for_region(mbcx.infcx.tcx, fr)?; - let (upvar_name, upvar_span) = - self.get_upvar_name_and_span_for_region(mbcx.infcx.tcx, &mbcx.upvars, upvar_index); - let region_name = renctx.synthesize_region_name(); + fn give_name_if_anonymous_region_appears_in_upvars(&self, fr: RegionVid) -> Option<RegionName> { + let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?; + let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( + self.infcx.tcx, + &self.upvars, + upvar_index, + ); + let region_name = self.synthesize_region_name(); Some(RegionName { name: region_name, @@ -684,25 +624,20 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// must be a closure since, in a free fn, such an argument would /// have to either also appear in an argument (if using elision) /// or be early bound (named, not in argument). - fn give_name_if_anonymous_region_appears_in_output( - &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, - fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, - ) -> Option<RegionName> { - let tcx = mbcx.infcx.tcx; + fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option<RegionName> { + let tcx = self.infcx.tcx; - let return_ty = self.universal_regions.unnormalized_output_ty; + let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { return None; } let mut highlight = RegionHighlightMode::default(); - highlight.highlighting_region_vid(fr, renctx.counter); - let type_name = mbcx.infcx.extract_type_name(&return_ty, Some(highlight)).0; + highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); + let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0; - let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir"); + let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir"); let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) { hir::Node::Expr(hir::Expr { @@ -719,14 +654,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { kind: hir::ImplItemKind::Method(method_sig, _), .. }) => (method_sig.decl.output.span(), ""), - _ => (mbcx.body.span, ""), + _ => (self.body.span, ""), }; Some(RegionName { // This counter value will already have been used, so this function will increment it // so the next value will be used next and return the region name that would have been // used. - name: renctx.synthesize_region_name(), + name: self.synthesize_region_name(), source: RegionNameSource::AnonRegionFromOutput( return_span, mir_description.to_string(), @@ -737,32 +672,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn give_name_if_anonymous_region_appears_in_yield_ty( &self, - mbcx: &MirBorrowckCtxt<'_, 'tcx>, fr: RegionVid, - renctx: &mut RegionErrorNamingCtx, ) -> Option<RegionName> { // Note: generators from `async fn` yield `()`, so we don't have to // worry about them here. - let yield_ty = self.universal_regions.yield_ty?; + let yield_ty = self.regioncx.universal_regions().yield_ty?; debug!("give_name_if_anonymous_region_appears_in_yield_ty: yield_ty = {:?}", yield_ty,); - let tcx = mbcx.infcx.tcx; + let tcx = self.infcx.tcx; if !tcx.any_free_region_meets(&yield_ty, |r| r.to_region_vid() == fr) { return None; } let mut highlight = RegionHighlightMode::default(); - highlight.highlighting_region_vid(fr, renctx.counter); - let type_name = mbcx.infcx.extract_type_name(&yield_ty, Some(highlight)).0; + highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap()); + let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0; - let mir_hir_id = tcx.hir().as_local_hir_id(mbcx.mir_def_id).expect("non-local mir"); + let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id).expect("non-local mir"); let yield_span = match tcx.hir().get(mir_hir_id) { hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, _, _, span, _), .. }) => (tcx.sess.source_map().end_point(*span)), - _ => mbcx.body.span, + _ => self.body.span, }; debug!( @@ -772,7 +705,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ); Some(RegionName { - name: renctx.synthesize_region_name(), + name: self.synthesize_region_name(), source: RegionNameSource::AnonRegionFromYieldTy(yield_span, type_name), }) } diff --git a/src/librustc_mir/borrow_check/diagnostics/var_name.rs b/src/librustc_mir/borrow_check/diagnostics/var_name.rs index 9e3d2a7d5f6..5f3585ce8b1 100644 --- a/src/librustc_mir/borrow_check/diagnostics/var_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/var_name.rs @@ -16,7 +16,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, ) -> Option<(Option<Symbol>, Span)> { debug!("get_var_name_and_span_for_region(fr={:?})", fr); - assert!(self.universal_regions.is_universal_region(fr)); + assert!(self.universal_regions().is_universal_region(fr)); debug!("get_var_name_and_span_for_region: attempting upvar"); self.get_upvar_index_for_region(tcx, fr) @@ -35,7 +35,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Search the upvars (if any) to find one that references fr. Return its index. crate fn get_upvar_index_for_region(&self, tcx: TyCtxt<'tcx>, fr: RegionVid) -> Option<usize> { let upvar_index = - self.universal_regions.defining_ty.upvar_tys(tcx).position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys(tcx).position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty); tcx.any_free_region_meets(&upvar_ty, |r| { let r = r.to_region_vid(); @@ -44,7 +44,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) })?; - let upvar_ty = self.universal_regions.defining_ty.upvar_tys(tcx).nth(upvar_index); + let upvar_ty = self.universal_regions().defining_ty.upvar_tys(tcx).nth(upvar_index); debug!( "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}", @@ -85,9 +85,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { tcx: TyCtxt<'tcx>, fr: RegionVid, ) -> Option<usize> { - let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); + let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); let argument_index = - self.universal_regions.unnormalized_input_tys.iter().skip(implicit_inputs).position( + self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position( |arg_ty| { debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty); tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) @@ -96,7 +96,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!( "get_argument_index_for_region: found {:?} in argument {} which has type {:?}", - fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index], + fr, + argument_index, + self.universal_regions().unnormalized_input_tys[argument_index], ); Some(argument_index) @@ -110,7 +112,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { local_names: &IndexVec<Local, Option<Symbol>>, argument_index: usize, ) -> (Option<Symbol>, Span) { - let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); + let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); let argument_local = Local::new(implicit_inputs + argument_index + 1); debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 7b0a103fd00..90927069242 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1,6 +1,6 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. -use rustc::infer::{opaque_types, InferCtxt}; +use rustc::infer::InferCtxt; use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT; use rustc::lint::builtin::UNUSED_MUT; use rustc::mir::{ @@ -11,7 +11,8 @@ use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, RegionVid, TyCtxt}; + use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; @@ -21,6 +22,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use smallvec::SmallVec; +use std::cell::RefCell; use std::collections::BTreeMap; use std::mem; use std::rc::Rc; @@ -39,9 +41,7 @@ use crate::dataflow::{do_dataflow, DebugFormatted}; use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use crate::transform::MirSource; -use self::diagnostics::{ - AccessKind, OutlivesSuggestionBuilder, RegionErrorKind, RegionErrorNamingCtx, RegionErrors, -}; +use self::diagnostics::{AccessKind, RegionName}; use self::flows::Flows; use self::location::LocationTable; use self::prefixes::PrefixSet; @@ -285,13 +285,15 @@ fn do_mir_borrowck<'a, 'tcx>( move_error_reported: BTreeMap::new(), uninitialized_error_reported: Default::default(), errors_buffer, - nonlexical_regioncx: regioncx, + regioncx, used_mut: Default::default(), used_mut_upvars: SmallVec::new(), borrow_set, dominators, upvars, local_names, + region_names: RefCell::default(), + next_region_name: RefCell::new(1), }; // Compute and report region errors, if any. @@ -476,10 +478,9 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { /// If the function we're checking is a closure, then we'll need to report back the list of /// mutable upvars that have been used. This field keeps track of them. used_mut_upvars: SmallVec<[Field; 8]>, - /// Non-lexical region inference context, if NLL is enabled. This - /// contains the results from region inference and lets us e.g. + /// Region inference context. This contains the results from region inference and lets us e.g. /// find out which CFG points are contained in each borrow region. - nonlexical_regioncx: Rc<RegionInferenceContext<'tcx>>, + regioncx: Rc<RegionInferenceContext<'tcx>>, /// The set of borrows extracted from the MIR borrow_set: Rc<BorrowSet<'tcx>>, @@ -492,6 +493,13 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { /// Names of local (user) variables (extracted from `var_debug_info`). local_names: IndexVec<Local, Option<Name>>, + + /// Record the region names generated for each region in the given + /// MIR def so that we can reuse them later in help/error messages. + region_names: RefCell<FxHashMap<RegionVid, RegionName>>, + + /// The counter for generating new region names. + next_region_name: RefCell<usize>, } // Check that: @@ -631,7 +639,7 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx debug!( "visit_terminator_drop \ - loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}", + loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}", loc, term, drop_place, drop_place_ty, span ); @@ -1465,120 +1473,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // initial reservation. } } - - /// Produces nice borrowck error diagnostics for all the errors collected in `nll_errors`. - fn report_region_errors(&mut self, nll_errors: RegionErrors<'tcx>) { - // Iterate through all the errors, producing a diagnostic for each one. The diagnostics are - // buffered in the `MirBorrowckCtxt`. - - // FIXME(mark-i-m): Would be great to get rid of the naming context. - let mut region_naming = RegionErrorNamingCtx::new(); - let mut outlives_suggestion = OutlivesSuggestionBuilder::default(); - - for nll_error in nll_errors.into_iter() { - match nll_error { - RegionErrorKind::TypeTestDoesNotLiveLongEnough { span, generic } => { - // FIXME. We should handle this case better. It - // indicates that we have e.g., some region variable - // whose value is like `'a+'b` where `'a` and `'b` are - // distinct unrelated univesal regions that are not - // known to outlive one another. It'd be nice to have - // some examples where this arises to decide how best - // to report it; we could probably handle it by - // iterating over the universal regions and reporting - // an error that multiple bounds are required. - self.infcx - .tcx - .sess - .struct_span_err(span, &format!("`{}` does not live long enough", generic)) - .buffer(&mut self.errors_buffer); - } - - RegionErrorKind::TypeTestGenericBoundError { - span, - generic, - lower_bound_region, - } => { - let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); - self.infcx - .construct_generic_bound_failure( - region_scope_tree, - span, - None, - generic, - lower_bound_region, - ) - .buffer(&mut self.errors_buffer); - } - - RegionErrorKind::UnexpectedHiddenRegion { - opaque_type_def_id, - hidden_ty, - member_region, - } => { - let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); - opaque_types::unexpected_hidden_region_diagnostic( - self.infcx.tcx, - Some(region_scope_tree), - opaque_type_def_id, - hidden_ty, - member_region, - ) - .buffer(&mut self.errors_buffer); - } - - RegionErrorKind::BoundUniversalRegionError { - longer_fr, - fr_origin, - error_region, - } => { - // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let (_, span) = self.nonlexical_regioncx.find_outlives_blame_span( - &self.body, - longer_fr, - fr_origin, - error_region, - ); - - // FIXME: improve this error message - self.infcx - .tcx - .sess - .struct_span_err(span, "higher-ranked subtype error") - .buffer(&mut self.errors_buffer); - } - - RegionErrorKind::RegionError { fr_origin, longer_fr, shorter_fr, is_reported } => { - if is_reported { - let db = self.nonlexical_regioncx.report_error( - self, - longer_fr, - fr_origin, - shorter_fr, - &mut outlives_suggestion, - &mut region_naming, - ); - - db.buffer(&mut self.errors_buffer); - } else { - // We only report the first error, so as not to overwhelm the user. See - // `RegRegionErrorKind` docs. - // - // FIXME: currently we do nothing with these, but perhaps we can do better? - // FIXME: try collecting these constraints on the outlives suggestion - // builder. Does it make the suggestions any better? - debug!( - "Unreported region error: can't prove that {:?}: {:?}", - longer_fr, shorter_fr - ); - } - } - } - } - - // Emit one outlives suggestions for each MIR def we borrowck - outlives_suggestion.add_suggestion(self, &mut region_naming); - } } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { @@ -2225,7 +2119,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let upvar = &self.upvars[field.index()]; debug!( "upvar.mutability={:?} local_mutation_is_allowed={:?} \ - place={:?}", + place={:?}", upvar, is_local_mutation_allowed, place ); match (upvar.mutability, is_local_mutation_allowed) { diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 7d2384f8a7d..26d9cf2e045 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -1,3 +1,4 @@ +use std::collections::VecDeque; use std::rc::Rc; use rustc::infer::canonical::QueryOutlivesConstraint; @@ -43,49 +44,48 @@ pub struct RegionInferenceContext<'tcx> { /// variables are identified by their index (`RegionVid`). The /// definition contains information about where the region came /// from as well as its final inferred value. - pub(in crate::borrow_check) definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>, + definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>, /// The liveness constraints added to each region. For most /// regions, these start out empty and steadily grow, though for /// each universally quantified region R they start out containing /// the entire CFG and `end(R)`. - pub(in crate::borrow_check) liveness_constraints: LivenessValues<RegionVid>, + liveness_constraints: LivenessValues<RegionVid>, /// The outlives constraints computed by the type-check. - pub(in crate::borrow_check) constraints: Rc<OutlivesConstraintSet>, + constraints: Rc<OutlivesConstraintSet>, /// The constraint-set, but in graph form, making it easy to traverse /// the constraints adjacent to a particular region. Used to construct /// the SCC (see `constraint_sccs`) and for error reporting. - pub(in crate::borrow_check) constraint_graph: Rc<NormalConstraintGraph>, + constraint_graph: Rc<NormalConstraintGraph>, /// The SCC computed from `constraints` and the constraint /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to /// compute the values of each region. - pub(in crate::borrow_check) constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>, + constraint_sccs: Rc<Sccs<RegionVid, ConstraintSccIndex>>, /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` /// exists if `B: A`. Computed lazilly. - pub(in crate::borrow_check) rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>, + rev_constraint_graph: Option<Rc<VecGraph<ConstraintSccIndex>>>, /// The "R0 member of [R1..Rn]" constraints, indexed by SCC. - pub(in crate::borrow_check) member_constraints: - Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>, + member_constraints: Rc<MemberConstraintSet<'tcx, ConstraintSccIndex>>, /// Records the member constraints that we applied to each scc. /// This is useful for error reporting. Once constraint /// propagation is done, this vector is sorted according to /// `member_region_scc`. - pub(in crate::borrow_check) member_constraints_applied: Vec<AppliedMemberConstraint>, + member_constraints_applied: Vec<AppliedMemberConstraint>, /// Map closure bounds to a `Span` that should be used for error reporting. - pub(in crate::borrow_check) closure_bounds_mapping: + closure_bounds_mapping: FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>, /// Contains the minimum universe of any variable within the same /// SCC. We will ensure that no SCC contains values that are not /// visible from this index. - pub(in crate::borrow_check) scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>, + scc_universes: IndexVec<ConstraintSccIndex, ty::UniverseIndex>, /// Contains a "representative" from each SCC. This will be the /// minimal RegionVid belonging to that universe. It is used as a @@ -94,23 +94,23 @@ pub struct RegionInferenceContext<'tcx> { /// of its SCC and be sure that -- if they have the same repr -- /// they *must* be equal (though not having the same repr does not /// mean they are unequal). - pub(in crate::borrow_check) scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>, + scc_representatives: IndexVec<ConstraintSccIndex, ty::RegionVid>, /// The final inferred values of the region variables; we compute /// one value per SCC. To get the value for any given *region*, /// you first find which scc it is a part of. - pub(in crate::borrow_check) scc_values: RegionValues<ConstraintSccIndex>, + scc_values: RegionValues<ConstraintSccIndex>, /// Type constraints that we check after solving. - pub(in crate::borrow_check) type_tests: Vec<TypeTest<'tcx>>, + type_tests: Vec<TypeTest<'tcx>>, /// Information about the universally quantified regions in scope /// on this function. - pub(in crate::borrow_check) universal_regions: Rc<UniversalRegions<'tcx>>, + universal_regions: Rc<UniversalRegions<'tcx>>, /// Information about how the universally quantified regions in /// scope on this function relate to one another. - pub(in crate::borrow_check) universal_region_relations: Rc<UniversalRegionRelations<'tcx>>, + universal_region_relations: Rc<UniversalRegionRelations<'tcx>>, } /// Each time that `apply_member_constraint` is successful, it appends @@ -225,6 +225,13 @@ enum RegionRelationCheckResult { Error, } +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +enum Trace { + StartRegion, + FromOutlivesConstraint(OutlivesConstraint), + NotVisited, +} + impl<'tcx> RegionInferenceContext<'tcx> { /// Creates a new region inference context with a total of /// `num_region_variables` valid inference variables; the first N @@ -838,39 +845,22 @@ impl<'tcx> RegionInferenceContext<'tcx> { } // Type-test failed. Report the error. - - // Try to convert the lower-bound region into something named we can print for the user. - let lower_bound_region = self.to_error_region(type_test.lower_bound); + let erased_generic_kind = infcx.tcx.erase_regions(&type_test.generic_kind); // Skip duplicate-ish errors. - let type_test_span = type_test.locations.span(body); - let erased_generic_kind = tcx.erase_regions(&type_test.generic_kind); - if !deduplicate_errors.insert(( + if deduplicate_errors.insert(( erased_generic_kind, - lower_bound_region, + type_test.lower_bound, type_test.locations, )) { - continue; - } else { debug!( "check_type_test: reporting error for erased_generic_kind={:?}, \ lower_bound_region={:?}, \ type_test.locations={:?}", - erased_generic_kind, lower_bound_region, type_test.locations, + erased_generic_kind, type_test.lower_bound, type_test.locations, ); - } - if let Some(lower_bound_region) = lower_bound_region { - errors_buffer.push(RegionErrorKind::TypeTestGenericBoundError { - span: type_test_span, - generic: type_test.generic_kind, - lower_bound_region, - }); - } else { - errors_buffer.push(RegionErrorKind::TypeTestDoesNotLiveLongEnough { - span: type_test_span, - generic: type_test.generic_kind, - }); + errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); } } } @@ -1355,7 +1345,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { for (longer_fr, shorter_fr) in subset_errors.into_iter() { debug!( "check_polonius_subset_errors: subset_error longer_fr={:?},\ - shorter_fr={:?}", + shorter_fr={:?}", longer_fr, shorter_fr ); @@ -1572,23 +1562,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("check_bound_universal_region: error_element = {:?}", error_element); // Find the region that introduced this `error_element`. - let error_region = match error_element { - RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), - RegionElement::RootUniversalRegion(r) => r, - RegionElement::PlaceholderRegion(error_placeholder) => self - .definitions - .iter_enumerated() - .filter_map(|(r, definition)| match definition.origin { - NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), - _ => None, - }) - .next() - .unwrap(), - }; - errors_buffer.push(RegionErrorKind::BoundUniversalRegionError { longer_fr, - error_region, + error_element, fr_origin: NLLRegionVariableOrigin::Placeholder(placeholder), }); } @@ -1628,6 +1604,425 @@ impl<'tcx> RegionInferenceContext<'tcx> { }); } } + + /// We have a constraint `fr1: fr2` that is not satisfied, where + /// `fr2` represents some universal region. Here, `r` is some + /// region where we know that `fr1: r` and this function has the + /// job of determining whether `r` is "to blame" for the fact that + /// `fr1: fr2` is required. + /// + /// This is true under two conditions: + /// + /// - `r == fr2` + /// - `fr2` is `'static` and `r` is some placeholder in a universe + /// that cannot be named by `fr1`; in that case, we will require + /// that `fr1: 'static` because it is the only way to `fr1: r` to + /// be satisfied. (See `add_incompatible_universe`.) + crate fn provides_universal_region( + &self, + r: RegionVid, + fr1: RegionVid, + fr2: RegionVid, + ) -> bool { + debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2); + let result = { + r == fr2 || { + fr2 == self.universal_regions.fr_static && self.cannot_name_placeholder(fr1, r) + } + }; + debug!("provides_universal_region: result = {:?}", result); + result + } + + /// If `r2` represents a placeholder region, then this returns + /// `true` if `r1` cannot name that placeholder in its + /// value; otherwise, returns `false`. + crate fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool { + debug!("cannot_name_value_of(r1={:?}, r2={:?})", r1, r2); + + match self.definitions[r2].origin { + NLLRegionVariableOrigin::Placeholder(placeholder) => { + let universe1 = self.definitions[r1].universe; + debug!( + "cannot_name_value_of: universe1={:?} placeholder={:?}", + universe1, placeholder + ); + universe1.cannot_name(placeholder.universe) + } + + NLLRegionVariableOrigin::FreeRegion | NLLRegionVariableOrigin::Existential { .. } => { + false + } + } + } + + crate fn retrieve_closure_constraint_info( + &self, + body: &Body<'tcx>, + constraint: &OutlivesConstraint, + ) -> (ConstraintCategory, bool, Span) { + let loc = match constraint.locations { + Locations::All(span) => return (constraint.category, false, span), + Locations::Single(loc) => loc, + }; + + let opt_span_category = + self.closure_bounds_mapping[&loc].get(&(constraint.sup, constraint.sub)); + opt_span_category.map(|&(category, span)| (category, true, span)).unwrap_or(( + constraint.category, + false, + body.source_info(loc).span, + )) + } + + /// Finds a good span to blame for the fact that `fr1` outlives `fr2`. + crate fn find_outlives_blame_span( + &self, + body: &Body<'tcx>, + fr1: RegionVid, + fr1_origin: NLLRegionVariableOrigin, + fr2: RegionVid, + ) -> (ConstraintCategory, Span) { + let (category, _, span) = self.best_blame_constraint(body, fr1, fr1_origin, |r| { + self.provides_universal_region(r, fr1, fr2) + }); + (category, span) + } + + /// Walks the graph of constraints (where `'a: 'b` is considered + /// an edge `'a -> 'b`) to find all paths from `from_region` to + /// `to_region`. The paths are accumulated into the vector + /// `results`. The paths are stored as a series of + /// `ConstraintIndex` values -- in other words, a list of *edges*. + /// + /// Returns: a series of constraints as well as the region `R` + /// that passed the target test. + crate fn find_constraint_paths_between_regions( + &self, + from_region: RegionVid, + target_test: impl Fn(RegionVid) -> bool, + ) -> Option<(Vec<OutlivesConstraint>, RegionVid)> { + let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); + context[from_region] = Trace::StartRegion; + + // Use a deque so that we do a breadth-first search. We will + // stop at the first match, which ought to be the shortest + // path (fewest constraints). + let mut deque = VecDeque::new(); + deque.push_back(from_region); + + while let Some(r) = deque.pop_front() { + debug!( + "find_constraint_paths_between_regions: from_region={:?} r={:?} value={}", + from_region, + r, + self.region_value_str(r), + ); + + // Check if we reached the region we were looking for. If so, + // we can reconstruct the path that led to it and return it. + if target_test(r) { + let mut result = vec![]; + let mut p = r; + loop { + match context[p] { + Trace::NotVisited => { + bug!("found unvisited region {:?} on path to {:?}", p, r) + } + + Trace::FromOutlivesConstraint(c) => { + result.push(c); + p = c.sup; + } + + Trace::StartRegion => { + result.reverse(); + return Some((result, r)); + } + } + } + } + + // Otherwise, walk over the outgoing constraints and + // enqueue any regions we find, keeping track of how we + // reached them. + + // A constraint like `'r: 'x` can come from our constraint + // graph. + let fr_static = self.universal_regions.fr_static; + let outgoing_edges_from_graph = + self.constraint_graph.outgoing_edges(r, &self.constraints, fr_static); + + // Always inline this closure because it can be hot. + let mut handle_constraint = #[inline(always)] + |constraint: OutlivesConstraint| { + debug_assert_eq!(constraint.sup, r); + let sub_region = constraint.sub; + if let Trace::NotVisited = context[sub_region] { + context[sub_region] = Trace::FromOutlivesConstraint(constraint); + deque.push_back(sub_region); + } + }; + + // This loop can be hot. + for constraint in outgoing_edges_from_graph { + handle_constraint(constraint); + } + + // Member constraints can also give rise to `'r: 'x` edges that + // were not part of the graph initially, so watch out for those. + // (But they are extremely rare; this loop is very cold.) + for constraint in self.applied_member_constraints(r) { + let p_c = &self.member_constraints[constraint.member_constraint_index]; + let constraint = OutlivesConstraint { + sup: r, + sub: constraint.min_choice, + locations: Locations::All(p_c.definition_span), + category: ConstraintCategory::OpaqueType, + }; + handle_constraint(constraint); + } + } + + None + } + + /// Finds some region R such that `fr1: R` and `R` is live at `elem`. + crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid { + debug!("find_sub_region_live_at(fr1={:?}, elem={:?})", fr1, elem); + self.find_constraint_paths_between_regions(fr1, |r| { + // First look for some `r` such that `fr1: r` and `r` is live at `elem` + debug!( + "find_sub_region_live_at: liveness_constraints for {:?} are {:?}", + r, + self.liveness_constraints.region_value_str(r), + ); + self.liveness_constraints.contains(r, elem) + }) + .or_else(|| { + // If we fail to find that, we may find some `r` such that + // `fr1: r` and `r` is a placeholder from some universe + // `fr1` cannot name. This would force `fr1` to be + // `'static`. + self.find_constraint_paths_between_regions(fr1, |r| { + self.cannot_name_placeholder(fr1, r) + }) + }) + .or_else(|| { + // If we fail to find THAT, it may be that `fr1` is a + // placeholder that cannot "fit" into its SCC. In that + // case, there should be some `r` where `fr1: r`, both + // `fr1` and `r` are in the same SCC, and `fr1` is a + // placeholder that `r` cannot name. We can blame that + // edge. + self.find_constraint_paths_between_regions(fr1, |r| { + self.constraint_sccs.scc(fr1) == self.constraint_sccs.scc(r) + && self.cannot_name_placeholder(r, fr1) + }) + }) + .map(|(_path, r)| r) + .unwrap() + } + + /// Get the region outlived by `longer_fr` and live at `element`. + crate fn region_from_element(&self, longer_fr: RegionVid, element: RegionElement) -> RegionVid { + match element { + RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), + RegionElement::RootUniversalRegion(r) => r, + RegionElement::PlaceholderRegion(error_placeholder) => self + .definitions + .iter_enumerated() + .filter_map(|(r, definition)| match definition.origin { + NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), + _ => None, + }) + .next() + .unwrap(), + } + } + + /// Get the region definition of `r`. + crate fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> { + &self.definitions[r] + } + + /// Check if the SCC of `r` contains `upper`. + crate fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool { + let r_scc = self.constraint_sccs.scc(r); + self.scc_values.contains(r_scc, upper) + } + + crate fn universal_regions(&self) -> &UniversalRegions<'tcx> { + self.universal_regions.as_ref() + } + + /// Tries to find the best constraint to blame for the fact that + /// `R: from_region`, where `R` is some region that meets + /// `target_test`. This works by following the constraint graph, + /// creating a constraint path that forces `R` to outlive + /// `from_region`, and then finding the best choices within that + /// path to blame. + crate fn best_blame_constraint( + &self, + body: &Body<'tcx>, + from_region: RegionVid, + from_region_origin: NLLRegionVariableOrigin, + target_test: impl Fn(RegionVid) -> bool, + ) -> (ConstraintCategory, bool, Span) { + debug!( + "best_blame_constraint(from_region={:?}, from_region_origin={:?})", + from_region, from_region_origin + ); + + // Find all paths + let (path, target_region) = + self.find_constraint_paths_between_regions(from_region, target_test).unwrap(); + debug!( + "best_blame_constraint: path={:#?}", + path.iter() + .map(|&c| format!( + "{:?} ({:?}: {:?})", + c, + self.constraint_sccs.scc(c.sup), + self.constraint_sccs.scc(c.sub), + )) + .collect::<Vec<_>>() + ); + + // Classify each of the constraints along the path. + let mut categorized_path: Vec<(ConstraintCategory, bool, Span)> = path + .iter() + .map(|constraint| { + if constraint.category == ConstraintCategory::ClosureBounds { + self.retrieve_closure_constraint_info(body, &constraint) + } else { + (constraint.category, false, constraint.locations.span(body)) + } + }) + .collect(); + debug!("best_blame_constraint: categorized_path={:#?}", categorized_path); + + // To find the best span to cite, we first try to look for the + // final constraint that is interesting and where the `sup` is + // not unified with the ultimate target region. The reason + // for this is that we have a chain of constraints that lead + // from the source to the target region, something like: + // + // '0: '1 ('0 is the source) + // '1: '2 + // '2: '3 + // '3: '4 + // '4: '5 + // '5: '6 ('6 is the target) + // + // Some of those regions are unified with `'6` (in the same + // SCC). We want to screen those out. After that point, the + // "closest" constraint we have to the end is going to be the + // most likely to be the point where the value escapes -- but + // we still want to screen for an "interesting" point to + // highlight (e.g., a call site or something). + let target_scc = self.constraint_sccs.scc(target_region); + let mut range = 0..path.len(); + + // As noted above, when reporting an error, there is typically a chain of constraints + // leading from some "source" region which must outlive some "target" region. + // In most cases, we prefer to "blame" the constraints closer to the target -- + // but there is one exception. When constraints arise from higher-ranked subtyping, + // we generally prefer to blame the source value, + // as the "target" in this case tends to be some type annotation that the user gave. + // Therefore, if we find that the region origin is some instantiation + // of a higher-ranked region, we start our search from the "source" point + // rather than the "target", and we also tweak a few other things. + // + // An example might be this bit of Rust code: + // + // ```rust + // let x: fn(&'static ()) = |_| {}; + // let y: for<'a> fn(&'a ()) = x; + // ``` + // + // In MIR, this will be converted into a combination of assignments and type ascriptions. + // In particular, the 'static is imposed through a type ascription: + // + // ```rust + // x = ...; + // AscribeUserType(x, fn(&'static ()) + // y = x; + // ``` + // + // We wind up ultimately with constraints like + // + // ```rust + // !a: 'temp1 // from the `y = x` statement + // 'temp1: 'temp2 + // 'temp2: 'static // from the AscribeUserType + // ``` + // + // and here we prefer to blame the source (the y = x statement). + let blame_source = match from_region_origin { + NLLRegionVariableOrigin::FreeRegion + | NLLRegionVariableOrigin::Existential { from_forall: false } => true, + NLLRegionVariableOrigin::Placeholder(_) + | NLLRegionVariableOrigin::Existential { from_forall: true } => false, + }; + + let find_region = |i: &usize| { + let constraint = path[*i]; + + let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); + + if blame_source { + match categorized_path[*i].0 { + ConstraintCategory::OpaqueType + | ConstraintCategory::Boring + | ConstraintCategory::BoringNoLocation + | ConstraintCategory::Internal => false, + ConstraintCategory::TypeAnnotation + | ConstraintCategory::Return + | ConstraintCategory::Yield => true, + _ => constraint_sup_scc != target_scc, + } + } else { + match categorized_path[*i].0 { + ConstraintCategory::OpaqueType + | ConstraintCategory::Boring + | ConstraintCategory::BoringNoLocation + | ConstraintCategory::Internal => false, + _ => true, + } + } + }; + + let best_choice = + if blame_source { range.rev().find(find_region) } else { range.find(find_region) }; + + debug!( + "best_blame_constraint: best_choice={:?} blame_source={}", + best_choice, blame_source + ); + + if let Some(i) = best_choice { + if let Some(next) = categorized_path.get(i + 1) { + if categorized_path[i].0 == ConstraintCategory::Return + && next.0 == ConstraintCategory::OpaqueType + { + // The return expression is being influenced by the return type being + // impl Trait, point at the return type and not the return expr. + return *next; + } + } + return categorized_path[i]; + } + + // If that search fails, that is.. unusual. Maybe everything + // is in the same SCC or something. In that case, find what + // appears to be the most interesting point to report to the + // user via an even more ad-hoc guess. + categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0)); + debug!("`: sorted_path={:#?}", categorized_path); + + *categorized_path.first().unwrap() + } } impl<'tcx> RegionDefinition<'tcx> { diff --git a/src/librustc_mir/borrow_check/region_infer/values.rs b/src/librustc_mir/borrow_check/region_infer/values.rs index e17efebfef8..3126d44014b 100644 --- a/src/librustc_mir/borrow_check/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/region_infer/values.rs @@ -114,7 +114,7 @@ rustc_index::newtype_index! { /// An individual element in a region value -- the value of a /// particular region variable consists of a set of these elements. -#[derive(Debug)] +#[derive(Debug, Clone)] crate enum RegionElement { /// A point in the control-flow graph. Location(Location), diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 947bbef4379..c9a1c465165 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -27,12 +27,12 @@ use rustc::ty::{ TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::{Span, DUMMY_SP}; +use syntax::ast; use crate::dataflow::move_paths::MoveData; use crate::dataflow::FlowAtLocation; @@ -1931,12 +1931,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { traits::ObligationCauseCode::RepeatVec(should_suggest), ), self.param_env, - ty::Predicate::Trait(ty::Binder::bind(ty::TraitPredicate { - trait_ref: ty::TraitRef::new( - self.tcx().lang_items().copy_trait().unwrap(), - tcx.mk_substs_trait(ty, &[]), - ), - })), + ty::Predicate::Trait( + ty::Binder::bind(ty::TraitPredicate { + trait_ref: ty::TraitRef::new( + self.tcx().lang_items().copy_trait().unwrap(), + tcx.mk_substs_trait(ty, &[]), + ), + }), + ast::Constness::NotConst, + ), ), &traits::SelectionError::Unimplemented, false, @@ -2574,7 +2577,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { category: ConstraintCategory, ) { self.prove_predicates( - Some(ty::Predicate::Trait(trait_ref.to_poly_trait_ref().to_poly_trait_predicate())), + Some(ty::Predicate::Trait( + trait_ref.to_poly_trait_ref().to_poly_trait_predicate(), + ast::Constness::NotConst, + )), locations, category, ); diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 1c25b269b18..5e42ba32790 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -7,7 +7,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(nll)] #![feature(in_band_lifetimes)] #![feature(inner_deref)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 85377180bea..f4611c32e0a 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -954,7 +954,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { // Nothing to do, just keep recursing. } - hir::ItemKind::Impl(..) => { + hir::ItemKind::Impl { .. } => { if self.mode == MonoItemCollectionMode::Eager { create_mono_items_for_default_impls(self.tcx, item, self.output); } @@ -1098,7 +1098,7 @@ fn create_mono_items_for_default_impls<'tcx>( output: &mut Vec<MonoItem<'tcx>>, ) { match item.kind { - hir::ItemKind::Impl(_, _, _, ref generics, .., ref impl_item_refs) => { + hir::ItemKind::Impl { ref generics, ref items, .. } => { for param in generics.params { match param.kind { hir::GenericParamKind::Lifetime { .. } => {} @@ -1119,7 +1119,7 @@ fn create_mono_items_for_default_impls<'tcx>( let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); let overridden_methods: FxHashSet<_> = - impl_item_refs.iter().map(|iiref| iiref.ident.modern()).collect(); + items.iter().map(|iiref| iiref.ident.modern()).collect(); for method in tcx.provided_trait_methods(trait_ref.def_id) { if overridden_methods.contains(&method.ident.modern()) { continue; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 01cecdd0679..b84616142cb 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -31,9 +31,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), - ty::InstanceDef::VtableShim(def_id) => { - build_call_shim(tcx, instance, Adjustment::DerefMove, CallKind::Direct(def_id), None) - } + ty::InstanceDef::VtableShim(def_id) => build_call_shim( + tcx, + instance, + Some(Adjustment::DerefMove), + CallKind::Direct(def_id), + None, + ), ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.lang_items().fn_trait_kind(trait_) { @@ -50,7 +54,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx)); let arg_tys = sig.inputs(); - build_call_shim(tcx, instance, adjustment, CallKind::Indirect, Some(arg_tys)) + build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect, Some(arg_tys)) } // We are generating a call back to our def-id, which the // codegen backend knows to turn to an actual call, be it @@ -58,7 +62,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx // indirect calls must be codegen'd differently than direct ones // (such as `#[track_caller]`). ty::InstanceDef::ReifyShim(def_id) => { - build_call_shim(tcx, instance, Adjustment::Identity, CallKind::Direct(def_id), None) + build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None) } ty::InstanceDef::ClosureOnceShim { call_once: _ } => { let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); @@ -68,7 +72,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx .unwrap() .def_id; - build_call_shim(tcx, instance, Adjustment::RefMut, CallKind::Direct(call_mut), None) + build_call_shim( + tcx, + instance, + Some(Adjustment::RefMut), + CallKind::Direct(call_mut), + None, + ) } ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty), ty::InstanceDef::CloneShim(def_id, ty) => { @@ -648,7 +658,7 @@ impl CloneShimBuilder<'tcx> { fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, - rcvr_adjustment: Adjustment, + rcvr_adjustment: Option<Adjustment>, call_kind: CallKind, untuple_args: Option<&[Ty<'tcx>]>, ) -> BodyAndCache<'tcx> { @@ -680,14 +690,16 @@ fn build_call_shim<'tcx>( let mut local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; - let rcvr_arg = Local::new(1 + 0); - let rcvr_l = Place::from(rcvr_arg); + let rcvr_place = || { + assert!(rcvr_adjustment.is_some()); + Place::from(Local::new(1 + 0)) + }; let mut statements = vec![]; - let rcvr = match rcvr_adjustment { - Adjustment::Identity => Operand::Move(rcvr_l), - Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)), - Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_l)), + let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment { + Adjustment::Identity => Operand::Move(rcvr_place()), + Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_place())), + Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())), Adjustment::RefMut => { // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push(temp_decl( @@ -703,15 +715,15 @@ fn build_call_shim<'tcx>( source_info, kind: StatementKind::Assign(box ( Place::from(ref_rcvr), - Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l), + Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()), )), }); Operand::Move(Place::from(ref_rcvr)) } - }; + }); let (callee, mut args) = match call_kind { - CallKind::Indirect => (rcvr, vec![]), + CallKind::Indirect => (rcvr.unwrap(), vec![]), CallKind::Direct(def_id) => { let ty = tcx.type_of(def_id); ( @@ -720,21 +732,35 @@ fn build_call_shim<'tcx>( user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }), - vec![rcvr], + rcvr.into_iter().collect::<Vec<_>>(), ) } }; + let mut arg_range = 0..sig.inputs().len(); + + // Take the `self` ("receiver") argument out of the range (it's adjusted above). + if rcvr_adjustment.is_some() { + arg_range.start += 1; + } + + // Take the last argument, if we need to untuple it (handled below). + if untuple_args.is_some() { + arg_range.end -= 1; + } + + // Pass all of the non-special arguments directly. + args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::new(1 + i))))); + + // Untuple the last argument, if we have to. if let Some(untuple_args) = untuple_args { + let tuple_arg = Local::new(1 + (sig.inputs().len() - 1)); args.extend(untuple_args.iter().enumerate().map(|(i, ity)| { - let arg_place = Place::from(Local::new(1 + 1)); - Operand::Move(tcx.mk_place_field(arg_place, Field::new(i), *ity)) + Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), Field::new(i), *ity)) })); - } else { - args.extend((1..sig.inputs().len()).map(|i| Operand::Move(Place::from(Local::new(1 + i))))); } - let n_blocks = if let Adjustment::RefMut = rcvr_adjustment { 5 } else { 2 }; + let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 }; let mut blocks = IndexVec::with_capacity(n_blocks); let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| { blocks.push(BasicBlockData { @@ -752,7 +778,7 @@ fn build_call_shim<'tcx>( func: callee, args, destination: Some((Place::return_place(), BasicBlock::new(1))), - cleanup: if let Adjustment::RefMut = rcvr_adjustment { + cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment { Some(BasicBlock::new(3)) } else { None @@ -762,13 +788,13 @@ fn build_call_shim<'tcx>( false, ); - if let Adjustment::RefMut = rcvr_adjustment { + if let Some(Adjustment::RefMut) = rcvr_adjustment { // BB #1 - drop for Self block( &mut blocks, vec![], TerminatorKind::Drop { - location: Place::from(rcvr_arg), + location: rcvr_place(), target: BasicBlock::new(2), unwind: None, }, @@ -777,13 +803,13 @@ fn build_call_shim<'tcx>( } // BB #1/#2 - return block(&mut blocks, vec![], TerminatorKind::Return, false); - if let Adjustment::RefMut = rcvr_adjustment { + if let Some(Adjustment::RefMut) = rcvr_adjustment { // BB #3 - drop if closure panics block( &mut blocks, vec![], TerminatorKind::Drop { - location: Place::from(rcvr_arg), + location: rcvr_place(), target: BasicBlock::new(4), unwind: None, }, diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index edb4eb4d7c3..3263905eadb 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -10,8 +10,6 @@ use rustc_span::{Span, Symbol}; use super::{ConstKind, Item}; -use rustc_error_codes::*; - /// An operation that is not *always* allowed in a const context. pub trait NonConstOp: std::fmt::Debug { /// Whether this operation can be evaluated by miri. diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 10a4b7d92b7..1d5fb33ee8e 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -6,7 +6,6 @@ use rustc::mir::*; use rustc::traits::{self, TraitEngine}; use rustc::ty::cast::CastTy; use rustc::ty::{self, TyCtxt}; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir::{def_id::DefId, HirId}; use rustc_index::bit_set::BitSet; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 072cdf2ebba..4e943547f07 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -18,8 +18,6 @@ use std::ops::Bound; use crate::const_eval::{is_const_fn, is_min_const_fn}; use crate::util; -use rustc_error_codes::*; - pub struct UnsafetyChecker<'a, 'tcx> { body: &'a Body<'tcx>, const_context: bool, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9d5dbe3564e..d645f6cf183 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -14,7 +14,7 @@ use rustc::mir::{ SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; -use rustc::traits::TraitQueryMode; +use rustc::traits; use rustc::ty::layout::{ HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout, }; @@ -90,28 +90,28 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // If there are unsatisfiable where clauses, then all bets are // off, and we just give up. // - // Note that we use TraitQueryMode::Canonical here, which causes - // us to treat overflow like any other error. This is because we - // are "speculatively" evaluating this item with the default substs. - // While this usually succeeds, it may fail with tricky impls - // (e.g. the typenum crate). Const-propagation is fundamentally - // "best-effort", and does not affect correctness in any way. - // Therefore, it's perfectly fine to just "give up" if we're - // unable to check the bounds with the default substs. + // We manually filter the predicates, skipping anything that's not + // "global". We are in a potentially generic context + // (e.g. we are evaluating a function without substituting generic + // parameters, so this filtering serves two purposes: // - // False negatives (failing to run const-prop on something when we actually - // could) are fine. However, false positives (running const-prop on - // an item with unsatisfiable bounds) can lead to us generating invalid - // MIR. - if !tcx.substitute_normalize_and_test_predicates(( - source.def_id(), - InternalSubsts::identity_for_item(tcx, source.def_id()), - TraitQueryMode::Canonical, - )) { - trace!( - "ConstProp skipped for item with unsatisfiable predicates: {:?}", - source.def_id() - ); + // 1. We skip evaluating any predicates that we would + // never be able prove are unsatisfiable (e.g. `<T as Foo>` + // 2. We avoid trying to normalize predicates involving generic + // parameters (e.g. `<T as Foo>::MyItem`). This can confuse + // the normalization code (leading to cycle errors), since + // it's usually never invoked in this way. + let predicates = tcx + .predicates_of(source.def_id()) + .predicates + .iter() + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) + .collect(); + if !traits::normalize_and_test_predicates( + tcx, + traits::elaborate_predicates(tcx, predicates).collect(), + ) { + trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", source.def_id()); return; } @@ -288,8 +288,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { } } -type Const<'tcx> = OpTy<'tcx>; - /// Finds optimization opportunities on the MIR. struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine>, @@ -387,7 +385,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn get_const(&self, local: Local) -> Option<Const<'tcx>> { + fn get_const(&self, local: Local) -> Option<OpTy<'tcx>> { if local == RETURN_PLACE { // Try to read the return place as an immediate so that if it is representable as a // scalar, we can handle it as such, but otherwise, just return the value as is. @@ -466,11 +464,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { r } - fn eval_constant( - &mut self, - c: &Constant<'tcx>, - source_info: SourceInfo, - ) -> Option<Const<'tcx>> { + fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> { self.ecx.tcx.span = c.span; // FIXME we need to revisit this for #67176 @@ -510,12 +504,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> { + fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> { trace!("eval_place(place={:?})", place); self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None)) } - fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> { + fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> { match *op { Operand::Constant(ref c) => self.eval_constant(c, source_info), Operand::Move(ref place) | Operand::Copy(ref place) => { @@ -636,28 +630,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?; } - // Work around: avoid ICE in miri. FIXME(wesleywiser) - // The Miri engine ICEs when taking a reference to an uninitialized unsized - // local. There's nothing it can do here: taking a reference needs an allocation - // which needs to know the size. Normally that's okay as during execution - // (e.g. for CTFE) it can never happen. But here in const_prop - // unknown data is uninitialized, so if e.g. a function argument is unsized - // and has a reference taken, we get an ICE. + // Do not try creating references (#67862) Rvalue::Ref(_, _, place_ref) => { - trace!("checking Ref({:?})", place_ref); + trace!("skipping Ref({:?})", place_ref); - if let Some(local) = place_ref.as_local() { - let alive = if let LocalValue::Live(_) = self.ecx.frame().locals[local].value { - true - } else { - false - }; - - if !alive { - trace!("skipping Ref({:?}) to uninitialized local", place); - return None; - } - } + return None; } _ => {} @@ -681,7 +658,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { fn replace_with_const( &mut self, rval: &mut Rvalue<'tcx>, - value: Const<'tcx>, + value: OpTy<'tcx>, source_info: SourceInfo, ) { trace!("attepting to replace {:?} with {:?}", rval, value); diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 70345567408..b047e534e4f 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use std::borrow::Cow; -use syntax::attr; +use syntax::{ast, attr}; type McfResult = Result<(), (Span, Cow<'static, str>)>; @@ -27,12 +27,19 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - bug!("closure kind predicate on function: {:#?}", predicate) } Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate), - Predicate::Trait(pred) => { + Predicate::Trait(pred, constness) => { if Some(pred.def_id()) == tcx.lang_items().sized_trait() { continue; } match pred.skip_binder().self_ty().kind { ty::Param(ref p) => { + // Allow `T: ?const Trait` + if *constness == ast::Constness::NotConst + && feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out) + { + continue; + } + let generics = tcx.generics_of(current); let def = generics.type_param(p, tcx); let span = tcx.def_span(def.def_id); @@ -309,7 +316,11 @@ fn check_terminator( ) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { - TerminatorKind::Goto { .. } | TerminatorKind::Return | TerminatorKind::Resume => Ok(()), + TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::Goto { .. } + | TerminatorKind::Return + | TerminatorKind::Resume => Ok(()), TerminatorKind::Drop { location, .. } => check_place(tcx, location, span, def_id, body), TerminatorKind::DropAndReplace { location, value, .. } => { @@ -317,13 +328,10 @@ fn check_terminator( check_operand(tcx, value, span, def_id, body) } - TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } - if !feature_allowed(tcx, def_id, sym::const_if_match) => - { + TerminatorKind::SwitchInt { .. } if !feature_allowed(tcx, def_id, sym::const_if_match) => { Err((span, "loops and conditional expressions are not stable in const fn".into())) } - TerminatorKind::FalseEdges { .. } => Ok(()), TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => { check_operand(tcx, discr, span, def_id, body) } @@ -367,13 +375,5 @@ fn check_terminator( TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => { check_operand(tcx, cond, span, def_id, body) } - - TerminatorKind::FalseUnwind { .. } if feature_allowed(tcx, def_id, sym::const_loop) => { - Ok(()) - } - - TerminatorKind::FalseUnwind { .. } => { - Err((span, "loops are not allowed in const fn".into())) - } } } diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index c275eecfb33..d8ee059f1a6 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -1,5 +1,4 @@ use rustc::ty::{self, Ty, TyCtxt}; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, DiagnosticBuilder, DiagnosticId}; use rustc_span::{MultiSpan, Span}; diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml index 79c73032755..f0d1d4c6515 100644 --- a/src/librustc_mir_build/Cargo.toml +++ b/src/librustc_mir_build/Cargo.toml @@ -25,4 +25,3 @@ rustc_span = { path = "../librustc_span" } rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } -rustc_error_codes = { path = "../librustc_error_codes" } diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 97e71811829..d6786ea2479 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -411,18 +411,21 @@ fn make_mirror_unadjusted<'a, 'tcx>( let def_id = cx.tcx.hir().local_def_id(count.hir_id); let substs = InternalSubsts::identity_for_item(cx.tcx, def_id); let span = cx.tcx.def_span(def_id); - let count = - match cx.tcx.const_eval_resolve(cx.param_env, def_id, substs, None, Some(span)) { - Ok(cv) => cv.eval_usize(cx.tcx, cx.param_env), - Err(ErrorHandled::Reported) => 0, - Err(ErrorHandled::TooGeneric) => { - let span = cx.tcx.def_span(def_id); - cx.tcx - .sess - .span_err(span, "array lengths can't depend on generic parameters"); - 0 - } - }; + let count = match cx.tcx.const_eval_resolve( + ty::ParamEnv::reveal_all(), + def_id, + substs, + None, + Some(span), + ) { + Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()), + Err(ErrorHandled::Reported) => 0, + Err(ErrorHandled::TooGeneric) => { + let span = cx.tcx.def_span(def_id); + cx.tcx.sess.span_err(span, "array lengths can't depend on generic parameters"); + 0 + } + }; ExprKind::Repeat { value: v.to_ref(), count } } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 84d57a89c98..eac52da7ba4 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -9,7 +9,6 @@ use rustc::lint; use rustc::session::parse::feature_err; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; -use rustc_error_codes::*; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::*; diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index 205e25f7f8f..26570505830 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -28,8 +28,6 @@ use syntax::ast; use std::cmp::Ordering; use std::fmt; -use rustc_error_codes::*; - #[derive(Clone, Debug)] crate enum PatternError { AssocConstInPattern(Span), diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs index 5a17f36e1da..42292d635bc 100644 --- a/src/librustc_mir_build/lib.rs +++ b/src/librustc_mir_build/lib.rs @@ -5,7 +5,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(bool_to_option)] #![recursion_limit = "256"] diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml index aa159c55ff2..8071bc6312b 100644 --- a/src/librustc_parse/Cargo.toml +++ b/src/librustc_parse/Cargo.toml @@ -16,7 +16,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_feature = { path = "../librustc_feature" } rustc_lexer = { path = "../librustc_lexer" } rustc_errors = { path = "../librustc_errors" } -rustc_error_codes = { path = "../librustc_error_codes" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 8467acc759c..bf696faf2f3 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -10,7 +10,6 @@ use crate::{parse_in, validate_attr}; use rustc_data_structures::fx::FxHashMap; -use rustc_error_codes::*; use rustc_errors::{error_code, struct_span_err, Applicability, Handler}; use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 9227e968ecc..08f4f210152 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -2,7 +2,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] use syntax::ast; use syntax::print::pprust; diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 6a18c63017e..80bc5c158a6 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -1,7 +1,6 @@ use super::{BlockMode, Parser, PathStyle, SemiColonMode, SeqSep, TokenExpectType, TokenType}; use rustc_data_structures::fx::FxHashSet; -use rustc_error_codes::*; use rustc_errors::{pluralize, struct_span_err}; use rustc_errors::{Applicability, DiagnosticBuilder, Handler, PResult}; use rustc_span::source_map::Spanned; diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d4756dff49a..31db7fc5f75 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -3,9 +3,8 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; -use rustc_span::source_map::{self, respan, Span, Spanned}; +use rustc_span::source_map::{self, respan, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::BytePos; use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; @@ -566,9 +565,9 @@ impl<'a> Parser<'a> { let constness = if self.eat_keyword(kw::Const) { let span = self.prev_span; self.sess.gated_spans.gate(sym::const_trait_impl, span); - Some(respan(span, Constness::Const)) + Constness::Const } else { - None + Constness::NotConst }; // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. @@ -631,37 +630,31 @@ impl<'a> Parser<'a> { err_path(ty_first.span) } }; - let constness = constness.map(|c| c.node); - let trait_ref = TraitRef { path, constness, ref_id: ty_first.id }; + let trait_ref = TraitRef { path, ref_id: ty_first.id }; - ItemKind::Impl( + ItemKind::Impl { unsafety, polarity, defaultness, + constness, generics, - Some(trait_ref), - ty_second, - impl_items, - ) + of_trait: Some(trait_ref), + self_ty: ty_second, + items: impl_items, + } } None => { - // Reject `impl const Type {}` here - if let Some(Spanned { node: Constness::Const, span }) = constness { - self.struct_span_err(span, "`const` cannot modify an inherent impl") - .help("only a trait impl can be `const`") - .emit(); - } - // impl Type - ItemKind::Impl( + ItemKind::Impl { unsafety, polarity, defaultness, + constness, generics, - None, - ty_first, - impl_items, - ) + of_trait: None, + self_ty: ty_first, + items: impl_items, + } } }; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 1368230168e..4a9016394d2 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -33,8 +33,6 @@ use std::borrow::Cow; use std::path::PathBuf; use std::{cmp, mem, slice}; -use rustc_error_codes::*; - bitflags::bitflags! { struct Restrictions: u8 { const STMT_EXPR = 1 << 0; diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 549acf67d38..edb9044df92 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -659,7 +659,6 @@ impl<'a> Parser<'a> { } pub(super) fn error_inclusive_range_with_no_end(&self, span: Span) { - use rustc_error_codes::E0586; struct_span_err!(self.sess.span_diagnostic, span, E0586, "inclusive range with no end") .span_suggestion_short( span, diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 065a3b14428..a4cc9fa48f2 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -3,7 +3,6 @@ use super::{Parser, PathStyle, PrevTokenKind, TokenType}; use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; -use rustc_error_codes::*; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym}; @@ -27,10 +26,12 @@ struct BoundModifiers { } impl BoundModifiers { - fn trait_bound_modifier(&self) -> TraitBoundModifier { - match self.maybe { - Some(_) => TraitBoundModifier::Maybe, - None => TraitBoundModifier::None, + fn to_trait_bound_modifier(&self) -> TraitBoundModifier { + match (self.maybe, self.maybe_const) { + (None, None) => TraitBoundModifier::None, + (Some(_), None) => TraitBoundModifier::Maybe, + (None, Some(_)) => TraitBoundModifier::MaybeConst, + (Some(_), Some(_)) => TraitBoundModifier::MaybeConstMaybe, } } } @@ -215,7 +216,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, TyKind> { assert_ne!(self.token, token::Question); - let poly_trait_ref = PolyTraitRef::new(generic_params, path, None, lo.to(self.prev_span)); + let poly_trait_ref = PolyTraitRef::new(generic_params, path, lo.to(self.prev_span)); let mut bounds = vec![GenericBound::Trait(poly_trait_ref, TraitBoundModifier::None)]; if parse_plus { self.eat_plus(); // `+`, or `+=` gets split and `+` is discarded @@ -557,9 +558,9 @@ impl<'a> Parser<'a> { self.expect(&token::CloseDelim(token::Paren))?; } - let constness = modifiers.maybe_const.map(|_| ast::Constness::NotConst); - let poly_trait = PolyTraitRef::new(lifetime_defs, path, constness, lo.to(self.prev_span)); - Ok(GenericBound::Trait(poly_trait, modifiers.trait_bound_modifier())) + let modifier = modifiers.to_trait_bound_modifier(); + let poly_trait = PolyTraitRef::new(lifetime_defs, path, lo.to(self.prev_span)); + Ok(GenericBound::Trait(poly_trait, modifier)) } /// Optionally parses `for<$generic_params>`. diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 639d8639c4b..338808f6d4a 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -20,4 +20,3 @@ rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } -rustc_error_codes = { path = "../librustc_error_codes" } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 39ba2fbc63b..faa85f68fab 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -12,7 +12,6 @@ use rustc::session::config::nightly_options; use rustc::session::parse::feature_err; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index f2778b2aa6b..2ff9d744f2c 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -405,10 +405,10 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { } } } - hir::ItemKind::Impl(.., ref opt_trait, _, impl_item_refs) => { - for impl_item_ref in impl_item_refs { + hir::ItemKind::Impl { ref of_trait, items, .. } => { + for impl_item_ref in items { let impl_item = self.krate.impl_item(impl_item_ref.id); - if opt_trait.is_some() + if of_trait.is_some() || has_allow_dead_code_or_lang_attr( self.tcx, impl_item.hir_id, @@ -586,7 +586,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { | hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Trait(..) - | hir::ItemKind::Impl(..) => { + | hir::ItemKind::Impl { .. } => { // FIXME(66095): Because item.span is annotated with things // like expansion data, and ident.span isn't, we use the // def_span method if it's part of a macro invocation diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index 028d7c66275..d36114fd3b5 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -12,8 +12,6 @@ use rustc_span::{Span, DUMMY_SP}; use syntax::attr; use syntax::entry::EntryPointType; -use rustc_error_codes::*; - struct EntryContext<'a, 'tcx> { session: &'a Session, diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 2c26707a518..782199003c7 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -11,8 +11,6 @@ use rustc_index::vec::Idx; use rustc_span::{sym, Span}; use rustc_target::spec::abi::Abi::RustIntrinsic; -use rustc_error_codes::*; - fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) { tcx.hir().visit_item_likes_in_module(module_def_id, &mut ItemVisitor { tcx }.as_deep_visitor()); } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 65eb07b989d..d746f097928 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -7,7 +7,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs index 8ae72912897..2e306a1b4f2 100644 --- a/src/librustc_passes/lib_features.rs +++ b/src/librustc_passes/lib_features.rs @@ -15,8 +15,6 @@ use rustc_span::symbol::Symbol; use rustc_span::{sym, Span}; use syntax::ast::{Attribute, MetaItem, MetaItemKind}; -use rustc_error_codes::*; - fn new_lib_features() -> LibFeatures { LibFeatures { stable: Default::default(), unstable: Default::default() } } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 5ad5795c777..69d6b38005c 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -1,7 +1,5 @@ use Context::*; -use rustc::session::Session; - use rustc::hir::map::Map; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; @@ -10,10 +8,9 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Destination, Movability, Node}; +use rustc_session::Session; use rustc_span::Span; -use rustc_error_codes::*; - #[derive(Clone, Copy, Debug, PartialEq)] enum Context { Normal, diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 5ce677f52ce..667898046ac 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -35,7 +35,7 @@ fn item_might_be_inlined(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>, attrs: Codegen hir::ItemKind::Fn(ref sig, ..) if sig.header.is_const() => { return true; } - hir::ItemKind::Impl(..) | hir::ItemKind::Fn(..) => { + hir::ItemKind::Impl { .. } | hir::ItemKind::Fn(..) => { let generics = tcx.generics_of(tcx.hir().local_def_id(item.hir_id)); generics.requires_monomorphization(tcx) } @@ -181,7 +181,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // does too. let impl_hir_id = self.tcx.hir().as_local_hir_id(impl_did).unwrap(); match self.tcx.hir().expect_item(impl_hir_id).kind { - hir::ItemKind::Impl(..) => { + hir::ItemKind::Impl { .. } => { let generics = self.tcx.generics_of(impl_did); generics.requires_monomorphization(self.tcx) } @@ -266,7 +266,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { | hir::ItemKind::Static(..) | hir::ItemKind::Mod(..) | hir::ItemKind::ForeignMod(..) - | hir::ItemKind::Impl(..) + | hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) | hir::ItemKind::Struct(..) @@ -349,9 +349,9 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a, 'tcx } // We need only trait impls here, not inherent impls, and only non-exported ones - if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.kind { + if let hir::ItemKind::Impl { of_trait: Some(ref trait_ref), ref items, .. } = item.kind { if !self.access_levels.is_reachable(item.hir_id) { - self.worklist.extend(impl_item_refs.iter().map(|ii_ref| ii_ref.id.hir_id)); + self.worklist.extend(items.iter().map(|ii_ref| ii_ref.id.hir_id)); let trait_def_id = match trait_ref.path.res { Res::Def(DefKind::Trait, def_id) => def_id, diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 5ec7e73f873..320b433190e 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -26,8 +26,6 @@ use std::cmp::Ordering; use std::mem::replace; use std::num::NonZeroU32; -use rustc_error_codes::*; - #[derive(PartialEq)] enum AnnotationKind { // Annotation is required if not inherited from unstable parents @@ -219,11 +217,11 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { // they don't have their own stability. They still can be annotated as unstable // and propagate this unstability to children, but this annotation is completely // optional. They inherit stability from their parents when unannotated. - hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => { + hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => { self.in_trait_impl = false; kind = AnnotationKind::Container; } - hir::ItemKind::Impl(.., Some(_), _, _) => { + hir::ItemKind::Impl { of_trait: Some(_), .. } => { self.in_trait_impl = true; } hir::ItemKind::Struct(ref sd, _) => { @@ -308,7 +306,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { // they don't have their own stability. They still can be annotated as unstable // and propagate this unstability to children, but this annotation is completely // optional. They inherit stability from their parents when unannotated. - hir::ItemKind::Impl(.., None, _, _) | hir::ItemKind::ForeignMod(..) => {} + hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {} _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant()), } @@ -463,9 +461,9 @@ impl Visitor<'tcx> for Checker<'tcx> { // For implementations of traits, check the stability of each item // individually as it's possible to have a stable trait with unstable // items. - hir::ItemKind::Impl(.., Some(ref t), _, impl_item_refs) => { + hir::ItemKind::Impl { of_trait: Some(ref t), items, .. } => { if let Res::Def(DefKind::Trait, trait_did) = t.path.res { - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); let trait_item_def_id = self .tcx diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml index 41e6c699c34..2214838c846 100644 --- a/src/librustc_plugin_impl/Cargo.toml +++ b/src/librustc_plugin_impl/Cargo.toml @@ -18,4 +18,3 @@ rustc_lint = { path = "../librustc_lint" } rustc_metadata = { path = "../librustc_metadata" } syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } -rustc_error_codes = { path = "../librustc_error_codes" } diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs index 65661ec24f0..84549c0dd45 100644 --- a/src/librustc_plugin_impl/load.rs +++ b/src/librustc_plugin_impl/load.rs @@ -3,7 +3,6 @@ use crate::Registry; use rustc::middle::cstore::MetadataLoader; use rustc::session::Session; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_metadata::locator; use rustc_span::symbol::sym; diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml index 795b6c107fe..4f341b54515 100644 --- a/src/librustc_privacy/Cargo.toml +++ b/src/librustc_privacy/Cargo.toml @@ -16,5 +16,4 @@ rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } rustc_data_structures = { path = "../librustc_data_structures" } -rustc_error_codes = { path = "../librustc_error_codes" } log = "0.4" diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 70d4841ec24..60bf271d2d2 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -27,8 +27,6 @@ use syntax::attr; use std::marker::PhantomData; use std::{cmp, fmt, mem}; -use rustc_error_codes::*; - //////////////////////////////////////////////////////////////////////////////// /// Generic infrastructure used to implement specific visitors below. //////////////////////////////////////////////////////////////////////////////// @@ -93,7 +91,7 @@ where let ty::GenericPredicates { parent: _, predicates } = predicates; for (predicate, _span) in predicates { match predicate { - ty::Predicate::Trait(poly_predicate) => { + ty::Predicate::Trait(poly_predicate, _) => { let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder(); if self.visit_trait(trait_ref) { return true; @@ -255,8 +253,8 @@ fn def_id_visibility<'tcx>( Node::ImplItem(impl_item) => { match tcx.hir().get(tcx.hir().get_parent_item(hir_id)) { Node::Item(item) => match &item.kind { - hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis, - hir::ItemKind::Impl(.., Some(trait_ref), _, _) => { + hir::ItemKind::Impl { of_trait: None, .. } => &impl_item.vis, + hir::ItemKind::Impl { of_trait: Some(trait_ref), .. } => { return def_id_visibility(tcx, trait_ref.path.res.def_id()); } kind => bug!("unexpected item kind: {:?}", kind), @@ -686,7 +684,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { let inherited_item_level = match item.kind { - hir::ItemKind::Impl(..) => { + hir::ItemKind::Impl { .. } => { Option::<AccessLevel>::of_impl(item.hir_id, self.tcx, &self.access_levels) } // Foreign modules inherit level from parents. @@ -730,9 +728,9 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } } } - hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => { - for impl_item_ref in impl_item_refs { - if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() { + hir::ItemKind::Impl { ref of_trait, items, .. } => { + for impl_item_ref in items { + if of_trait.is_some() || impl_item_ref.vis.node.is_pub() { self.update(impl_item_ref.id.hir_id, item_level); } } @@ -827,11 +825,11 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } } // Visit everything except for private impl items. - hir::ItemKind::Impl(.., impl_item_refs) => { + hir::ItemKind::Impl { items, .. } => { if item_level.is_some() { self.reach(item.hir_id, item_level).generics().predicates().ty().trait_ref(); - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { let impl_item_level = self.get(impl_item_ref.id.hir_id); if impl_item_level.is_some() { self.reach(impl_item_ref.id.hir_id, impl_item_level) @@ -1237,7 +1235,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // The traits' privacy in bodies is already checked as a part of trait object types. let bounds = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref); - for (trait_predicate, _) in bounds.trait_bounds { + for (trait_predicate, _, _) in bounds.trait_bounds { if self.visit_trait(*trait_predicate.skip_binder()) { return; } @@ -1510,7 +1508,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // (i.e., we could just return here to not check them at // all, or some worse estimation of whether an impl is // publicly visible). - hir::ItemKind::Impl(.., ref g, ref trait_ref, ref self_, impl_item_refs) => { + hir::ItemKind::Impl { generics: ref g, ref of_trait, ref self_ty, items, .. } => { // `impl [... for] Private` is never visible. let self_contains_private; // `impl [... for] Public<...>`, but not `impl [... for] @@ -1525,7 +1523,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { at_outer_type: true, outer_type_is_public_path: false, }; - visitor.visit_ty(&self_); + visitor.visit_ty(&self_ty); self_contains_private = visitor.contains_private; self_is_public_path = visitor.outer_type_is_public_path; } @@ -1533,7 +1531,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // Miscellaneous info about the impl: // `true` iff this is `impl Private for ...`. - let not_private_trait = trait_ref.as_ref().map_or( + let not_private_trait = of_trait.as_ref().map_or( true, // no trait counts as public trait |tr| { let did = tr.path.res.def_id(); @@ -1554,8 +1552,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // directly because we might have `impl<T: Foo<Private>> ...`, // and we shouldn't warn about the generics if all the methods // are private (because `T` won't be visible externally). - let trait_or_some_public_method = trait_ref.is_some() - || impl_item_refs.iter().any(|impl_item_ref| { + let trait_or_some_public_method = of_trait.is_some() + || items.iter().any(|impl_item_ref| { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => { @@ -1570,9 +1568,9 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { if !self_contains_private && not_private_trait && trait_or_some_public_method { intravisit::walk_generics(self, g); - match *trait_ref { + match of_trait { None => { - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { // This is where we choose whether to walk down // further into the impl to check its items. We // should only walk into public items so that we @@ -1594,7 +1592,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } } - Some(ref tr) => { + Some(tr) => { // Any private types in a trait impl fall into three // categories. // 1. mentioned in the trait definition @@ -1611,7 +1609,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { intravisit::walk_path(self, &tr.path); // Those in 3. are warned with this call. - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); if let hir::ImplItemKind::TyAlias(ref ty) = impl_item.kind { self.visit_ty(ty); @@ -1619,11 +1617,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } } } - } else if trait_ref.is_none() && self_is_public_path { + } else if of_trait.is_none() && self_is_public_path { // `impl Public<Private> { ... }`. Any public static // methods will be visible as `Public::foo`. let mut found_pub_static = false; - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { if self.item_is_public(&impl_item_ref.id.hir_id, &impl_item_ref.vis) { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item_ref.kind { @@ -1997,12 +1995,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> // Subitems of inherent impls have their own publicity. // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. - hir::ItemKind::Impl(.., ref trait_ref, _, impl_item_refs) => { + hir::ItemKind::Impl { ref of_trait, items, .. } => { let impl_vis = ty::Visibility::of_impl(item.hir_id, tcx, &Default::default()); self.check(item.hir_id, impl_vis).generics().predicates(); - for impl_item_ref in impl_item_refs { + for impl_item_ref in items { let impl_item = tcx.hir().impl_item(impl_item_ref.id); - let impl_item_vis = if trait_ref.is_none() { + let impl_item_vis = if of_trait.is_none() { min( ty::Visibility::from_hir(&impl_item.vis, item.hir_id, tcx), impl_vis, diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index af37e7b5b76..c4cc6b09c73 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -23,7 +23,6 @@ rustc_expand = { path = "../librustc_expand" } rustc_feature = { path = "../librustc_feature" } rustc_hir = { path = "../librustc_hir" } rustc_metadata = { path = "../librustc_metadata" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e8ed64a1870..7ff076268ab 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -21,7 +21,6 @@ use rustc::hir::exports::Export; use rustc::middle::cstore::CrateStore; use rustc::ty; use rustc_data_structures::sync::Lrc; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Applicability}; use rustc_expand::base::SyntaxExtension; use rustc_expand::expand::AstFragment; @@ -815,7 +814,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // These items do not add names to modules. - ItemKind::Impl(..) | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} + ItemKind::Impl { .. } | ItemKind::ForeignMod(..) | ItemKind::GlobalAsm(..) => {} ItemKind::MacroDef(..) | ItemKind::Mac(_) => unreachable!(), } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index f564ea644bd..696ba0e994c 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -104,7 +104,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better let def_data = match &i.kind { - ItemKind::Impl(..) => DefPathData::Impl, + ItemKind::Impl { .. } => DefPathData::Impl, ItemKind::Mod(..) if i.ident.name == kw::Invalid => { return visit::walk_item(self, i); } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a433ae8ed67..77dfe3d9f1d 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -5,8 +5,9 @@ use rustc::bug; use rustc::session::Session; use rustc::ty::{self, DefIdTree}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_feature::BUILTIN_ATTRIBUTES; +use rustc_hir as hir; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -25,8 +26,6 @@ use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, Modu use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError}; use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment}; -use rustc_error_codes::*; - type Res = def::Res<ast::NodeId>; /// A vector of spans and replacements, a message and applicability. @@ -1447,3 +1446,74 @@ crate fn show_candidates( } } } + +crate fn report_missing_lifetime_specifiers( + sess: &Session, + span: Span, + count: usize, +) -> DiagnosticBuilder<'_> { + struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count)) +} + +crate fn add_missing_lifetime_specifiers_label( + err: &mut DiagnosticBuilder<'_>, + span: Span, + count: usize, + lifetime_names: &FxHashSet<ast::Ident>, + snippet: Option<&str>, + missing_named_lifetime_spots: &[&hir::Generics<'_>], +) { + if count > 1 { + err.span_label(span, format!("expected {} lifetime parameters", count)); + } else { + let suggest_existing = |err: &mut DiagnosticBuilder<'_>, sugg| { + err.span_suggestion( + span, + "consider using the named lifetime", + sugg, + Applicability::MaybeIncorrect, + ); + }; + let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg| { + err.span_label(span, "expected named lifetime parameter"); + + if let Some(generics) = missing_named_lifetime_spots.iter().last() { + let mut introduce_suggestion = vec![]; + introduce_suggestion.push(match &generics.params { + [] => (generics.span, "<'lifetime>".to_string()), + [param, ..] => (param.span.shrink_to_lo(), "'lifetime, ".to_string()), + }); + introduce_suggestion.push((span, sugg)); + err.multipart_suggestion( + "consider introducing a named lifetime parameter", + introduce_suggestion, + Applicability::MaybeIncorrect, + ); + } + }; + + match (lifetime_names.len(), lifetime_names.iter().next(), snippet) { + (1, Some(name), Some("&")) => { + suggest_existing(err, format!("&{} ", name)); + } + (1, Some(name), Some("'_")) => { + suggest_existing(err, name.to_string()); + } + (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => { + suggest_existing(err, format!("{}<{}>", snippet, name)); + } + (0, _, Some("&")) => { + suggest_new(err, "&'lifetime ".to_string()); + } + (0, _, Some("'_")) => { + suggest_new(err, "'lifetime".to_string()); + } + (0, _, Some(snippet)) if !snippet.ends_with(">") => { + suggest_new(err, format!("{}<'lifetime>", snippet)); + } + _ => { + err.span_label(span, "expected lifetime parameter"); + } + } + } +} diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 9f459834175..55ce51e0ff0 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -29,8 +29,6 @@ use syntax::ast::{Ident, Name, NodeId}; use syntax::unwrap_or; use syntax::util::lev_distance::find_best_match_for_name; -use rustc_error_codes::*; - use log::*; use std::cell::Cell; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index defca4944bc..5e08ac8e2c3 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -31,8 +31,6 @@ use log::debug; use std::collections::BTreeSet; use std::mem::replace; -use rustc_error_codes::*; - mod diagnostics; type Res = def::Res<NodeId>; @@ -797,14 +795,14 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.resolve_adt(item, generics); } - ItemKind::Impl(.., ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => { - self.resolve_implementation( - generics, - opt_trait_ref, - &self_type, - item.id, - impl_items, - ) + ItemKind::Impl { + ref generics, + ref of_trait, + ref self_ty, + items: ref impl_items, + .. + } => { + self.resolve_implementation(generics, of_trait, &self_ty, item.id, impl_items); } ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => { diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 151f3e834e5..6a98c9e59a9 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -6,7 +6,6 @@ use crate::{PathResult, PathSource, Segment}; use rustc::session::config::nightly_options; use rustc_data_structures::fx::FxHashSet; -use rustc_error_codes::*; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind}; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 60a0049f5da..0e6f40fa846 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -11,6 +11,7 @@ #![feature(crate_visibility_modifier)] #![feature(label_break_value)] #![feature(nll)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![recursion_limit = "256"] pub use rustc_hir::def::{Namespace, PerNS}; @@ -61,8 +62,6 @@ use imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver, NameReso use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use macros::{LegacyBinding, LegacyScope}; -use rustc_error_codes::*; - type Res = def::Res<NodeId>; mod build_reduced_graph; diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index d6143eec73c..6e9ed5fdc17 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -5,14 +5,16 @@ //! used between functions, and they operate in a purely top-down //! way. Therefore, we break lifetime name resolution into a separate pass. +use crate::diagnostics::{ + add_missing_lifetime_specifiers_label, report_missing_lifetime_specifiers, +}; use rustc::hir::map::Map; use rustc::lint; use rustc::middle::resolve_lifetime::*; -use rustc::session::Session; use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use rustc::{bug, span_bug}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; @@ -30,8 +32,6 @@ use syntax::walk_list; use log::debug; -use rustc_error_codes::*; - // This counts the no of times a lifetime is used #[derive(Clone, Copy, Debug)] pub enum LifetimeUseSet<'tcx> { @@ -183,6 +183,10 @@ struct LifetimeContext<'a, 'tcx> { xcrate_object_lifetime_defaults: DefIdMap<Vec<ObjectLifetimeDefault>>, lifetime_uses: &'a mut DefIdMap<LifetimeUseSet<'tcx>>, + + /// When encountering an undefined named lifetime, we will suggest introducing it in these + /// places. + missing_named_lifetime_spots: Vec<&'tcx hir::Generics<'tcx>>, } #[derive(Debug)] @@ -342,6 +346,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { labels_in_fn: vec![], xcrate_object_lifetime_defaults: Default::default(), lifetime_uses: &mut Default::default(), + missing_named_lifetime_spots: vec![], }; for (_, item) in &krate.items { visitor.visit_item(item); @@ -384,9 +389,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { match item.kind { hir::ItemKind::Fn(ref sig, ref generics, _) => { + self.missing_named_lifetime_spots.push(generics); self.visit_early_late(None, &sig.decl, generics, |this| { intravisit::walk_item(this, item); }); + self.missing_named_lifetime_spots.pop(); } hir::ItemKind::ExternCrate(_) @@ -416,11 +423,13 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { | hir::ItemKind::Union(_, ref generics) | hir::ItemKind::Trait(_, _, ref generics, ..) | hir::ItemKind::TraitAlias(ref generics, ..) - | hir::ItemKind::Impl(_, _, _, ref generics, ..) => { + | hir::ItemKind::Impl { ref generics, .. } => { + self.missing_named_lifetime_spots.push(generics); + // Impls permit `'_` to be used and it is equivalent to "some fresh lifetime name". // This is not true for other kinds of items.x let track_lifetime_uses = match item.kind { - hir::ItemKind::Impl(..) => true, + hir::ItemKind::Impl { .. } => true, _ => false, }; // These kinds of items have only early-bound lifetime parameters. @@ -454,6 +463,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { this.check_lifetime_params(old_scope, &generics.params); intravisit::walk_item(this, item); }); + self.missing_named_lifetime_spots.pop(); } } } @@ -686,6 +696,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { use self::hir::TraitItemKind::*; + self.missing_named_lifetime_spots.push(&trait_item.generics); match trait_item.kind { Method(ref sig, _) => { let tcx = self.tcx; @@ -737,10 +748,12 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { intravisit::walk_trait_item(self, trait_item); } } + self.missing_named_lifetime_spots.pop(); } fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) { use self::hir::ImplItemKind::*; + self.missing_named_lifetime_spots.push(&impl_item.generics); match impl_item.kind { Method(ref sig, _) => { let tcx = self.tcx; @@ -824,6 +837,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { intravisit::walk_impl_item(self, impl_item); } } + self.missing_named_lifetime_spots.pop(); } fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) { @@ -1309,6 +1323,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let LifetimeContext { tcx, map, lifetime_uses, .. } = self; let labels_in_fn = take(&mut self.labels_in_fn); let xcrate_object_lifetime_defaults = take(&mut self.xcrate_object_lifetime_defaults); + let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots); let mut this = LifetimeContext { tcx: *tcx, map: map, @@ -1317,7 +1332,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { is_in_fn_syntax: self.is_in_fn_syntax, labels_in_fn, xcrate_object_lifetime_defaults, - lifetime_uses: lifetime_uses, + lifetime_uses, + missing_named_lifetime_spots, }; debug!("entering scope {:?}", this.scope); f(self.scope, &mut this); @@ -1325,6 +1341,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { debug!("exiting scope {:?}", this.scope); self.labels_in_fn = this.labels_in_fn; self.xcrate_object_lifetime_defaults = this.xcrate_object_lifetime_defaults; + self.missing_named_lifetime_spots = this.missing_named_lifetime_spots; } /// helper method to determine the span to remove when suggesting the @@ -1638,7 +1655,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } match parent.kind { hir::ItemKind::Trait(_, _, ref generics, ..) - | hir::ItemKind::Impl(_, _, _, ref generics, ..) => { + | hir::ItemKind::Impl { ref generics, .. } => { index += generics.params.len() as u32; } _ => {} @@ -1807,15 +1824,29 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { self.insert_lifetime(lifetime_ref, def); } else { - struct_span_err!( + let mut err = struct_span_err!( self.tcx.sess, lifetime_ref.span, E0261, "use of undeclared lifetime name `{}`", lifetime_ref - ) - .span_label(lifetime_ref.span, "undeclared lifetime") - .emit(); + ); + err.span_label(lifetime_ref.span, "undeclared lifetime"); + if !self.is_in_fn_syntax { + for generics in &self.missing_named_lifetime_spots { + let (span, sugg) = match &generics.params { + [] => (generics.span, format!("<{}>", lifetime_ref)), + [param, ..] => (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)), + }; + err.span_suggestion( + span, + &format!("consider introducing lifetime `{}` here", lifetime_ref), + sugg, + Applicability::MaybeIncorrect, + ); + } + } + err.emit(); } } @@ -2067,12 +2098,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => { - if let hir::ItemKind::Impl(.., ref self_ty, ref impl_items) = + if let hir::ItemKind::Impl { ref self_ty, ref items, .. } = self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind { impl_self = Some(self_ty); assoc_item_kind = - impl_items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind); + items.iter().find(|ii| ii.id.hir_id == parent).map(|ii| ii.kind); } Some(body) } @@ -2369,6 +2400,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { lifetime_refs.len(), &lifetime_names, self.tcx.sess.source_map().span_to_snippet(span).ok().as_ref().map(|s| s.as_str()), + &self.missing_named_lifetime_spots, ); } @@ -2864,34 +2896,3 @@ fn insert_late_bound_lifetimes( } } } - -fn report_missing_lifetime_specifiers( - sess: &Session, - span: Span, - count: usize, -) -> DiagnosticBuilder<'_> { - struct_span_err!(sess, span, E0106, "missing lifetime specifier{}", pluralize!(count)) -} - -fn add_missing_lifetime_specifiers_label( - err: &mut DiagnosticBuilder<'_>, - span: Span, - count: usize, - lifetime_names: &FxHashSet<ast::Ident>, - snippet: Option<&str>, -) { - if count > 1 { - err.span_label(span, format!("expected {} lifetime parameters", count)); - } else if let (1, Some(name), Some("&")) = - (lifetime_names.len(), lifetime_names.iter().next(), snippet) - { - err.span_suggestion( - span, - "consider using the named lifetime", - format!("&{} ", name), - Applicability::MaybeIncorrect, - ); - } else { - err.span_label(span, "expected lifetime parameter"); - } -} diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 2f2ba560fa2..d252fc542c3 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1300,8 +1300,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.process_struct(item, def, ty_params) } Enum(ref def, ref ty_params) => self.process_enum(item, def, ty_params), - Impl(.., ref ty_params, ref trait_ref, ref typ, ref impl_items) => { - self.process_impl(item, ty_params, trait_ref, &typ, impl_items) + Impl { ref generics, ref of_trait, ref self_ty, ref items, .. } => { + self.process_impl(item, generics, of_trait, &self_ty, items) } Trait(_, _, ref generics, ref trait_refs, ref methods) => { self.process_trait(item, generics, trait_refs, methods) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c3221d925bc..537fe198a0c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -305,8 +305,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Impl(.., ref trait_ref, ref typ, ref impls) => { - if let ast::TyKind::Path(None, ref path) = typ.kind { + ast::ItemKind::Impl { ref of_trait, ref self_ty, ref items, .. } => { + if let ast::TyKind::Path(None, ref path) = self_ty.kind { // Common case impl for a struct or something basic. if generated_code(path.span) { return None; @@ -317,14 +317,14 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { let impl_id = self.next_impl_id(); let span = self.span_from_span(sub_span); - let type_data = self.lookup_def_id(typ.id); + let type_data = self.lookup_def_id(self_ty.id); type_data.map(|type_data| { Data::RelationData( Relation { kind: RelationKind::Impl { id: impl_id }, span: span.clone(), from: id_from_def_id(type_data), - to: trait_ref + to: of_trait .as_ref() .and_then(|t| self.lookup_def_id(t.ref_id)) .map(id_from_def_id) @@ -332,14 +332,14 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { }, Impl { id: impl_id, - kind: match *trait_ref { + kind: match *of_trait { Some(_) => ImplKind::Direct, None => ImplKind::Inherent, }, span: span, value: String::new(), parent: None, - children: impls + children: items .iter() .map(|i| id_from_node_id(i.id, self)) .collect(), @@ -405,9 +405,9 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { { Some(impl_id) => match self.tcx.hir().get_if_local(impl_id) { Some(Node::Item(item)) => match item.kind { - hir::ItemKind::Impl(.., ref ty, _) => { + hir::ItemKind::Impl { ref self_ty, .. } => { let mut qualname = String::from("<"); - qualname.push_str(&self.tcx.hir().hir_to_pretty_string(ty.hir_id)); + qualname.push_str(&self.tcx.hir().hir_to_pretty_string(self_ty.hir_id)); let trait_id = self.tcx.trait_id_of_impl(impl_id); let mut decl_id = None; diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index e7b86cfba4f..a9d2bfabb1b 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -482,15 +482,16 @@ impl Sig for ast::Item { Ok(sig) } - ast::ItemKind::Impl( + ast::ItemKind::Impl { unsafety, polarity, defaultness, + constness, ref generics, - ref opt_trait, - ref ty, - _, - ) => { + ref of_trait, + ref self_ty, + items: _, + } => { let mut text = String::new(); if let ast::Defaultness::Default = defaultness { text.push_str("default "); @@ -499,13 +500,16 @@ impl Sig for ast::Item { text.push_str("unsafe "); } text.push_str("impl"); + if constness == ast::Constness::Const { + text.push_str(" const"); + } let generics_sig = generics.make(offset + text.len(), id, scx)?; text.push_str(&generics_sig.text); text.push(' '); - let trait_sig = if let Some(ref t) = *opt_trait { + let trait_sig = if let Some(ref t) = *of_trait { if polarity == ast::ImplPolarity::Negative { text.push('!'); } @@ -517,7 +521,7 @@ impl Sig for ast::Item { text_sig(String::new()) }; - let ty_sig = ty.make(offset + text.len(), id, scx)?; + let ty_sig = self_ty.make(offset + text.len(), id, scx)?; text.push_str(&ty_sig.text); text.push_str(" {}"); diff --git a/src/librustc_session/Cargo.toml b/src/librustc_session/Cargo.toml index 377ea141ed5..47c23bc4dcf 100644 --- a/src/librustc_session/Cargo.toml +++ b/src/librustc_session/Cargo.toml @@ -10,7 +10,6 @@ path = "lib.rs" [dependencies] log = "0.4" -rustc_error_codes = { path = "../librustc_error_codes" } rustc_errors = { path = "../librustc_errors" } rustc_feature = { path = "../librustc_feature" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 4b5736adc17..2a0ed27b63b 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -923,8 +923,12 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, self_profile: SwitchWithOptPath = (SwitchWithOptPath::Disabled, parse_switch_with_opt_path, [UNTRACKED], "run the self profiler and output the raw event data"), + // keep this in sync with the event filter names in librustc_data_structures/profiling.rs self_profile_events: Option<Vec<String>> = (None, parse_opt_comma_list, [UNTRACKED], - "specifies which kinds of events get recorded by the self profiler"), + "specifies which kinds of events get recorded by the self profiler; + for example: `-Z self-profile-events=default,query-keys` + all options: none, all, default, generic-activity, query-provider, query-cache-hit + query-blocked, incr-cache-load, query-keys"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emits a section containing stack size metadata"), plt: Option<bool> = (None, parse_opt_bool, [TRACKED], diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index a98cf929095..72c68fcb244 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -6,7 +6,6 @@ use crate::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::{Lock, Lrc, Once}; -use rustc_error_codes::E0658; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{error_code, Applicability, DiagnosticBuilder}; use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures}; diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index fb5fcf4a830..9c7c0f0c8b0 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -473,20 +473,23 @@ impl SourceMap { lo.line != hi.line } - pub fn span_to_lines(&self, sp: Span) -> FileLinesResult { - debug!("span_to_lines(sp={:?})", sp); - + pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> { let lo = self.lookup_char_pos(sp.lo()); debug!("span_to_lines: lo={:?}", lo); let hi = self.lookup_char_pos(sp.hi()); debug!("span_to_lines: hi={:?}", hi); - if lo.file.start_pos != hi.file.start_pos { return Err(SpanLinesError::DistinctSources(DistinctSources { begin: (lo.file.name.clone(), lo.file.start_pos), end: (hi.file.name.clone(), hi.file.start_pos), })); } + Ok((lo, hi)) + } + + pub fn span_to_lines(&self, sp: Span) -> FileLinesResult { + debug!("span_to_lines(sp={:?})", sp); + let (lo, hi) = self.is_valid_span(sp)?; assert!(hi.line >= lo.line); let mut lines = Vec::with_capacity(hi.line - lo.line + 1); diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 17413e77f90..84c6d720b8e 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -11,7 +11,7 @@ #![feature(box_syntax)] #![feature(bool_to_option)] #![feature(nll)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #[macro_use] extern crate log; diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index 315efe5cf71..7df27e67d5b 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -195,8 +195,8 @@ crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> { }, Node::Item(item) => match item.kind { - ItemKind::Impl(.., Some(..), _, _) => NodeKind::TraitImpl, - ItemKind::Impl(.., None, _, _) => NodeKind::InherentImpl, + ItemKind::Impl { of_trait: Some(_), .. } => NodeKind::TraitImpl, + ItemKind::Impl { of_trait: None, .. } => NodeKind::InherentImpl, ItemKind::Fn(..) => NodeKind::Fn, _ => NodeKind::Other, }, diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 4b4fa4b7147..b77c603da9a 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -94,7 +94,7 @@ impl<'tcx> Lower<PolyDomainGoal<'tcx>> for ty::Predicate<'tcx> { use rustc::ty::Predicate; match self { - Predicate::Trait(predicate) => predicate.lower(), + Predicate::Trait(predicate, _) => predicate.lower(), Predicate::RegionOutlives(predicate) => predicate.lower(), Predicate::TypeOutlives(predicate) => predicate.lower(), Predicate::Projection(predicate) => predicate.lower(), diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs index 2548d2cff97..e5ec98743e0 100644 --- a/src/librustc_ty/lib.rs +++ b/src/librustc_ty/lib.rs @@ -8,7 +8,7 @@ #![feature(bool_to_option)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index fc8beb67e4a..8b62403e6ce 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -2,7 +2,7 @@ use rustc::hir::map as hir_map; use rustc::session::CrateDisambiguator; use rustc::traits::{self}; use rustc::ty::subst::Subst; -use rustc::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -58,6 +58,7 @@ fn sized_constraint_for_ty(tcx: TyCtxt<'tcx>, adtdef: &ty::AdtDef, ty: Ty<'tcx>) def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]), }) + .without_const() .to_predicate(); let predicates = tcx.predicates_of(adtdef.did).predicates; if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } @@ -128,8 +129,8 @@ fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem { let parent_def_id = tcx.hir().local_def_id(parent_id); let parent_item = tcx.hir().expect_item(parent_id); match parent_item.kind { - hir::ItemKind::Impl(.., ref impl_item_refs) => { - if let Some(impl_item_ref) = impl_item_refs.iter().find(|i| i.id.hir_id == id) { + hir::ItemKind::Impl { ref items, .. } => { + if let Some(impl_item_ref) = items.iter().find(|i| i.id.hir_id == id) { let assoc_item = associated_item_from_impl_item_ref(tcx, parent_def_id, impl_item_ref); debug_assert_eq!(assoc_item.def_id, def_id); @@ -194,8 +195,8 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { .map(|trait_item_ref| trait_item_ref.id) .map(|id| tcx.hir().local_def_id(id.hir_id)), ), - hir::ItemKind::Impl(.., ref impl_item_refs) => tcx.arena.alloc_from_iter( - impl_item_refs + hir::ItemKind::Impl { ref items, .. } => tcx.arena.alloc_from_iter( + items .iter() .map(|impl_item_ref| impl_item_ref.id) .map(|id| tcx.hir().local_def_id(id.hir_id)), diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 84e5f56d9c2..4b27d86dd02 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -22,4 +22,3 @@ smallvec = { version = "1.0", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } rustc_index = { path = "../librustc_index" } -rustc_error_codes = { path = "../librustc_error_codes" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a3be264ddc1..89eeed8d11e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -3,6 +3,8 @@ //! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an //! instance of `AstConv`. +// ignore-tidy-filelength + use crate::collect::PlaceholderHirTyCollector; use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; @@ -17,7 +19,7 @@ use rustc::traits::astconv_object_safety_violations; use rustc::traits::error_reporting::report_object_safety_error; use rustc::traits::wf::object_region_bounds; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; -use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId}; @@ -31,7 +33,7 @@ use rustc_span::symbol::sym; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; use smallvec::SmallVec; -use syntax::ast; +use syntax::ast::{self, Constness}; use syntax::util::lev_distance::find_best_match_for_name; use std::collections::BTreeSet; @@ -39,7 +41,6 @@ use std::iter; use std::slice; use rustc::mir::interpret::LitToConstInput; -use rustc_error_codes::*; #[derive(Debug)] pub struct PathSeg(pub DefId, pub usize); @@ -49,6 +50,8 @@ pub trait AstConv<'tcx> { fn item_def_id(&self) -> Option<DefId>; + fn default_constness_for_trait_bounds(&self) -> Constness; + /// Returns predicates in scope of the form `X: Foo`, where `X` is /// a type parameter `X` with the given id `def_id`. This is a /// subset of the full set of predicates. @@ -919,6 +922,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, trait_ref: &hir::TraitRef<'_>, span: Span, + constness: Constness, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, @@ -947,7 +951,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); - bounds.trait_bounds.push((poly_trait_ref, span)); + bounds.trait_bounds.push((poly_trait_ref, span, constness)); let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { @@ -993,12 +997,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn instantiate_poly_trait_ref( &self, poly_trait_ref: &hir::PolyTraitRef<'_>, + constness: Constness, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, ) -> Option<Vec<Span>> { self.instantiate_poly_trait_ref_inner( &poly_trait_ref.trait_ref, poly_trait_ref.span, + constness, self_ty, bounds, false, @@ -1181,18 +1187,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut trait_bounds = Vec::new(); let mut region_bounds = Vec::new(); + let constness = self.default_constness_for_trait_bounds(); for ast_bound in ast_bounds { match *ast_bound { hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => { - trait_bounds.push(b) + trait_bounds.push((b, constness)) + } + hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::MaybeConst) => { + trait_bounds.push((b, Constness::NotConst)) } hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} hir::GenericBound::Outlives(ref l) => region_bounds.push(l), } } - for bound in trait_bounds { - let _ = self.instantiate_poly_trait_ref(bound, param_ty, bounds); + for (bound, constness) in trait_bounds { + let _ = self.instantiate_poly_trait_ref(bound, constness, param_ty, bounds); } bounds.region_bounds.extend( @@ -1226,7 +1236,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut bounds = Bounds::default(); self.add_bounds(param_ty, ast_bounds, &mut bounds); - bounds.trait_bounds.sort_by_key(|(t, _)| t.def_id()); + bounds.trait_bounds.sort_by_key(|(t, _, _)| t.def_id()); bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { if !self.is_unsized(ast_bounds, span) { Some(span) } else { None } @@ -1320,10 +1330,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // those that do. self.one_bound_for_assoc_type( || traits::supertraits(tcx, trait_ref), - &trait_ref.print_only_trait_path().to_string(), + || trait_ref.print_only_trait_path().to_string(), binding.item_name, path_span, - match binding.kind { + || match binding.kind { ConvertedBindingKind::Equality(ty) => Some(ty.to_string()), _ => None, }, @@ -1417,15 +1427,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; for trait_bound in trait_bounds.iter().rev() { - let cur_potential_assoc_types = - self.instantiate_poly_trait_ref(trait_bound, dummy_self, &mut bounds); + let cur_potential_assoc_types = self.instantiate_poly_trait_ref( + trait_bound, + Constness::NotConst, + dummy_self, + &mut bounds, + ); potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); } // Expand trait aliases recursively and check that only one regular (non-auto) trait // is used and no 'maybe' bounds are used. - let expanded_traits = - traits::expand_trait_aliases(tcx, bounds.trait_bounds.iter().cloned()); + let expanded_traits = traits::expand_trait_aliases( + tcx, + bounds.trait_bounds.iter().map(|&(a, b, _)| (a.clone(), b)), + ); let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { @@ -1481,16 +1497,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let regular_traits_refs_spans = bounds .trait_bounds .into_iter() - .filter(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id())); + .filter(|(trait_ref, _, _)| !tcx.trait_is_auto(trait_ref.def_id())); + + for (base_trait_ref, span, constness) in regular_traits_refs_spans { + assert_eq!(constness, ast::Constness::NotConst); - for (base_trait_ref, span) in regular_traits_refs_spans { for trait_ref in traits::elaborate_trait_ref(tcx, base_trait_ref) { debug!( "conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", trait_ref ); match trait_ref { - ty::Predicate::Trait(pred) => { + ty::Predicate::Trait(pred, _) => { associated_types.entry(span).or_default().extend( tcx.associated_items(pred.def_id()) .filter(|item| item.kind == ty::AssocKind::Type) @@ -1880,10 +1898,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()), ) }, - ¶m_name.as_str(), + || param_name.to_string(), assoc_name, span, - None, + || None, ) } @@ -1892,10 +1910,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn one_bound_for_assoc_type<I>( &self, all_candidates: impl Fn() -> I, - ty_param_name: &str, + ty_param_name: impl Fn() -> String, assoc_name: ast::Ident, span: Span, - is_equality: Option<String>, + is_equality: impl Fn() -> Option<String>, ) -> Result<ty::PolyTraitRef<'tcx>, ErrorReported> where I: Iterator<Item = ty::PolyTraitRef<'tcx>>, @@ -1908,7 +1926,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { None => { self.complain_about_assoc_type_not_found( all_candidates, - ty_param_name, + &ty_param_name(), assoc_name, span, ); @@ -1921,6 +1939,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(bound2) = matching_candidates.next() { debug!("one_bound_for_assoc_type: bound2 = {:?}", bound2); + let is_equality = is_equality(); let bounds = iter::once(bound).chain(iter::once(bound2)).chain(matching_candidates); let mut err = if is_equality.is_some() { // More specific Error Index entry. @@ -1930,7 +1949,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { E0222, "ambiguous associated type `{}` in bounds of `{}`", assoc_name, - ty_param_name + ty_param_name() ) } else { struct_span_err!( @@ -1939,7 +1958,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { E0221, "ambiguous associated type `{}` in bounds of `{}`", assoc_name, - ty_param_name + ty_param_name() ) }; err.span_label(span, format!("ambiguous associated type `{}`", assoc_name)); @@ -1977,7 +1996,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "use fully qualified syntax to disambiguate", format!( "<{} as {}>::{}", - ty_param_name, + ty_param_name(), bound.print_only_trait_path(), assoc_name, ), @@ -1987,7 +2006,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { err.note(&format!( "associated type `{}` could derive from `{}`", - ty_param_name, + ty_param_name(), bound.print_only_trait_path(), )); } @@ -1996,7 +2015,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.help(&format!( "consider introducing a new type parameter `T` and adding `where` constraints:\ \n where\n T: {},\n{}", - ty_param_name, + ty_param_name(), where_bounds.join(",\n"), )); } @@ -2110,10 +2129,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.one_bound_for_assoc_type( || traits::supertraits(tcx, ty::Binder::bind(trait_ref)), - "Self", + || "Self".to_string(), assoc_ident, span, - None, + || None, )? } (&ty::Param(_), Res::SelfTy(Some(param_did), None)) @@ -2948,7 +2967,7 @@ pub struct Bounds<'tcx> { /// A list of trait bounds. So if you had `T: Debug` this would be /// `T: Debug`. Note that the self-type is explicit here. - pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span)>, + pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, Constness)>, /// A list of projection equality bounds. So if you had `T: /// Iterator<Item = u32>` this would include `<T as @@ -2979,7 +2998,7 @@ impl<'tcx> Bounds<'tcx> { def_id: sized, substs: tcx.mk_substs_trait(param_ty, &[]), }); - (trait_ref.to_predicate(), span) + (trait_ref.without_const().to_predicate(), span) }) }); @@ -2996,11 +3015,10 @@ impl<'tcx> Bounds<'tcx> { let outlives = ty::OutlivesPredicate(param_ty, region_bound); (ty::Binder::bind(outlives).to_predicate(), span) }) - .chain( - self.trait_bounds - .iter() - .map(|&(bound_trait_ref, span)| (bound_trait_ref.to_predicate(), span)), - ) + .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| { + let predicate = bound_trait_ref.with_constness(constness).to_predicate(); + (predicate, span) + })) .chain( self.projection_bounds .iter() diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 8d6b74c3015..e4dec97183c 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -5,7 +5,7 @@ use rustc::infer::{InferCtxt, InferOk}; use rustc::session::DiagnosticMessageId; use rustc::traits::{self, TraitEngine}; use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; -use rustc::ty::{self, TraitRef, Ty, TyCtxt}; +use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; use rustc::ty::{ToPredicate, TypeFoldable}; use rustc_errors::struct_span_err; use rustc_hir as hir; @@ -13,8 +13,6 @@ use rustc_hir as hir; use rustc_span::Span; use syntax::ast::Ident; -use rustc_error_codes::*; - use std::iter; #[derive(Copy, Clone, Debug)] @@ -124,8 +122,11 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { let cause = traits::ObligationCause::misc(self.span, self.body_id); - let obligation = - traits::Obligation::new(cause.clone(), self.param_env, trait_ref.to_predicate()); + let obligation = traits::Obligation::new( + cause.clone(), + self.param_env, + trait_ref.without_const().to_predicate(), + ); if !self.infcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); return None; diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 58f407b8902..b33cc52b238 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -8,7 +8,6 @@ use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoB use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::{infer, traits}; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::Res; diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index cbbfe2d6278..d254a84df72 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -49,8 +49,6 @@ use rustc_hir as hir; use rustc_span::Span; use syntax::ast; -use rustc_error_codes::*; - /// Reifies a cast check to be checked once we have full type information for /// a function context. pub struct CastCheck<'tcx> { diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index a32fbff7bfe..54b32c3a50f 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -65,7 +65,6 @@ use rustc::ty::fold::TypeFoldable; use rustc::ty::relate::RelateResult; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeAndMut}; -use rustc_error_codes::*; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -565,7 +564,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { + ty::Predicate::Trait(ref tr, _) if traits.contains(&tr.def_id()) => { if unsize_did == tr.def_id() { let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind; if let ty::Tuple(..) = sty { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index c35661ac649..414f80d84b6 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -15,8 +15,6 @@ use rustc_span::Span; use super::{potentially_plural_count, FnCtxt, Inherited}; -use rustc_error_codes::*; - /// Checks that a method from an impl conforms to the signature of /// the same method as declared in the trait. /// diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 88e7a265ebb..32773e2ed80 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -14,8 +14,6 @@ use rustc_errors::struct_span_err; use rustc_span::Span; -use rustc_error_codes::*; - /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is /// attached to (Issue #8142). @@ -234,7 +232,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let predicate_matches_closure = |p: &'_ Predicate<'tcx>| { let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env); match (predicate, p) { - (Predicate::Trait(a), Predicate::Trait(b)) => relator.relate(a, b).is_ok(), + (Predicate::Trait(a, _), Predicate::Trait(b, _)) => relator.relate(a, b).is_ok(), (Predicate::Projection(a), Predicate::Projection(b)) => { relator.relate(a, b).is_ok() } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 35342de59a0..201a09fdc63 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -38,8 +38,6 @@ use rustc_span::symbol::{kw, sym, Symbol}; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; -use rustc_error_codes::*; - use std::fmt::Display; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 0441514c83c..3572eda5c13 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -6,7 +6,6 @@ use crate::require_same_types; use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_span::symbol::Symbol; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 636ea5b87d6..2012a2a1526 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -569,7 +569,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { traits::elaborate_predicates(self.tcx, predicates.predicates.clone()) .filter_map(|predicate| match predicate { - ty::Predicate::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => { + ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => { Some(trait_pred) } _ => None, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 711c285d17e..c1cf3522b5d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -17,7 +17,7 @@ use rustc::traits; use rustc::ty::subst::Subst; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::GenericParamDefKind; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -322,7 +322,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.body_id, self.param_env, - poly_trait_ref.to_predicate(), + poly_trait_ref.without_const().to_predicate(), ); // Now we want to know if this can be matched diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b2542cc27a5..2adf125f048 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -25,6 +25,7 @@ use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, + WithConstness, }; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; @@ -38,8 +39,6 @@ use std::ops::Deref; use syntax::ast; use syntax::util::lev_distance::{find_best_match_for_name, lev_distance}; -use rustc_error_codes::*; - use smallvec::{smallvec, SmallVec}; use self::CandidateKind::*; @@ -826,7 +825,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // FIXME: do we want to commit to this behavior for param bounds? let bounds = self.param_env.caller_bounds.iter().filter_map(|predicate| match *predicate { - ty::Predicate::Trait(ref trait_predicate) => { + ty::Predicate::Trait(ref trait_predicate, _) => { match trait_predicate.skip_binder().trait_ref.self_ty().kind { ty::Param(ref p) if *p == param_ty => Some(trait_predicate.to_poly_trait_ref()), _ => None, @@ -1396,7 +1395,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } TraitCandidate(trait_ref) => { - let predicate = trait_ref.to_predicate(); + let predicate = trait_ref.without_const().to_predicate(); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) { @@ -1430,7 +1429,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - if let &ty::Predicate::Trait(ref pred) = &o.predicate { + if let &ty::Predicate::Trait(ref pred, _) = &o.predicate { possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index d6c0d9c77b4..e9942fad3bc 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -9,7 +9,7 @@ use rustc::hir::map::Map; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::traits::Obligation; use rustc::ty::print::with_crate_prefix; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -21,8 +21,6 @@ use rustc_span::{source_map, FileName, Span}; use syntax::ast; use syntax::util::lev_distance; -use rustc_error_codes::*; - use std::cmp::Ordering; use super::probe::Mode; @@ -59,7 +57,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, self.body_id, self.param_env, - poly_trait_ref.to_predicate(), + poly_trait_ref.without_const().to_predicate(), ); self.predicate_may_hold(&obligation) }) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index dff68b9986c..3818750e920 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,6 +90,7 @@ pub mod writeback; use crate::astconv::{AstConv, PathSeg}; use crate::middle::lang_items; use crate::namespace::Namespace; +use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; @@ -112,7 +113,7 @@ use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSel use rustc::ty::util::{Discr, IntTypeExt, Representability}; use rustc::ty::{ self, AdtKind, CanonicalUserType, Const, GenericParamDefKind, RegionKind, ToPolyTraitRef, - ToPredicate, Ty, TyCtxt, UserType, + ToPredicate, Ty, TyCtxt, UserType, WithConstness, }; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -133,8 +134,6 @@ use syntax::ast; use syntax::attr; use syntax::util::parser::ExprPrecedence; -use rustc_error_codes::*; - use std::cell::{Cell, Ref, RefCell, RefMut}; use std::cmp; use std::collections::hash_map::Entry; @@ -1423,7 +1422,7 @@ fn check_fn<'a, 'tcx>( inherited.register_predicate(traits::Obligation::new( cause, param_env, - trait_ref.to_predicate(), + trait_ref.without_const().to_predicate(), )); } } @@ -1709,17 +1708,11 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { check_enum(tcx, it.span, &enum_definition.variants, it.hir_id); } hir::ItemKind::Fn(..) => {} // entirely within check_item_body - hir::ItemKind::Impl(.., ref impl_item_refs) => { + hir::ItemKind::Impl { ref items, .. } => { debug!("ItemKind::Impl {} with id {}", it.ident, it.hir_id); let impl_def_id = tcx.hir().local_def_id(it.hir_id); if let Some(impl_trait_ref) = tcx.impl_trait_ref(impl_def_id) { - check_impl_items_against_trait( - tcx, - it.span, - impl_def_id, - impl_trait_ref, - impl_item_refs, - ); + check_impl_items_against_trait(tcx, it.span, impl_def_id, impl_trait_ref, items); let trait_def_id = impl_trait_ref.def_id; check_on_unimplemented(tcx, trait_def_id, it); } @@ -2618,6 +2611,16 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { None } + fn default_constness_for_trait_bounds(&self) -> ast::Constness { + // FIXME: refactor this into a method + let node = self.tcx.hir().get(self.body_id); + if let Some(fn_like) = FnLikeNode::from_node(node) { + fn_like.constness() + } else { + ast::Constness::NotConst + } + } + fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { let tcx = self.tcx; let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -2629,7 +2632,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { parent: None, predicates: tcx.arena.alloc_from_iter(self.param_env.caller_bounds.iter().filter_map( |&predicate| match predicate { - ty::Predicate::Trait(ref data) + ty::Predicate::Trait(ref data, _) if data.skip_binder().self_ty().is_param(index) => { // HACK(eddyb) should get the original `Span`. @@ -3701,7 +3704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Predicate::Projection(ref data) => { Some((data.to_poly_trait_ref(self.tcx), obligation)) } - ty::Predicate::Trait(ref data) => Some((data.to_poly_trait_ref(), obligation)), + ty::Predicate::Trait(ref data, _) => Some((data.to_poly_trait_ref(), obligation)), ty::Predicate::Subtype(..) => None, ty::Predicate::RegionOutlives(..) => None, ty::Predicate::TypeOutlives(..) => None, @@ -4004,7 +4007,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } - if let ty::Predicate::Trait(predicate) = error.obligation.predicate { + if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate { // Collect the argument position for all arguments that could have caused this // `FulfillmentError`. let mut referenced_in = final_arg_types @@ -4048,7 +4051,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::ExprKind::Path(qpath) = &path.kind { if let hir::QPath::Resolved(_, path) = &qpath { for error in errors { - if let ty::Predicate::Trait(predicate) = error.obligation.predicate { + if let ty::Predicate::Trait(predicate, _) = error.obligation.predicate { // If any of the type arguments in this path segment caused the // `FullfillmentError`, point at its span (#61860). for arg in path diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index edf9d19dea3..91e1731ac45 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -11,8 +11,6 @@ use rustc_hir as hir; use rustc_span::Span; use syntax::ast::Ident; -use rustc_error_codes::*; - impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a <op>= b` pub fn check_binop_assign( diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 1478b35a25d..f9dee0e477f 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -15,8 +15,6 @@ use rustc_span::Span; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; -use rustc_error_codes::*; - use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index a496a6e12ce..82811826ae7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -6,7 +6,9 @@ use rustc::middle::lang_items; use rustc::session::parse::feature_err; use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::subst::{InternalSubsts, Subst}; -use rustc::ty::{self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{ + self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, +}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir::def_id::DefId; @@ -18,8 +20,6 @@ use syntax::ast; use rustc_hir as hir; use rustc_hir::itemlikevisit::ParItemLikeVisitor; -use rustc_error_codes::*; - /// Helper type of a temporary returned by `.for_item(...)`. /// This is necessary because we can't write the following bound: /// @@ -97,7 +97,7 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) { // // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` - hir::ItemKind::Impl(_, _, defaultness, _, ref trait_ref, ref self_ty, _) => { + hir::ItemKind::Impl { defaultness, ref of_trait, ref self_ty, .. } => { let is_auto = tcx .impl_trait_ref(tcx.hir().local_def_id(item.hir_id)) .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); @@ -107,11 +107,11 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) { } match polarity { ty::ImplPolarity::Positive => { - check_impl(tcx, item, self_ty, trait_ref); + check_impl(tcx, item, self_ty, of_trait); } ty::ImplPolarity::Negative => { // FIXME(#27579): what amount of WF checking do we need for neg impls? - if trait_ref.is_some() && !is_auto { + if of_trait.is_some() && !is_auto { struct_span_err!( tcx.sess, item.span, @@ -955,7 +955,8 @@ fn receiver_is_implemented( substs: fcx.tcx.mk_substs_trait(receiver_ty, &[]), }; - let obligation = traits::Obligation::new(cause, fcx.param_env, trait_ref.to_predicate()); + let obligation = + traits::Obligation::new(cause, fcx.param_env, trait_ref.without_const().to_predicate()); if fcx.predicate_must_hold_modulo_regions(&obligation) { true diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 8b3db15c02b..79a006a898a 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -12,7 +12,6 @@ use rustc::traits::{self, ObligationCause, TraitEngine}; use rustc::ty::adjustment::CoerceUnsizedInfo; use rustc::ty::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -57,7 +56,7 @@ fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) { let impl_hir_id = tcx.hir().as_local_hir_id(impl_did).expect("foreign Drop impl on non-ADT"); let sp = match tcx.hir().expect_item(impl_hir_id).kind { - ItemKind::Impl(.., ty, _) => ty.span, + ItemKind::Impl { self_ty, .. } => self_ty.span, _ => bug!("expected Drop impl item"), }; @@ -94,7 +93,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) { Ok(()) => {} Err(CopyImplementationError::InfrigingFields(fields)) => { let item = tcx.hir().expect_item(impl_hir_id); - let span = if let ItemKind::Impl(.., Some(ref tr), _, _) = item.kind { + let span = if let ItemKind::Impl { of_trait: Some(ref tr), .. } = item.kind { tr.path.span } else { span @@ -113,7 +112,8 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: DefId) { } Err(CopyImplementationError::NotAnAdt) => { let item = tcx.hir().expect_item(impl_hir_id); - let span = if let ItemKind::Impl(.., ref ty, _) = item.kind { ty.span } else { span }; + let span = + if let ItemKind::Impl { self_ty, .. } = item.kind { self_ty.span } else { span }; struct_span_err!( tcx.sess, @@ -490,7 +490,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn return err_info; } else if diff_fields.len() > 1 { let item = tcx.hir().expect_item(impl_hir_id); - let span = if let ItemKind::Impl(.., Some(ref t), _, _) = item.kind { + let span = if let ItemKind::Impl { of_trait: Some(ref t), .. } = item.kind { t.path.span } else { tcx.hir().span(impl_hir_id) diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index 673c1bd9fd8..d4c89b7e037 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -16,8 +16,6 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_span::Span; use syntax::ast; -use rustc_error_codes::*; - /// On-demand query: yields a map containing all types mapped to their inherent impls. pub fn crate_inherent_impls(tcx: TyCtxt<'_>, crate_num: CrateNum) -> &CrateInherentImpls { assert_eq!(crate_num, LOCAL_CRATE); @@ -47,7 +45,7 @@ struct InherentCollect<'tcx> { impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { let ty = match item.kind { - hir::ItemKind::Impl(.., None, ref ty, _) => ty, + hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty, _ => return, }; diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index a9228c7f6bb..d60c3cfba9a 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -6,8 +6,6 @@ use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_error_codes::*; - pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) { assert_eq!(crate_num, LOCAL_CRATE); let krate = tcx.hir().krate(); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index fd685e77b41..5583e3418b2 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -8,7 +8,6 @@ use rustc::traits; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; -use rustc_error_codes::*; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::HirId; diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 1878f9385a8..80521666476 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -7,8 +7,6 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_error_codes::*; - pub fn check(tcx: TyCtxt<'_>) { let mut orphan = OrphanChecker { tcx }; tcx.hir().krate().visit_all_item_likes(&mut orphan); @@ -27,7 +25,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { fn visit_item(&mut self, item: &hir::Item<'_>) { let def_id = self.tcx.hir().local_def_id(item.hir_id); // "Trait" impl - if let hir::ItemKind::Impl(.., generics, Some(tr), impl_ty, _) = &item.kind { + if let hir::ItemKind::Impl { generics, of_trait: Some(ref tr), self_ty, .. } = &item.kind { debug!( "coherence2::orphan check: trait impl {}", self.tcx.hir().node_to_string(item.hir_id) @@ -72,7 +70,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { let msg = format!("{} is not defined in the current crate{}", ty, postfix); if *is_target_ty { // Point at `D<A>` in `impl<A, B> for C<B> in D<A>` - err.span_label(impl_ty.span, &msg); + err.span_label(self_ty.span, &msg); } else { // Point at `C<B>` in `impl<A, B> for C<B> in D<A>` err.span_label(tr.path.span, &msg); diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index 3f4035b0998..a6044217403 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -7,8 +7,6 @@ use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::Unsafety; -use rustc_error_codes::*; - pub fn check(tcx: TyCtxt<'_>) { let mut unsafety = UnsafetyChecker { tcx }; tcx.hir().krate().visit_all_item_likes(&mut unsafety); @@ -88,7 +86,7 @@ impl UnsafetyChecker<'tcx> { impl ItemLikeVisitor<'v> for UnsafetyChecker<'tcx> { fn visit_item(&mut self, item: &'v hir::Item<'v>) { - if let hir::ItemKind::Impl(unsafety, polarity, _, ref generics, ..) = item.kind { + if let hir::ItemKind::Impl { unsafety, polarity, ref generics, .. } = item.kind { self.check_unsafety_coherence(item, Some(generics), unsafety, polarity); } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index dca3289747e..5821977391b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -20,6 +20,7 @@ use crate::constrained_generic_params as cgp; use crate::lint; use crate::middle::resolve_lifetime as rl; use crate::middle::weak_lang_items; +use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::mir::mono::Linkage; @@ -30,7 +31,7 @@ use rustc::ty::subst::GenericArgKind; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::Discr; use rustc::ty::util::IntTypeExt; -use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt}; +use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness}; use rustc::ty::{ReprOptions, ToPredicate}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; @@ -47,8 +48,6 @@ use syntax::ast; use syntax::ast::{Ident, MetaItemKind}; use syntax::attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr}; -use rustc_error_codes::*; - struct OnlySelfBounds(bool); /////////////////////////////////////////////////////////////////////////// @@ -184,7 +183,7 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir | hir::ItemKind::Enum(_, generics) | hir::ItemKind::TraitAlias(generics, _) | hir::ItemKind::Trait(_, _, generics, ..) - | hir::ItemKind::Impl(_, _, _, generics, ..) + | hir::ItemKind::Impl { generics, .. } | hir::ItemKind::Struct(_, generics) => (generics, true), hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }) | hir::ItemKind::TyAlias(_, generics) => (generics, false), @@ -288,6 +287,22 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { Some(self.item_def_id) } + fn default_constness_for_trait_bounds(&self) -> ast::Constness { + // FIXME: refactor this into a method + let hir_id = self + .tcx + .hir() + .as_local_hir_id(self.item_def_id) + .expect("Non-local call to local provider is_const_fn"); + + let node = self.tcx.hir().get(hir_id); + if let Some(fn_like) = FnLikeNode::from_node(node) { + fn_like.constness() + } else { + ast::Constness::NotConst + } + } + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { self.tcx.at(span).type_param_predicates((self.item_def_id, def_id)) } @@ -401,7 +416,7 @@ fn type_param_predicates( Node::Item(item) => { match item.kind { ItemKind::Fn(.., ref generics, _) - | ItemKind::Impl(_, _, _, ref generics, ..) + | ItemKind::Impl { ref generics, .. } | ItemKind::TyAlias(_, ref generics) | ItemKind::OpaqueTy(OpaqueTy { ref generics, impl_trait_fn: None, .. }) | ItemKind::Enum(_, ref generics) @@ -411,7 +426,8 @@ fn type_param_predicates( // Implied `Self: Trait` and supertrait bounds. if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - extend = Some((identity_trait_ref.to_predicate(), item.span)); + extend = + Some((identity_trait_ref.without_const().to_predicate(), item.span)); } generics } @@ -432,7 +448,7 @@ fn type_param_predicates( icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true)) .into_iter() .filter(|(predicate, _)| match predicate { - ty::Predicate::Trait(ref data) => data.skip_binder().self_ty().is_param(index), + ty::Predicate::Trait(ref data, _) => data.skip_binder().self_ty().is_param(index), _ => false, }), ); @@ -453,6 +469,7 @@ impl ItemCtxt<'tcx> { ty: Ty<'tcx>, only_self_bounds: OnlySelfBounds, ) -> Vec<(ty::Predicate<'tcx>, Span)> { + let constness = self.default_constness_for_trait_bounds(); let from_ty_params = ast_generics .params .iter() @@ -461,7 +478,7 @@ impl ItemCtxt<'tcx> { _ => None, }) .flat_map(|bounds| bounds.iter()) - .flat_map(|b| predicates_from_bound(self, ty, b)); + .flat_map(|b| predicates_from_bound(self, ty, b, constness)); let from_where_clauses = ast_generics .where_clause @@ -481,7 +498,7 @@ impl ItemCtxt<'tcx> { }; bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b))) }) - .flat_map(|(bt, b)| predicates_from_bound(self, bt, b)); + .flat_map(|(bt, b)| predicates_from_bound(self, bt, b, constness)); from_ty_params.chain(from_where_clauses).collect() } @@ -531,7 +548,7 @@ fn convert_item(tcx: TyCtxt<'_>, item_id: hir::HirId) { tcx.predicates_of(def_id); convert_enum_variant_types(tcx, def_id, &enum_definition.variants); } - hir::ItemKind::Impl(..) => { + hir::ItemKind::Impl { .. } => { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.impl_trait_ref(def_id); @@ -857,7 +874,7 @@ fn super_predicates_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> ty::GenericPredi // which will, in turn, reach indirect supertraits. for &(pred, span) in superbounds { debug!("superbound: {:?}", pred); - if let ty::Predicate::Trait(bound) = pred { + if let ty::Predicate::Trait(bound, _) = pred { tcx.at(span).super_predicates_of(bound.def_id()); } } @@ -1052,9 +1069,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { Node::Item(item) => { match item.kind { - ItemKind::Fn(.., ref generics, _) | ItemKind::Impl(_, _, _, ref generics, ..) => { - generics - } + ItemKind::Fn(.., ref generics, _) | ItemKind::Impl { ref generics, .. } => generics, ItemKind::TyAlias(_, ref generics) | ItemKind::Enum(_, ref generics) @@ -1338,7 +1353,9 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { icx.to_ty(ty) } } - ItemKind::TyAlias(ref ty, _) | ItemKind::Impl(.., ref ty, _) => icx.to_ty(ty), + ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => { + icx.to_ty(self_ty) + } ItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs) @@ -1956,12 +1973,10 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::TraitRef<'_>> { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); match tcx.hir().expect_item(hir_id).kind { - hir::ItemKind::Impl(.., ref opt_trait_ref, _, _) => { - opt_trait_ref.as_ref().map(|ast_trait_ref| { - let selfty = tcx.type_of(def_id); - AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) - }) - } + hir::ItemKind::Impl { ref of_trait, .. } => of_trait.as_ref().map(|ast_trait_ref| { + let selfty = tcx.type_of(def_id); + AstConv::instantiate_mono_trait_ref(&icx, ast_trait_ref, selfty) + }), _ => bug!(), } } @@ -1971,19 +1986,21 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); let item = tcx.hir().expect_item(hir_id); match &item.kind { - hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => { + hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => { if is_rustc_reservation { tcx.sess.span_err(item.span, "reservation impls can't be negative"); } ty::ImplPolarity::Negative } - hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => { + hir::ItemKind::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => { if is_rustc_reservation { tcx.sess.span_err(item.span, "reservation impls can't be inherent"); } ty::ImplPolarity::Positive } - hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => { + hir::ItemKind::Impl { + polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. + } => { if is_rustc_reservation { ty::ImplPolarity::Reservation } else { @@ -2056,7 +2073,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { let span = tcx.def_span(def_id); result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).to_predicate(), + ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(), span, )))); } @@ -2106,6 +2123,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat let mut is_default_impl_trait = None; let icx = ItemCtxt::new(tcx, def_id); + let constness = icx.default_constness_for_trait_bounds(); const NO_GENERICS: &hir::Generics<'_> = &hir::Generics::empty(); @@ -2142,7 +2160,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat Node::Item(item) => { match item.kind { - ItemKind::Impl(_, _, defaultness, ref generics, ..) => { + ItemKind::Impl { defaultness, ref generics, .. } => { if defaultness.is_default() { is_default_impl_trait = tcx.impl_trait_ref(def_id); } @@ -2230,7 +2248,10 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.push((trait_ref.to_poly_trait_ref().to_predicate(), tcx.def_span(def_id))); + predicates.push(( + trait_ref.to_poly_trait_ref().without_const().to_predicate(), + tcx.def_span(def_id), + )); } // Collect the region predicates that were declared inline as @@ -2304,11 +2325,18 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat for bound in bound_pred.bounds.iter() { match bound { - &hir::GenericBound::Trait(ref poly_trait_ref, _) => { + &hir::GenericBound::Trait(ref poly_trait_ref, modifier) => { + let constness = match modifier { + hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst, + hir::TraitBoundModifier::None => constness, + hir::TraitBoundModifier::Maybe => bug!("this wasn't handled"), + }; + let mut bounds = Bounds::default(); let _ = AstConv::instantiate_poly_trait_ref( &icx, poly_trait_ref, + constness, ty, &mut bounds, ); @@ -2359,7 +2387,7 @@ fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicat // before uses of `U`. This avoids false ambiguity errors // in trait checking. See `setup_constraining_predicates` // for details. - if let Node::Item(&Item { kind: ItemKind::Impl(..), .. }) = node { + if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node { let self_ty = tcx.type_of(def_id); let trait_ref = tcx.impl_trait_ref(def_id); cgp::setup_constraining_predicates( @@ -2484,11 +2512,18 @@ fn predicates_from_bound<'tcx>( astconv: &dyn AstConv<'tcx>, param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, + constness: ast::Constness, ) -> Vec<(ty::Predicate<'tcx>, Span)> { match *bound { - hir::GenericBound::Trait(ref tr, hir::TraitBoundModifier::None) => { + hir::GenericBound::Trait(ref tr, modifier) => { + let constness = match modifier { + hir::TraitBoundModifier::Maybe => return vec![], + hir::TraitBoundModifier::MaybeConst => ast::Constness::NotConst, + hir::TraitBoundModifier::None => constness, + }; + let mut bounds = Bounds::default(); - let _ = astconv.instantiate_poly_trait_ref(tr, param_ty, &mut bounds); + let _ = astconv.instantiate_poly_trait_ref(tr, constness, param_ty, &mut bounds); bounds.predicates(astconv.tcx(), param_ty) } hir::GenericBound::Outlives(ref lifetime) => { @@ -2496,7 +2531,6 @@ fn predicates_from_bound<'tcx>( let pred = ty::Binder::bind(ty::OutlivesPredicate(param_ty, region)); vec![(ty::Predicate::TypeOutlives(pred), lifetime.span)] } - hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => vec![], } } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index fb87b285fa2..e9c18b59da9 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -20,8 +20,6 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use rustc_span::Span; -use rustc_error_codes::*; - /// Checks that all the type/lifetime parameters on an impl also /// appear in the trait ref or self type (or are constrained by a /// where-clause). These rules are needed to ensure that, given a @@ -75,10 +73,10 @@ struct ImplWfCheck<'tcx> { impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { - if let hir::ItemKind::Impl(.., ref impl_item_refs) = item.kind { + if let hir::ItemKind::Impl { ref items, .. } = item.kind { let impl_def_id = self.tcx.hir().local_def_id(item.hir_id); - enforce_impl_params_are_constrained(self.tcx, impl_def_id, impl_item_refs); - enforce_impl_items_are_distinct(self.tcx, impl_item_refs); + enforce_impl_params_are_constrained(self.tcx, impl_def_id, items); + enforce_impl_items_are_distinct(self.tcx, items); } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index b951883ac19..3d27f9191dd 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -64,7 +64,7 @@ This API is completely unstable and subject to change. #![feature(exhaustive_patterns)] #![feature(in_band_lifetimes)] #![feature(nll)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(try_blocks)] #![feature(never_type)] #![recursion_limit = "256"] @@ -109,8 +109,6 @@ use rustc_hir::Node; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; -use rustc_error_codes::*; - use std::iter; use astconv::{AstConv, Bounds}; @@ -382,6 +380,7 @@ pub fn hir_trait_to_predicates<'tcx>( &item_cx, hir_trait, DUMMY_SP, + syntax::ast::Constness::NotConst, tcx.types.err, &mut bounds, true, diff --git a/src/librustc_typeck/outlives/test.rs b/src/librustc_typeck/outlives/test.rs index 908429c8dc4..980d58ad939 100644 --- a/src/librustc_typeck/outlives/test.rs +++ b/src/librustc_typeck/outlives/test.rs @@ -4,8 +4,6 @@ use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_span::symbol::sym; -use rustc_error_codes::*; - pub fn test_inferred_outlives(tcx: TyCtxt<'_>) { tcx.hir().krate().visit_all_item_likes(&mut OutlivesTest { tcx }); } diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs index 068814723f5..99b7b2001a9 100644 --- a/src/librustc_typeck/structured_errors.rs +++ b/src/librustc_typeck/structured_errors.rs @@ -3,8 +3,6 @@ use rustc::ty::{Ty, TypeFoldable}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_span::Span; -use rustc_error_codes::*; - pub trait StructuredDiagnostic<'tcx> { fn session(&self) -> &Session; diff --git a/src/librustc_typeck/variance/test.rs b/src/librustc_typeck/variance/test.rs index 2f41bee1819..ee94b1015a1 100644 --- a/src/librustc_typeck/variance/test.rs +++ b/src/librustc_typeck/variance/test.rs @@ -4,8 +4,6 @@ use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_span::symbol::sym; -use rustc_error_codes::*; - pub fn test_variance(tcx: TyCtxt<'_>) { tcx.hir().krate().visit_all_item_likes(&mut VarianceTest { tcx }); } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index f37f6921ceb..27f8059691a 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -462,7 +462,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { .filter(|p| { !orig_bounds.contains(p) || match p { - &&ty::Predicate::Trait(pred) => pred.def_id() == sized_trait, + ty::Predicate::Trait(pred, _) => pred.def_id() == sized_trait, _ => false, } }) diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 525b1b2e6ec..18ebd254507 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,7 +1,7 @@ use rustc::infer::InferOk; use rustc::traits; use rustc::ty::subst::Subst; -use rustc::ty::ToPredicate; +use rustc::ty::{ToPredicate, WithConstness}; use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_span::DUMMY_SP; @@ -64,7 +64,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { match infcx.evaluate_obligation(&traits::Obligation::new( cause, param_env, - trait_ref.to_predicate(), + trait_ref.without_const().to_predicate(), )) { Ok(eval_result) => eval_result.may_apply(), Err(traits::OverflowError) => true, // overflow doesn't mean yes *or* no diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c7e0f1e9e70..8a6abe036dc 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -273,6 +273,22 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef { clean::Typedef { type_: cx.tcx.type_of(did).clean(cx), generics: (cx.tcx.generics_of(did), predicates).clean(cx), + item_type: build_type_alias_type(cx, did), + } +} + +fn build_type_alias_type(cx: &DocContext<'_>, did: DefId) -> Option<clean::Type> { + let type_ = cx.tcx.type_of(did).clean(cx); + type_.def_id().and_then(|did| build_ty(cx, did)) +} + +pub fn build_ty(cx: &DocContext, did: DefId) -> Option<clean::Type> { + match cx.tcx.def_kind(did)? { + DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Const | DefKind::Static => { + Some(cx.tcx.type_of(did).clean(cx)) + } + DefKind::TyAlias => build_type_alias_type(cx, did), + _ => None, } } @@ -331,7 +347,7 @@ pub fn build_impl( let for_ = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) { match tcx.hir().expect_item(hir_id).kind { - hir::ItemKind::Impl(.., ref t, _) => t.clean(cx), + hir::ItemKind::Impl { self_ty, .. } => self_ty.clean(cx), _ => panic!("did given to build_impl was not an impl"), } } else { @@ -351,9 +367,9 @@ pub fn build_impl( let predicates = tcx.explicit_predicates_of(did); let (trait_items, generics) = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) { match tcx.hir().expect_item(hir_id).kind { - hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => ( - item_ids.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>(), - gen.clean(cx), + hir::ItemKind::Impl { ref generics, ref items, .. } => ( + items.iter().map(|item| tcx.hir().impl_item(item.id).clean(cx)).collect::<Vec<_>>(), + generics.clean(cx), ), _ => panic!("did given to build_impl was not an impl"), } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index be9654612f5..7a7d69c68a5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -482,7 +482,7 @@ impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> { use rustc::ty::Predicate; match *self { - Predicate::Trait(ref pred) => Some(pred.clean(cx)), + Predicate::Trait(ref pred, _) => Some(pred.clean(cx)), Predicate::Subtype(ref pred) => Some(pred.clean(cx)), Predicate::RegionOutlives(ref pred) => pred.clean(cx), Predicate::TypeOutlives(ref pred) => pred.clean(cx), @@ -1122,7 +1122,9 @@ impl Clean<Item> for hir::ImplItem<'_> { MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx)) } hir::ImplItemKind::TyAlias(ref ty) => { - TypedefItem(Typedef { type_: ty.clean(cx), generics: Generics::default() }, true) + let type_ = ty.clean(cx); + let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); + TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true) } hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem( OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() }, @@ -1282,10 +1284,13 @@ impl Clean<Item> for ty::AssocItem { AssocTypeItem(bounds, ty.clean(cx)) } else { + let type_ = cx.tcx.type_of(self.def_id).clean(cx); + let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); TypedefItem( Typedef { - type_: cx.tcx.type_of(self.def_id).clean(cx), + type_, generics: Generics { params: Vec::new(), where_predicates: Vec::new() }, + item_type, }, true, ) @@ -1989,6 +1994,8 @@ impl Clean<String> for ast::Name { impl Clean<Item> for doctree::Typedef<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { + let type_ = self.ty.clean(cx); + let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did)); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -1997,10 +2004,7 @@ impl Clean<Item> for doctree::Typedef<'_> { visibility: self.vis.clean(cx), stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), - inner: TypedefItem( - Typedef { type_: self.ty.clean(cx), generics: self.gen.clean(cx) }, - false, - ), + inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false), } } } @@ -2101,7 +2105,7 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> { build_deref_target_impls(cx, &items, &mut ret); } - let provided = trait_ + let provided: FxHashSet<String> = trait_ .def_id() .map(|did| { cx.tcx @@ -2112,7 +2116,12 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> { }) .unwrap_or_default(); - ret.push(Item { + let for_ = self.for_.clean(cx); + let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) { + Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)), + _ => None, + }); + let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), @@ -2123,15 +2132,19 @@ impl Clean<Vec<Item>> for doctree::Impl<'_> { inner: ImplItem(Impl { unsafety: self.unsafety, generics: self.generics.clean(cx), - provided_trait_methods: provided, + provided_trait_methods: provided.clone(), trait_, - for_: self.for_.clean(cx), + for_, items, polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), synthetic: false, blanket_impl: None, }), - }); + }; + if let Some(type_alias) = type_alias { + ret.push(make_item(trait_.clone(), type_alias, items.clone())); + } + ret.push(make_item(trait_, for_, items)); ret } } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index c7b12d38c43..2b59c60f0b7 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -141,7 +141,7 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) .predicates .iter() .filter_map(|(pred, _)| { - if let ty::Predicate::Trait(ref pred) = *pred { + if let ty::Predicate::Trait(ref pred, _) = *pred { if pred.skip_binder().trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 5d8e27ecadb..79a078ca7a9 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1406,6 +1406,14 @@ pub struct PathSegment { pub struct Typedef { pub type_: Type, pub generics: Generics, + // Type of target item. + pub item_type: Option<Type>, +} + +impl GetDefId for Typedef { + fn def_id(&self) -> Option<DefId> { + self.type_.def_id() + } } #[derive(Clone, Debug)] diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 178ba692772..218674b757f 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -203,6 +203,7 @@ pub struct Impl<'hir> { pub unsafety: hir::Unsafety, pub polarity: hir::ImplPolarity, pub defaultness: hir::Defaultness, + pub constness: ast::Constness, pub generics: &'hir hir::Generics<'hir>, pub trait_: &'hir Option<hir::TraitRef<'hir>>, pub for_: &'hir hir::Ty<'hir>, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 6434dccdfc7..79923fc3d36 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -361,6 +361,7 @@ impl clean::GenericBound { let modifier_str = match modifier { hir::TraitBoundModifier::None => "", hir::TraitBoundModifier::Maybe => "?", + hir::TraitBoundModifier::MaybeConst => "?const", }; if f.alternate() { write!(f, "{}{:#}", modifier_str, ty.print()) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index aa52b769c38..5bea1b56141 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -41,7 +41,7 @@ pub fn render_with_highlighting( let fm = sess .source_map() .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned()); - let highlight_result = { + let highlight_result = rustc_driver::catch_fatal_errors(|| { let lexer = lexer::StringReader::new(&sess, fm, None); let mut classifier = Classifier::new(lexer, sess.source_map()); @@ -51,7 +51,8 @@ pub fn render_with_highlighting( } else { Ok(String::from_utf8_lossy(&highlighted_source).into_owned()) } - }; + }) + .unwrap_or(Err(())); match highlight_result { Ok(highlighted_source) => { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c5f88f9f7f4..c87964af020 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -380,7 +380,10 @@ impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, } _ => {} } - self.buf.push_back(event); + match event { + Event::Start(Tag::Link(_, _, _)) | Event::End(Tag::Link(..)) => {} + event => self.buf.push_back(event), + } } let id = self.id_map.derive(id); @@ -395,7 +398,7 @@ impl<'a, 'b, 'ids, I: Iterator<Item = Event<'a>>> Iterator for HeadingLinks<'a, let start_tags = format!( "<h{level} id=\"{id}\" class=\"section-header\">\ - <a href=\"#{id}\">", + <a href=\"#{id}\">", id = id, level = level ); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2d932eb7668..ab38eec5f3e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2321,8 +2321,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func "{}{}{}{}{:#}fn {}{:#}", it.visibility.print_with_space(), f.header.constness.print_with_space(), - f.header.unsafety.print_with_space(), f.header.asyncness.print_with_space(), + f.header.unsafety.print_with_space(), print_abi_with_space(f.header.abi), it.name.as_ref().unwrap(), f.generics.print() @@ -2332,12 +2332,12 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func render_attributes(w, it, false); write!( w, - "{vis}{constness}{unsafety}{asyncness}{abi}fn \ + "{vis}{constness}{asyncness}{unsafety}{abi}fn \ {name}{generics}{decl}{where_clause}</pre>", vis = it.visibility.print_with_space(), constness = f.header.constness.print_with_space(), - unsafety = f.header.unsafety.print_with_space(), asyncness = f.header.asyncness.print_with_space(), + unsafety = f.header.unsafety.print_with_space(), abi = print_abi_with_space(f.header.abi), name = it.name.as_ref().unwrap(), generics = f.generics.print(), @@ -2832,8 +2832,8 @@ fn render_assoc_item( "{}{}{}{}{}{:#}fn {}{:#}", meth.visibility.print_with_space(), header.constness.print_with_space(), - header.unsafety.print_with_space(), header.asyncness.print_with_space(), + header.unsafety.print_with_space(), print_default_space(meth.is_default()), print_abi_with_space(header.abi), name, @@ -2854,8 +2854,8 @@ fn render_assoc_item( if parent == ItemType::Trait { " " } else { "" }, meth.visibility.print_with_space(), header.constness.print_with_space(), - header.unsafety.print_with_space(), header.asyncness.print_with_space(), + header.unsafety.print_with_space(), print_default_space(meth.is_default()), print_abi_with_space(header.abi), href = href, @@ -3469,20 +3469,23 @@ fn render_deref_methods( deref_mut: bool, ) { let deref_type = impl_.inner_impl().trait_.as_ref().unwrap(); - let target = impl_ + let (target, real_target) = impl_ .inner_impl() .items .iter() .filter_map(|item| match item.inner { - clean::TypedefItem(ref t, true) => Some(&t.type_), + clean::TypedefItem(ref t, true) => Some(match *t { + clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), + _ => (&t.type_, &t.type_), + }), _ => None, }) .next() .expect("Expected associated type binding"); let what = - AssocItemRender::DerefFor { trait_: deref_type, type_: target, deref_mut_: deref_mut }; + AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; if let Some(did) = target.def_id() { - render_assoc_items(w, cx, container_item, did, what) + render_assoc_items(w, cx, container_item, did, what); } else { if let Some(prim) = target.primitive_type() { if let Some(&did) = cx.cache.primitive_locations.get(&prim) { @@ -4123,12 +4126,15 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .filter(|i| i.inner_impl().trait_.is_some()) .find(|i| i.inner_impl().trait_.def_id() == c.deref_trait_did) { - if let Some(target) = impl_ + if let Some((target, real_target)) = impl_ .inner_impl() .items .iter() .filter_map(|item| match item.inner { - clean::TypedefItem(ref t, true) => Some(&t.type_), + clean::TypedefItem(ref t, true) => Some(match *t { + clean::Typedef { item_type: Some(ref type_), .. } => (type_, &t.type_), + _ => (&t.type_, &t.type_), + }), _ => None, }) .next() @@ -4147,7 +4153,7 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { "{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print() )), - Escape(&format!("{:#}", target.print())) + Escape(&format!("{:#}", real_target.print())) )); out.push_str("</a>"); let mut ret = impls diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 22507443b08..f1f83acdda5 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -277,7 +277,7 @@ impl DocFolder for Cache { | clean::StructFieldItem(..) | clean::VariantItem(..) => ( ( - Some(*self.parent_stack.last().unwrap()), + Some(*self.parent_stack.last().expect("parent_stack is empty")), Some(&self.stack[..self.stack.len() - 1]), ), false, @@ -286,7 +286,7 @@ impl DocFolder for Cache { if self.parent_stack.is_empty() { ((None, None), false) } else { - let last = self.parent_stack.last().unwrap(); + let last = self.parent_stack.last().expect("parent_stack is empty 2"); let did = *last; let path = match self.paths.get(&did) { // The current stack not necessarily has correlation @@ -468,7 +468,7 @@ impl DocFolder for Cache { self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); } } else { - let trait_did = impl_item.trait_did().unwrap(); + let trait_did = impl_item.trait_did().expect("no trait did"); self.orphan_trait_impls.push((trait_did, dids, impl_item)); } None @@ -478,10 +478,10 @@ impl DocFolder for Cache { }); if pushed { - self.stack.pop().unwrap(); + self.stack.pop().expect("stack already empty"); } if parent_pushed { - self.parent_stack.pop().unwrap(); + self.parent_stack.pop().expect("parent stack already empty"); } self.stripped_mod = orig_stripped_mod; self.parent_is_trait_impl = orig_parent_is_trait_impl; @@ -594,7 +594,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { for item in search_index { item.parent_idx = item.parent.map(|nodeid| { if nodeid_to_pathid.contains_key(&nodeid) { - *nodeid_to_pathid.get(&nodeid).unwrap() + *nodeid_to_pathid.get(&nodeid).expect("no pathid") } else { let pathid = lastpathid; nodeid_to_pathid.insert(nodeid, pathid); @@ -639,7 +639,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { items: crate_items, paths: crate_paths, }) - .unwrap() + .expect("failed serde conversion") ) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1da00e3a47b..403c8d0160d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -23,7 +23,6 @@ extern crate getopts; extern crate rustc; extern crate rustc_data_structures; extern crate rustc_driver; -extern crate rustc_error_codes; extern crate rustc_errors; extern crate rustc_expand; extern crate rustc_feature; diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 0bab4423b3d..2903fd9dcd6 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { dox[code_block.code].to_owned(), ); - let validation_status = { + let validation_status = rustc_driver::catch_fatal_errors(|| { let mut has_syntax_errors = false; let mut only_whitespace = true; // even if there is a syntax error, we need to run the lexer over the whole file @@ -61,7 +61,8 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { } else { None } - }; + }) + .unwrap_or(Some(CodeBlockInvalid::SyntaxError)); if let Some(code_block_invalid) = validation_status { let mut diag = if let Some(sp) = diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index f899e722a56..d89dc2adafe 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -43,7 +43,7 @@ pub fn run(options: Options) -> i32 { let crate_types = if options.proc_macro_crate { vec![config::CrateType::ProcMacro] } else { - vec![config::CrateType::Dylib] + vec![config::CrateType::Rlib] }; let sessopts = config::Options { @@ -117,12 +117,16 @@ pub fn run(options: Options) -> i32 { intravisit::walk_crate(this, krate); }); }); + compiler.session().abort_if_errors(); let ret: Result<_, ErrorReported> = Ok(collector.tests); ret }) - }) - .expect("compiler aborted in rustdoc!"); + }); + let tests = match tests { + Ok(tests) => tests, + Err(ErrorReported) => return 1, + }; test_args.insert(0, "rustdoctest".to_string()); @@ -905,8 +909,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { } fn visit_item(&mut self, item: &'hir hir::Item) { - let name = if let hir::ItemKind::Impl(.., ref ty, _) = item.kind { - self.map.hir_to_pretty_string(ty.hir_id) + let name = if let hir::ItemKind::Impl { ref self_ty, .. } = item.kind { + self.map.hir_to_pretty_string(self_ty.hir_id) } else { item.ident.to_string() }; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 5fa9270959c..d3d45ccccad 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -558,27 +558,29 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.trait_aliases.push(t); } - hir::ItemKind::Impl( + hir::ItemKind::Impl { unsafety, polarity, defaultness, + constness, ref generics, - ref trait_, - for_, - ref item_ids, - ) => { + ref of_trait, + self_ty, + ref items, + } => { // Don't duplicate impls when inlining or if it's implementing a trait, we'll pick // them up regardless of where they're located. - if !self.inlining && trait_.is_none() { + if !self.inlining && of_trait.is_none() { let items = - item_ids.iter().map(|ii| self.cx.tcx.hir().impl_item(ii.id)).collect(); + items.iter().map(|item| self.cx.tcx.hir().impl_item(item.id)).collect(); let i = Impl { unsafety, polarity, defaultness, + constness, generics, - trait_, - for_, + trait_: of_trait, + for_: self_ty, items, attrs: &item.attrs, id: item.hir_id, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f90647472c6..dc93ac90482 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -275,7 +275,6 @@ #![feature(link_args)] #![feature(linkage)] #![feature(log_syntax)] -#![feature(manually_drop_take)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] #![feature(needs_panic_runtime)] @@ -294,7 +293,7 @@ #![feature(shrink_to)] #![feature(slice_concat_ext)] #![feature(slice_internals)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(specialization)] #![feature(staged_api)] #![feature(std_internals)] diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 0b6e728dceb..5bc8fe5ae6d 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -65,7 +65,7 @@ pub use core::time::Duration; /// /// | Platform | System call | /// |:---------:|:--------------------------------------------------------------------:| -/// | Cloud ABI | [clock_time_get (Monotonic Clock)] | +/// | CloudABI | [clock_time_get (Monotonic Clock)] | /// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | /// | UNIX | [clock_gettime (Monotonic Clock)] | /// | Darwin | [mach_absolute_time] | @@ -79,7 +79,7 @@ pub use core::time::Duration; /// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/CraneStation/wasmtime/blob/master/docs/WASI-api.md#clock_time_get /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime /// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html -/// [clock_time_get (Monotonic Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt +/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get /// /// **Disclaimer:** These system calls might change over time. /// @@ -144,7 +144,7 @@ pub struct Instant(time::Instant); /// /// | Platform | System call | /// |:---------:|:--------------------------------------------------------------------:| -/// | Cloud ABI | [clock_time_get (Realtime Clock)] | +/// | CloudABI | [clock_time_get (Realtime Clock)] | /// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | /// | UNIX | [clock_gettime (Realtime Clock)] | /// | DARWIN | [gettimeofday] | @@ -152,7 +152,7 @@ pub struct Instant(time::Instant); /// | WASI | [__wasi_clock_time_get (Realtime Clock)] | /// | Windows | [GetSystemTimeAsFileTime] | /// -/// [clock_time_get (Realtime Clock)]: https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt +/// [clock_time_get (Realtime Clock)]: https://nuxi.nl/cloudabi/#clock_time_get /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode /// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index 7d9f715e9fe..2e647d2a1e0 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -21,5 +21,4 @@ rustc_index = { path = "../librustc_index" } rustc_lexer = { path = "../librustc_lexer" } rustc_macros = { path = "../librustc_macros" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_session = { path = "../librustc_session" } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 331eb109ec0..5f38ac4cc0f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -266,12 +266,24 @@ pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0); /// small, positive ids. pub const DUMMY_NODE_ID: NodeId = NodeId::MAX; -/// A modifier on a bound, currently this is only used for `?Sized`, where the -/// modifier is `Maybe`. Negative bounds should also be handled here. +/// A modifier on a bound, e.g., `?Sized` or `?const Trait`. +/// +/// Negative bounds should also be handled here. #[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)] pub enum TraitBoundModifier { + /// No modifiers None, + + /// `?Trait` Maybe, + + /// `?const Trait` + MaybeConst, + + /// `?const ?Trait` + // + // This parses but will be rejected during AST validation. + MaybeConstMaybe, } /// The AST represents all type param bounds as types. @@ -1033,7 +1045,7 @@ impl Expr { pub fn to_bound(&self) -> Option<GenericBound> { match &self.kind { ExprKind::Path(None, path) => Some(GenericBound::Trait( - PolyTraitRef::new(Vec::new(), path.clone(), None, self.span), + PolyTraitRef::new(Vec::new(), path.clone(), self.span), TraitBoundModifier::None, )), _ => None, @@ -2158,7 +2170,8 @@ impl IsAsync { } } -#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] +#[derive(HashStable_Generic)] pub enum Constness { Const, NotConst, @@ -2376,15 +2389,6 @@ pub enum AttrKind { pub struct TraitRef { pub path: Path, pub ref_id: NodeId, - - /// The `const` modifier, if any, that appears before this trait. - /// - /// | | `constness` | - /// |----------------|-----------------------------| - /// | `Trait` | `None` | - /// | `const Trait` | `Some(Constness::Const)` | - /// | `?const Trait` | `Some(Constness::NotConst)` | - pub constness: Option<Constness>, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] @@ -2399,15 +2403,10 @@ pub struct PolyTraitRef { } impl PolyTraitRef { - pub fn new( - generic_params: Vec<GenericParam>, - path: Path, - constness: Option<Constness>, - span: Span, - ) -> Self { + pub fn new(generic_params: Vec<GenericParam>, path: Path, span: Span) -> Self { PolyTraitRef { bound_generic_params: generic_params, - trait_ref: TraitRef { path, constness, ref_id: DUMMY_NODE_ID }, + trait_ref: TraitRef { path, ref_id: DUMMY_NODE_ID }, span, } } @@ -2614,15 +2613,19 @@ pub enum ItemKind { /// An implementation. /// /// E.g., `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`. - Impl( - Unsafety, - ImplPolarity, - Defaultness, - Generics, - Option<TraitRef>, // (optional) trait this impl implements - P<Ty>, // self - Vec<AssocItem>, - ), + Impl { + unsafety: Unsafety, + polarity: ImplPolarity, + defaultness: Defaultness, + constness: Constness, + generics: Generics, + + /// The trait being implemented, if any. + of_trait: Option<TraitRef>, + + self_ty: P<Ty>, + items: Vec<AssocItem>, + }, /// A macro invocation. /// /// E.g., `foo!(..)`. @@ -2649,7 +2652,7 @@ impl ItemKind { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl(..) => "item", + ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl { .. } => "item", } } } diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 70f4f47621a..6cfe4f2de1e 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -12,8 +12,6 @@ use rustc_span::hygiene::Transparency; use rustc_span::{symbol::sym, symbol::Symbol, Span}; use std::num::NonZeroU32; -use rustc_error_codes::*; - pub fn is_builtin_attr(attr: &Attribute) -> bool { attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some() } diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 0184a3214b5..b0c2aa3dbb2 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -13,7 +13,7 @@ #![feature(label_break_value)] #![feature(nll)] #![feature(try_trait)] -#![feature(slice_patterns)] +#![cfg_attr(bootstrap, feature(slice_patterns))] #![feature(unicode_internals)] #![recursion_limit = "256"] diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 58d4e46111b..4a460c5d7b2 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -838,8 +838,7 @@ pub fn noop_visit_variant_data<T: MutVisitor>(vdata: &mut VariantData, vis: &mut } } -pub fn noop_visit_trait_ref<T: MutVisitor>(tr: &mut TraitRef, vis: &mut T) { - let TraitRef { path, ref_id, constness: _ } = tr; +pub fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut TraitRef, vis: &mut T) { vis.visit_path(path); vis.visit_id(ref_id); } @@ -918,10 +917,19 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) { vis.visit_variant_data(variant_data); vis.visit_generics(generics); } - ItemKind::Impl(_unsafety, _polarity, _defaultness, generics, trait_ref, ty, items) => { + ItemKind::Impl { + unsafety: _, + polarity: _, + defaultness: _, + constness: _, + generics, + of_trait, + self_ty, + items, + } => { vis.visit_generics(generics); - visit_opt(trait_ref, |trait_ref| vis.visit_trait_ref(trait_ref)); - vis.visit_ty(ty); + visit_opt(of_trait, |trait_ref| vis.visit_trait_ref(trait_ref)); + vis.visit_ty(self_ty); items.flat_map_in_place(|item| vis.flat_map_impl_item(item)); } ItemKind::Trait(_is_auto, _unsafety, generics, bounds, items) => { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 11c8cb8ef75..3927e4f9030 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1226,20 +1226,22 @@ impl<'a> State<'a> { self.head(visibility_qualified(&item.vis, "union")); self.print_struct(struct_def, generics, item.ident, item.span, true); } - ast::ItemKind::Impl( + ast::ItemKind::Impl { unsafety, polarity, defaultness, + constness, ref generics, - ref opt_trait, - ref ty, - ref impl_items, - ) => { + ref of_trait, + ref self_ty, + ref items, + } => { self.head(""); self.print_visibility(&item.vis); self.print_defaultness(defaultness); self.print_unsafety(unsafety); self.word_nbsp("impl"); + self.print_constness(constness); if !generics.params.is_empty() { self.print_generic_params(&generics.params); @@ -1250,19 +1252,19 @@ impl<'a> State<'a> { self.s.word("!"); } - if let Some(ref t) = *opt_trait { + if let Some(ref t) = *of_trait { self.print_trait_ref(t); self.s.space(); self.word_space("for"); } - self.print_type(ty); + self.print_type(self_ty); self.print_where_clause(&generics.where_clause); self.s.space(); self.bopen(); self.print_inner_attributes(&item.attrs); - for impl_item in impl_items { + for impl_item in items { self.print_assoc_item(impl_item); } self.bclose(item.span); @@ -2773,6 +2775,13 @@ impl<'a> State<'a> { } } + crate fn print_constness(&mut self, s: ast::Constness) { + match s { + ast::Constness::Const => self.word_nbsp("const"), + ast::Constness::NotConst => {} + } + } + crate fn print_is_auto(&mut self, s: ast::IsAuto) { match s { ast::IsAuto::Yes => self.word_nbsp("auto"), diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 3c2ebacbc4e..946a0d29cd3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -308,11 +308,20 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { visitor.visit_generics(generics); visitor.visit_enum_def(enum_definition, generics, item.id, item.span) } - ItemKind::Impl(_, _, _, ref generics, ref opt_trait_reference, ref typ, ref impl_items) => { + ItemKind::Impl { + unsafety: _, + polarity: _, + defaultness: _, + constness: _, + ref generics, + ref of_trait, + ref self_ty, + ref items, + } => { visitor.visit_generics(generics); - walk_list!(visitor, visit_trait_ref, opt_trait_reference); - visitor.visit_ty(typ); - walk_list!(visitor, visit_impl_item, impl_items); + walk_list!(visitor, visit_trait_ref, of_trait); + visitor.visit_ty(self_ty); + walk_list!(visitor, visit_impl_item, items); } ItemKind::Struct(ref struct_definition, ref generics) | ItemKind::Union(ref struct_definition, ref generics) => { diff --git a/src/llvm-project b/src/llvm-project -Subproject 9330ec5a4c1df5fc1fa62f993ed6a04da68cb04 +Subproject cd87134ab77e6bacb2128137065b328b9c35e0e diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs index d5ddfb5e1c2..27fb3cb1380 100644 --- a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs +++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs @@ -4,7 +4,7 @@ #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<drop_in_place_intrinsic::StructWithDtor[0]> @@ drop_in_place_intrinsic-cgu.0[Internal] struct StructWithDtor(u32); impl Drop for StructWithDtor { @@ -16,7 +16,7 @@ impl Drop for StructWithDtor { #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]; 2]> @@ drop_in_place_intrinsic-cgu.0[Internal] let x = [StructWithDtor(0), StructWithDtor(1)]; drop_slice_in_place(&x); @@ -31,7 +31,6 @@ fn drop_slice_in_place(x: &[StructWithDtor]) { // not have drop-glue for the unsized [StructWithDtor]. This has to be // generated though when the drop_in_place() intrinsic is used. //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<[drop_in_place_intrinsic::StructWithDtor[0]]> @@ drop_in_place_intrinsic-cgu.0[Internal] ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]); } } diff --git a/src/test/codegen-units/item-collection/generic-drop-glue.rs b/src/test/codegen-units/item-collection/generic-drop-glue.rs index 94e79f0b320..675bdfdb4d2 100644 --- a/src/test/codegen-units/item-collection/generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/generic-drop-glue.rs @@ -37,7 +37,7 @@ enum EnumNoDrop<T1, T2> { struct NonGenericNoDrop(i32); struct NonGenericWithDrop(i32); -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::NonGenericWithDrop[0]> @@ generic_drop_glue-cgu.0[Internal] impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::{{impl}}[2]::drop[0] @@ -47,11 +47,11 @@ impl Drop for NonGenericWithDrop { //~ MONO_ITEM fn generic_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<i8, char>> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<i8, char> let _ = StructWithDrop { x: 0i8, y: 'a' }.x; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructWithDrop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]>> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[0]::drop[0]<&str, generic_drop_glue::NonGenericNoDrop[0]> let _ = StructWithDrop { x: "&str", y: NonGenericNoDrop(0) }.y; @@ -60,17 +60,17 @@ fn start(_: isize, _: *const *const u8) -> isize { // This is supposed to generate drop-glue because it contains a field that // needs to be dropped. - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::StructNoDrop[0]<generic_drop_glue::NonGenericWithDrop[0], f64>> @@ generic_drop_glue-cgu.0[Internal] let _ = StructNoDrop { x: NonGenericWithDrop(0), y: 0f64 }.y; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<i32, i64>> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<i32, i64> let _ = match EnumWithDrop::A::<i32, i64>(0) { EnumWithDrop::A(x) => x, EnumWithDrop::B(x) => x as i32 }; - //~MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal] + //~MONO_ITEM fn core::ptr[0]::drop_in_place[0]<generic_drop_glue::EnumWithDrop[0]<f64, f32>> @@ generic_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn generic_drop_glue::{{impl}}[1]::drop[0]<f64, f32> let _ = match EnumWithDrop::B::<f64, f32>(1.0) { EnumWithDrop::A(x) => x, diff --git a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs index e79b069b25c..db0390b58c8 100644 --- a/src/test/codegen-units/item-collection/instantiation-through-vtable.rs +++ b/src/test/codegen-units/item-collection/instantiation-through-vtable.rs @@ -24,13 +24,13 @@ impl<T> Trait for Struct<T> { fn start(_: isize, _: *const *const u8) -> isize { let s1 = Struct { _a: 0u32 }; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u32>> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u32> //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u32> let _ = &s1 as &Trait; let s1 = Struct { _a: 0u64 }; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<instantiation_through_vtable::Struct[0]<u64>> @@ instantiation_through_vtable-cgu.0[Internal] //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::foo[0]<u64> //~ MONO_ITEM fn instantiation_through_vtable::{{impl}}[0]::bar[0]<u64> let _ = &s1 as &Trait; diff --git a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs index f13952bb781..a899b8b2c8b 100644 --- a/src/test/codegen-units/item-collection/non-generic-drop-glue.rs +++ b/src/test/codegen-units/item-collection/non-generic-drop-glue.rs @@ -5,7 +5,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::StructWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal] struct StructWithDrop { x: i32 } @@ -19,7 +19,7 @@ struct StructNoDrop { x: i32 } -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<non_generic_drop_glue::EnumWithDrop[0]> @@ non_generic_drop_glue-cgu.0[Internal] enum EnumWithDrop { A(i32) } diff --git a/src/test/codegen-units/item-collection/transitive-drop-glue.rs b/src/test/codegen-units/item-collection/transitive-drop-glue.rs index 14545a33b59..7e29af43538 100644 --- a/src/test/codegen-units/item-collection/transitive-drop-glue.rs +++ b/src/test/codegen-units/item-collection/transitive-drop-glue.rs @@ -5,11 +5,11 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Root[0]> @@ transitive_drop_glue-cgu.0[Internal] struct Root(Intermediate); -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Intermediate[0]> @@ transitive_drop_glue-cgu.0[Internal] struct Intermediate(Leaf); -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::Leaf[0]> @@ transitive_drop_glue-cgu.0[Internal] struct Leaf; impl Drop for Leaf { @@ -30,15 +30,15 @@ impl<T> Drop for LeafGen<T> { fn start(_: isize, _: *const *const u8) -> isize { let _ = Root(Intermediate(Leaf)); - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<u32>> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<u32> let _ = RootGen(IntermediateGen(LeafGen(0u32))); - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::RootGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::IntermediateGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<transitive_drop_glue::LeafGen[0]<i16>> @@ transitive_drop_glue-cgu.0[Internal] //~ MONO_ITEM fn transitive_drop_glue::{{impl}}[1]::drop[0]<i16> let _ = RootGen(IntermediateGen(LeafGen(0i16))); diff --git a/src/test/codegen-units/item-collection/tuple-drop-glue.rs b/src/test/codegen-units/item-collection/tuple-drop-glue.rs index 54aff575f91..d77de53ce01 100644 --- a/src/test/codegen-units/item-collection/tuple-drop-glue.rs +++ b/src/test/codegen-units/item-collection/tuple-drop-glue.rs @@ -5,7 +5,7 @@ #![deny(dead_code)] #![feature(start)] -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<tuple_drop_glue::Dropped[0]> @@ tuple_drop_glue-cgu.0[Internal] struct Dropped; impl Drop for Dropped { @@ -16,11 +16,11 @@ impl Drop for Dropped { //~ MONO_ITEM fn tuple_drop_glue::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, tuple_drop_glue::Dropped[0])> @@ tuple_drop_glue-cgu.0[Internal] let x = (0u32, Dropped); - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(i16, (tuple_drop_glue::Dropped[0], bool))> @@ tuple_drop_glue-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(tuple_drop_glue::Dropped[0], bool)> @@ tuple_drop_glue-cgu.0[Internal] let x = (0i16, (Dropped, true)); 0 diff --git a/src/test/codegen-units/item-collection/unsizing.rs b/src/test/codegen-units/item-collection/unsizing.rs index fd794df3760..1ed60dcf265 100644 --- a/src/test/codegen-units/item-collection/unsizing.rs +++ b/src/test/codegen-units/item-collection/unsizing.rs @@ -48,13 +48,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Wrapper<U>> for Wrapper<T> fn start(_: isize, _: *const *const u8) -> isize { // simple case let bool_sized = &true; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<bool> @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[0]::foo[0] let _bool_unsized = bool_sized as &Trait; let char_sized = &'a'; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<char> @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<char> @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[1]::foo[0] let _char_unsized = char_sized as &Trait; @@ -64,13 +64,13 @@ fn start(_: isize, _: *const *const u8) -> isize { _b: 2, _c: 3.0f64 }; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<f64> @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[2]::foo[0] let _struct_unsized = struct_sized as &Struct<Trait>; // custom coercion let wrapper_sized = Wrapper(&0u32); - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ unsizing-cgu.0[Internal] //~ MONO_ITEM fn unsizing::{{impl}}[3]::foo[0] let _wrapper_sized = wrapper_sized as Wrapper<Trait>; diff --git a/src/test/codegen-units/partitioning/extern-drop-glue.rs b/src/test/codegen-units/partitioning/extern-drop-glue.rs index 0f3d72d16a9..f85ae0c0774 100644 --- a/src/test/codegen-units/partitioning/extern-drop-glue.rs +++ b/src/test/codegen-units/partitioning/extern-drop-glue.rs @@ -11,14 +11,14 @@ // aux-build:cgu_extern_drop_glue.rs extern crate cgu_extern_drop_glue; -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<cgu_extern_drop_glue::Struct[0]> @@ extern_drop_glue[Internal] extern_drop_glue-mod1[Internal] struct LocalStruct(cgu_extern_drop_glue::Struct); //~ MONO_ITEM fn extern_drop_glue::user[0] @@ extern_drop_glue[External] pub fn user() { - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::LocalStruct[0]> @@ extern_drop_glue[Internal] let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); } @@ -30,7 +30,7 @@ pub mod mod1 { //~ MONO_ITEM fn extern_drop_glue::mod1[0]::user[0] @@ extern_drop_glue-mod1[External] pub fn user() { - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<extern_drop_glue::mod1[0]::LocalStruct[0]> @@ extern_drop_glue-mod1[Internal] let _ = LocalStruct(cgu_extern_drop_glue::Struct(0)); } } diff --git a/src/test/codegen-units/partitioning/local-drop-glue.rs b/src/test/codegen-units/partitioning/local-drop-glue.rs index 938d4ffb693..366af4d4c38 100644 --- a/src/test/codegen-units/partitioning/local-drop-glue.rs +++ b/src/test/codegen-units/partitioning/local-drop-glue.rs @@ -7,7 +7,7 @@ #![allow(dead_code)] #![crate_type="rlib"] -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Struct[0]> @@ local_drop_glue[Internal] local_drop_glue-mod1[Internal] struct Struct { _a: u32 } @@ -17,7 +17,7 @@ impl Drop for Struct { fn drop(&mut self) {} } -//~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal] +//~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::Outer[0]> @@ local_drop_glue[Internal] struct Outer { _a: Struct } @@ -36,10 +36,10 @@ pub mod mod1 { use super::Struct; - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<local_drop_glue::mod1[0]::Struct2[0]> @@ local_drop_glue-mod1[Internal] struct Struct2 { _a: Struct, - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<(u32, local_drop_glue::Struct[0])> @@ local_drop_glue-mod1[Internal] _b: (u32, Struct), } diff --git a/src/test/codegen-units/partitioning/vtable-through-const.rs b/src/test/codegen-units/partitioning/vtable-through-const.rs index 5d23a4e13cb..06e2ef6bb22 100644 --- a/src/test/codegen-units/partitioning/vtable-through-const.rs +++ b/src/test/codegen-units/partitioning/vtable-through-const.rs @@ -66,7 +66,7 @@ mod mod1 { //~ MONO_ITEM fn vtable_through_const::start[0] #[start] fn start(_: isize, _: *const *const u8) -> isize { - //~ MONO_ITEM fn core::ptr[0]::real_drop_in_place[0]<u32> @@ vtable_through_const[Internal] + //~ MONO_ITEM fn core::ptr[0]::drop_in_place[0]<u32> @@ vtable_through_const[Internal] // Since Trait1::do_something() is instantiated via its default implementation, // it is considered a generic and is instantiated here only because it is diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index 959929fbafb..0c7f3bb2020 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -21,7 +21,7 @@ pub fn droppy() { // regular function exit. We used to have problems with quadratic growths of drop calls in such // functions. // FIXME(eddyb) the `void @` forces a match on the instruction, instead of the -// comment, that's `; call core::ptr::real_drop_in_place::<drop::SomeUniqueName>` +// comment, that's `; call core::intrinsics::drop_in_place::<drop::SomeUniqueName>` // for the `v0` mangling, should switch to matching on that once `legacy` is gone. // CHECK-NOT: invoke void @{{.*}}drop_in_place{{.*}}SomeUniqueName // CHECK: call void @{{.*}}drop_in_place{{.*}}SomeUniqueName diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs index 5808a8be176..ca539fb7462 100644 --- a/src/test/mir-opt/const_prop/ref_deref_project.rs +++ b/src/test/mir-opt/const_prop/ref_deref_project.rs @@ -1,5 +1,5 @@ fn main() { - *(&(4, 5).1); + *(&(4, 5).1); // This does not currently propagate (#67862) } // END RUST SOURCE @@ -35,7 +35,7 @@ fn main() { // ... // _4 = const main::promoted[0]; // _2 = &((*_4).1: i32); -// _1 = const 5i32; +// _1 = (*_2); // ... // } // END rustc.main.ConstProp.after.mir diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index ccecaeac96b..1c88a9e4d5a 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -113,8 +113,8 @@ fn main() { // } // } // END rustc.main-{{closure}}.EraseRegions.after.mir -// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir -// fn std::ptr::real_drop_in_place(_1: &mut Test) -> () { +// START rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir +// fn std::intrinsics::drop_in_place(_1: *mut Test) -> () { // ... // bb0: { // Retag([raw] _1); @@ -126,4 +126,4 @@ fn main() { // return; // } // } -// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir +// END rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir diff --git a/src/test/mir-opt/slice-drop-shim.rs b/src/test/mir-opt/slice-drop-shim.rs index 5a37b67229c..a25375594d3 100644 --- a/src/test/mir-opt/slice-drop-shim.rs +++ b/src/test/mir-opt/slice-drop-shim.rs @@ -6,7 +6,7 @@ fn main() { // END RUST SOURCE -// START rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir +// START rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir // let mut _2: usize; // let mut _3: usize; // let mut _4: usize; @@ -87,4 +87,4 @@ fn main() { // _3 = Len((*_1)); // switchInt(move _2) -> [0usize: bb8, otherwise: bb14]; // } -// END rustc.ptr-real_drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir +// END rustc.ptr-drop_in_place.[std__string__String].AddMovesForPackedDrops.before.mir diff --git a/src/test/mir-opt/uniform_array_move_out.rs b/src/test/mir-opt/uniform_array_move_out.rs index f2e1864096e..d587d237227 100644 --- a/src/test/mir-opt/uniform_array_move_out.rs +++ b/src/test/mir-opt/uniform_array_move_out.rs @@ -1,5 +1,4 @@ #![feature(box_syntax)] -#![feature(slice_patterns)] fn move_out_from_end() { let a = [box 1, box 2]; diff --git a/src/test/mir-opt/unusual-item-types.rs b/src/test/mir-opt/unusual-item-types.rs index f4d848dfc7a..88cfb62a0d0 100644 --- a/src/test/mir-opt/unusual-item-types.rs +++ b/src/test/mir-opt/unusual-item-types.rs @@ -45,7 +45,7 @@ fn main() { // } // END rustc.E-V-{{constant}}.mir_map.0.mir -// START rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir +// START rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir // bb0: { // goto -> bb7; // } @@ -71,7 +71,7 @@ fn main() { // _2 = &mut (*_1); // _3 = const <std::vec::Vec<i32> as std::ops::Drop>::drop(move _2) -> [return: bb6, unwind: bb5]; // } -// END rustc.ptr-real_drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir +// END rustc.ptr-drop_in_place.std__vec__Vec_i32_.AddMovesForPackedDrops.before.mir // START rustc.Test-X-{{constructor}}.mir_map.0.mir // fn Test::X(_1: usize) -> Test { diff --git a/src/test/run-make-fulldeps/issue64319/Makefile b/src/test/run-make-fulldeps/issue64319/Makefile new file mode 100644 index 00000000000..5592f5a71ff --- /dev/null +++ b/src/test/run-make-fulldeps/issue64319/Makefile @@ -0,0 +1,39 @@ +-include ../../run-make-fulldeps/tools.mk + +# Different optimization levels imply different values for `-Zshare-generics`, +# so try out a whole bunch of combinations to make sure everything is compatible +all: + # First up, try some defaults + $(RUSTC) --crate-type rlib foo.rs + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 + + # Next try mixing up some things explicitly + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + + # Now combine a whole bunch of options together + $(RUSTC) --crate-type rlib foo.rs + $(RUSTC) --crate-type dylib bar.rs + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes diff --git a/src/test/run-make-fulldeps/issue64319/bar.rs b/src/test/run-make-fulldeps/issue64319/bar.rs new file mode 100644 index 00000000000..3895c0b6cdb --- /dev/null +++ b/src/test/run-make-fulldeps/issue64319/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +pub fn bar() { + foo::foo(); +} diff --git a/src/test/run-make-fulldeps/issue64319/foo.rs b/src/test/run-make-fulldeps/issue64319/foo.rs new file mode 100644 index 00000000000..c54a238e9ad --- /dev/null +++ b/src/test/run-make-fulldeps/issue64319/foo.rs @@ -0,0 +1,9 @@ +pub fn foo() { + bar::<usize>(); +} + +pub fn bar<T>() { + baz(); +} + +fn baz() {} diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile deleted file mode 100644 index 7f5e9049b2f..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-address/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# needs-sanitizer-support - --include ../tools.mk - -LOG := $(TMPDIR)/log.txt - -# NOTE the address sanitizer only supports x86_64 linux and macOS - -ifeq ($(TARGET),x86_64-apple-darwin) -EXTRA_RUSTFLAG=-C rpath -else -ifeq ($(TARGET),x86_64-unknown-linux-gnu) - -# Apparently there are very specific Linux kernels, notably the one that's -# currently on Travis CI, which contain a buggy commit that triggers failures in -# the ASan implementation, detailed at google/sanitizers#837. As noted in -# google/sanitizers#856 the "fix" is to avoid using PIE binaries, so we pass a -# different relocation model to avoid generating a PIE binary. Once Travis is no -# longer running kernel 4.4.0-93 we can remove this and pass an empty set of -# flags again. -EXTRA_RUSTFLAG=-C relocation-model=dynamic-no-pic -endif -endif - -all: - $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) rustc_rt.asan - # Verify that stack buffer overflow is detected: - $(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow - # Verify that variable name is included in address sanitizer report: - $(TMPDIR)/overflow 2>&1 | $(CGREP) "'xs'" diff --git a/src/test/run-make-fulldeps/sanitizer-address/overflow.rs b/src/test/run-make-fulldeps/sanitizer-address/overflow.rs deleted file mode 100644 index b997a74cc3e..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-address/overflow.rs +++ /dev/null @@ -1,4 +0,0 @@ -fn main() { - let xs = [0, 1, 2, 3]; - let _y = unsafe { *xs.as_ptr().offset(4) }; -} diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile b/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile deleted file mode 100644 index 2a23f0fe3d4..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-invalid-target/Makefile +++ /dev/null @@ -1,5 +0,0 @@ --include ../tools.mk - -all: - $(RUSTC) -Z sanitizer=leak --target i686-unknown-linux-gnu hello.rs 2>&1 | \ - $(CGREP) 'LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target' diff --git a/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs b/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs deleted file mode 100644 index d3dd5ed03d9..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-invalid-target/hello.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![feature(no_core)] -#![no_core] -#![no_main] diff --git a/src/test/run-make-fulldeps/sanitizer-leak/Makefile b/src/test/run-make-fulldeps/sanitizer-leak/Makefile deleted file mode 100644 index da370335ca9..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-leak/Makefile +++ /dev/null @@ -1,7 +0,0 @@ --include ../tools.mk - -# needs-sanitizer-support - -all: - $(RUSTC) -O -Z sanitizer=leak -Z print-link-args leak.rs | $(CGREP) rustc_rt.lsan - $(TMPDIR)/leak 2>&1 | $(CGREP) 'detected memory leaks' diff --git a/src/test/run-make-fulldeps/sanitizer-memory/Makefile b/src/test/run-make-fulldeps/sanitizer-memory/Makefile deleted file mode 100644 index 8bc9df1b4ba..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-memory/Makefile +++ /dev/null @@ -1,11 +0,0 @@ --include ../tools.mk - -# needs-sanitizer-support -# only-linux -# only-x86_64 - -all: - $(RUSTC) -g -Z sanitizer=memory -Z print-link-args uninit.rs | $(CGREP) rustc_rt.msan - $(TMPDIR)/uninit 2>&1 | $(CGREP) use-of-uninitialized-value - $(RUSTC) -g -Z sanitizer=memory -Z print-link-args maybeuninit.rs | $(CGREP) rustc_rt.msan - $(TMPDIR)/maybeuninit 2>&1 | $(CGREP) use-of-uninitialized-value diff --git a/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs deleted file mode 100644 index a9ae85f5763..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-memory/maybeuninit.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::mem::MaybeUninit; - -fn main() { - // This is technically not sound -- but we're literally trying to test - // that the sanitizer catches this, so I guess "intentionally unsound"? - let xs: [u8; 4] = unsafe { MaybeUninit::uninit().assume_init() }; - let y = xs[0] + xs[1]; -} diff --git a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs b/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs deleted file mode 100644 index eae52508f65..00000000000 --- a/src/test/run-make-fulldeps/sanitizer-memory/uninit.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - // This is technically not sound -- but we're literally trying to test - // that the sanitizer catches this, so I guess "intentionally unsound"? - #[allow(deprecated)] - let xs: [u8; 4] = unsafe { std::mem::uninitialized() }; - let y = xs[0] + xs[1]; -} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/Makefile b/src/test/run-make-fulldeps/share-generics-dylib/Makefile new file mode 100644 index 00000000000..c6b5efcb4cd --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/Makefile @@ -0,0 +1,22 @@ +# This test makes sure all generic instances get re-exported from Rust dylibs for use by +# `-Zshare-generics`. There are two rlibs (`instance_provider_a` and `instance_provider_b`) +# which both provide an instance of `Cell<i32>::set`. There is `instance_user_dylib` which is +# supposed to re-export both these instances, and then there are `instance_user_a_rlib` and +# `instance_user_b_rlib` which each rely on a specific instance to be available. +# +# In the end everything is linked together into `linked_leaf`. If `instance_user_dylib` does +# not export both then we'll get an `undefined reference` error for one of the instances. +# +# This is regression test for https://github.com/rust-lang/rust/issues/67276. + +-include ../../run-make-fulldeps/tools.mk + +COMMON_ARGS=-Cprefer-dynamic -Zshare-generics=yes -Ccodegen-units=1 -Zsymbol-mangling-version=v0 + +all: + $(RUSTC) instance_provider_a.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) instance_provider_b.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) instance_user_dylib.rs $(COMMON_ARGS) --crate-type=dylib + $(RUSTC) instance_user_a_rlib.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) instance_user_b_rlib.rs $(COMMON_ARGS) --crate-type=rlib + $(RUSTC) linked_leaf.rs $(COMMON_ARGS) --crate-type=bin diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs new file mode 100644 index 00000000000..b4e125ac052 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_a.rs @@ -0,0 +1,6 @@ +use std::cell::Cell; + +pub fn foo() { + let a: Cell<i32> = Cell::new(1); + a.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs new file mode 100644 index 00000000000..f613db873e6 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_provider_b.rs @@ -0,0 +1,6 @@ +use std::cell::Cell; + +pub fn foo() { + let b: Cell<i32> = Cell::new(1); + b.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs new file mode 100644 index 00000000000..c8e6ab95cf9 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_a_rlib.rs @@ -0,0 +1,9 @@ +extern crate instance_provider_a as upstream; +use std::cell::Cell; + +pub fn foo() { + upstream::foo(); + + let b: Cell<i32> = Cell::new(1); + b.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs new file mode 100644 index 00000000000..7c34af6d0dc --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_b_rlib.rs @@ -0,0 +1,9 @@ +extern crate instance_provider_b as upstream; +use std::cell::Cell; + +pub fn foo() { + upstream::foo(); + + let b: Cell<i32> = Cell::new(1); + b.set(123); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs new file mode 100644 index 00000000000..7c8368eec65 --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/instance_user_dylib.rs @@ -0,0 +1,7 @@ +extern crate instance_provider_a; +extern crate instance_provider_b; + +pub fn foo() { + instance_provider_a::foo(); + instance_provider_b::foo(); +} diff --git a/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs new file mode 100644 index 00000000000..e510dad691c --- /dev/null +++ b/src/test/run-make-fulldeps/share-generics-dylib/linked_leaf.rs @@ -0,0 +1,15 @@ +extern crate instance_user_dylib; +extern crate instance_user_a_rlib; +extern crate instance_user_b_rlib; + +use std::cell::Cell; + +fn main() { + + instance_user_a_rlib::foo(); + instance_user_b_rlib::foo(); + instance_user_dylib::foo(); + + let a: Cell<i32> = Cell::new(1); + a.set(123); +} diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs index 34e92c42104..72037dd74be 100644 --- a/src/test/rustdoc-ui/invalid-syntax.rs +++ b/src/test/rustdoc-ui/invalid-syntax.rs @@ -93,3 +93,9 @@ pub fn empty_rust_with_whitespace() {} /// pub fn indent_after_fenced() {} //~^^^ WARNING could not parse code block as Rust code + +/// ``` +/// "invalid +/// ``` +pub fn invalid() {} +//~^^^^ WARNING could not parse code block as Rust code diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr index 32cc20755ec..a90d3bbb979 100644 --- a/src/test/rustdoc-ui/invalid-syntax.stderr +++ b/src/test/rustdoc-ui/invalid-syntax.stderr @@ -132,3 +132,18 @@ LL | /// \____/ | = note: error from rustc: unknown start of token: \ +warning: could not parse code block as Rust code + --> $DIR/invalid-syntax.rs:97:5 + | +LL | /// ``` + | _____^ +LL | | /// "invalid +LL | | /// ``` + | |_______^ + | + = note: error from rustc: unterminated double quote string +help: mark blocks that do not contain Rust code as text + | +LL | /// ```text + | ^^^^^^^ + diff --git a/src/test/rustdoc-ui/test-compile-fail1.rs b/src/test/rustdoc-ui/test-compile-fail1.rs new file mode 100644 index 00000000000..a0539023878 --- /dev/null +++ b/src/test/rustdoc-ui/test-compile-fail1.rs @@ -0,0 +1,8 @@ +// compile-flags:--test + +/// ``` +/// assert!(true) +/// ``` +pub fn f() {} + +pub fn f() {} diff --git a/src/test/rustdoc-ui/test-compile-fail1.stderr b/src/test/rustdoc-ui/test-compile-fail1.stderr new file mode 100644 index 00000000000..2b38ba9e973 --- /dev/null +++ b/src/test/rustdoc-ui/test-compile-fail1.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `f` is defined multiple times + --> $DIR/test-compile-fail1.rs:8:1 + | +6 | pub fn f() {} + | ---------- previous definition of the value `f` here +7 | +8 | pub fn f() {} + | ^^^^^^^^^^ `f` redefined here + | + = note: `f` must be defined only once in the value namespace of this module + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/src/test/rustdoc-ui/test-compile-fail2.rs b/src/test/rustdoc-ui/test-compile-fail2.rs new file mode 100644 index 00000000000..651ded0a047 --- /dev/null +++ b/src/test/rustdoc-ui/test-compile-fail2.rs @@ -0,0 +1,3 @@ +// compile-flags:--test + +fail diff --git a/src/test/rustdoc-ui/test-compile-fail2.stderr b/src/test/rustdoc-ui/test-compile-fail2.stderr new file mode 100644 index 00000000000..cee5b63cf50 --- /dev/null +++ b/src/test/rustdoc-ui/test-compile-fail2.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `<eof>` + --> $DIR/test-compile-fail2.rs:3:1 + | +3 | fail + | ^^^^ expected one of `!` or `::` + +error: aborting due to previous error + diff --git a/src/test/rustdoc-ui/test-compile-fail3.rs b/src/test/rustdoc-ui/test-compile-fail3.rs new file mode 100644 index 00000000000..faa30ad8367 --- /dev/null +++ b/src/test/rustdoc-ui/test-compile-fail3.rs @@ -0,0 +1,3 @@ +// compile-flags:--test + +"fail diff --git a/src/test/rustdoc-ui/test-compile-fail3.stderr b/src/test/rustdoc-ui/test-compile-fail3.stderr new file mode 100644 index 00000000000..7a2f1815ed8 --- /dev/null +++ b/src/test/rustdoc-ui/test-compile-fail3.stderr @@ -0,0 +1,8 @@ +error: unterminated double quote string + --> $DIR/test-compile-fail3.rs:3:1 + | +3 | "fail + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/rustdoc-ui/test-no_std.rs b/src/test/rustdoc-ui/test-no_std.rs new file mode 100644 index 00000000000..166a87382cb --- /dev/null +++ b/src/test/rustdoc-ui/test-no_std.rs @@ -0,0 +1,12 @@ +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" +// build-pass + +#![no_std] + +extern crate alloc; + +/// ``` +/// assert!(true) +/// ``` +pub fn f() {} diff --git a/src/test/rustdoc-ui/test-no_std.stdout b/src/test/rustdoc-ui/test-no_std.stdout new file mode 100644 index 00000000000..9cdcac2a483 --- /dev/null +++ b/src/test/rustdoc-ui/test-no_std.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/test-no_std.rs - f (line 9) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 5f9708a3972..5a03e821e8a 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -15,6 +15,11 @@ pub async fn baz<T>(a: T) -> T { a } +// @has async_fn/fn.qux.html '//pre[@class="rust fn"]' 'pub async unsafe fn qux() -> char' +pub async unsafe fn qux() -> char { + 'âš ' +} + trait Bar {} impl Bar for () {} @@ -26,8 +31,10 @@ pub async fn quux() -> impl Bar { // @has async_fn/struct.Foo.html // @matches - '//code' 'pub async fn f\(\)$' +// @matches - '//code' 'pub async unsafe fn g\(\)$' pub struct Foo; impl Foo { pub async fn f() {} + pub async unsafe fn g() {} } diff --git a/src/test/rustdoc/bad-codeblock-syntax.rs b/src/test/rustdoc/bad-codeblock-syntax.rs index ae8fbe4a2a8..afef86ec9c7 100644 --- a/src/test/rustdoc/bad-codeblock-syntax.rs +++ b/src/test/rustdoc/bad-codeblock-syntax.rs @@ -33,3 +33,10 @@ pub fn ok() {} /// <script>alert("not valid Rust");</script> /// ``` pub fn escape() {} + +// @has bad_codeblock_syntax/fn.unterminated.html +// @has - '//*[@class="docblock"]/pre/code' '"unterminated' +/// ``` +/// "unterminated +/// ``` +pub fn unterminated() {} diff --git a/src/test/rustdoc/deref-typedef.rs b/src/test/rustdoc/deref-typedef.rs new file mode 100644 index 00000000000..770f8d7289c --- /dev/null +++ b/src/test/rustdoc/deref-typedef.rs @@ -0,0 +1,33 @@ +#![crate_name = "foo"] + +// @has 'foo/struct.Bar.html' +// @has '-' '//*[@id="deref-methods"]' 'Methods from Deref<Target = FooC>' +// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_a"]' 'pub fn foo_a(&self)' +// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_b"]' 'pub fn foo_b(&self)' +// @has '-' '//*[@class="impl-items"]//*[@id="method.foo_c"]' 'pub fn foo_c(&self)' +// @has '-' '//*[@class="sidebar-title"]' 'Methods from Deref<Target=FooC>' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_a"]' 'foo_a' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_b"]' 'foo_b' +// @has '-' '//*[@class="sidebar-links"]/a[@href="#method.foo_c"]' 'foo_c' + +pub struct FooA; +pub type FooB = FooA; +pub type FooC = FooB; + +impl FooA { + pub fn foo_a(&self) {} +} + +impl FooB { + pub fn foo_b(&self) {} +} + +impl FooC { + pub fn foo_c(&self) {} +} + +pub struct Bar; +impl std::ops::Deref for Bar { + type Target = FooC; + fn deref(&self) -> &Self::Target { unimplemented!() } +} diff --git a/src/test/rustdoc/remove-url-from-headings.rs b/src/test/rustdoc/remove-url-from-headings.rs new file mode 100644 index 00000000000..9761c1ddbe2 --- /dev/null +++ b/src/test/rustdoc/remove-url-from-headings.rs @@ -0,0 +1,17 @@ +#![crate_name = "foo"] + +// @has foo/fn.foo.html +// !@has - '//a[@href="http://a.a"]' +// @has - '//a[@href="#implementing-stuff-somewhere"]' 'Implementing stuff somewhere' +// @has - '//a[@href="#another-one-urg"]' 'Another one urg' + +/// fooo +/// +/// # Implementing [stuff](http://a.a "title") somewhere +/// +/// hello +/// +/// # Another [one][two] urg +/// +/// [two]: http://a.a +pub fn foo() {} diff --git a/src/test/ui/match/match-vec-mismatch.rs b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs index a0ef92743ac..34adb42a32f 100644 --- a/src/test/ui/match/match-vec-mismatch.rs +++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn main() { match "foo".to_string() { ['f', 'o', ..] => {} diff --git a/src/test/ui/match/match-vec-mismatch.stderr b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr index a3523bb689e..c4548142c13 100644 --- a/src/test/ui/match/match-vec-mismatch.stderr +++ b/src/test/ui/array-slice-vec/slice-pat-type-mismatches.stderr @@ -1,29 +1,29 @@ error[E0425]: cannot find value `does_not_exist` in this scope - --> $DIR/match-vec-mismatch.rs:28:11 + --> $DIR/slice-pat-type-mismatches.rs:26:11 | LL | match does_not_exist { | ^^^^^^^^^^^^^^ not found in this scope error[E0529]: expected an array or slice, found `std::string::String` - --> $DIR/match-vec-mismatch.rs:5:9 + --> $DIR/slice-pat-type-mismatches.rs:3:9 | LL | ['f', 'o', ..] => {} | ^^^^^^^^^^^^^^ pattern cannot match with input type `std::string::String` error[E0527]: pattern requires 1 element but array has 3 - --> $DIR/match-vec-mismatch.rs:20:9 + --> $DIR/slice-pat-type-mismatches.rs:18:9 | LL | [0] => {}, | ^^^ expected 3 elements error[E0528]: pattern requires at least 4 elements but array has 3 - --> $DIR/match-vec-mismatch.rs:25:9 + --> $DIR/slice-pat-type-mismatches.rs:23:9 | LL | [0, 1, 2, 3, x @ ..] => {} | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 3 elements error[E0282]: type annotations needed - --> $DIR/match-vec-mismatch.rs:36:9 + --> $DIR/slice-pat-type-mismatches.rs:34:9 | LL | [] => {} | ^^ cannot infer type diff --git a/src/test/ui/parser/match-vec-invalid.rs b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs index 00f4374b256..97e33624bf6 100644 --- a/src/test/ui/parser/match-vec-invalid.rs +++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.rs @@ -3,8 +3,6 @@ fn main() { match a { [1, tail @ .., tail @ ..] => {}, //~^ ERROR identifier `tail` is bound more than once in the same pattern - //~| ERROR subslice patterns are unstable - //~| ERROR subslice patterns are unstable //~| ERROR `..` can only be used once per slice pattern _ => () } diff --git a/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr new file mode 100644 index 00000000000..4d6078788b2 --- /dev/null +++ b/src/test/ui/array-slice-vec/subslice-only-once-semantic-restriction.stderr @@ -0,0 +1,24 @@ +error[E0416]: identifier `tail` is bound more than once in the same pattern + --> $DIR/subslice-only-once-semantic-restriction.rs:4:24 + | +LL | [1, tail @ .., tail @ ..] => {}, + | ^^^^ used in a pattern more than once + +error: `..` can only be used once per slice pattern + --> $DIR/subslice-only-once-semantic-restriction.rs:4:31 + | +LL | [1, tail @ .., tail @ ..] => {}, + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error[E0308]: mismatched types + --> $DIR/subslice-only-once-semantic-restriction.rs:11:30 + | +LL | const RECOVERY_WITNESS: () = 0; + | ^ expected `()`, found integer + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0416. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs index 0e767d9613a..69c33921868 100644 --- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval-match.rs @@ -2,7 +2,7 @@ // run-pass -#![feature(slice_patterns, const_fn, const_if_match)] +#![feature(const_fn, const_if_match)] #[derive(PartialEq, Debug, Clone)] struct N(u8); diff --git a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs index 5444f8a9051..0b793fa0120 100644 --- a/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs +++ b/src/test/ui/array-slice-vec/subslice-patterns-const-eval.rs @@ -2,8 +2,6 @@ // run-pass -#![feature(slice_patterns)] - #[derive(PartialEq, Debug, Clone)] struct N(u8); diff --git a/src/test/ui/array-slice-vec/subslice-patterns-pass.rs b/src/test/ui/array-slice-vec/subslice-patterns-pass.rs index 1ebf3def788..e05790911f5 100644 --- a/src/test/ui/array-slice-vec/subslice-patterns-pass.rs +++ b/src/test/ui/array-slice-vec/subslice-patterns-pass.rs @@ -4,8 +4,6 @@ // run-pass -#![feature(slice_patterns)] - #![allow(unreachable_patterns)] use std::convert::identity; diff --git a/src/test/ui/array-slice-vec/vec-matching-fixed.rs b/src/test/ui/array-slice-vec/vec-matching-fixed.rs index 5253bc1b214..fdeb7e4fda6 100644 --- a/src/test/ui/array-slice-vec/vec-matching-fixed.rs +++ b/src/test/ui/array-slice-vec/vec-matching-fixed.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(slice_patterns)] - fn a() { let x = [1, 2, 3]; match x { diff --git a/src/test/ui/array-slice-vec/vec-matching-fold.rs b/src/test/ui/array-slice-vec/vec-matching-fold.rs index f416160db24..998899271e4 100644 --- a/src/test/ui/array-slice-vec/vec-matching-fold.rs +++ b/src/test/ui/array-slice-vec/vec-matching-fold.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(slice_patterns)] - use std::fmt::Debug; fn foldl<T, U, F>(values: &[T], diff --git a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs index f0602c328b0..ed34f074a92 100644 --- a/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs +++ b/src/test/ui/array-slice-vec/vec-matching-legal-tail-element-borrow.rs @@ -1,7 +1,6 @@ // run-pass -#![allow(unused_variables)] -#![feature(slice_patterns)] +#![allow(unused_variables)] pub fn main() { let x = &[1, 2, 3, 4, 5]; diff --git a/src/test/ui/array-slice-vec/vec-matching.rs b/src/test/ui/array-slice-vec/vec-matching.rs index 49c736bd728..7009244aa18 100644 --- a/src/test/ui/array-slice-vec/vec-matching.rs +++ b/src/test/ui/array-slice-vec/vec-matching.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(slice_patterns)] - fn a() { let x = [1]; match x { diff --git a/src/test/ui/array-slice-vec/vec-tail-matching.rs b/src/test/ui/array-slice-vec/vec-tail-matching.rs index 3c7b160dcc5..5f1699227d8 100644 --- a/src/test/ui/array-slice-vec/vec-tail-matching.rs +++ b/src/test/ui/array-slice-vec/vec-tail-matching.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(slice_patterns)] - struct Foo { string: &'static str } diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs index 645c903c6ba..ceeebbca519 100644 --- a/src/test/ui/async-await/async-fn-nonsend.rs +++ b/src/test/ui/async-await/async-fn-nonsend.rs @@ -2,15 +2,15 @@ // edition:2018 // compile-flags: --crate-type lib -use std::{ - cell::RefCell, - fmt::Debug, - rc::Rc, -}; +use std::{cell::RefCell, fmt::Debug, rc::Rc}; -fn non_sync() -> impl Debug { RefCell::new(()) } +fn non_sync() -> impl Debug { + RefCell::new(()) +} -fn non_send() -> impl Debug { Rc::new(()) } +fn non_send() -> impl Debug { + Rc::new(()) +} fn take_ref<T>(_: &T) {} @@ -53,5 +53,4 @@ pub fn pass_assert() { //~^ ERROR future cannot be sent between threads safely assert_send(non_sync_with_method_call()); //~^ ERROR future cannot be sent between threads safely - //~^^ ERROR future cannot be sent between threads safely } diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 5c870ca2d02..105fd23ecfb 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -62,27 +62,5 @@ LL | } LL | } | - `f` is later dropped here -error: future cannot be sent between threads safely - --> $DIR/async-fn-nonsend.rs:54:5 - | -LL | fn assert_send(_: impl Send) {} - | ----------- ---- required by this bound in `assert_send` -... -LL | assert_send(non_sync_with_method_call()); - | ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send` - | - = help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` -note: future is not `Send` as this value is used across an await - --> $DIR/async-fn-nonsend.rs:43:9 - | -LL | let f: &mut std::fmt::Formatter = panic!(); - | - has type `&mut std::fmt::Formatter<'_>` -LL | if non_sync().fmt(f).unwrap() == () { -LL | fut().await; - | ^^^^^^^^^^^ await occurs here, with `f` maybe used later -LL | } -LL | } - | - `f` is later dropped here - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/binding/empty-types-in-patterns.rs b/src/test/ui/binding/empty-types-in-patterns.rs index 4271ffb7b1b..0d0dbcaf40f 100644 --- a/src/test/ui/binding/empty-types-in-patterns.rs +++ b/src/test/ui/binding/empty-types-in-patterns.rs @@ -1,7 +1,8 @@ // run-pass + #![feature(never_type, never_type_fallback)] #![feature(exhaustive_patterns)] -#![feature(slice_patterns)] + #![allow(unreachable_patterns)] #![allow(unreachable_code)] #![allow(unused_variables)] diff --git a/src/test/ui/binding/irrefutable-slice-patterns.rs b/src/test/ui/binding/irrefutable-slice-patterns.rs index ac733ef6e9c..048e1e5e9b4 100644 --- a/src/test/ui/binding/irrefutable-slice-patterns.rs +++ b/src/test/ui/binding/irrefutable-slice-patterns.rs @@ -1,7 +1,6 @@ // run-pass -// #47096 -#![feature(slice_patterns)] +// Regression test for #47096. fn foo(s: &[i32]) -> &[i32] { let &[ref xs @ ..] = s; diff --git a/src/test/ui/binding/match-byte-array-patterns.rs b/src/test/ui/binding/match-byte-array-patterns.rs index e87745705da..f0c988c01c2 100644 --- a/src/test/ui/binding/match-byte-array-patterns.rs +++ b/src/test/ui/binding/match-byte-array-patterns.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn main() { let buf = &[0u8; 4]; diff --git a/src/test/ui/binding/match-vec-alternatives.rs b/src/test/ui/binding/match-vec-alternatives.rs index 9b06a86a7b9..af95eb95df0 100644 --- a/src/test/ui/binding/match-vec-alternatives.rs +++ b/src/test/ui/binding/match-vec-alternatives.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str { match (l1, l2) { diff --git a/src/test/ui/binding/zero_sized_subslice_match.rs b/src/test/ui/binding/zero_sized_subslice_match.rs index 5326fa612a8..187c2983633 100644 --- a/src/test/ui/binding/zero_sized_subslice_match.rs +++ b/src/test/ui/binding/zero_sized_subslice_match.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn main() { let x = [(), ()]; diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs index a70ccb7aa4b..0229ca37a69 100644 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns-ok.rs @@ -1,6 +1,5 @@ // Check that closure captures for slice patterns are inferred correctly -#![feature(slice_patterns)] #![allow(unused_variables)] // run-pass diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs index 984eb8804b7..32057d5c126 100644 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.rs @@ -1,7 +1,5 @@ // Check that closure captures for slice patterns are inferred correctly -#![feature(slice_patterns)] - fn arr_by_ref(mut x: [String; 3]) { let f = || { let [ref y, ref z @ ..] = x; diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr index c5b27f5f8b4..483975e5778 100644 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-closures-slice-patterns.rs:9:13 + --> $DIR/borrowck-closures-slice-patterns.rs:7:13 | LL | let f = || { | -- immutable borrow occurs here @@ -13,7 +13,7 @@ LL | f(); | - immutable borrow later used here error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-closures-slice-patterns.rs:18:13 + --> $DIR/borrowck-closures-slice-patterns.rs:16:13 | LL | let mut f = || { | -- mutable borrow occurs here @@ -27,7 +27,7 @@ LL | f(); | - mutable borrow later used here error[E0382]: borrow of moved value: `x` - --> $DIR/borrowck-closures-slice-patterns.rs:27:5 + --> $DIR/borrowck-closures-slice-patterns.rs:25:5 | LL | fn arr_by_move(x: [String; 3]) { | - move occurs because `x` has type `[std::string::String; 3]`, which does not implement the `Copy` trait @@ -40,7 +40,7 @@ LL | &x; | ^^ value borrowed here after move error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-closures-slice-patterns.rs:35:13 + --> $DIR/borrowck-closures-slice-patterns.rs:33:13 | LL | let f = || { | -- immutable borrow occurs here @@ -54,7 +54,7 @@ LL | f(); | - immutable borrow later used here error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access - --> $DIR/borrowck-closures-slice-patterns.rs:44:13 + --> $DIR/borrowck-closures-slice-patterns.rs:42:13 | LL | let mut f = || { | -- closure construction occurs here @@ -68,7 +68,7 @@ LL | f(); | - first borrow later used here error[E0382]: borrow of moved value: `x` - --> $DIR/borrowck-closures-slice-patterns.rs:53:5 + --> $DIR/borrowck-closures-slice-patterns.rs:51:5 | LL | fn arr_box_by_move(x: Box<[String; 3]>) { | - move occurs because `x` has type `std::boxed::Box<[std::string::String; 3]>`, which does not implement the `Copy` trait @@ -81,7 +81,7 @@ LL | &x; | ^^ value borrowed here after move error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-closures-slice-patterns.rs:61:13 + --> $DIR/borrowck-closures-slice-patterns.rs:59:13 | LL | let f = || { | -- immutable borrow occurs here @@ -95,7 +95,7 @@ LL | f(); | - immutable borrow later used here error[E0501]: cannot borrow `x` as immutable because previous closure requires unique access - --> $DIR/borrowck-closures-slice-patterns.rs:70:13 + --> $DIR/borrowck-closures-slice-patterns.rs:68:13 | LL | let mut f = || { | -- closure construction occurs here diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.rs b/src/test/ui/borrowck/borrowck-describe-lvalue.rs index 8425960aa86..c8bfbe0729c 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.rs @@ -1,7 +1,5 @@ // ignore-tidy-linelength -#![feature(slice_patterns)] - pub struct Foo { x: u32 } diff --git a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr index 4213523d2fa..075e0e2e451 100644 --- a/src/test/ui/borrowck/borrowck-describe-lvalue.stderr +++ b/src/test/ui/borrowck/borrowck-describe-lvalue.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:258:13 + --> $DIR/borrowck-describe-lvalue.rs:256:13 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -9,7 +9,7 @@ LL | *y = 1; | ------ first borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time - --> $DIR/borrowck-describe-lvalue.rs:268:20 + --> $DIR/borrowck-describe-lvalue.rs:266:20 | LL | let y = &mut x; | ------ first mutable borrow occurs here @@ -19,7 +19,7 @@ LL | *y = 1; | ------ first borrow later used here error: captured variable cannot escape `FnMut` closure body - --> $DIR/borrowck-describe-lvalue.rs:266:16 + --> $DIR/borrowck-describe-lvalue.rs:264:16 | LL | || { | - inferred to be a `FnMut` closure @@ -35,7 +35,7 @@ LL | | } = note: ...therefore, they cannot allow references to captured variables to escape error[E0503]: cannot use `f.x` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:41:9 + --> $DIR/borrowck-describe-lvalue.rs:39:9 | LL | let x = f.x(); | - borrow of `f` occurs here @@ -45,7 +45,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `g.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:48:9 + --> $DIR/borrowck-describe-lvalue.rs:46:9 | LL | let x = g.x(); | - borrow of `g` occurs here @@ -55,7 +55,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `h.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:55:9 + --> $DIR/borrowck-describe-lvalue.rs:53:9 | LL | let x = &mut h.0; | -------- borrow of `h.0` occurs here @@ -65,7 +65,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `e.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:63:20 + --> $DIR/borrowck-describe-lvalue.rs:61:20 | LL | let x = e.x(); | - borrow of `e` occurs here @@ -77,7 +77,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `u.a` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:71:9 + --> $DIR/borrowck-describe-lvalue.rs:69:9 | LL | let x = &mut u.a; | -------- borrow of `u.a` occurs here @@ -87,7 +87,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `f.x` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:78:9 + --> $DIR/borrowck-describe-lvalue.rs:76:9 | LL | let x = f.x(); | - borrow of `*f` occurs here @@ -97,7 +97,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `g.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:85:9 + --> $DIR/borrowck-describe-lvalue.rs:83:9 | LL | let x = g.x(); | - borrow of `*g` occurs here @@ -107,7 +107,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `h.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:92:9 + --> $DIR/borrowck-describe-lvalue.rs:90:9 | LL | let x = &mut h.0; | -------- borrow of `h.0` occurs here @@ -117,7 +117,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `e.0` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:100:20 + --> $DIR/borrowck-describe-lvalue.rs:98:20 | LL | let x = e.x(); | - borrow of `*e` occurs here @@ -129,7 +129,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `u.a` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:109:9 + --> $DIR/borrowck-describe-lvalue.rs:107:9 | LL | let x = &mut u.a; | -------- borrow of `u.a` occurs here @@ -139,7 +139,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:117:15 + --> $DIR/borrowck-describe-lvalue.rs:115:15 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -151,7 +151,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:122:18 + --> $DIR/borrowck-describe-lvalue.rs:120:18 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -163,7 +163,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:127:25 + --> $DIR/borrowck-describe-lvalue.rs:125:25 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -175,7 +175,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:132:28 + --> $DIR/borrowck-describe-lvalue.rs:130:28 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -187,7 +187,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:143:15 + --> $DIR/borrowck-describe-lvalue.rs:141:15 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -199,7 +199,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:148:18 + --> $DIR/borrowck-describe-lvalue.rs:146:18 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -211,7 +211,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:153:15 + --> $DIR/borrowck-describe-lvalue.rs:151:15 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -223,7 +223,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[..]` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:158:18 + --> $DIR/borrowck-describe-lvalue.rs:156:18 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -235,7 +235,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `e` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:171:13 + --> $DIR/borrowck-describe-lvalue.rs:169:13 | LL | let x = &mut e; | ------ borrow of `e` occurs here @@ -247,7 +247,7 @@ LL | drop(x); | - borrow later used here error[E0502]: cannot borrow `e.0` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:171:18 + --> $DIR/borrowck-describe-lvalue.rs:169:18 | LL | let x = &mut e; | ------ mutable borrow occurs here @@ -259,7 +259,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:175:23 + --> $DIR/borrowck-describe-lvalue.rs:173:23 | LL | let x = &mut e; | ------ mutable borrow occurs here @@ -271,7 +271,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:188:22 + --> $DIR/borrowck-describe-lvalue.rs:186:22 | LL | let x = &mut s; | ------ mutable borrow occurs here @@ -283,7 +283,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:194:28 + --> $DIR/borrowck-describe-lvalue.rs:192:28 | LL | let x = &mut s; | ------ mutable borrow occurs here @@ -295,7 +295,7 @@ LL | drop(x); | - mutable borrow later used here error[E0503]: cannot use `*v` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:236:9 + --> $DIR/borrowck-describe-lvalue.rs:234:9 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -306,7 +306,7 @@ LL | drop(x); | - borrow later used here error[E0503]: cannot use `v[_].y` because it was mutably borrowed - --> $DIR/borrowck-describe-lvalue.rs:236:9 + --> $DIR/borrowck-describe-lvalue.rs:234:9 | LL | let x = &mut v; | ------ borrow of `v` occurs here @@ -317,7 +317,7 @@ LL | drop(x); | - borrow later used here error[E0502]: cannot borrow `v[..].x` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:247:24 + --> $DIR/borrowck-describe-lvalue.rs:245:24 | LL | let x = &mut v; | ------ mutable borrow occurs here @@ -329,7 +329,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:210:29 + --> $DIR/borrowck-describe-lvalue.rs:208:29 | LL | let x = &mut block; | ---------- mutable borrow occurs here @@ -340,7 +340,7 @@ LL | drop(x); | - mutable borrow later used here error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-describe-lvalue.rs:225:33 + --> $DIR/borrowck-describe-lvalue.rs:223:33 | LL | let x = &mut block; | ---------- mutable borrow occurs here @@ -351,7 +351,7 @@ LL | drop(x); | - mutable borrow later used here error[E0382]: use of moved value: `x` - --> $DIR/borrowck-describe-lvalue.rs:278:22 + --> $DIR/borrowck-describe-lvalue.rs:276:22 | LL | drop(x); | - value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs index 232d43679b4..c1513fcba8a 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr index e46a58a8a35..84930b000cc 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-match.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-match.rs:15:14 + --> $DIR/borrowck-move-out-from-array-match.rs:13:14 | LL | [_, _, _x] => {} | -- value moved here @@ -10,7 +10,7 @@ LL | [.., _y] => {} = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-match.rs:25:14 + --> $DIR/borrowck-move-out-from-array-match.rs:23:14 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -21,7 +21,7 @@ LL | [.., _y] => {} = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array-match.rs:35:15 + --> $DIR/borrowck-move-out-from-array-match.rs:33:15 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -32,7 +32,7 @@ LL | [.., (_y, _)] => {} = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-match.rs:46:11 + --> $DIR/borrowck-move-out-from-array-match.rs:44:11 | LL | [_x, _, _] => {} | -- value moved here @@ -43,7 +43,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-match.rs:57:11 + --> $DIR/borrowck-move-out-from-array-match.rs:55:11 | LL | [.., _x] => {} | -- value moved here @@ -54,7 +54,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-match.rs:68:11 + --> $DIR/borrowck-move-out-from-array-match.rs:66:11 | LL | [(_x, _), _, _] => {} | -- value moved here @@ -65,7 +65,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-match.rs:79:11 + --> $DIR/borrowck-move-out-from-array-match.rs:77:11 | LL | [.., (_x, _)] => {} | -- value moved here @@ -76,7 +76,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array-match.rs:91:11 + --> $DIR/borrowck-move-out-from-array-match.rs:89:11 | LL | [_y @ .., _, _] => {} | ------- value moved here @@ -87,7 +87,7 @@ LL | [(_x, _), _, _] => {} = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array-match.rs:101:15 + --> $DIR/borrowck-move-out-from-array-match.rs:99:15 | LL | [_, _, _y @ ..] => {} | ------- value moved here @@ -98,7 +98,7 @@ LL | [.., (_x, _)] => {} = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-match.rs:112:11 + --> $DIR/borrowck-move-out-from-array-match.rs:110:11 | LL | [x @ .., _] => {} | ------ value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs index e5e61697c68..056b8e672bd 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.rs @@ -3,8 +3,6 @@ // Once the bug is fixed, the test, which is derived from a // passing test for `let` statements, should become check-pass. -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr index 72cd4207cce..ff5eab2442c 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap-match.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:19:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:17:11 | LL | [_, _, _x] => {} | -- value moved here @@ -10,7 +10,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:30:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:28:11 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -21,7 +21,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:43:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:41:11 | LL | [_x, _, _] => {} | -- value moved here @@ -32,7 +32,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:54:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:52:11 | LL | [.., _x] => {} | -- value moved here @@ -43,7 +43,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:65:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:63:11 | LL | [(_x, _), _, _] => {} | -- value moved here @@ -54,7 +54,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:76:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:74:11 | LL | [.., (_x, _)] => {} | -- value moved here @@ -65,7 +65,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:87:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:85:11 | LL | [_, _y @ ..] => {} | ------- value moved here @@ -76,7 +76,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:98:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:96:11 | LL | [_y @ .., _] => {} | ------- value moved here @@ -87,7 +87,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:111:11 + --> $DIR/borrowck-move-out-from-array-no-overlap-match.rs:109:11 | LL | [x @ .., _, _] => {} | ------ value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs index 8f274cf73cb..c91b4286b64 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-no-overlap.rs @@ -1,7 +1,5 @@ // check-pass -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs index 1ca3df52ada..604a25cdcc1 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr index 028442a4c07..0ef63105cfb 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-match.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use-match.rs:15:14 + --> $DIR/borrowck-move-out-from-array-use-match.rs:13:14 | LL | [_, _, _x] => {} | -- value moved here @@ -10,7 +10,7 @@ LL | [.., ref _y] => {} = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use-match.rs:25:14 + --> $DIR/borrowck-move-out-from-array-use-match.rs:23:14 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -21,7 +21,7 @@ LL | [.., ref _y] => {} = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array-use-match.rs:35:15 + --> $DIR/borrowck-move-out-from-array-use-match.rs:33:15 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -32,7 +32,7 @@ LL | [.., (ref _y, _)] => {} = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:46:11 + --> $DIR/borrowck-move-out-from-array-use-match.rs:44:11 | LL | [_x, _, _] => {} | -- value moved here @@ -43,7 +43,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:57:11 + --> $DIR/borrowck-move-out-from-array-use-match.rs:55:11 | LL | [.., _x] => {} | -- value moved here @@ -54,7 +54,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:68:11 + --> $DIR/borrowck-move-out-from-array-use-match.rs:66:11 | LL | [(_x, _), _, _] => {} | -- value moved here @@ -65,7 +65,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:79:11 + --> $DIR/borrowck-move-out-from-array-use-match.rs:77:11 | LL | [.., (_x, _)] => {} | -- value moved here @@ -76,7 +76,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use-match.rs:91:11 + --> $DIR/borrowck-move-out-from-array-use-match.rs:89:11 | LL | [_y @ .., _, _] => {} | ------- value moved here @@ -87,7 +87,7 @@ LL | [(ref _x, _), _, _] => {} = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use-match.rs:101:15 + --> $DIR/borrowck-move-out-from-array-use-match.rs:99:15 | LL | [_, _, _y @ ..] => {} | ------- value moved here @@ -98,7 +98,7 @@ LL | [.., (ref _x, _)] => {} = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:112:11 + --> $DIR/borrowck-move-out-from-array-use-match.rs:110:11 | LL | [x @ .., _] => {} | ------ value moved here @@ -109,7 +109,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:125:5 + --> $DIR/borrowck-move-out-from-array-use-match.rs:123:5 | LL | [_, _, _x] => {} | -- value moved here @@ -120,7 +120,7 @@ LL | a[2] = Default::default(); = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:133:5 + --> $DIR/borrowck-move-out-from-array-use-match.rs:131:5 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -131,7 +131,7 @@ LL | a[2].1 = Default::default(); = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:141:5 + --> $DIR/borrowck-move-out-from-array-use-match.rs:139:5 | LL | [_, _, _x @ ..] => {} | ------- value moved here @@ -142,7 +142,7 @@ LL | a[0] = Default::default(); = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-match.rs:149:5 + --> $DIR/borrowck-move-out-from-array-use-match.rs:147:5 | LL | [_, _, _x @ ..] => {} | ------- value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs index 79fe5930096..5afd6835dcf 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.rs @@ -3,8 +3,6 @@ // Once the bug is fixed, the test, which is derived from a // passing test for `let` statements, should become check-pass. -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr index 43ba2b664a1..a4042ce7db3 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap-match.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:19:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:17:11 | LL | [_, _, _x] => {} | -- value moved here @@ -10,7 +10,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:30:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:28:11 | LL | [_, _, (_x, _)] => {} | -- value moved here @@ -21,7 +21,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:43:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:41:11 | LL | [_x, _, _] => {} | -- value moved here @@ -32,7 +32,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:54:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:52:11 | LL | [.., _x] => {} | -- value moved here @@ -43,7 +43,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:65:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:63:11 | LL | [(_x, _), _, _] => {} | -- value moved here @@ -54,7 +54,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:76:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:74:11 | LL | [.., (_x, _)] => {} | -- value moved here @@ -65,7 +65,7 @@ LL | match a { = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:87:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:85:11 | LL | [_, _y @ ..] => {} | ------- value moved here @@ -76,7 +76,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:98:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:96:11 | LL | [_y @ .., _] => {} | ------- value moved here @@ -87,7 +87,7 @@ LL | match a { = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:111:11 + --> $DIR/borrowck-move-out-from-array-use-no-overlap-match.rs:109:11 | LL | [x @ .., _, _] => {} | ------ value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs index 57ce2417570..e3498cef377 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use-no-overlap.rs @@ -1,7 +1,5 @@ // check-pass -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs index 778beefbf2c..ad08367a3b5 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr index 2a7b89132c1..7ad4116645e 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array-use.stderr @@ -1,5 +1,5 @@ error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use.rs:12:14 + --> $DIR/borrowck-move-out-from-array-use.rs:10:14 | LL | let [_, _, _x] = a; | -- value moved here @@ -9,7 +9,7 @@ LL | let [.., ref _y] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use.rs:18:14 + --> $DIR/borrowck-move-out-from-array-use.rs:16:14 | LL | let [_, _, (_x, _)] = a; | -- value moved here @@ -19,7 +19,7 @@ LL | let [.., ref _y] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array-use.rs:24:15 + --> $DIR/borrowck-move-out-from-array-use.rs:22:15 | LL | let [_, _, (_x, _)] = a; | -- value moved here @@ -29,7 +29,7 @@ LL | let [.., (ref _y, _)] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:32:10 + --> $DIR/borrowck-move-out-from-array-use.rs:30:10 | LL | let [_x, _, _] = a; | -- value moved here @@ -39,7 +39,7 @@ LL | let [ref _y @ .., _, _] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:38:16 + --> $DIR/borrowck-move-out-from-array-use.rs:36:16 | LL | let [.., _x] = a; | -- value moved here @@ -49,7 +49,7 @@ LL | let [_, _, ref _y @ ..] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:44:10 + --> $DIR/borrowck-move-out-from-array-use.rs:42:10 | LL | let [(_x, _), _, _] = a; | -- value moved here @@ -59,7 +59,7 @@ LL | let [ref _y @ .., _, _] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:50:16 + --> $DIR/borrowck-move-out-from-array-use.rs:48:16 | LL | let [.., (_x, _)] = a; | -- value moved here @@ -69,7 +69,7 @@ LL | let [_, _, ref _y @ ..] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use.rs:56:11 + --> $DIR/borrowck-move-out-from-array-use.rs:54:11 | LL | let [_y @ .., _, _] = a; | ------- value moved here @@ -79,7 +79,7 @@ LL | let [(ref _x, _), _, _] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array-use.rs:62:15 + --> $DIR/borrowck-move-out-from-array-use.rs:60:15 | LL | let [_, _, _y @ ..] = a; | ------- value moved here @@ -89,7 +89,7 @@ LL | let [.., (ref _x, _)] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: borrow of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:70:13 + --> $DIR/borrowck-move-out-from-array-use.rs:68:13 | LL | let [x @ .., _] = a; | ------ value moved here @@ -99,7 +99,7 @@ LL | let [_, ref _y @ ..] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:78:5 + --> $DIR/borrowck-move-out-from-array-use.rs:76:5 | LL | let [_, _, _x] = a; | -- value moved here @@ -109,7 +109,7 @@ LL | a[2] = Default::default(); = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:84:5 + --> $DIR/borrowck-move-out-from-array-use.rs:82:5 | LL | let [_, _, (_x, _)] = a; | -- value moved here @@ -119,7 +119,7 @@ LL | a[2].1 = Default::default(); = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:90:5 + --> $DIR/borrowck-move-out-from-array-use.rs:88:5 | LL | let [_, _, _x @ ..] = a; | ------- value moved here @@ -129,7 +129,7 @@ LL | a[0] = Default::default(); = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array-use.rs:96:5 + --> $DIR/borrowck-move-out-from-array-use.rs:94:5 | LL | let [_, _, _x @ ..] = a; | ------- value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.rs b/src/test/ui/borrowck/borrowck-move-out-from-array.rs index f9d3f6f2c07..83755812f4b 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.rs +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn array() -> [(String, String); 3] { Default::default() } diff --git a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr index 08134a2a323..b7babd93ed7 100644 --- a/src/test/ui/borrowck/borrowck-move-out-from-array.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-from-array.stderr @@ -1,5 +1,5 @@ error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array.rs:12:14 + --> $DIR/borrowck-move-out-from-array.rs:10:14 | LL | let [_, _, _x] = a; | -- value moved here @@ -9,7 +9,7 @@ LL | let [.., _y] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..]` - --> $DIR/borrowck-move-out-from-array.rs:18:14 + --> $DIR/borrowck-move-out-from-array.rs:16:14 | LL | let [_, _, (_x, _)] = a; | -- value moved here @@ -19,7 +19,7 @@ LL | let [.., _y] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array.rs:24:15 + --> $DIR/borrowck-move-out-from-array.rs:22:15 | LL | let [_, _, (_x, _)] = a; | -- value moved here @@ -29,7 +29,7 @@ LL | let [.., (_y, _)] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array.rs:32:10 + --> $DIR/borrowck-move-out-from-array.rs:30:10 | LL | let [_x, _, _] = a; | -- value moved here @@ -39,7 +39,7 @@ LL | let [_y @ .., _, _] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array.rs:38:16 + --> $DIR/borrowck-move-out-from-array.rs:36:16 | LL | let [.., _x] = a; | -- value moved here @@ -49,7 +49,7 @@ LL | let [_, _, _y @ ..] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array.rs:44:10 + --> $DIR/borrowck-move-out-from-array.rs:42:10 | LL | let [(_x, _), _, _] = a; | -- value moved here @@ -59,7 +59,7 @@ LL | let [_y @ .., _, _] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array.rs:50:16 + --> $DIR/borrowck-move-out-from-array.rs:48:16 | LL | let [.., (_x, _)] = a; | -- value moved here @@ -69,7 +69,7 @@ LL | let [_, _, _y @ ..] = a; = note: move occurs because `a[..].0` has type `std::string::String`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array.rs:56:11 + --> $DIR/borrowck-move-out-from-array.rs:54:11 | LL | let [_y @ .., _, _] = a; | ------- value moved here @@ -79,7 +79,7 @@ LL | let [(_x, _), _, _] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a[..].0` - --> $DIR/borrowck-move-out-from-array.rs:62:15 + --> $DIR/borrowck-move-out-from-array.rs:60:15 | LL | let [_, _, _y @ ..] = a; | ------- value moved here @@ -89,7 +89,7 @@ LL | let [.., (_x, _)] = a; = note: move occurs because `a[..]` has type `(std::string::String, std::string::String)`, which does not implement the `Copy` trait error[E0382]: use of moved value: `a` - --> $DIR/borrowck-move-out-from-array.rs:70:13 + --> $DIR/borrowck-move-out-from-array.rs:68:13 | LL | let [x @ .., _] = a; | ------ value moved here diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs index fa9a3c217db..8ece81a3c84 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs +++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.rs @@ -1,7 +1,5 @@ // Test that we do not permit moves from &[] matched by a vec pattern. -#![feature(slice_patterns)] - #[derive(Clone, Debug)] struct Foo { string: String diff --git a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr index 8fb4c062c03..a345c1238f0 100644 --- a/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr +++ b/src/test/ui/borrowck/borrowck-move-out-of-vec-tail.stderr @@ -1,5 +1,5 @@ error[E0508]: cannot move out of type `[Foo]`, a non-copy slice - --> $DIR/borrowck-move-out-of-vec-tail.rs:19:19 + --> $DIR/borrowck-move-out-of-vec-tail.rs:17:19 | LL | match tail { | ^^^^ cannot move out of here diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs index 7d91a212647..a8e56f648e2 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array-no-overlap.rs @@ -1,7 +1,5 @@ // check-pass -#![feature(slice_patterns)] - fn nop(_s: &[& i32]) {} fn nop_subslice(_s: &[i32]) {} diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs index f03a2ab8fa8..6b210d73228 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn nop(_s: &[& i32]) {} fn nop_subslice(_s: &[i32]) {} diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr index e50e7eb3e22..0432aaf51d2 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-array.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:8:13 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:6:13 | LL | let [ref first, ref second, ..] = *s; | ---------- immutable borrow occurs here @@ -9,7 +9,7 @@ LL | nop(&[first, second, second2, third]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:14:14 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:12:14 | LL | let [.., ref fourth, ref third, _, ref first] = *s; | --------- immutable borrow occurs here @@ -19,7 +19,7 @@ LL | nop(&[first, third, third2, fourth]); | ----- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:16 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:19:16 | LL | let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s; | ------------- immutable borrow occurs here @@ -30,7 +30,7 @@ LL | nop(&[from_begin2, from_end1, from_end3, from_end4]); | --------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:23:19 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:21:19 | LL | let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s; | ------------- immutable borrow occurs here @@ -41,7 +41,7 @@ LL | nop(&[from_begin3, from_end1, from_end3, from_end4]); | --------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:28:14 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:26:14 | LL | let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s; | --------------- immutable borrow occurs here @@ -52,7 +52,7 @@ LL | nop(&[from_begin0, from_begin1, from_begin3, from_end3]); | ----------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:34:13 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:32:13 | LL | let [ref first, ref second, ..] = *s; | ---------- immutable borrow occurs here @@ -62,7 +62,7 @@ LL | nop(&[first, second]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:41:10 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:39:10 | LL | let [.., ref second, ref first] = *s; | ---------- immutable borrow occurs here @@ -72,7 +72,7 @@ LL | nop(&[first, second]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-array.rs:48:10 + --> $DIR/borrowck-slice-pattern-element-loan-array.rs:46:10 | LL | let [_, ref s1 @ ..] = *s; | ----------- immutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs index 048813b2b93..4367596c6ea 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-rpass.rs @@ -1,7 +1,4 @@ // run-pass -//compile-flags: -Z borrowck=mir - -#![feature(slice_patterns)] fn mut_head_tail<'a, A>(v: &'a mut [A]) -> Option<(&'a mut A, &'a mut [A])> { match *v { diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs index e69071f8772..6390dc3a91a 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice-no-overlap.rs @@ -1,7 +1,5 @@ // check-pass -#![feature(slice_patterns)] - fn nop(_s: &[& i32]) {} fn nop_subslice(_s: &[i32]) {} diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs index 2ef98741dc3..0e1c90a1cd8 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn nop(_s: &[& i32]) {} fn nop_subslice(_s: &[i32]) {} diff --git a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr index b6f5ac64b20..d3388e071aa 100644 --- a/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr +++ b/src/test/ui/borrowck/borrowck-slice-pattern-element-loan-slice.stderr @@ -1,5 +1,5 @@ error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:8:20 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:6:20 | LL | if let [ref first, ref second, ..] = *s { | ---------- immutable borrow occurs here @@ -9,7 +9,7 @@ LL | nop(&[first, second, second2, third]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:16:21 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:14:21 | LL | if let [.., ref fourth, ref third, _, ref first] = *s { | --------- immutable borrow occurs here @@ -19,7 +19,7 @@ LL | nop(&[first, third, third2, fourth]); | ----- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:24:20 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:22:20 | LL | if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { | ------------- immutable borrow occurs here @@ -29,7 +29,7 @@ LL | nop(&[from_begin1, from_end1, from_end3, from_end4]); | --------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:27:23 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:25:23 | LL | if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { | ------------- immutable borrow occurs here @@ -40,7 +40,7 @@ LL | nop(&[from_begin2, from_end1, from_end3, from_end4]); | --------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:30:26 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:28:26 | LL | if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s { | ------------- immutable borrow occurs here @@ -51,7 +51,7 @@ LL | nop(&[from_begin3, from_end1, from_end3, from_end4]); | --------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:35:21 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:33:21 | LL | if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { | --------------- immutable borrow occurs here @@ -61,7 +61,7 @@ LL | nop(&[from_begin0, from_begin1, from_begin3, from_end2]); | ----------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:38:21 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:36:21 | LL | if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { | --------------- immutable borrow occurs here @@ -72,7 +72,7 @@ LL | nop(&[from_begin0, from_begin1, from_begin3, from_end3]); | ----------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:41:21 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:39:21 | LL | if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] = *s { | --------------- immutable borrow occurs here @@ -83,7 +83,7 @@ LL | nop(&[from_begin0, from_begin1, from_begin3, from_end4]); | ----------- immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:49:20 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:47:20 | LL | if let [ref first, ref second, ..] = *s { | ---------- immutable borrow occurs here @@ -93,7 +93,7 @@ LL | nop(&[first, second]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:58:17 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:56:17 | LL | if let [.., ref second, ref first] = *s { | ---------- immutable borrow occurs here @@ -103,7 +103,7 @@ LL | nop(&[first, second]); | ------ immutable borrow later used here error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:67:17 + --> $DIR/borrowck-slice-pattern-element-loan-slice.rs:65:17 | LL | if let [_, _, _, ref s1 @ ..] = *s { | ----------- immutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs index 53a9bcef74a..cd853b83363 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn a<'a>() -> &'a [isize] { let vec = vec![1, 2, 3, 4]; let vec: &[isize] = &vec; diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr index da6d9293b40..170982b1693 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-element-loan.stderr @@ -1,5 +1,5 @@ error[E0515]: cannot return value referencing local variable `vec` - --> $DIR/borrowck-vec-pattern-element-loan.rs:10:5 + --> $DIR/borrowck-vec-pattern-element-loan.rs:8:5 | LL | let vec: &[isize] = &vec; | ---- `vec` is borrowed here @@ -8,7 +8,7 @@ LL | tail | ^^^^ returns a value referencing data owned by the current function error[E0515]: cannot return value referencing local variable `vec` - --> $DIR/borrowck-vec-pattern-element-loan.rs:20:5 + --> $DIR/borrowck-vec-pattern-element-loan.rs:18:5 | LL | let vec: &[isize] = &vec; | ---- `vec` is borrowed here @@ -17,7 +17,7 @@ LL | init | ^^^^ returns a value referencing data owned by the current function error[E0515]: cannot return value referencing local variable `vec` - --> $DIR/borrowck-vec-pattern-element-loan.rs:30:5 + --> $DIR/borrowck-vec-pattern-element-loan.rs:28:5 | LL | let vec: &[isize] = &vec; | ---- `vec` is borrowed here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs index dd9023f6d9f..05859c95d17 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn a() { let mut v = vec![1, 2, 3]; let vb: &mut [isize] = &mut v; diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr index 251f4459290..5141fcc1bb2 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.stderr @@ -1,5 +1,5 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time - --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:8:13 + --> $DIR/borrowck-vec-pattern-loan-from-mut.rs:6:13 | LL | let vb: &mut [isize] = &mut v; | ------ first mutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs index 420223009a4..9b8ba2ea8ad 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.rs @@ -1,7 +1,3 @@ -// http://rust-lang.org/COPYRIGHT. - -#![feature(slice_patterns)] - fn main() { let mut a = [1, 2, 3, 4]; let t = match a { diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr index 9f8e6fe3b68..ff70ba9fcca 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-move-tail.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `a[_]` because it is borrowed - --> $DIR/borrowck-vec-pattern-move-tail.rs:12:5 + --> $DIR/borrowck-vec-pattern-move-tail.rs:8:5 | LL | [1, 2, ref tail @ ..] => tail, | ------------- borrow of `a[_]` occurs here diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs index e274d105e05..67b6c12ba80 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.rs @@ -1,6 +1,5 @@ #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(slice_patterns)] fn a() { let mut vec = [box 1, box 2, box 3]; diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr index a3324f25d0b..e2c0852dd83 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-nesting.stderr @@ -1,5 +1,5 @@ error[E0506]: cannot assign to `vec[_]` because it is borrowed - --> $DIR/borrowck-vec-pattern-nesting.rs:10:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:9:13 | LL | [box ref _a, _, _] => { | ------ borrow of `vec[_]` occurs here @@ -11,7 +11,7 @@ LL | _a.use_ref(); | -- borrow later used here error[E0506]: cannot assign to `vec[_]` because it is borrowed - --> $DIR/borrowck-vec-pattern-nesting.rs:24:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:23:13 | LL | &mut [ref _b @ ..] => { | ----------- borrow of `vec[_]` occurs here @@ -23,7 +23,7 @@ LL | _b.use_ref(); | -- borrow later used here error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:35:11 + --> $DIR/borrowck-vec-pattern-nesting.rs:34:11 | LL | match vec { | ^^^ cannot move out of here @@ -45,7 +45,7 @@ LL | ] => { | error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:47:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:46:13 | LL | let a = vec[0]; | ^^^^^^ @@ -55,7 +55,7 @@ LL | let a = vec[0]; | help: consider borrowing here: `&vec[0]` error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:56:11 + --> $DIR/borrowck-vec-pattern-nesting.rs:55:11 | LL | match vec { | ^^^ cannot move out of here @@ -74,7 +74,7 @@ LL | _b] => {} | error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:66:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:65:13 | LL | let a = vec[0]; | ^^^^^^ @@ -84,7 +84,7 @@ LL | let a = vec[0]; | help: consider borrowing here: `&vec[0]` error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:75:11 + --> $DIR/borrowck-vec-pattern-nesting.rs:74:11 | LL | match vec { | ^^^ cannot move out of here @@ -100,7 +100,7 @@ LL | &mut [_a, _b, _c] => {} = note: move occurs because these variables have types that don't implement the `Copy` trait error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice - --> $DIR/borrowck-vec-pattern-nesting.rs:86:13 + --> $DIR/borrowck-vec-pattern-nesting.rs:85:13 | LL | let a = vec[0]; | ^^^^^^ diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs index c35be2f6be6..39872825cd2 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs +++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn a<'a>() -> &'a isize { let vec = vec![1, 2, 3, 4]; let vec: &[isize] = &vec; diff --git a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr index c1290a6f63f..7e21c55f21b 100644 --- a/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr +++ b/src/test/ui/borrowck/borrowck-vec-pattern-tail-element-loan.stderr @@ -1,5 +1,5 @@ error[E0515]: cannot return value referencing local variable `vec` - --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:10:5 + --> $DIR/borrowck-vec-pattern-tail-element-loan.rs:8:5 | LL | let vec: &[isize] = &vec; | ---- `vec` is borrowed here diff --git a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr index 8b70b15fa6e..89107e799bd 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.nll.stderr @@ -87,12 +87,12 @@ error[E0597]: `ap1` does not live long enough --> $DIR/variadic-ffi-4.rs:24:11 | LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) { - | - let's call the lifetime of this reference `'1` + | - let's call the lifetime of this reference `'3` LL | ap0 = &mut ap1; | ------^^^^^^^^ | | | | | borrowed value does not live long enough - | assignment requires that `ap1` is borrowed for `'1` + | assignment requires that `ap1` is borrowed for `'3` ... LL | } | - `ap1` dropped here while still borrowed diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs new file mode 100644 index 00000000000..30fbfda112c --- /dev/null +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs @@ -0,0 +1,18 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn takes_closure_of_array_3<F>(f: F) where F: Fn([i32; 3]) { + f([1, 2, 3]); +} + +fn takes_closure_of_array_3_apit(f: impl Fn([i32; 3])) { + f([1, 2, 3]); +} + +fn returns_closure_of_array_3() -> impl Fn([i32; 3]) { + |_| {} +} + +fn main() {} diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr new file mode 100644 index 00000000000..7f37f3e2791 --- /dev/null +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index 64aeb46894d..af63d1f75a7 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -1,4 +1,5 @@ // build-pass +// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) #![warn(const_err)] diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 50ad8e83e90..e93aa324784 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -1,17 +1,17 @@ warning: index out of bounds: the len is 3 but the index is 4 - --> $DIR/array-literal-index-oob.rs:6:8 + --> $DIR/array-literal-index-oob.rs:7:8 | LL | &{ [1, 2, 3][4] }; | ^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/array-literal-index-oob.rs:3:9 + --> $DIR/array-literal-index-oob.rs:4:9 | LL | #![warn(const_err)] | ^^^^^^^^^ warning: reaching this expression at runtime will panic or abort - --> $DIR/array-literal-index-oob.rs:6:8 + --> $DIR/array-literal-index-oob.rs:7:8 | LL | &{ [1, 2, 3][4] }; | ---^^^^^^^^^^^^-- @@ -19,7 +19,7 @@ LL | &{ [1, 2, 3][4] }; | indexing out of bounds: the len is 3 but the index is 4 warning: erroneous constant used - --> $DIR/array-literal-index-oob.rs:6:5 + --> $DIR/array-literal-index-oob.rs:7:5 | LL | &{ [1, 2, 3][4] }; | ^^^^^^^^^^^^^^^^^ referenced constant has errors diff --git a/src/test/ui/consts/associated_const_generic.rs b/src/test/ui/consts/associated_const_generic.rs new file mode 100644 index 00000000000..dee376cc17b --- /dev/null +++ b/src/test/ui/consts/associated_const_generic.rs @@ -0,0 +1,25 @@ +// check-pass + +trait TraitA { + const VALUE: usize; +} + +struct A; +impl TraitA for A { + const VALUE: usize = 1; +} + +trait TraitB { + type MyA: TraitA; + const VALUE: usize = Self::MyA::VALUE; +} + +struct B; +impl TraitB for B { + type MyA = A; +} + +fn main() { + let _ = [0; A::VALUE]; + let _ = [0; B::VALUE]; // Indirectly refers to `A::VALUE` +} diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index fee232185d2..22f863fb15a 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,4 +1,5 @@ // build-pass +// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) // compile-flags: -O #![warn(const_err)] diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 4de22fdf4ab..b4330deb3ef 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -1,59 +1,59 @@ warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:8:14 + --> $DIR/promoted_errors.rs:9:14 | LL | let _x = 0u32 - 1; | ^^^^^^^^ attempt to subtract with overflow | note: lint level defined here - --> $DIR/promoted_errors.rs:4:9 + --> $DIR/promoted_errors.rs:5:9 | LL | #![warn(const_err)] | ^^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:11:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:11:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:11:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ referenced constant has errors warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:14:14 + --> $DIR/promoted_errors.rs:15:14 | LL | let _x = 1 / (1 - 1); | ^^^^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:17:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:17:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:17:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ referenced constant has errors warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:21:14 | LL | let _x = 1 / (false as u32); | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs index 41a989d91c5..62c77f76d90 100644 --- a/src/test/ui/consts/const-eval/promoted_errors2.rs +++ b/src/test/ui/consts/const-eval/promoted_errors2.rs @@ -1,4 +1,5 @@ // build-pass +// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) // compile-flags: -C overflow-checks=on -O #![warn(const_err)] diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr index 4f7ba8bf385..a4dad295edd 100644 --- a/src/test/ui/consts/const-eval/promoted_errors2.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr @@ -1,65 +1,65 @@ warning: attempt to subtract with overflow - --> $DIR/promoted_errors2.rs:7:20 + --> $DIR/promoted_errors2.rs:8:20 | LL | println!("{}", 0u32 - 1); | ^^^^^^^^ | note: lint level defined here - --> $DIR/promoted_errors2.rs:4:9 + --> $DIR/promoted_errors2.rs:5:9 | LL | #![warn(const_err)] | ^^^^^^^^^ warning: attempt to subtract with overflow - --> $DIR/promoted_errors2.rs:9:14 + --> $DIR/promoted_errors2.rs:10:14 | LL | let _x = 0u32 - 1; | ^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:11:20 + --> $DIR/promoted_errors2.rs:12:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors2.rs:11:20 + --> $DIR/promoted_errors2.rs:12:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors2.rs:11:20 + --> $DIR/promoted_errors2.rs:12:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ referenced constant has errors warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:15:14 + --> $DIR/promoted_errors2.rs:16:14 | LL | let _x = 1 / (1 - 1); | ^^^^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:17:20 + --> $DIR/promoted_errors2.rs:18:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors2.rs:17:20 + --> $DIR/promoted_errors2.rs:18:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors2.rs:17:20 + --> $DIR/promoted_errors2.rs:18:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ referenced constant has errors warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:21:14 + --> $DIR/promoted_errors2.rs:22:14 | LL | let _x = 1 / (false as u32); | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const_prop_slice_pat_ice.rs b/src/test/ui/consts/const_prop_slice_pat_ice.rs index 5fec36e44bd..60b06a497d6 100644 --- a/src/test/ui/consts/const_prop_slice_pat_ice.rs +++ b/src/test/ui/consts/const_prop_slice_pat_ice.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(slice_patterns)] fn main() { match &[0, 1] as &[i32] { diff --git a/src/test/ui/consts/issue-67529.rs b/src/test/ui/consts/issue-67529.rs new file mode 100644 index 00000000000..df4bc668bee --- /dev/null +++ b/src/test/ui/consts/issue-67529.rs @@ -0,0 +1,11 @@ +// compile-flags: -Z mir-opt-level=2 +// run-pass + +struct Baz<T: ?Sized> { + a: T +} + +fn main() { + let d : Baz<[i32; 4]> = Baz { a: [1,2,3,4] }; + assert_eq!([1, 2, 3, 4], d.a); +} diff --git a/src/test/ui/consts/issue-67640.rs b/src/test/ui/consts/issue-67640.rs new file mode 100644 index 00000000000..bc0ee8d386f --- /dev/null +++ b/src/test/ui/consts/issue-67640.rs @@ -0,0 +1,24 @@ +// compile-flags: -Z mir-opt-level=3 +// run-pass + +struct X { + x: isize +} + +fn f1(a: &mut X, b: &mut isize, c: isize) -> isize { + let r = a.x + *b + c; + a.x = 0; + *b = 10; + return r; +} + +fn f2<F>(a: isize, f: F) -> isize where F: FnOnce(isize) { f(1); return a; } + +pub fn main() { + let mut a = X {x: 1}; + let mut b = 2; + let c = 3; + assert_eq!(f1(&mut a, &mut b, c), 6); + assert_eq!(a.x, 0); + assert_eq!(f2(a.x, |_| a.x = 50), 0); +} diff --git a/src/test/ui/consts/issue-67641.rs b/src/test/ui/consts/issue-67641.rs new file mode 100644 index 00000000000..f50fba287a2 --- /dev/null +++ b/src/test/ui/consts/issue-67641.rs @@ -0,0 +1,24 @@ +// compile-flags: -Z mir-opt-level=2 +// run-pass + +use std::cell::Cell; + +#[derive(Debug)] +struct B<'a> { + a: [Cell<Option<&'a B<'a>>>; 2] +} + +impl<'a> B<'a> { + fn new() -> B<'a> { + B { a: [Cell::new(None), Cell::new(None)] } + } +} + +fn f() { + let b2 = B::new(); + b2.a[0].set(Some(&b2)); +} + +fn main() { + f(); +} diff --git a/src/test/ui/consts/issue-67862.rs b/src/test/ui/consts/issue-67862.rs new file mode 100644 index 00000000000..84f72154d26 --- /dev/null +++ b/src/test/ui/consts/issue-67862.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z mir-opt-level=2 +// run-pass + +fn e220() -> (i64, i64) { + #[inline(never)] + fn get_displacement() -> [i64; 2] { + [139776, 963904] + } + + let res = get_displacement(); + match (&res[0], &res[1]) { + (arg0, arg1) => (*arg0, *arg1), + } +} + +fn main() { + assert_eq!(e220(), (139776, 963904)); +} diff --git a/src/test/ui/consts/issue-68264-overflow.rs b/src/test/ui/consts/issue-68264-overflow.rs new file mode 100644 index 00000000000..8f21e0648d4 --- /dev/null +++ b/src/test/ui/consts/issue-68264-overflow.rs @@ -0,0 +1,43 @@ +// check-pass +// compile-flags: --emit=mir,link +// Regression test for issue #68264 +// Checks that we don't encounter overflow +// when running const-prop on functions with +// complicated bounds +pub trait Query {} + +pub trait AsQuery { + type Query: Query; +} +pub trait Table: AsQuery + Sized {} + +pub trait LimitDsl { + type Output; +} + +pub(crate) trait LoadQuery<Conn, U>: RunQueryDsl<Conn> {} + +impl<T: Query> AsQuery for T { + type Query = Self; +} + +impl<T> LimitDsl for T +where + T: Table, + T::Query: LimitDsl, +{ + type Output = <T::Query as LimitDsl>::Output; +} + +pub(crate) trait RunQueryDsl<Conn>: Sized { + fn first<U>(self, _conn: &Conn) -> U + where + Self: LimitDsl, + Self::Output: LoadQuery<Conn, U>, + { + // Overflow is caused by this function body + unimplemented!() + } +} + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr index 2cdeb598c8c..2439d527bd1 100644 --- a/src/test/ui/consts/miri_unleashed/drop.stderr +++ b/src/test/ui/consts/miri_unleashed/drop.stderr @@ -7,17 +7,17 @@ LL | let _v: Vec<i32> = Vec::new(); error[E0080]: could not evaluate static initializer --> $SRC_DIR/libcore/ptr/mod.rs:LL:COL | -LL | / unsafe fn real_drop_in_place<T: ?Sized>(to_drop: &mut T) { +LL | / pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) { LL | | // Code here does not matter - this is replaced by the LL | | // real drop glue by the compiler. -LL | | real_drop_in_place(to_drop) +LL | | drop_in_place(to_drop) LL | | } | |_^ calling non-const function `<std::vec::Vec<i32> as std::ops::Drop>::drop` | ::: $DIR/drop.rs:23:1 | LL | }; - | - inside call to `std::ptr::real_drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1 + | - inside call to `std::intrinsics::drop_in_place::<std::vec::Vec<i32>> - shim(Some(std::vec::Vec<i32>))` at $DIR/drop.rs:23:1 error: aborting due to previous error diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index 655c31763ef..0d7fb845a40 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:346:17 +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:356:17 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: internal compiler error: unexpected panic diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index 91063edf0f6..30a89605944 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -7,7 +7,6 @@ // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default -#![feature(slice_patterns)] #![allow(unused)] use std::{ diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 0f0ec0ba460..b4406204a5d 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -1,11 +1,10 @@ // run-pass -#![allow(unused_assignments)] -#![allow(unused_variables)] - // ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait, untagged_unions)] -#![feature(slice_patterns)] + +#![allow(unused_assignments)] +#![allow(unused_variables)] use std::cell::{Cell, RefCell}; use std::mem::ManuallyDrop; diff --git a/src/test/ui/error-codes/E0106.rs b/src/test/ui/error-codes/E0106.rs index d6537d12363..cc3438727a8 100644 --- a/src/test/ui/error-codes/E0106.rs +++ b/src/test/ui/error-codes/E0106.rs @@ -16,7 +16,7 @@ struct Buzz<'a, 'b>(&'a str, &'b str); struct Quux { baz: Baz, //~^ ERROR E0106 - //~| expected lifetime parameter + //~| expected named lifetime parameter buzz: Buzz, //~^ ERROR E0106 //~| expected 2 lifetime parameters diff --git a/src/test/ui/error-codes/E0106.stderr b/src/test/ui/error-codes/E0106.stderr index cea9581e701..e01e0a6f54b 100644 --- a/src/test/ui/error-codes/E0106.stderr +++ b/src/test/ui/error-codes/E0106.stderr @@ -2,25 +2,49 @@ error[E0106]: missing lifetime specifier --> $DIR/E0106.rs:2:8 | LL | x: &bool, - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct Foo<'lifetime> { +LL | x: &'lifetime bool, + | error[E0106]: missing lifetime specifier --> $DIR/E0106.rs:7:7 | LL | B(&bool), - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | enum Bar<'lifetime> { +LL | A(u8), +LL | B(&'lifetime bool), + | error[E0106]: missing lifetime specifier --> $DIR/E0106.rs:10:14 | LL | type MyStr = &str; - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type MyStr<'lifetime> = &'lifetime str; + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/E0106.rs:17:10 | LL | baz: Baz, - | ^^^ expected lifetime parameter + | ^^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct Quux<'lifetime> { +LL | baz: Baz<'lifetime>, + | error[E0106]: missing lifetime specifiers --> $DIR/E0106.rs:20:11 diff --git a/src/test/ui/error-codes/E0261.stderr b/src/test/ui/error-codes/E0261.stderr index 3bf5e9d8154..0eab2dc0ee0 100644 --- a/src/test/ui/error-codes/E0261.stderr +++ b/src/test/ui/error-codes/E0261.stderr @@ -2,11 +2,15 @@ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/E0261.rs:1:12 | LL | fn foo(x: &'a str) { } - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/E0261.rs:5:9 | +LL | struct Foo { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | x: &'a str, | ^^ undeclared lifetime diff --git a/src/test/ui/error-codes/E0528.rs b/src/test/ui/error-codes/E0528.rs index 17d03b14fc6..0a337c9611c 100644 --- a/src/test/ui/error-codes/E0528.rs +++ b/src/test/ui/error-codes/E0528.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn main() { let r = &[1, 2]; match r { diff --git a/src/test/ui/error-codes/E0528.stderr b/src/test/ui/error-codes/E0528.stderr index 0f566091145..21615f954c3 100644 --- a/src/test/ui/error-codes/E0528.stderr +++ b/src/test/ui/error-codes/E0528.stderr @@ -1,5 +1,5 @@ error[E0528]: pattern requires at least 3 elements but array has 2 - --> $DIR/E0528.rs:6:10 + --> $DIR/E0528.rs:4:10 | LL | &[a, b, c, rest @ ..] => { | ^^^^^^^^^^^^^^^^^^^^ pattern cannot match array of 2 elements diff --git a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr index 5c64bf6539c..bbf3ea8a89f 100644 --- a/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr +++ b/src/test/ui/feature-gates/feature-gate-in_band_lifetimes.stderr @@ -2,103 +2,207 @@ error[E0261]: use of undeclared lifetime name `'x` --> $DIR/feature-gate-in_band_lifetimes.rs:3:12 | LL | fn foo(x: &'x u8) -> &'x u8 { x } - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'x` here: `<'x>` error[E0261]: use of undeclared lifetime name `'x` --> $DIR/feature-gate-in_band_lifetimes.rs:3:23 | LL | fn foo(x: &'x u8) -> &'x u8 { x } - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'x` here: `<'x>` error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:15:12 | LL | impl<'a> X<'b> { - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'b` here: `'b,` error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:17:27 | LL | fn inner_2(&self) -> &'b u8 { | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> X<'b> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn inner_2<'b>(&self) -> &'b u8 { + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:23:8 | LL | impl X<'b> { - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'b` here: `<'b>` error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:25:27 | LL | fn inner_3(&self) -> &'b u8 { | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b> X<'b> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn inner_3<'b>(&self) -> &'b u8 { + | ^^^^ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/feature-gate-in_band_lifetimes.rs:33:9 | LL | impl Y<&'a u8> { - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/feature-gate-in_band_lifetimes.rs:35:25 | LL | fn inner(&self) -> &'a u8 { | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | impl<'a> Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'a` here + | +LL | fn inner<'a>(&self) -> &'a u8 { + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:43:27 | LL | fn any_lifetime() -> &'b u8; | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | trait MyTrait<'b, 'a> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn any_lifetime<'b>() -> &'b u8; + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:45:27 | LL | fn borrowed_lifetime(&'b self) -> &'b u8; | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | trait MyTrait<'b, 'a> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8; + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:45:40 | LL | fn borrowed_lifetime(&'b self) -> &'b u8; | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | trait MyTrait<'b, 'a> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8; + | ^^^^ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/feature-gate-in_band_lifetimes.rs:50:14 | LL | impl MyTrait<'a> for Y<&'a u8> { - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/feature-gate-in_band_lifetimes.rs:50:25 | LL | impl MyTrait<'a> for Y<&'a u8> { - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/feature-gate-in_band_lifetimes.rs:53:31 | LL | fn my_lifetime(&self) -> &'a u8 { self.0 } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'a` here + | +LL | impl<'a> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'a` here + | +LL | fn my_lifetime<'a>(&self) -> &'a u8 { self.0 } + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:55:27 | LL | fn any_lifetime() -> &'b u8 { &0 } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn any_lifetime<'b>() -> &'b u8 { &0 } + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:57:27 | LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 } + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/feature-gate-in_band_lifetimes.rs:57:40 | LL | fn borrowed_lifetime(&'b self) -> &'b u8 { &*self.0 } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b> MyTrait<'a> for Y<&'a u8> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | fn borrowed_lifetime<'b>(&'b self) -> &'b u8 { &*self.0 } + | ^^^^ error: aborting due to 17 previous errors diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs b/src/test/ui/feature-gates/feature-gate-slice-patterns.rs deleted file mode 100644 index f2a1b135b69..00000000000 --- a/src/test/ui/feature-gates/feature-gate-slice-patterns.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Test that slice pattern syntax with `..` is gated by `slice_patterns` feature gate - -fn main() { - let x = [1, 2, 3, 4, 5]; - match x { - [1, 2, ..] => {} //~ ERROR subslice patterns are unstable - [1, .., 5] => {} //~ ERROR subslice patterns are unstable - [.., 4, 5] => {} //~ ERROR subslice patterns are unstable - } - - let x = [ 1, 2, 3, 4, 5 ]; - match x { - [ xs @ .., 4, 5 ] => {} //~ ERROR subslice patterns are unstable - [ 1, xs @ .., 5 ] => {} //~ ERROR subslice patterns are unstable - [ 1, 2, xs @ .. ] => {} //~ ERROR subslice patterns are unstable - } -} diff --git a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr b/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr deleted file mode 100644 index d4946a42b8f..00000000000 --- a/src/test/ui/feature-gates/feature-gate-slice-patterns.stderr +++ /dev/null @@ -1,57 +0,0 @@ -error[E0658]: subslice patterns are unstable - --> $DIR/feature-gate-slice-patterns.rs:6:16 - | -LL | [1, 2, ..] => {} - | ^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error[E0658]: subslice patterns are unstable - --> $DIR/feature-gate-slice-patterns.rs:7:13 - | -LL | [1, .., 5] => {} - | ^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error[E0658]: subslice patterns are unstable - --> $DIR/feature-gate-slice-patterns.rs:8:10 - | -LL | [.., 4, 5] => {} - | ^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error[E0658]: subslice patterns are unstable - --> $DIR/feature-gate-slice-patterns.rs:13:11 - | -LL | [ xs @ .., 4, 5 ] => {} - | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error[E0658]: subslice patterns are unstable - --> $DIR/feature-gate-slice-patterns.rs:14:14 - | -LL | [ 1, xs @ .., 5 ] => {} - | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error[E0658]: subslice patterns are unstable - --> $DIR/feature-gate-slice-patterns.rs:15:17 - | -LL | [ 1, 2, xs @ .. ] => {} - | ^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr index 81137e81dc4..fc2ce1cb866 100644 --- a/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr +++ b/src/test/ui/generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr @@ -3,12 +3,30 @@ error[E0261]: use of undeclared lifetime name `'b` | LL | + Deref<Target = Self::Item<'b>>; | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | trait Iterable<'b> { + | ^^^^ +help: consider introducing lifetime `'b` here + | +LL | type Iter<'b, 'a>: Iterator<Item = Self::Item<'a>> + | ^^^ error[E0261]: use of undeclared lifetime name `'undeclared` --> $DIR/generic_associated_type_undeclared_lifetimes.rs:12:41 | LL | fn iter<'a>(&'a self) -> Self::Iter<'undeclared>; | ^^^^^^^^^^^ undeclared lifetime + | +help: consider introducing lifetime `'undeclared` here + | +LL | trait Iterable<'undeclared> { + | ^^^^^^^^^^^^^ +help: consider introducing lifetime `'undeclared` here + | +LL | fn iter<'undeclared, 'a>(&'a self) -> Self::Iter<'undeclared>; + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/ignore-all-the-things.rs b/src/test/ui/ignore-all-the-things.rs index 8c046a289fa..5980e1a857f 100644 --- a/src/test/ui/ignore-all-the-things.rs +++ b/src/test/ui/ignore-all-the-things.rs @@ -3,9 +3,6 @@ #![allow(non_shorthand_field_patterns)] #![allow(dead_code)] #![allow(unused_variables)] -// pretty-expanded FIXME #23616 - -#![feature(slice_patterns)] struct Foo(isize, isize, isize, isize); struct Bar{a: isize, b: isize, c: isize, d: isize} diff --git a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr index 492ca872187..14c53f90665 100644 --- a/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr +++ b/src/test/ui/impl-header-lifetime-elision/assoc-type.stderr @@ -2,13 +2,23 @@ error[E0106]: missing lifetime specifier --> $DIR/assoc-type.rs:11:19 | LL | type Output = &i32; - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type Output<'lifetime> = &'lifetime i32; + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/assoc-type.rs:16:20 | LL | type Output = &'_ i32; - | ^^ expected lifetime parameter + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | type Output<'lifetime> = &'lifetime i32; + | ^^^^^^^^^^^ ^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr index 9579abb76b3..5f101a24c1d 100644 --- a/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr +++ b/src/test/ui/in-band-lifetimes/issue-61124-anon-lifetime-in-struct-declaration.stderr @@ -2,7 +2,12 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-61124-anon-lifetime-in-struct-declaration.rs:8:19 | LL | struct Heartbreak(Betrayal); - | ^^^^^^^^ expected lifetime parameter + | ^^^^^^^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct Heartbreak<'lifetime>(Betrayal<'lifetime>); + | ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr index a270dd03926..fe656f7af7e 100644 --- a/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr +++ b/src/test/ui/in-band-lifetimes/no_in_band_in_struct.stderr @@ -1,12 +1,16 @@ error[E0261]: use of undeclared lifetime name `'test` --> $DIR/no_in_band_in_struct.rs:5:9 | +LL | struct Foo { + | - help: consider introducing lifetime `'test` here: `<'test>` LL | x: &'test u32, | ^^^^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'test` --> $DIR/no_in_band_in_struct.rs:9:10 | +LL | enum Bar { + | - help: consider introducing lifetime `'test` here: `<'test>` LL | Baz(&'test u32), | ^^^^^ undeclared lifetime diff --git a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr index c307066be6b..bfb20ade035 100644 --- a/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr +++ b/src/test/ui/in-band-lifetimes/no_introducing_in_band_in_locals.stderr @@ -1,6 +1,8 @@ error[E0261]: use of undeclared lifetime name `'test` --> $DIR/no_introducing_in_band_in_locals.rs:5:13 | +LL | fn foo(x: &u32) { + | - help: consider introducing lifetime `'test` here: `<'test>` LL | let y: &'test u32 = x; | ^^^^^ undeclared lifetime diff --git a/src/test/ui/issues/issue-12369.rs b/src/test/ui/issues/issue-12369.rs index 08661318074..0481c1fd9e1 100644 --- a/src/test/ui/issues/issue-12369.rs +++ b/src/test/ui/issues/issue-12369.rs @@ -1,4 +1,3 @@ -#![feature(slice_patterns)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/ui/issues/issue-12369.stderr b/src/test/ui/issues/issue-12369.stderr index f27425e28c6..754b94bab75 100644 --- a/src/test/ui/issues/issue-12369.stderr +++ b/src/test/ui/issues/issue-12369.stderr @@ -1,11 +1,11 @@ error: unreachable pattern - --> $DIR/issue-12369.rs:10:9 + --> $DIR/issue-12369.rs:9:9 | LL | &[10,a, ref rest @ ..] => 10 | ^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-12369.rs:2:9 + --> $DIR/issue-12369.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/issues/issue-12567.rs b/src/test/ui/issues/issue-12567.rs index 643d9a2fc69..1b2a37de475 100644 --- a/src/test/ui/issues/issue-12567.rs +++ b/src/test/ui/issues/issue-12567.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) { match (l1, l2) { //~^ ERROR: cannot move out of type `[T]`, a non-copy slice diff --git a/src/test/ui/issues/issue-12567.stderr b/src/test/ui/issues/issue-12567.stderr index 9d9a88f4f9b..2a88d8f0524 100644 --- a/src/test/ui/issues/issue-12567.stderr +++ b/src/test/ui/issues/issue-12567.stderr @@ -1,5 +1,5 @@ error[E0508]: cannot move out of type `[T]`, a non-copy slice - --> $DIR/issue-12567.rs:4:11 + --> $DIR/issue-12567.rs:2:11 | LL | match (l1, l2) { | ^^^^^^^^ cannot move out of here @@ -13,7 +13,7 @@ LL | (&[hd1, ..], &[hd2, ..]) = note: move occurs because these variables have types that don't implement the `Copy` trait error[E0508]: cannot move out of type `[T]`, a non-copy slice - --> $DIR/issue-12567.rs:4:11 + --> $DIR/issue-12567.rs:2:11 | LL | match (l1, l2) { | ^^^^^^^^ cannot move out of here diff --git a/src/test/ui/issues/issue-15080.rs b/src/test/ui/issues/issue-15080.rs index b11b1cda38a..4dd6981d448 100644 --- a/src/test/ui/issues/issue-15080.rs +++ b/src/test/ui/issues/issue-15080.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn main() { let mut x: &[_] = &[1, 2, 3, 4]; diff --git a/src/test/ui/issues/issue-15104.rs b/src/test/ui/issues/issue-15104.rs index ee977541137..47b207ea9cb 100644 --- a/src/test/ui/issues/issue-15104.rs +++ b/src/test/ui/issues/issue-15104.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn main() { assert_eq!(count_members(&[1, 2, 3, 4]), 4); diff --git a/src/test/ui/issues/issue-17877.rs b/src/test/ui/issues/issue-17877.rs index fefa3f2f873..126e01de5ee 100644 --- a/src/test/ui/issues/issue-17877.rs +++ b/src/test/ui/issues/issue-17877.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn main() { assert_eq!(match [0u8; 1024] { diff --git a/src/test/ui/issues/issue-19707.stderr b/src/test/ui/issues/issue-19707.stderr index c85ce0eb3a7..8a627bc0bd4 100644 --- a/src/test/ui/issues/issue-19707.stderr +++ b/src/test/ui/issues/issue-19707.stderr @@ -2,17 +2,25 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:3:28 | LL | type Foo = fn(&u8, &u8) -> &u8; - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider introducing a named lifetime parameter + | +LL | type Foo<'lifetime> = fn(&u8, &u8) -> &'lifetime u8; + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/issue-19707.rs:5:27 | LL | fn bar<F: Fn(&u8, &u8) -> &u8>(f: &F) {} - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider introducing a named lifetime parameter + | +LL | fn bar<'lifetime, F: Fn(&u8, &u8) -> &'lifetime u8>(f: &F) {} + | ^^^^^^^^^^ ^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-23311.rs b/src/test/ui/issues/issue-23311.rs index f275c6338b1..62c96840b3b 100644 --- a/src/test/ui/issues/issue-23311.rs +++ b/src/test/ui/issues/issue-23311.rs @@ -1,7 +1,6 @@ // run-pass -// Test that we do not ICE when pattern matching an array against a slice. -#![feature(slice_patterns)] +// Test that we do not ICE when pattern matching an array against a slice. fn main() { match "foo".as_bytes() { diff --git a/src/test/ui/issues/issue-26619.rs b/src/test/ui/issues/issue-26619.rs index 00e09f3f077..b9d34b0555a 100644 --- a/src/test/ui/issues/issue-26619.rs +++ b/src/test/ui/issues/issue-26619.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - pub struct History<'a> { pub _s: &'a str } impl<'a> History<'a> { diff --git a/src/test/ui/issues/issue-26619.stderr b/src/test/ui/issues/issue-26619.stderr index d1157cda92b..1282fd7d3c2 100644 --- a/src/test/ui/issues/issue-26619.stderr +++ b/src/test/ui/issues/issue-26619.stderr @@ -1,5 +1,5 @@ error[E0515]: cannot return value referencing function parameter - --> $DIR/issue-26619.rs:7:76 + --> $DIR/issue-26619.rs:5:76 | LL | for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) { | -------- ^^^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function diff --git a/src/test/ui/issues/issue-26638.stderr b/src/test/ui/issues/issue-26638.stderr index 6d7c1b0c43f..85d5d9cc42e 100644 --- a/src/test/ui/issues/issue-26638.stderr +++ b/src/test/ui/issues/issue-26638.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:1:62 | LL | fn parse_type(iter: Box<dyn Iterator<Item=&str>+'static>) -> &str { iter.next() } - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say which one of `iter`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn parse_type<'lifetime>(iter: Box<dyn Iterator<Item=&str>+'static>) -> &'lifetime str { iter.next() } + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/issue-26638.rs:4:40 diff --git a/src/test/ui/issues/issue-30255.stderr b/src/test/ui/issues/issue-30255.stderr index c53129b7f29..c9402277640 100644 --- a/src/test/ui/issues/issue-30255.stderr +++ b/src/test/ui/issues/issue-30255.stderr @@ -2,25 +2,37 @@ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:9:24 | LL | fn f(a: &S, b: i32) -> &i32 { - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say which one of `a`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn f<'lifetime>(a: &S, b: i32) -> &'lifetime i32 { + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:14:34 | LL | fn g(a: &S, b: bool, c: &i32) -> &i32 { - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from one of `a`'s 2 lifetimes or `c` +help: consider introducing a named lifetime parameter + | +LL | fn g<'lifetime>(a: &S, b: bool, c: &i32) -> &'lifetime i32 { + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/issue-30255.rs:19:44 | LL | fn h(a: &bool, b: bool, c: &S, d: &i32) -> &i32 { - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `a`, one of `c`'s 2 lifetimes, or `d` +help: consider introducing a named lifetime parameter + | +LL | fn h<'lifetime>(a: &bool, b: bool, c: &S, d: &i32) -> &'lifetime i32 { + | ^^^^^^^^^^^ ^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-37598.rs b/src/test/ui/issues/issue-37598.rs index 31b3aba6bc2..458e999c3fa 100644 --- a/src/test/ui/issues/issue-37598.rs +++ b/src/test/ui/issues/issue-37598.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(slice_patterns)] fn check(list: &[u8]) { match list { diff --git a/src/test/ui/issues/issue-7784.rs b/src/test/ui/issues/issue-7784.rs index 5b70bd6e5ff..b7323f09daf 100644 --- a/src/test/ui/issues/issue-7784.rs +++ b/src/test/ui/issues/issue-7784.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] use std::ops::Add; diff --git a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr index 3f7c3934a0b..1d5eeac23f9 100644 --- a/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr +++ b/src/test/ui/lifetimes/lifetime-elision-return-type-requires-explicit-lifetime.stderr @@ -10,17 +10,25 @@ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:7:33 | LL | fn g(_x: &isize, _y: &isize) -> &isize { - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_x` or `_y` +help: consider introducing a named lifetime parameter + | +LL | fn g<'lifetime>(_x: &isize, _y: &isize) -> &'lifetime isize { + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:17:19 | LL | fn h(_x: &Foo) -> &isize { - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say which one of `_x`'s 2 lifetimes it is borrowed from +help: consider introducing a named lifetime parameter + | +LL | fn h<'lifetime>(_x: &Foo) -> &'lifetime isize { + | ^^^^^^^^^^^ ^^^^^^^^^^ error[E0106]: missing lifetime specifier --> $DIR/lifetime-elision-return-type-requires-explicit-lifetime.rs:21:20 diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr index a4e0d71a3fa..2990ab86824 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1b-return-no-names-if-else.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/ex1b-return-no-names-if-else.rs:1:29 | LL | fn foo(x: &i32, y: &i32) -> &i32 { - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` +help: consider introducing a named lifetime parameter + | +LL | fn foo<'lifetime>(x: &i32, y: &i32) -> &'lifetime i32 { + | ^^^^^^^^^^^ ^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs new file mode 100644 index 00000000000..c2b81959f2c --- /dev/null +++ b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.rs @@ -0,0 +1,29 @@ +#![deny(non_snake_case)] +#![allow(unused_variables)] +#![allow(dead_code)] + +enum Foo { + Bad { + lowerCamelCaseName: bool, + //~^ ERROR structure field `lowerCamelCaseName` should have a snake case name + }, + Good { + snake_case_name: bool, + }, +} + +fn main() { + let b = Foo::Bad { lowerCamelCaseName: true }; + + match b { + Foo::Bad { lowerCamelCaseName } => {} + Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + //~^ ERROR variable `lowerCamelCaseBinding` should have a snake case name + } + + if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `anotherLowerCamelCaseBinding` should have a snake case name + + if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + //~^ ERROR variable `yetAnotherLowerCamelCaseBinding` should have a snake case name +} diff --git a/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr new file mode 100644 index 00000000000..68956f21e8f --- /dev/null +++ b/src/test/ui/lint/issue-66362-no-snake-case-warning-for-field-puns.stderr @@ -0,0 +1,32 @@ +error: structure field `lowerCamelCaseName` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:7:9 + | +LL | lowerCamelCaseName: bool, + | ^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_name` + | +note: lint level defined here + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:1:9 + | +LL | #![deny(non_snake_case)] + | ^^^^^^^^^^^^^^ + +error: variable `lowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:20:38 + | +LL | Foo::Good { snake_case_name: lowerCamelCaseBinding } => { } + | ^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `lower_camel_case_binding` + +error: variable `anotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:24:41 + | +LL | if let Foo::Good { snake_case_name: anotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `another_lower_camel_case_binding` + +error: variable `yetAnotherLowerCamelCaseBinding` should have a snake case name + --> $DIR/issue-66362-no-snake-case-warning-for-field-puns.rs:27:43 + | +LL | if let Foo::Bad { lowerCamelCaseName: yetAnotherLowerCamelCaseBinding } = b { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `yet_another_lower_camel_case_binding` + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs b/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs new file mode 100644 index 00000000000..0af706615e3 --- /dev/null +++ b/src/test/ui/marker_trait_attr/issue-61651-type-mismatch.rs @@ -0,0 +1,17 @@ +// check-pass +// Regression test for issue #61651 +// Verifies that we don't try to constrain inference +// variables due to the presence of multiple applicable +// marker trait impls + +#![feature(marker_trait_attr)] + +#[marker] // Remove this line and it works?!? +trait Foo<T> {} +impl Foo<u16> for u8 {} +impl Foo<[u8; 1]> for u8 {} +fn foo<T: Foo<U>, U>(_: T) -> U { unimplemented!() } + +fn main() { + let _: u16 = foo(0_u8); +} diff --git a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr index 67fd8d7a13e..c9f235c4f7d 100644 --- a/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr +++ b/src/test/ui/methods/method-call-lifetime-args-unresolved.stderr @@ -1,6 +1,8 @@ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/method-call-lifetime-args-unresolved.rs:2:15 | +LL | fn main() { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | 0.clone::<'a>(); | ^^ undeclared lifetime diff --git a/src/test/ui/moves/move-out-of-array-ref.rs b/src/test/ui/moves/move-out-of-array-ref.rs index 4ca60ddfec2..343f00ff291 100644 --- a/src/test/ui/moves/move-out-of-array-ref.rs +++ b/src/test/ui/moves/move-out-of-array-ref.rs @@ -1,7 +1,5 @@ // Ensure that we cannot move out of a reference to a fixed-size array -#![feature(slice_patterns)] - struct D { _x: u8 } impl Drop for D { fn drop(&mut self) { } } diff --git a/src/test/ui/moves/move-out-of-array-ref.stderr b/src/test/ui/moves/move-out-of-array-ref.stderr index ae3d2f5f282..fd682e56ae1 100644 --- a/src/test/ui/moves/move-out-of-array-ref.stderr +++ b/src/test/ui/moves/move-out-of-array-ref.stderr @@ -1,5 +1,5 @@ error[E0508]: cannot move out of type `[D; 4]`, a non-copy array - --> $DIR/move-out-of-array-ref.rs:10:24 + --> $DIR/move-out-of-array-ref.rs:8:24 | LL | let [_, e, _, _] = *a; | - ^^ @@ -10,7 +10,7 @@ LL | let [_, e, _, _] = *a; | move occurs because `e` has type `D`, which does not implement the `Copy` trait error[E0508]: cannot move out of type `[D; 4]`, a non-copy array - --> $DIR/move-out-of-array-ref.rs:15:27 + --> $DIR/move-out-of-array-ref.rs:13:27 | LL | let [_, s @ .. , _] = *a; | ------ ^^ @@ -21,7 +21,7 @@ LL | let [_, s @ .. , _] = *a; | move occurs because `s` has type `[D; 2]`, which does not implement the `Copy` trait error[E0508]: cannot move out of type `[D; 4]`, a non-copy array - --> $DIR/move-out-of-array-ref.rs:20:24 + --> $DIR/move-out-of-array-ref.rs:18:24 | LL | let [_, e, _, _] = *a; | - ^^ @@ -32,7 +32,7 @@ LL | let [_, e, _, _] = *a; | move occurs because `e` has type `D`, which does not implement the `Copy` trait error[E0508]: cannot move out of type `[D; 4]`, a non-copy array - --> $DIR/move-out-of-array-ref.rs:25:27 + --> $DIR/move-out-of-array-ref.rs:23:27 | LL | let [_, s @ .. , _] = *a; | ------ ^^ diff --git a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs index d7c191bb5a2..8b0be2e7a66 100644 --- a/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs +++ b/src/test/ui/or-patterns/exhaustiveness-non-exhaustive.rs @@ -1,5 +1,5 @@ #![feature(or_patterns)] -#![feature(slice_patterns)] + #![allow(incomplete_features)] #![deny(unreachable_patterns)] diff --git a/src/test/ui/or-patterns/exhaustiveness-pass.rs b/src/test/ui/or-patterns/exhaustiveness-pass.rs index ce0fe6fc2a3..f0dc3447f31 100644 --- a/src/test/ui/or-patterns/exhaustiveness-pass.rs +++ b/src/test/ui/or-patterns/exhaustiveness-pass.rs @@ -1,5 +1,5 @@ #![feature(or_patterns)] -#![feature(slice_patterns)] + #![allow(incomplete_features)] #![deny(unreachable_patterns)] diff --git a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs index 860c7a1bde5..81bc1176f57 100644 --- a/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs +++ b/src/test/ui/or-patterns/exhaustiveness-unreachable-pattern.rs @@ -1,5 +1,5 @@ #![feature(or_patterns)] -#![feature(slice_patterns)] + #![allow(incomplete_features)] #![deny(unreachable_patterns)] diff --git a/src/test/ui/parser/match-vec-invalid.stderr b/src/test/ui/parser/match-vec-invalid.stderr deleted file mode 100644 index 58343e86d7b..00000000000 --- a/src/test/ui/parser/match-vec-invalid.stderr +++ /dev/null @@ -1,42 +0,0 @@ -error[E0416]: identifier `tail` is bound more than once in the same pattern - --> $DIR/match-vec-invalid.rs:4:24 - | -LL | [1, tail @ .., tail @ ..] => {}, - | ^^^^ used in a pattern more than once - -error[E0658]: subslice patterns are unstable - --> $DIR/match-vec-invalid.rs:4:13 - | -LL | [1, tail @ .., tail @ ..] => {}, - | ^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error[E0658]: subslice patterns are unstable - --> $DIR/match-vec-invalid.rs:4:24 - | -LL | [1, tail @ .., tail @ ..] => {}, - | ^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - -error: `..` can only be used once per slice pattern - --> $DIR/match-vec-invalid.rs:4:31 - | -LL | [1, tail @ .., tail @ ..] => {}, - | -- ^^ can only be used once per slice pattern - | | - | previously used here - -error[E0308]: mismatched types - --> $DIR/match-vec-invalid.rs:13:30 - | -LL | const RECOVERY_WITNESS: () = 0; - | ^ expected `()`, found integer - -error: aborting due to 5 previous errors - -Some errors have detailed explanations: E0308, E0416, E0658. -For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/pat-lt-bracket-6.rs b/src/test/ui/parser/pat-lt-bracket-6.rs index f27caa5d78c..7becffa9fe2 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.rs +++ b/src/test/ui/parser/pat-lt-bracket-6.rs @@ -4,7 +4,6 @@ fn main() { let Test(&desc[..]) = x; //~^ ERROR: expected one of `)`, `,`, `@`, or `|`, found `[` - //~^^ ERROR subslice patterns are unstable } const RECOVERY_WITNESS: () = 0; //~ ERROR mismatched types diff --git a/src/test/ui/parser/pat-lt-bracket-6.stderr b/src/test/ui/parser/pat-lt-bracket-6.stderr index fe9603cb57f..035d0dbfe06 100644 --- a/src/test/ui/parser/pat-lt-bracket-6.stderr +++ b/src/test/ui/parser/pat-lt-bracket-6.stderr @@ -7,22 +7,12 @@ LL | let Test(&desc[..]) = x; | expected one of `)`, `,`, `@`, or `|` | help: missing `,` -error[E0658]: subslice patterns are unstable - --> $DIR/pat-lt-bracket-6.rs:5:20 - | -LL | let Test(&desc[..]) = x; - | ^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/62254 - = help: add `#![feature(slice_patterns)]` to the crate attributes to enable - error[E0308]: mismatched types - --> $DIR/pat-lt-bracket-6.rs:10:30 + --> $DIR/pat-lt-bracket-6.rs:9:30 | LL | const RECOVERY_WITNESS: () = 0; | ^ expected `()`, found integer -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0308, E0658. -For more information about an error, try `rustc --explain E0308`. +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/trait-object-trait-parens.stderr b/src/test/ui/parser/trait-object-trait-parens.stderr index 03fb764ee03..4b9f49423cb 100644 --- a/src/test/ui/parser/trait-object-trait-parens.stderr +++ b/src/test/ui/parser/trait-object-trait-parens.stderr @@ -33,6 +33,9 @@ LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; error[E0261]: use of undeclared lifetime name `'a` --> $DIR/trait-object-trait-parens.rs:11:31 | +LL | fn main() { + | - help: consider introducing lifetime `'a` here: `<'a>` +... LL | let _: Box<(for<'a> Trait<'a>) + (Copy) + (?Sized)>; | ^^ undeclared lifetime diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs index 1d9f341c514..2cd375da9a5 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.rs @@ -1,7 +1,6 @@ // Test that moving on both sides of an `@` pattern is not allowed. #![feature(bindings_after_at)] -#![feature(slice_patterns)] fn main() { struct U; // Not copy! diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr index f3f8fd655ce..12ebcb72af1 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr @@ -1,53 +1,53 @@ error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:12:9 + --> $DIR/borrowck-move-and-move.rs:11:9 | LL | let a @ b = U; | ^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:16:9 + --> $DIR/borrowck-move-and-move.rs:15:9 | LL | let a @ (b, c) = (U, U); | ^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:20:9 + --> $DIR/borrowck-move-and-move.rs:19:9 | LL | let a @ (b, c) = (u(), u()); | ^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:25:9 + --> $DIR/borrowck-move-and-move.rs:24:9 | LL | a @ Ok(b) | a @ Err(b) => {} | ^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:25:21 + --> $DIR/borrowck-move-and-move.rs:24:21 | LL | a @ Ok(b) | a @ Err(b) => {} | ^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:37:9 + --> $DIR/borrowck-move-and-move.rs:36:9 | LL | xs @ [a, .., b] => {} | ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:43:9 + --> $DIR/borrowck-move-and-move.rs:42:9 | LL | xs @ [_, ys @ .., _] => {} | ^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-move-and-move.rs:32:12 + --> $DIR/borrowck-move-and-move.rs:31:12 | LL | fn fun(a @ b: U) {} | ^^^^^ binds an already bound by-move value by moving it error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:12:13 + --> $DIR/borrowck-move-and-move.rs:11:13 | LL | let a @ b = U; | ----^ - move occurs because value has type `main::U`, which does not implement the `Copy` trait @@ -56,7 +56,7 @@ LL | let a @ b = U; | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:16:17 + --> $DIR/borrowck-move-and-move.rs:15:17 | LL | let a @ (b, c) = (U, U); | --------^- ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait @@ -65,7 +65,7 @@ LL | let a @ (b, c) = (U, U); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:20:17 + --> $DIR/borrowck-move-and-move.rs:19:17 | LL | let a @ (b, c) = (u(), u()); | --------^- ---------- move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait @@ -74,7 +74,7 @@ LL | let a @ (b, c) = (u(), u()); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:25:16 + --> $DIR/borrowck-move-and-move.rs:24:16 | LL | match Ok(U) { | ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait @@ -85,7 +85,7 @@ LL | a @ Ok(b) | a @ Err(b) => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:25:29 + --> $DIR/borrowck-move-and-move.rs:24:29 | LL | match Ok(U) { | ----- move occurs because value has type `std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait @@ -96,7 +96,7 @@ LL | a @ Ok(b) | a @ Err(b) => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:37:22 + --> $DIR/borrowck-move-and-move.rs:36:22 | LL | match [u(), u(), u(), u()] { | -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait @@ -107,7 +107,7 @@ LL | xs @ [a, .., b] => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:43:18 + --> $DIR/borrowck-move-and-move.rs:42:18 | LL | match [u(), u(), u(), u()] { | -------------------- move occurs because value has type `[main::U; 4]`, which does not implement the `Copy` trait @@ -118,7 +118,7 @@ LL | xs @ [_, ys @ .., _] => {} | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-move-and-move.rs:32:16 + --> $DIR/borrowck-move-and-move.rs:31:16 | LL | fn fun(a @ b: U) {} | ----^ diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs index afac8d990b4..092bd1133dd 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box-pass.rs @@ -4,7 +4,6 @@ #![feature(bindings_after_at)] #![feature(box_patterns)] -#![feature(slice_patterns)] #[derive(Copy, Clone)] struct C; diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs index fce31409e16..3b2f598dc01 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.rs @@ -2,7 +2,6 @@ #![feature(bindings_after_at)] #![feature(box_patterns)] -#![feature(slice_patterns)] #[derive(Copy, Clone)] struct C; diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr index 5772fadd1e7..e96c15b0fa7 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr @@ -1,23 +1,23 @@ error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:17:9 + --> $DIR/borrowck-pat-at-and-box.rs:16:9 | LL | let a @ box &b = Box::new(&C); | ^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:21:9 + --> $DIR/borrowck-pat-at-and-box.rs:20:9 | LL | let a @ box b = Box::new(C); | ^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:33:25 + --> $DIR/borrowck-pat-at-and-box.rs:32:25 | LL | match Box::new(C) { a @ box b => {} } | ^^^^^^^^^ binds an already bound by-move value by moving it error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-at-and-box.rs:37:21 + --> $DIR/borrowck-pat-at-and-box.rs:36:21 | LL | let ref a @ box b = Box::new(NC); | ------------^ @@ -26,7 +26,7 @@ LL | let ref a @ box b = Box::new(NC); | by-ref pattern here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:39:9 + --> $DIR/borrowck-pat-at-and-box.rs:38:9 | LL | let ref a @ box ref mut b = Box::new(nc()); | -----^^^^^^^--------- @@ -35,7 +35,7 @@ LL | let ref a @ box ref mut b = Box::new(nc()); | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:41:9 + --> $DIR/borrowck-pat-at-and-box.rs:40:9 | LL | let ref a @ box ref mut b = Box::new(NC); | -----^^^^^^^--------- @@ -44,7 +44,7 @@ LL | let ref a @ box ref mut b = Box::new(NC); | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:43:9 + --> $DIR/borrowck-pat-at-and-box.rs:42:9 | LL | let ref a @ box ref mut b = Box::new(NC); | -----^^^^^^^--------- @@ -53,7 +53,7 @@ LL | let ref a @ box ref mut b = Box::new(NC); | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:46:9 + --> $DIR/borrowck-pat-at-and-box.rs:45:9 | LL | let ref a @ box ref mut b = Box::new(NC); | -----^^^^^^^--------- @@ -62,7 +62,7 @@ LL | let ref a @ box ref mut b = Box::new(NC); | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:52:9 + --> $DIR/borrowck-pat-at-and-box.rs:51:9 | LL | let ref mut a @ box ref b = Box::new(NC); | ---------^^^^^^^----- @@ -71,7 +71,7 @@ LL | let ref mut a @ box ref b = Box::new(NC); | mutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:66:9 + --> $DIR/borrowck-pat-at-and-box.rs:65:9 | LL | ref mut a @ box ref b => { | ---------^^^^^^^----- @@ -80,7 +80,7 @@ LL | ref mut a @ box ref b => { | mutable borrow occurs here error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-at-and-box.rs:75:38 + --> $DIR/borrowck-pat-at-and-box.rs:74:38 | LL | box [Ok(a), ref xs @ .., Err(b)] => {} | ----------- ^ by-move pattern here @@ -88,7 +88,7 @@ LL | box [Ok(a), ref xs @ .., Err(b)] => {} | by-ref pattern here error[E0009]: cannot bind by-move and by-ref in the same pattern - --> $DIR/borrowck-pat-at-and-box.rs:81:46 + --> $DIR/borrowck-pat-at-and-box.rs:80:46 | LL | [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} | ----- ----------- ^ --------- by-ref pattern here @@ -98,19 +98,19 @@ LL | [Ok(box ref a), ref xs @ .., Err(box b), Err(box ref mut c)] => {} | by-ref pattern here error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:25:11 + --> $DIR/borrowck-pat-at-and-box.rs:24:11 | LL | fn f1(a @ box &b: Box<&C>) {} | ^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-at-and-box.rs:29:11 + --> $DIR/borrowck-pat-at-and-box.rs:28:11 | LL | fn f2(a @ box b: Box<C>) {} | ^^^^^^^^^ binds an already bound by-move value by moving it error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:58:11 + --> $DIR/borrowck-pat-at-and-box.rs:57:11 | LL | fn f5(ref mut a @ box ref b: Box<NC>) { | ---------^^^^^^^----- @@ -119,7 +119,7 @@ LL | fn f5(ref mut a @ box ref b: Box<NC>) { | mutable borrow occurs here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:17:18 + --> $DIR/borrowck-pat-at-and-box.rs:16:18 | LL | let a @ box &b = Box::new(&C); | ---------^ ------------ move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait @@ -128,7 +128,7 @@ LL | let a @ box &b = Box::new(&C); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:21:17 + --> $DIR/borrowck-pat-at-and-box.rs:20:17 | LL | let a @ box b = Box::new(C); | --------^ ----------- move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait @@ -137,7 +137,7 @@ LL | let a @ box b = Box::new(C); | value moved here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:33:33 + --> $DIR/borrowck-pat-at-and-box.rs:32:33 | LL | match Box::new(C) { a @ box b => {} } | ----------- --------^ @@ -147,7 +147,7 @@ LL | match Box::new(C) { a @ box b => {} } | move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-at-and-box.rs:46:21 + --> $DIR/borrowck-pat-at-and-box.rs:45:21 | LL | let ref a @ box ref mut b = Box::new(NC); | ------------^^^^^^^^^ @@ -159,7 +159,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:52:25 + --> $DIR/borrowck-pat-at-and-box.rs:51:25 | LL | let ref mut a @ box ref b = Box::new(NC); | ----------------^^^^^ @@ -171,7 +171,7 @@ LL | *a = Box::new(NC); | -- mutable borrow later used here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:66:25 + --> $DIR/borrowck-pat-at-and-box.rs:65:25 | LL | ref mut a @ box ref b => { | ----------------^^^^^ @@ -183,7 +183,7 @@ LL | *a = Box::new(NC); | -- mutable borrow later used here error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:25:20 + --> $DIR/borrowck-pat-at-and-box.rs:24:20 | LL | fn f1(a @ box &b: Box<&C>) {} | ---------^ @@ -193,7 +193,7 @@ LL | fn f1(a @ box &b: Box<&C>) {} | move occurs because value has type `std::boxed::Box<&C>`, which does not implement the `Copy` trait error[E0382]: use of moved value - --> $DIR/borrowck-pat-at-and-box.rs:29:19 + --> $DIR/borrowck-pat-at-and-box.rs:28:19 | LL | fn f2(a @ box b: Box<C>) {} | --------^ @@ -203,7 +203,7 @@ LL | fn f2(a @ box b: Box<C>) {} | move occurs because value has type `std::boxed::Box<C>`, which does not implement the `Copy` trait error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-at-and-box.rs:58:27 + --> $DIR/borrowck-pat-at-and-box.rs:57:27 | LL | fn f5(ref mut a @ box ref b: Box<NC>) { | ----------------^^^^^ diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs index be19e5f2a85..c4ce50c8b9a 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-copy-bindings-in-at.rs @@ -2,7 +2,6 @@ // Test `Copy` bindings in the rhs of `@` patterns. -#![feature(slice_patterns)] #![feature(bindings_after_at)] #[derive(Copy, Clone)] diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs index edf9fb31458..fb243016a11 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-both-sides.rs @@ -4,7 +4,6 @@ // of an `@` pattern according to NLL borrowck. #![feature(bindings_after_at)] -#![feature(slice_patterns)] fn main() { struct U; // Not copy! diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs index 559925c282f..e8510dfa649 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs @@ -1,5 +1,4 @@ #![feature(bindings_after_at)] -#![feature(slice_patterns)] enum Option<T> { None, diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr index b5c26a1fa03..0d7b703f181 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr @@ -1,5 +1,5 @@ error: cannot borrow `z` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:9 | LL | ref mut z @ &mut Some(ref a) => { | ---------^^^^^^^^^^^^^-----^ @@ -8,7 +8,7 @@ LL | ref mut z @ &mut Some(ref a) => { | mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:9 | LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub | ---------^^^^-----------------^ @@ -18,7 +18,7 @@ LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub | first mutable borrow occurs here error: cannot borrow `b` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:32:22 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:31:22 | LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub | -----^^^--------- @@ -27,7 +27,7 @@ LL | let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:36:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:35:9 | LL | let ref a @ ref mut b = U; | -----^^^--------- @@ -36,7 +36,7 @@ LL | let ref a @ ref mut b = U; | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:38:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9 | LL | let ref mut a @ ref b = U; | ---------^^^----- @@ -45,7 +45,7 @@ LL | let ref mut a @ ref b = U; | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:40:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ @@ -55,7 +55,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:42:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ---------^^^^-----^^-----^ @@ -65,7 +65,7 @@ LL | let ref mut a @ (ref b, ref c) = (U, U); | mutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:9 | LL | let ref mut a @ ref b = u(); | ---------^^^----- @@ -74,7 +74,7 @@ LL | let ref mut a @ ref b = u(); | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:9 | LL | let ref a @ ref mut b = u(); | -----^^^--------- @@ -83,7 +83,7 @@ LL | let ref a @ ref mut b = u(); | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:56:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:55:9 | LL | let ref mut a @ ref b = U; | ---------^^^----- @@ -92,7 +92,7 @@ LL | let ref mut a @ ref b = U; | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:60:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:59:9 | LL | let ref a @ ref mut b = U; | -----^^^--------- @@ -101,7 +101,7 @@ LL | let ref a @ ref mut b = U; | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { | ---------^^^^^^-----^ @@ -110,7 +110,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { | mutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:66:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:65:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { | ---------^^^^^^^-----^ @@ -119,7 +119,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => { | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | -----^^^^^^---------^ @@ -128,7 +128,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | -----^^^^^^^---------^ @@ -137,7 +137,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} | -----^^^^^^---------^ @@ -146,7 +146,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} | -----^^^^^^^---------^ @@ -155,7 +155,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ---------^^^^^^-----^ @@ -164,7 +164,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | mutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ---------^^^^^^^-----^ @@ -173,7 +173,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:9 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | -----^^^^^^---------^ @@ -182,7 +182,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:33 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | -----^^^^^^^---------^ @@ -191,7 +191,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:9 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ---------^^^^^^-----^ @@ -200,7 +200,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | mutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:33 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:33 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ---------^^^^^^^-----^ @@ -209,7 +209,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:116:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:115:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ @@ -219,7 +219,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ @@ -229,7 +229,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | immutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | -----^^^^---------^^---------^ @@ -239,7 +239,7 @@ LL | let ref a @ (ref mut b, ref mut c) = (U, U); | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:132:9 | LL | let ref mut a @ (ref b, ref c) = (U, U); | ---------^^^^-----^^-----^ @@ -249,7 +249,7 @@ LL | let ref mut a @ (ref b, ref c) = (U, U); | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:25:11 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11 | LL | fn f1(ref a @ ref mut b: U) {} | -----^^^--------- @@ -258,7 +258,7 @@ LL | fn f1(ref a @ ref mut b: U) {} | immutable borrow occurs here error: cannot borrow `a` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:27:11 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11 | LL | fn f2(ref mut a @ ref b: U) {} | ---------^^^----- @@ -267,7 +267,7 @@ LL | fn f2(ref mut a @ ref b: U) {} | mutable borrow occurs here error: cannot borrow `a` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:29:11 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:11 | LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} | -----^^^^^^^^^^^----------------^^^^^^^^ @@ -276,7 +276,7 @@ LL | fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {} | immutable borrow occurs here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:11:31 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:10:31 | LL | ref mut z @ &mut Some(ref a) => { | ----------------------^^^^^- @@ -288,7 +288,7 @@ LL | **z = None; | ---------- mutable borrow later used here error[E0502]: cannot borrow `_` as immutable because it is also borrowed as mutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:45:21 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:44:21 | LL | let ref mut a @ ref b = u(); | ------------^^^^^ @@ -300,7 +300,7 @@ LL | *a = u(); | -------- mutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:50:17 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:49:17 | LL | let ref a @ ref mut b = u(); | --------^^^^^^^^^ @@ -312,7 +312,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:20 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:20 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | -----------^^^^^^^^^- @@ -324,7 +324,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:75:45 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:74:45 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => { | ------------^^^^^^^^^- @@ -336,7 +336,7 @@ LL | drop(a); | - immutable borrow later used here error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:86:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:85:61 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {} | ^^^^^^ cannot assign @@ -344,7 +344,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } = note: variables bound in patterns are immutable until the end of the pattern guard error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:93:61 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:92:61 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {} | ^^^^^^^^^^^ cannot assign @@ -352,7 +352,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa = note: variables bound in patterns are immutable until the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait @@ -360,7 +360,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `b` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:100:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:99:66 | LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {} | ^ move occurs because `b` has type `&mut main::U`, which does not implement the `Copy` trait @@ -368,7 +368,7 @@ LL | ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait @@ -376,7 +376,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0507]: cannot move out of `a` in pattern guard - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:108:66 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:107:66 | LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {} | ^ move occurs because `a` has type `&mut std::result::Result<main::U, main::U>`, which does not implement the `Copy` trait @@ -384,7 +384,7 @@ LL | ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false = note: variables bound in patterns cannot be moved from until after the end of the pattern guard error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:18 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ---------^^^^^^^^^------------ @@ -396,7 +396,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:29 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:120:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | --------------------^^^^^^^^^- @@ -408,7 +408,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:18 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:18 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | ---------^^^^^^^^^------------ @@ -420,7 +420,7 @@ LL | drop(a); | - immutable borrow later used here error[E0502]: cannot borrow `_` as mutable because it is also borrowed as immutable - --> $DIR/borrowck-pat-ref-mut-and-ref.rs:128:29 + --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:29 | LL | let ref a @ (ref mut b, ref mut c) = (U, U); | --------------------^^^^^^^^^- diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs index 6b8b7545e68..f425b35630d 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs @@ -1,7 +1,6 @@ // Test that `ref mut x @ ref mut y` and varieties of that are not allowed. #![feature(bindings_after_at)] -#![feature(slice_patterns)] fn main() { struct U; diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index 1b5e6c74117..d07ad140cc2 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -1,5 +1,5 @@ error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:25:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:24:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- @@ -8,7 +8,7 @@ LL | let ref mut a @ ref mut b = U; | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:28:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- @@ -17,7 +17,7 @@ LL | let ref mut a @ ref mut b = U; | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:32:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:31:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- @@ -26,7 +26,7 @@ LL | let ref mut a @ ref mut b = U; | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:35:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:34:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- @@ -35,7 +35,7 @@ LL | let ref mut a @ ref mut b = U; | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:38:9 | LL | let ref mut a @ ref mut b = U; | ---------^^^--------- @@ -44,7 +44,7 @@ LL | let ref mut a @ ref mut b = U; | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:43:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:42:9 | LL | let ref mut a @ ( | ^-------- @@ -66,7 +66,7 @@ LL | | ) = (U, [U, U, U]); | |_____^ error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:53:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:52:9 | LL | let ref mut a @ ( | ^-------- @@ -88,31 +88,31 @@ LL | | ) = (u(), [u(), u(), u()]); | |_________^ error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:63:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:62:9 | LL | let a @ (ref mut b, ref mut c) = (U, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:66:9 | LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | ^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:71:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 | LL | let a @ &mut ref mut b = &mut U; | ^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it error[E0007]: cannot bind by-move with sub-bindings - --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:73:9 | LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ binds an already bound by-move value by moving it error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:79:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:78:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ @@ -121,7 +121,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:79:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:78:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ @@ -130,7 +130,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:85:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:84:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ @@ -139,7 +139,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:85:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:84:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ @@ -148,7 +148,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:92:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ @@ -157,7 +157,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:92:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ @@ -166,7 +166,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:104:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:103:9 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^---------^ @@ -175,7 +175,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:104:37 + --> $DIR/borrowck-pat-ref-mut-twice.rs:103:37 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------^^^^^^^---------^ @@ -184,7 +184,7 @@ LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:11:11 + --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11 | LL | fn f1(ref mut a @ ref mut b: U) {} | ---------^^^--------- @@ -193,7 +193,7 @@ LL | fn f1(ref mut a @ ref mut b: U) {} | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:13:11 + --> $DIR/borrowck-pat-ref-mut-twice.rs:12:11 | LL | fn f2(ref mut a @ ref mut b: U) {} | ---------^^^--------- @@ -202,7 +202,7 @@ LL | fn f2(ref mut a @ ref mut b: U) {} | first mutable borrow occurs here error: cannot borrow `a` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:16:9 + --> $DIR/borrowck-pat-ref-mut-twice.rs:15:9 | LL | ref mut a @ [ | ^-------- @@ -220,7 +220,7 @@ LL | | ] : [[U; 4]; 5] | |_________^ error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:25:21 + --> $DIR/borrowck-pat-ref-mut-twice.rs:24:21 | LL | let ref mut a @ ref mut b = U; | ------------^^^^^^^^^ @@ -232,7 +232,7 @@ LL | drop(a); | - first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:35:21 + --> $DIR/borrowck-pat-ref-mut-twice.rs:34:21 | LL | let ref mut a @ ref mut b = U; | ------------^^^^^^^^^ @@ -244,7 +244,7 @@ LL | *a = U; | ------ first borrow later used here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:63:25 + --> $DIR/borrowck-pat-ref-mut-twice.rs:62:25 | LL | let a @ (ref mut b, ref mut c) = (U, U); | ----------------^^^^^^^^^- ------ move occurs because value has type `(main::U, main::U)`, which does not implement the `Copy` trait @@ -253,7 +253,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U); | value moved here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:67:21 + --> $DIR/borrowck-pat-ref-mut-twice.rs:66:21 | LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | ------------^-- -------- move occurs because value has type `&mut (main::U, [main::U; 2])`, which does not implement the `Copy` trait @@ -262,7 +262,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | value moved here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:71:18 + --> $DIR/borrowck-pat-ref-mut-twice.rs:70:18 | LL | let a @ &mut ref mut b = &mut U; | ---------^^^^^^^^^ ------ move occurs because value has type `&mut main::U`, which does not implement the `Copy` trait @@ -271,7 +271,7 @@ LL | let a @ &mut ref mut b = &mut U; | value moved here error[E0382]: borrow of moved value - --> $DIR/borrowck-pat-ref-mut-twice.rs:74:30 + --> $DIR/borrowck-pat-ref-mut-twice.rs:73:30 | LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | ---------------------^^^^^^^^^- ----------- move occurs because value has type `&mut (main::U, main::U)`, which does not implement the `Copy` trait @@ -280,7 +280,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | value moved here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:92:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------------^^^^^^^^^- @@ -292,7 +292,7 @@ LL | *a = Err(U); | ----------- first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:92:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:91:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ----------------^^^^^^^^^- @@ -304,7 +304,7 @@ LL | *a = Err(U); | ----------- first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:104:24 + --> $DIR/borrowck-pat-ref-mut-twice.rs:103:24 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ---------------^^^^^^^^^- @@ -316,7 +316,7 @@ LL | drop(a); | - first borrow later used here error[E0499]: cannot borrow `_` as mutable more than once at a time - --> $DIR/borrowck-pat-ref-mut-twice.rs:104:53 + --> $DIR/borrowck-pat-ref-mut-twice.rs:103:53 | LL | ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => { | ----------------^^^^^^^^^- diff --git a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs index c910cded96b..5b0482de220 100644 --- a/src/test/ui/pattern/issue-53820-slice-pattern-large-array.rs +++ b/src/test/ui/pattern/usefulness/issue-53820-slice-pattern-large-array.rs @@ -1,8 +1,6 @@ // check-pass -// This used to cause a stack overflow in the compiler. - -#![feature(slice_patterns)] +// This used to cause a stack overflow during exhaustiveness checking in the compiler. fn main() { const LARGE_SIZE: usize = 1024 * 1024; diff --git a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs index 6c54c938bf1..54dfa889ee3 100644 --- a/src/test/ui/pattern/usefulness/65413-constants-and-slices-exhaustiveness.rs +++ b/src/test/ui/pattern/usefulness/issue-65413-constants-and-slices-exhaustiveness.rs @@ -1,5 +1,5 @@ // check-pass -#![feature(slice_patterns)] + #![deny(unreachable_patterns)] const C0: &'static [u8] = b"\x00"; diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs index 7541ea3e2e2..9b6c8bd5556 100644 --- a/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs +++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.rs @@ -1,4 +1,3 @@ -#![feature(slice_patterns)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr index b28646b50cf..09484692fab 100644 --- a/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr +++ b/src/test/ui/pattern/usefulness/match-byte-array-patterns.stderr @@ -1,53 +1,53 @@ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:9:9 + --> $DIR/match-byte-array-patterns.rs:8:9 | LL | &[0x41, 0x41, 0x41, 0x41] => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/match-byte-array-patterns.rs:2:9 + --> $DIR/match-byte-array-patterns.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:15:9 + --> $DIR/match-byte-array-patterns.rs:14:9 | LL | b"AAAA" => {}, | ^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:21:9 + --> $DIR/match-byte-array-patterns.rs:20:9 | LL | b"AAAA" => {}, | ^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:27:9 + --> $DIR/match-byte-array-patterns.rs:26:9 | LL | b"AAAA" => {}, | ^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:35:9 + --> $DIR/match-byte-array-patterns.rs:34:9 | LL | &[0x41, 0x41, 0x41, 0x41] => {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:41:9 + --> $DIR/match-byte-array-patterns.rs:40:9 | LL | b"AAAA" => {}, | ^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:47:9 + --> $DIR/match-byte-array-patterns.rs:46:9 | LL | b"AAAA" => {}, | ^^^^^^^ error: unreachable pattern - --> $DIR/match-byte-array-patterns.rs:53:9 + --> $DIR/match-byte-array-patterns.rs:52:9 | LL | b"AAAA" => {}, | ^^^^^^^ diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.rs b/src/test/ui/pattern/usefulness/match-slice-patterns.rs index af7fd53a1f1..92d74b8c229 100644 --- a/src/test/ui/pattern/usefulness/match-slice-patterns.rs +++ b/src/test/ui/pattern/usefulness/match-slice-patterns.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn check(list: &[Option<()>]) { match list { //~^ ERROR `&[_, Some(_), .., None, _]` not covered diff --git a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr index 72ae5d5fe3b..977a1128081 100644 --- a/src/test/ui/pattern/usefulness/match-slice-patterns.stderr +++ b/src/test/ui/pattern/usefulness/match-slice-patterns.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `&[_, Some(_), .., None, _]` not covered - --> $DIR/match-slice-patterns.rs:4:11 + --> $DIR/match-slice-patterns.rs:2:11 | LL | match list { | ^^^^ pattern `&[_, Some(_), .., None, _]` not covered diff --git a/src/test/ui/pattern/usefulness/match-vec-unreachable.rs b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs index 78810525bad..3342389be6e 100644 --- a/src/test/ui/pattern/usefulness/match-vec-unreachable.rs +++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.rs @@ -1,4 +1,3 @@ -#![feature(slice_patterns)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr index 415c24ae77e..e9a751074c2 100644 --- a/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr +++ b/src/test/ui/pattern/usefulness/match-vec-unreachable.stderr @@ -1,23 +1,23 @@ error: unreachable pattern - --> $DIR/match-vec-unreachable.rs:9:9 + --> $DIR/match-vec-unreachable.rs:8:9 | LL | [(1, 2), (2, 3), b] => (), | ^^^^^^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/match-vec-unreachable.rs:2:9 + --> $DIR/match-vec-unreachable.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-vec-unreachable.rs:19:9 + --> $DIR/match-vec-unreachable.rs:18:9 | LL | [_, _, _, _, _] => { } | ^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/match-vec-unreachable.rs:27:9 + --> $DIR/match-vec-unreachable.rs:26:9 | LL | ['a', 'b', 'c'] => {} | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs index 9423a2891a6..d198144790b 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - enum T { A(U), B } enum U { C, D } diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr index 67c818e19cb..72b4b522198 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match-nested.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `(Some(&[]), Err(_))` not covered - --> $DIR/non-exhaustive-match-nested.rs:7:11 + --> $DIR/non-exhaustive-match-nested.rs:5:11 | LL | match (l1, l2) { | ^^^^^^^^ pattern `(Some(&[]), Err(_))` not covered @@ -7,7 +7,7 @@ LL | match (l1, l2) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `A(C)` not covered - --> $DIR/non-exhaustive-match-nested.rs:17:11 + --> $DIR/non-exhaustive-match-nested.rs:15:11 | LL | enum T { A(U), B } | ------------------ diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs index bfca5352353..9947989dc12 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.rs @@ -1,4 +1,3 @@ -#![feature(slice_patterns)] #![allow(illegal_floating_point_literal_pattern)] enum T { A, B } diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr index 577867e4e71..a06ad578851 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-match.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `A` not covered - --> $DIR/non-exhaustive-match.rs:8:11 + --> $DIR/non-exhaustive-match.rs:7:11 | LL | enum T { A, B } | --------------- @@ -13,7 +13,7 @@ LL | match x { T::B => { } } = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `false` not covered - --> $DIR/non-exhaustive-match.rs:9:11 + --> $DIR/non-exhaustive-match.rs:8:11 | LL | match true { | ^^^^ pattern `false` not covered @@ -21,7 +21,7 @@ LL | match true { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Some(_)` not covered - --> $DIR/non-exhaustive-match.rs:12:11 + --> $DIR/non-exhaustive-match.rs:11:11 | LL | match Some(10) { | ^^^^^^^^ pattern `Some(_)` not covered @@ -29,7 +29,7 @@ LL | match Some(10) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered - --> $DIR/non-exhaustive-match.rs:15:11 + --> $DIR/non-exhaustive-match.rs:14:11 | LL | match (2, 3, 4) { | ^^^^^^^^^ patterns `(_, _, std::i32::MIN..=3i32)` and `(_, _, 5i32..=std::i32::MAX)` not covered @@ -37,7 +37,7 @@ LL | match (2, 3, 4) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(A, A)` not covered - --> $DIR/non-exhaustive-match.rs:19:11 + --> $DIR/non-exhaustive-match.rs:18:11 | LL | match (T::A, T::A) { | ^^^^^^^^^^^^ pattern `(A, A)` not covered @@ -45,7 +45,7 @@ LL | match (T::A, T::A) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `B` not covered - --> $DIR/non-exhaustive-match.rs:23:11 + --> $DIR/non-exhaustive-match.rs:22:11 | LL | enum T { A, B } | --------------- @@ -59,7 +59,7 @@ LL | match T::A { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `[]` not covered - --> $DIR/non-exhaustive-match.rs:34:11 + --> $DIR/non-exhaustive-match.rs:33:11 | LL | match *vec { | ^^^^ pattern `[]` not covered @@ -67,7 +67,7 @@ LL | match *vec { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `[_, _, _, _, ..]` not covered - --> $DIR/non-exhaustive-match.rs:47:11 + --> $DIR/non-exhaustive-match.rs:46:11 | LL | match *vec { | ^^^^ pattern `[_, _, _, _, ..]` not covered diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs index 4ca1cbcebcc..abb4ea8daf5 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - struct Foo { first: bool, second: Option<[usize; 4]> diff --git a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr index a0b497dd4c0..2a9fa07d22f 100644 --- a/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr +++ b/src/test/ui/pattern/usefulness/non-exhaustive-pattern-witness.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `Foo { first: false, second: Some([_, _, _, _]) }` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:9:11 + --> $DIR/non-exhaustive-pattern-witness.rs:7:11 | LL | / struct Foo { LL | | first: bool, @@ -13,7 +13,7 @@ LL | match (Foo { first: true, second: None }) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Red` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:25:11 + --> $DIR/non-exhaustive-pattern-witness.rs:23:11 | LL | / enum Color { LL | | Red, @@ -29,7 +29,7 @@ LL | match Color::Red { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `East`, `South` and `West` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:37:11 + --> $DIR/non-exhaustive-pattern-witness.rs:35:11 | LL | / enum Direction { LL | | North, East, South, West @@ -46,7 +46,7 @@ LL | match Direction::North { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `Second`, `Third`, `Fourth` and 8 more not covered - --> $DIR/non-exhaustive-pattern-witness.rs:48:11 + --> $DIR/non-exhaustive-pattern-witness.rs:46:11 | LL | / enum ExcessiveEnum { LL | | First, Second, Third, Fourth, Fifth, Sixth, Seventh, Eighth, Ninth, Tenth, Eleventh, Twelfth @@ -59,7 +59,7 @@ LL | match ExcessiveEnum::First { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `CustomRGBA { a: true, .. }` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:56:11 + --> $DIR/non-exhaustive-pattern-witness.rs:54:11 | LL | / enum Color { LL | | Red, @@ -75,7 +75,7 @@ LL | match Color::Red { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `[Second(true), Second(false)]` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:72:11 + --> $DIR/non-exhaustive-pattern-witness.rs:70:11 | LL | match *x { | ^^ pattern `[Second(true), Second(false)]` not covered @@ -83,7 +83,7 @@ LL | match *x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `((), false)` not covered - --> $DIR/non-exhaustive-pattern-witness.rs:85:11 + --> $DIR/non-exhaustive-pattern-witness.rs:83:11 | LL | match ((), false) { | ^^^^^^^^^^^ pattern `((), false)` not covered diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs index 41ba2cc4501..52d1320dad1 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs +++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - fn main() { let s: &[bool] = &[true; 0]; let s1: &[bool; 1] = &[false; 1]; diff --git a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr index 8cb342f33df..b3701efef3d 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr +++ b/src/test/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `&[false, _]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:10:11 + --> $DIR/slice-patterns-exhaustiveness.rs:8:11 | LL | match s2 { | ^^ pattern `&[false, _]` not covered @@ -7,7 +7,7 @@ LL | match s2 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:14:11 + --> $DIR/slice-patterns-exhaustiveness.rs:12:11 | LL | match s3 { | ^^ pattern `&[false, ..]` not covered @@ -15,7 +15,7 @@ LL | match s3 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:18:11 + --> $DIR/slice-patterns-exhaustiveness.rs:16:11 | LL | match s10 { | ^^^ pattern `&[false, ..]` not covered @@ -23,7 +23,7 @@ LL | match s10 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, true]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:27:11 + --> $DIR/slice-patterns-exhaustiveness.rs:25:11 | LL | match s2 { | ^^ pattern `&[false, true]` not covered @@ -31,7 +31,7 @@ LL | match s2 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:32:11 + --> $DIR/slice-patterns-exhaustiveness.rs:30:11 | LL | match s3 { | ^^ pattern `&[false, .., true]` not covered @@ -39,7 +39,7 @@ LL | match s3 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, .., true]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:37:11 + --> $DIR/slice-patterns-exhaustiveness.rs:35:11 | LL | match s { | ^ pattern `&[false, .., true]` not covered @@ -47,7 +47,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:44:11 + --> $DIR/slice-patterns-exhaustiveness.rs:42:11 | LL | match s { | ^ pattern `&[_, ..]` not covered @@ -55,7 +55,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[_, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:48:11 + --> $DIR/slice-patterns-exhaustiveness.rs:46:11 | LL | match s { | ^ pattern `&[_, _, ..]` not covered @@ -63,7 +63,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:53:11 + --> $DIR/slice-patterns-exhaustiveness.rs:51:11 | LL | match s { | ^ pattern `&[false, ..]` not covered @@ -71,7 +71,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false, _, ..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:58:11 + --> $DIR/slice-patterns-exhaustiveness.rs:56:11 | LL | match s { | ^ pattern `&[false, _, ..]` not covered @@ -79,7 +79,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[_, .., false]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:64:11 + --> $DIR/slice-patterns-exhaustiveness.rs:62:11 | LL | match s { | ^ pattern `&[_, .., false]` not covered @@ -87,7 +87,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[_, _, .., true]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:71:11 + --> $DIR/slice-patterns-exhaustiveness.rs:69:11 | LL | match s { | ^ pattern `&[_, _, .., true]` not covered @@ -95,7 +95,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[true, _, .., _]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:78:11 + --> $DIR/slice-patterns-exhaustiveness.rs:76:11 | LL | match s { | ^ pattern `&[true, _, .., _]` not covered @@ -103,7 +103,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[..]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:87:11 + --> $DIR/slice-patterns-exhaustiveness.rs:85:11 | LL | match s { | ^ pattern `&[..]` not covered @@ -111,7 +111,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[true]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:91:11 + --> $DIR/slice-patterns-exhaustiveness.rs:89:11 | LL | match s { | ^ pattern `&[true]` not covered @@ -119,7 +119,7 @@ LL | match s { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `&[false]` not covered - --> $DIR/slice-patterns-exhaustiveness.rs:99:11 + --> $DIR/slice-patterns-exhaustiveness.rs:97:11 | LL | match s1 { | ^^ pattern `&[false]` not covered diff --git a/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs b/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs index 3b716bae772..cbf64e2c53d 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs +++ b/src/test/ui/pattern/usefulness/slice-patterns-irrefutable.rs @@ -1,5 +1,4 @@ // check-pass -#![feature(slice_patterns)] fn main() { let s: &[bool] = &[true; 0]; diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs index cd229a0fcbe..7c747b5e0b9 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs +++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.rs @@ -1,4 +1,3 @@ -#![feature(slice_patterns)] #![deny(unreachable_patterns)] fn main() { diff --git a/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr b/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr index 333ce170283..e24d1028117 100644 --- a/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr +++ b/src/test/ui/pattern/usefulness/slice-patterns-reachability.stderr @@ -1,41 +1,41 @@ error: unreachable pattern - --> $DIR/slice-patterns-reachability.rs:9:9 + --> $DIR/slice-patterns-reachability.rs:8:9 | LL | [true, ..] => {} | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/slice-patterns-reachability.rs:2:9 + --> $DIR/slice-patterns-reachability.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/slice-patterns-reachability.rs:10:9 + --> $DIR/slice-patterns-reachability.rs:9:9 | LL | [true] => {} | ^^^^^^ error: unreachable pattern - --> $DIR/slice-patterns-reachability.rs:15:9 + --> $DIR/slice-patterns-reachability.rs:14:9 | LL | [.., true] => {} | ^^^^^^^^^^ error: unreachable pattern - --> $DIR/slice-patterns-reachability.rs:16:9 + --> $DIR/slice-patterns-reachability.rs:15:9 | LL | [true] => {} | ^^^^^^ error: unreachable pattern - --> $DIR/slice-patterns-reachability.rs:21:9 + --> $DIR/slice-patterns-reachability.rs:20:9 | LL | [false, .., true] => {} | ^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/slice-patterns-reachability.rs:22:9 + --> $DIR/slice-patterns-reachability.rs:21:9 | LL | [false, true] => {} | ^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/item-error.stderr b/src/test/ui/proc-macro/item-error.stderr index e801c26c43b..01eadbe252e 100644 --- a/src/test/ui/proc-macro/item-error.stderr +++ b/src/test/ui/proc-macro/item-error.stderr @@ -2,7 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/item-error.rs:10:8 | LL | a: &u64 - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct A<'lifetime> { +LL | a: &'lifetime u64 + | error: aborting due to previous error diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs index 0fcf77d8722..d9996b80ac0 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.rs @@ -1,6 +1,6 @@ // Dropck shouldn't hit a recursion limit from checking `S<u32>` since it has // no free regions or type parameters. -// Codegen however, has to error for the infinitely many `real_drop_in_place` +// Codegen however, has to error for the infinitely many `drop_in_place` // functions it has been asked to create. // build-fail diff --git a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr index 77309a82a0f..de6df4cd026 100644 --- a/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr +++ b/src/test/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr @@ -1,4 +1,4 @@ -error: reached the recursion limit while instantiating `std::ptr::real_drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))` +error: reached the recursion limit while instantiating `std::intrinsics::drop_in_place::<S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>> - shim(Some(S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>))` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-in-enums-anon.stderr b/src/test/ui/regions/regions-in-enums-anon.stderr index ae06e7653db..41655a210b3 100644 --- a/src/test/ui/regions/regions-in-enums-anon.stderr +++ b/src/test/ui/regions/regions-in-enums-anon.stderr @@ -2,7 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/regions-in-enums-anon.rs:4:9 | LL | Bar(&isize) - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | enum Foo<'lifetime> { +LL | Bar(&'lifetime isize) + | error: aborting due to previous error diff --git a/src/test/ui/regions/regions-in-enums.stderr b/src/test/ui/regions/regions-in-enums.stderr index cfed9feba4b..66537653291 100644 --- a/src/test/ui/regions/regions-in-enums.stderr +++ b/src/test/ui/regions/regions-in-enums.stderr @@ -1,12 +1,16 @@ error[E0261]: use of undeclared lifetime name `'foo` --> $DIR/regions-in-enums.rs:13:9 | +LL | enum No0 { + | - help: consider introducing lifetime `'foo` here: `<'foo>` LL | X5(&'foo usize) | ^^^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-in-enums.rs:17:9 | +LL | enum No1 { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | X6(&'a usize) | ^^ undeclared lifetime diff --git a/src/test/ui/regions/regions-in-structs-anon.stderr b/src/test/ui/regions/regions-in-structs-anon.stderr index a1d4ebb597b..fbe8036880f 100644 --- a/src/test/ui/regions/regions-in-structs-anon.stderr +++ b/src/test/ui/regions/regions-in-structs-anon.stderr @@ -2,7 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/regions-in-structs-anon.rs:4:8 | LL | x: &isize - | ^ expected lifetime parameter + | ^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct Foo<'lifetime> { +LL | x: &'lifetime isize + | error: aborting due to previous error diff --git a/src/test/ui/regions/regions-in-structs.stderr b/src/test/ui/regions/regions-in-structs.stderr index 8314942759d..5dfdc2ee93b 100644 --- a/src/test/ui/regions/regions-in-structs.stderr +++ b/src/test/ui/regions/regions-in-structs.stderr @@ -1,12 +1,17 @@ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-in-structs.rs:10:9 | +LL | struct StructDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | a: &'a isize, | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-in-structs.rs:11:9 | +LL | struct StructDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | a: &'a isize, LL | b: &'a isize, | ^^ undeclared lifetime diff --git a/src/test/ui/regions/regions-name-undeclared.stderr b/src/test/ui/regions/regions-name-undeclared.stderr index 5f6a48a35f3..79ebef41dcc 100644 --- a/src/test/ui/regions/regions-name-undeclared.stderr +++ b/src/test/ui/regions/regions-name-undeclared.stderr @@ -3,34 +3,67 @@ error[E0261]: use of undeclared lifetime name `'b` | LL | fn m4(&self, arg: &'b isize) { } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> Foo<'a> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn m4<'b>(&self, arg: &'b isize) { } + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:16:12 | LL | fn m5(&'b self) { } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> Foo<'a> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn m5<'b>(&'b self) { } + | ^^^^ error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:17:27 | LL | fn m6(&self, arg: Foo<'b>) { } | ^^ undeclared lifetime + | +help: consider introducing lifetime `'b` here + | +LL | impl<'b, 'a> Foo<'a> { + | ^^^ +help: consider introducing lifetime `'b` here + | +LL | fn m6<'b>(&self, arg: Foo<'b>) { } + | ^^^^ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:25:22 | LL | type X = Option<&'a isize>; - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:27:13 | +LL | enum E { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | E1(&'a isize) | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:30:13 | +LL | struct S { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | f: &'a isize | ^^ undeclared lifetime @@ -38,13 +71,17 @@ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:32:14 | LL | fn f(a: &'a isize) { } - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:40:17 | LL | fn fn_types(a: &'a isize, - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'b` --> $DIR/regions-name-undeclared.rs:42:36 @@ -61,6 +98,9 @@ LL | ... &'b isize)>, error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-name-undeclared.rs:46:17 | +LL | fn fn_types(a: &'a isize, + | - help: consider introducing lifetime `'a` here: `<'a>` +... LL | c: &'a isize) | ^^ undeclared lifetime diff --git a/src/test/ui/regions/regions-undeclared.stderr b/src/test/ui/regions/regions-undeclared.stderr index 495aec3fde5..6bfde5524ac 100644 --- a/src/test/ui/regions/regions-undeclared.stderr +++ b/src/test/ui/regions/regions-undeclared.stderr @@ -7,12 +7,17 @@ LL | static c_x: &'blk isize = &22; error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-undeclared.rs:4:10 | +LL | enum EnumDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` LL | Foo(&'a isize), | ^^ undeclared lifetime error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-undeclared.rs:5:10 | +LL | enum EnumDecl { + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | Foo(&'a isize), LL | Bar(&'a isize), | ^^ undeclared lifetime @@ -20,11 +25,15 @@ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-undeclared.rs:8:15 | LL | fn fnDecl(x: &'a isize, - | ^^ undeclared lifetime + | - ^^ undeclared lifetime + | | + | help: consider introducing lifetime `'a` here: `<'a>` error[E0261]: use of undeclared lifetime name `'a` --> $DIR/regions-undeclared.rs:9:15 | +LL | fn fnDecl(x: &'a isize, + | - help: consider introducing lifetime `'a` here: `<'a>` LL | y: &'a isize) | ^^ undeclared lifetime diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfc-2005-default-binding-mode/slice.rs index 1484b8c4a1f..363a0e3e649 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/slice.rs @@ -1,5 +1,3 @@ -#![feature(slice_patterns)] - pub fn main() { let sl: &[u8] = b"foo"; diff --git a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr index f1e91a05f08..c234fdf46ed 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/slice.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/slice.stderr @@ -1,5 +1,5 @@ error[E0004]: non-exhaustive patterns: `&[]` not covered - --> $DIR/slice.rs:6:11 + --> $DIR/slice.rs:4:11 | LL | match sl { | ^^ pattern `&[]` not covered diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs new file mode 100644 index 00000000000..0407eafbfd4 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(track_caller)] + +fn pass_to_ptr_call<T>(f: fn(T), x: T) { + f(x); +} + +#[track_caller] +fn tracked_unit(_: ()) { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); +} + +fn main() { + pass_to_ptr_call(tracked_unit, ()); +} diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs new file mode 100644 index 00000000000..a4baaa26ced --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(track_caller)] + +fn ptr_call(f: fn()) { + f(); +} + +#[track_caller] +fn tracked() { + let expected_line = line!() - 1; + let location = std::panic::Location::caller(); + assert_eq!(location.file(), file!()); + assert_eq!(location.line(), expected_line, "call shims report location as fn definition"); +} + +fn main() { + ptr_call(tracked); +} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr index 0bf337ad08d..e4f4d4262b6 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.gated.stderr @@ -1,8 +1,8 @@ -error: `?const` on trait bounds is not yet implemented - --> $DIR/feature-gate.rs:11:29 +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate.rs:16:1 | -LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST } - | ^^^^^^^^ +LL | fn main() {} + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs index cf1ed30da0f..d600b53e448 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs @@ -3,6 +3,7 @@ #![cfg_attr(gated, feature(const_trait_bound_opt_out))] #![allow(incomplete_features)] +#![feature(rustc_attrs)] trait T { const CONST: i32; @@ -10,6 +11,6 @@ trait T { const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST } //[stock]~^ ERROR `?const` on trait bounds is experimental -//[stock,gated]~^^ ERROR `?const` on trait bounds is not yet implemented -fn main() {} +#[rustc_error] +fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr index 64388004b5b..fbd3840cb1d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: `?const` on trait bounds is experimental - --> $DIR/feature-gate.rs:11:29 + --> $DIR/feature-gate.rs:12:29 | LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST } | ^^^^^^ @@ -7,12 +7,6 @@ LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST } = note: for more information, see https://github.com/rust-lang/rust/issues/67794 = help: add `#![feature(const_trait_bound_opt_out)]` to the crate attributes to enable -error: `?const` on trait bounds is not yet implemented - --> $DIR/feature-gate.rs:11:29 - | -LL | const fn get_assoc_const<S: ?const T>() -> i32 { <S as T>::CONST } - | ^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs index e4e6bedd937..f5561a922dd 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.rs @@ -8,18 +8,14 @@ impl T for S {} fn rpit() -> impl ?const T { S } //~^ ERROR `?const` is not permitted in `impl Trait` -//~| ERROR `?const` on trait bounds is not yet implemented fn apit(_: impl ?const T) {} //~^ ERROR `?const` is not permitted in `impl Trait` -//~| ERROR `?const` on trait bounds is not yet implemented fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) } //~^ ERROR `?const` is not permitted in `impl Trait` -//~| ERROR `?const` on trait bounds is not yet implemented fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {} //~^ ERROR `?const` is not permitted in `impl Trait` -//~| ERROR `?const` on trait bounds is not yet implemented fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr index f4abd4b714e..06cd00a956a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-impl-trait.stderr @@ -5,46 +5,22 @@ LL | fn rpit() -> impl ?const T { S } | ^^^^^^^^ error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:13:17 + --> $DIR/in-impl-trait.rs:12:17 | LL | fn apit(_: impl ?const T) {} | ^^^^^^^^ error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:17:50 + --> $DIR/in-impl-trait.rs:15:50 | LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) } | ^^^^^^^^ error: `?const` is not permitted in `impl Trait` - --> $DIR/in-impl-trait.rs:21:48 + --> $DIR/in-impl-trait.rs:18:48 | LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {} | ^^^^^^^^ -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-impl-trait.rs:9:19 - | -LL | fn rpit() -> impl ?const T { S } - | ^^^^^^^^ - -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-impl-trait.rs:13:17 - | -LL | fn apit(_: impl ?const T) {} - | ^^^^^^^^ - -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-impl-trait.rs:17:50 - | -LL | fn rpit_assoc_bound() -> impl IntoIterator<Item: ?const T> { Some(S) } - | ^^^^^^^^ - -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-impl-trait.rs:21:48 - | -LL | fn apit_assoc_bound(_: impl IntoIterator<Item: ?const T>) {} - | ^^^^^^^^ - -error: aborting due to 8 previous errors +error: aborting due to 4 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs index 4523b46bc51..fc9ed5b1dc2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.rs @@ -4,6 +4,5 @@ trait Super {} trait T: ?const Super {} //~^ ERROR `?const` is not permitted in supertraits -//~| ERROR `?const` on trait bounds is not yet implemented fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr index 8003361be7d..a0d8f95acd2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-bounds.stderr @@ -4,11 +4,5 @@ error: `?const` is not permitted in supertraits LL | trait T: ?const Super {} | ^^^^^^^^^^^^ -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-trait-bounds.rs:5:10 - | -LL | trait T: ?const Super {} - | ^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs index 6cfca715486..b3d1f48ace1 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.rs @@ -9,14 +9,11 @@ impl T for S {} // An inherent impl for the trait object `?const T`. impl ?const T {} //~^ ERROR `?const` is not permitted in trait objects -//~| ERROR `?const` on trait bounds is not yet implemented fn trait_object() -> &'static dyn ?const T { &S } //~^ ERROR `?const` is not permitted in trait objects -//~| ERROR `?const` on trait bounds is not yet implemented fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {} //~^ ERROR `?const` is not permitted in trait objects -//~| ERROR `?const` on trait bounds is not yet implemented fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr index c059f169022..331fe0423fa 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/in-trait-object.stderr @@ -5,34 +5,16 @@ LL | impl ?const T {} | ^^^^^^^^ error: `?const` is not permitted in trait objects - --> $DIR/in-trait-object.rs:14:35 + --> $DIR/in-trait-object.rs:13:35 | LL | fn trait_object() -> &'static dyn ?const T { &S } | ^^^^^^^^ error: `?const` is not permitted in trait objects - --> $DIR/in-trait-object.rs:18:61 + --> $DIR/in-trait-object.rs:16:61 | LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {} | ^^^^^^^^ -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-trait-object.rs:10:6 - | -LL | impl ?const T {} - | ^^^^^^^^ - -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-trait-object.rs:14:35 - | -LL | fn trait_object() -> &'static dyn ?const T { &S } - | ^^^^^^^^ - -error: `?const` on trait bounds is not yet implemented - --> $DIR/in-trait-object.rs:18:61 - | -LL | fn trait_object_in_apit(_: impl IntoIterator<Item = Box<dyn ?const T>>) {} - | ^^^^^^^^ - -error: aborting due to 6 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs index 425784f4e43..c2c8689e294 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.rs @@ -3,6 +3,5 @@ struct S<T: ?const ?Sized>(std::marker::PhantomData<T>); //~^ ERROR `?const` and `?` are mutually exclusive -//~| ERROR `?const` on trait bounds is not yet implemented fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr index 44f6d464ae6..e8e9d6c1e76 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/with-maybe-sized.stderr @@ -4,11 +4,5 @@ error: `?const` and `?` are mutually exclusive LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>); | ^^^^^^^^^^^^^ -error: `?const` on trait bounds is not yet implemented - --> $DIR/with-maybe-sized.rs:4:13 - | -LL | struct S<T: ?const ?Sized>(std::marker::PhantomData<T>); - | ^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs index 9cffe75addd..7f064c0c53a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs @@ -1,5 +1,3 @@ -// compile-flags: -Z parse-only - #![feature(const_trait_impl)] #![feature(const_trait_bound_opt_out)] #![allow(incomplete_features)] @@ -8,7 +6,12 @@ struct S; trait T {} +impl const S {} +//~^ ERROR inherent impls cannot be `const` +//~| ERROR const trait impls are not yet implemented + impl const T {} -//~^ ERROR `const` cannot modify an inherent impl +//~^ ERROR inherent impls cannot be `const` +//~| ERROR const trait impls are not yet implemented fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr index 1d245576559..508c6f4c747 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr @@ -1,10 +1,30 @@ -error: `const` cannot modify an inherent impl - --> $DIR/inherent-impl.rs:11:6 +error: inherent impls cannot be `const` + --> $DIR/inherent-impl.rs:9:1 + | +LL | impl const S {} + | ^^^^^^^^^^^^^^^ + | + = note: only trait implementations may be annotated with `const` + +error: inherent impls cannot be `const` + --> $DIR/inherent-impl.rs:13:1 | LL | impl const T {} - | ^^^^^ + | ^^^^^^^^^^^^^^^ + | + = note: only trait implementations may be annotated with `const` + +error: const trait impls are not yet implemented + --> $DIR/inherent-impl.rs:9:1 + | +LL | impl const S {} + | ^^^^^^^^^^^^^^^ + +error: const trait impls are not yet implemented + --> $DIR/inherent-impl.rs:13:1 | - = help: only a trait impl can be `const` +LL | impl const T {} + | ^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: aborting due to 4 previous errors diff --git a/src/test/ui/rfc1623.stderr b/src/test/ui/rfc1623.stderr index 171c00ba7b8..5b665e18141 100644 --- a/src/test/ui/rfc1623.stderr +++ b/src/test/ui/rfc1623.stderr @@ -2,7 +2,7 @@ error[E0106]: missing lifetime specifier --> $DIR/rfc1623.rs:8:42 | LL | static NON_ELIDABLE_FN: &fn(&u8, &u8) -> &u8 = - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 @@ -10,7 +10,7 @@ error[E0106]: missing lifetime specifier --> $DIR/rfc1623.rs:10:39 | LL | &(non_elidable as fn(&u8, &u8) -> &u8); - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs index 38b0941aad0..33229a205f4 100644 --- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs +++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/slice.rs @@ -1,5 +1,4 @@ // run-pass -#![feature(slice_patterns)] fn slice_pat() { let sl: &[u8] = b"foo"; diff --git a/src/test/ui/sanitizer-address.rs b/src/test/ui/sanitizer-address.rs new file mode 100644 index 00000000000..d27a30a2dc5 --- /dev/null +++ b/src/test/ui/sanitizer-address.rs @@ -0,0 +1,21 @@ +// needs-sanitizer-support +// only-x86_64 +// +// compile-flags: -Z sanitizer=address -O +// +// run-fail +// error-pattern: AddressSanitizer: stack-buffer-overflow +// error-pattern: 'xs' <== Memory access at offset + +#![feature(test)] + +use std::hint::black_box; +use std::mem; + +fn main() { + let xs = [0, 1, 2, 3]; + // Avoid optimizing everything out. + let xs = black_box(xs.as_ptr()); + let code = unsafe { *xs.offset(4) }; + std::process::exit(code); +} diff --git a/src/test/run-make-fulldeps/sanitizer-leak/leak.rs b/src/test/ui/sanitizer-leak.rs index fb0a917dd98..5c2f2cb4e86 100644 --- a/src/test/run-make-fulldeps/sanitizer-leak/leak.rs +++ b/src/test/ui/sanitizer-leak.rs @@ -1,3 +1,11 @@ +// needs-sanitizer-support +// only-x86_64 +// +// compile-flags: -Z sanitizer=leak -O +// +// run-fail +// error-pattern: LeakSanitizer: detected memory leaks + #![feature(test)] use std::hint::black_box; diff --git a/src/test/ui/sanitizer-memory.rs b/src/test/ui/sanitizer-memory.rs new file mode 100644 index 00000000000..3e1cf4509a3 --- /dev/null +++ b/src/test/ui/sanitizer-memory.rs @@ -0,0 +1,44 @@ +// needs-sanitizer-support +// only-linux +// only-x86_64 +// +// compile-flags: -Z sanitizer=memory -Zsanitizer-memory-track-origins -O +// +// run-fail +// error-pattern: MemorySanitizer: use-of-uninitialized-value +// error-pattern: Uninitialized value was created by an allocation +// error-pattern: in the stack frame of function 'random' +// +// This test case intentionally limits the usage of the std, +// since it will be linked with an uninstrumented version of it. + +#![feature(core_intrinsics)] +#![feature(start)] +#![feature(test)] + +use std::hint::black_box; +use std::mem::MaybeUninit; + +#[inline(never)] +#[no_mangle] +fn random() -> [isize; 32] { + let r = unsafe { MaybeUninit::uninit().assume_init() }; + // Avoid optimizing everything out. + black_box(r) +} + +#[inline(never)] +#[no_mangle] +fn xor(a: &[isize]) -> isize { + let mut s = 0; + for i in 0..a.len() { + s = s ^ a[i]; + } + s +} + +#[start] +fn main(_: isize, _: *const *const u8) -> isize { + let r = random(); + xor(&r) +} diff --git a/src/test/ui/sanitizer-unsupported-target.rs b/src/test/ui/sanitizer-unsupported-target.rs new file mode 100644 index 00000000000..444333c3f01 --- /dev/null +++ b/src/test/ui/sanitizer-unsupported-target.rs @@ -0,0 +1,7 @@ +// ignore-tidy-linelength +// compile-flags: -Z sanitizer=leak --target i686-unknown-linux-gnu +// error-pattern: error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target + +#![feature(no_core)] +#![no_core] +#![no_main] diff --git a/src/test/ui/sanitizer-unsupported-target.stderr b/src/test/ui/sanitizer-unsupported-target.stderr new file mode 100644 index 00000000000..38be58dd4b3 --- /dev/null +++ b/src/test/ui/sanitizer-unsupported-target.stderr @@ -0,0 +1,4 @@ +error: LeakSanitizer only works with the `x86_64-unknown-linux-gnu` or `x86_64-apple-darwin` target + +error: aborting due to previous error + diff --git a/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs index 44beb9dc1e5..2f6d35f01be 100644 --- a/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs +++ b/src/test/ui/threads-sendsync/sync-send-iterators-in-libcore.rs @@ -88,6 +88,7 @@ fn main() { is_sync_send!((1..)); is_sync_send!(repeat(1)); is_sync_send!(empty::<usize>()); + is_sync_send!(empty::<*mut i32>()); is_sync_send!(once(1)); // for option.rs diff --git a/src/test/ui/trailing-comma.rs b/src/test/ui/trailing-comma.rs index 929c35a9e11..97006ae50a0 100644 --- a/src/test/ui/trailing-comma.rs +++ b/src/test/ui/trailing-comma.rs @@ -1,8 +1,6 @@ // run-pass // pretty-expanded FIXME #23616 -#![feature(slice_patterns)] - fn f<T,>(_: T,) {} struct Foo<T,>(T); diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr index 9fb9a07166f..0a028e44919 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-lifetime-elision.stderr @@ -2,9 +2,18 @@ error[E0106]: missing lifetime specifier --> $DIR/unboxed-closure-sugar-lifetime-elision.rs:26:39 | LL | let _: dyn Foo(&isize, &usize) -> &usize; - | ^ expected lifetime parameter + | ^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2 +help: consider introducing a named lifetime parameter + | +LL | fn main<'lifetime>() { +LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=&'a isize>, +LL | dyn Foo(&isize) -> &isize >(); +LL | eq::< dyn for<'a> Foo<(&'a isize,), Output=(&'a isize, &'a isize)>, +LL | dyn Foo(&isize) -> (&isize, &isize) >(); +LL | + ... error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr index b20c23ade2b..04df2e45703 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -2,7 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/dyn-trait-underscore-in-struct.rs:9:24 | LL | x: Box<dyn Debug + '_>, - | ^^ expected lifetime parameter + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct Foo<'lifetime> { +LL | x: Box<dyn Debug + 'lifetime>, + | error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound --> $DIR/dyn-trait-underscore-in-struct.rs:9:12 diff --git a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr index ed61bdfddda..cf820249c80 100644 --- a/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr +++ b/src/test/ui/underscore-lifetime/in-fn-return-illegal.stderr @@ -2,9 +2,13 @@ error[E0106]: missing lifetime specifier --> $DIR/in-fn-return-illegal.rs:5:30 | LL | fn foo(x: &u32, y: &u32) -> &'_ u32 { loop { } } - | ^^ expected lifetime parameter + | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `x` or `y` +help: consider introducing a named lifetime parameter + | +LL | fn foo<'lifetime>(x: &u32, y: &u32) -> &'lifetime u32 { loop { } } + | ^^^^^^^^^^^ ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/underscore-lifetime/in-struct.stderr b/src/test/ui/underscore-lifetime/in-struct.stderr index 6bbdc71195a..e01b39a4b64 100644 --- a/src/test/ui/underscore-lifetime/in-struct.stderr +++ b/src/test/ui/underscore-lifetime/in-struct.stderr @@ -2,13 +2,25 @@ error[E0106]: missing lifetime specifier --> $DIR/in-struct.rs:6:9 | LL | x: &'_ u32, - | ^^ expected lifetime parameter + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | struct Foo<'lifetime> { +LL | x: &'lifetime u32, + | error[E0106]: missing lifetime specifier --> $DIR/in-struct.rs:10:14 | LL | Variant(&'_ u32), - | ^^ expected lifetime parameter + | ^^ expected named lifetime parameter + | +help: consider introducing a named lifetime parameter + | +LL | enum Bar<'lifetime> { +LL | Variant(&'lifetime u32), + | error: aborting due to 2 previous errors diff --git a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr index ef9e7e39df0..517904ee628 100644 --- a/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr +++ b/src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr @@ -14,7 +14,7 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:2:17 | LL | struct Baz<'a>(&'_ &'a u8); - | ^^ expected lifetime parameter + | ^^ help: consider using the named lifetime: `'a` error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:10:33 @@ -28,9 +28,13 @@ error[E0106]: missing lifetime specifier --> $DIR/underscore-lifetime-binders.rs:16:35 | LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y } - | ^^ expected lifetime parameter + | ^^ expected named lifetime parameter | = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y` +help: consider introducing a named lifetime parameter + | +LL | fn foo2<'lifetime>(_: &'_ u8, y: &'_ u8) -> &'lifetime u8 { y } + | ^^^^^^^^^^^ ^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/uninhabited/uninhabited-patterns.rs b/src/test/ui/uninhabited/uninhabited-patterns.rs index 1bf01184a08..58c726d2185 100644 --- a/src/test/ui/uninhabited/uninhabited-patterns.rs +++ b/src/test/ui/uninhabited/uninhabited-patterns.rs @@ -2,7 +2,7 @@ #![feature(box_syntax)] #![feature(never_type)] #![feature(exhaustive_patterns)] -#![feature(slice_patterns)] + #![deny(unreachable_patterns)] mod foo { diff --git a/src/test/ui/where-clauses/where-lifetime-resolution.stderr b/src/test/ui/where-clauses/where-lifetime-resolution.stderr index 0081ae07163..49799a93017 100644 --- a/src/test/ui/where-clauses/where-lifetime-resolution.stderr +++ b/src/test/ui/where-clauses/where-lifetime-resolution.stderr @@ -1,6 +1,9 @@ error[E0261]: use of undeclared lifetime name `'a` --> $DIR/where-lifetime-resolution.rs:6:38 | +LL | fn f() where + | - help: consider introducing lifetime `'a` here: `<'a>` +LL | for<'a> dyn Trait1<'a>: Trait1<'a>, // OK LL | (dyn for<'a> Trait1<'a>): Trait1<'a>, | ^^ undeclared lifetime @@ -13,6 +16,9 @@ LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, error[E0261]: use of undeclared lifetime name `'b` --> $DIR/where-lifetime-resolution.rs:8:52 | +LL | fn f() where + | - help: consider introducing lifetime `'b` here: `<'b>` +... LL | for<'a> dyn for<'b> Trait2<'a, 'b>: Trait2<'a, 'b>, | ^^ undeclared lifetime diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 481163a1a9a..cff04e197e4 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -110,6 +110,7 @@ static TARGETS: &[&str] = &[ "riscv32imac-unknown-none-elf", "riscv64imac-unknown-none-elf", "riscv64gc-unknown-none-elf", + "riscv64gc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", diff --git a/src/tools/clippy b/src/tools/clippy -Subproject a8d90f6a57925d204efb21b3f6d9726d6674f9b +Subproject fd0428f622feee209e6014b802f5717d48d9e97 |
